Skip to content

Commit a3daedc

Browse files
author
Anirudh Bagri
committed
add client certificate authentication mechanism
1 parent 7518804 commit a3daedc

File tree

5 files changed

+116
-4
lines changed

5 files changed

+116
-4
lines changed

src/main/java/se/bjurr/violations/comments/bitbucketserver/lib/BitbucketServerCommentsProvider.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ public BitbucketServerCommentsProvider(
7676
final Integer proxyHostPort = violationCommentsToBitbucketApi.getProxyHostPort();
7777
final String proxyUser = violationCommentsToBitbucketApi.getProxyUser();
7878
final String proxyPassword = violationCommentsToBitbucketApi.getProxyPassword();
79+
final String keyStorePath = violationCommentsToBitbucketApi.getPropKeyStorePath();
80+
final String keyStorePass = violationCommentsToBitbucketApi.getPropKeyStorePass();
7981
this.client =
8082
new BitbucketServerClient(
8183
violationsLogger,
@@ -86,6 +88,8 @@ public BitbucketServerCommentsProvider(
8688
bitbucketServerUser,
8789
bitbucketServerPassword,
8890
bitbucketPersonalAccessToken,
91+
keyStorePath,
92+
keyStorePass,
8993
proxyHostNameOrIp,
9094
proxyHostPort,
9195
proxyUser,

src/main/java/se/bjurr/violations/comments/bitbucketserver/lib/ViolationCommentsToBitbucketServerApi.java

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public class ViolationCommentsToBitbucketServerApi {
1919
public static final String DEFAULT_PROP_VIOLATIONS_PASSWORD = "VIOLATIONS_PASSWORD";
2020
public static final String DEFAULT_PROP_VIOLATIONS_USERNAME = "VIOLATIONS_USERNAME";
2121
public static final String DEFAULT_PROP_PERSONAL_ACCESS_TOKEN = "VIOLATIONS_PAT";
22+
public static final String DEFAULT_PROP_KEYSTORE_PATH = "VIOLATIONS_KEYSTORE_PATH";
23+
public static final String DEFAULT_PROP_KEYSTORE_PASS = "VIOLATIONS_KEYSTORE_PASS";
2224

2325
public static ViolationCommentsToBitbucketServerApi violationCommentsToBitbucketServerApi() {
2426
return new ViolationCommentsToBitbucketServerApi();
@@ -33,6 +35,8 @@ public static ViolationCommentsToBitbucketServerApi violationCommentsToBitbucket
3335
private String propPassword = DEFAULT_PROP_VIOLATIONS_PASSWORD;
3436
private String propUsername = DEFAULT_PROP_VIOLATIONS_USERNAME;
3537
private String propPersonalAccessToken = DEFAULT_PROP_PERSONAL_ACCESS_TOKEN;
38+
private String propKeyStorePath = DEFAULT_PROP_KEYSTORE_PATH;
39+
private String propKeyStorePass = DEFAULT_PROP_KEYSTORE_PASS;
3640
private int pullRequestId;
3741
private String repoSlug;
3842
private String username;
@@ -67,9 +71,10 @@ private ViolationCommentsToBitbucketServerApi() {}
6771
private void checkState() {
6872
final boolean noUsername = isNullOrEmpty(this.username) || isNullOrEmpty(this.password);
6973
final boolean noPat = isNullOrEmpty(this.personalAccessToken);
70-
if (noUsername && noPat) {
74+
final boolean noCert = isNullOrEmpty(this.propKeyStorePath);
75+
if (noUsername && noPat && noCert) {
7176
throw new IllegalStateException(
72-
"User and Password, or personal access token, must be set! They can be set with the API or by setting properties.\n"
77+
"User and Password, or personal access token, or keystore path and keystore pass, must be set! They can be set with the API or by setting properties.\n"
7378
+ //
7479
"Username/password:\n"
7580
+ //
@@ -83,7 +88,14 @@ private void checkState() {
8388
+ //
8489
"-D"
8590
+ DEFAULT_PROP_PERSONAL_ACCESS_TOKEN
86-
+ "=asdasd");
91+
+ "=asdasd"
92+
+ "\n\nKeystore path and pass"
93+
+ //
94+
"-D"
95+
+ DEFAULT_PROP_KEYSTORE_PATH
96+
+ "=keystorepath -D"
97+
+ DEFAULT_PROP_KEYSTORE_PASS
98+
+ "=keystorepass");
8799
}
88100
checkNotNull(this.bitbucketServerUrl, "BitbucketServerURL");
89101
checkNotNull(this.pullRequestId, "PullRequestId");
@@ -177,6 +189,14 @@ public String getProxyPassword() {
177189
return this.proxyPassword;
178190
}
179191

192+
public String getPropKeyStorePath() {
193+
return this.propKeyStorePath;
194+
}
195+
196+
public String getPropKeyStorePass() {
197+
return this.propKeyStorePass;
198+
}
199+
180200
private void populateFromEnvironmentVariables() {
181201
if (System.getProperty(this.propUsername) != null) {
182202
this.username = firstNonNull(this.username, System.getProperty(this.propUsername));
@@ -188,6 +208,14 @@ private void populateFromEnvironmentVariables() {
188208
this.personalAccessToken =
189209
firstNonNull(this.personalAccessToken, System.getProperty(this.propPersonalAccessToken));
190210
}
211+
if (System.getProperty(this.propKeyStorePath) != null) {
212+
this.propKeyStorePath =
213+
firstNonNull(this.propKeyStorePath, System.getProperty(this.propKeyStorePath));
214+
}
215+
if (System.getProperty(this.propKeyStorePass) != null) {
216+
this.propKeyStorePass =
217+
firstNonNull(this.propKeyStorePass, System.getProperty(this.propKeyStorePass));
218+
}
191219
}
192220

193221
public void toPullRequest() throws Exception {
@@ -322,6 +350,17 @@ public ViolationCommentsToBitbucketServerApi withCommentTemplate(final String co
322350
return this;
323351
}
324352

353+
public ViolationCommentsToBitbucketServerApi withKeyStorePath(final String keyStorePath) {
354+
this.propKeyStorePath = keyStorePath;
355+
return this;
356+
}
357+
358+
public ViolationCommentsToBitbucketServerApi withKeyStorePass(final String keyStorePass) {
359+
this.propKeyStorePass = keyStorePass;
360+
return this;
361+
}
362+
363+
325364
public Optional<String> findCommentTemplate() {
326365
return ofNullable(this.commentTemplate);
327366
}

src/main/java/se/bjurr/violations/comments/bitbucketserver/lib/client/BitbucketServerClient.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public static void setBitbucketServerInvoker(
4141
private final String bitbucketServerUser;
4242
private final String bitbucketPersonalAccessToken;
4343
private final ProxyConfig proxyInformation;
44+
private CertificateConfig certificateConfig = null;
4445

4546
public BitbucketServerClient(
4647
final ViolationsLogger violationsLogger,
@@ -51,6 +52,8 @@ public BitbucketServerClient(
5152
final String bitbucketServerUser,
5253
final String bitbucketServerPassword,
5354
final String bitbucketPersonalAccessToken,
55+
final String keyStorePath,
56+
final String keyStorePass,
5457
final String proxyHostNameOrIp,
5558
final Integer proxyHostPort,
5659
final String proxyUser,
@@ -68,6 +71,9 @@ public BitbucketServerClient(
6871
this.bitbucketServerUser = bitbucketServerUser;
6972
this.bitbucketServerPassword = bitbucketServerPassword;
7073
this.bitbucketPersonalAccessToken = bitbucketPersonalAccessToken;
74+
if(!isNullOrEmpty(keyStorePath) && !isNullOrEmpty(keyStorePass)) {
75+
this.certificateConfig = new CertificateConfig(keyStorePath, keyStorePass);
76+
}
7177
this.proxyInformation =
7278
new ProxyConfig(proxyHostNameOrIp, proxyHostPort, proxyUser, proxyPassword);
7379
}
@@ -131,7 +137,16 @@ public void pullRequestComment(final String message) {
131137
}
132138

133139
private String doInvokeUrl(final String url, final Method method, final String postContent) {
134-
if (isNullOrEmpty(this.bitbucketServerUser) || isNullOrEmpty(this.bitbucketServerPassword)) {
140+
141+
if (this.certificateConfig != null) {
142+
return bitbucketServerInvoker.invokeUrl(
143+
this.violationsLogger,
144+
url,
145+
method,
146+
postContent,
147+
this.certificateConfig,
148+
this.proxyInformation);
149+
} else if (isNullOrEmpty(this.bitbucketServerUser) || isNullOrEmpty(this.bitbucketServerPassword)) {
135150
return bitbucketServerInvoker.invokeUrl(
136151
this.violationsLogger,
137152
url,

src/main/java/se/bjurr/violations/comments/bitbucketserver/lib/client/BitbucketServerInvoker.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public enum Method {
3232
POST
3333
}
3434

35+
private CertificateConfig certificateConfig = null;
36+
3537
public String invokeUrl(
3638
final ViolationsLogger violationsLogger,
3739
final String url,
@@ -64,6 +66,19 @@ public String invokeUrl(
6466
violationsLogger, url, method, postContent, authorizationValue, proxyConfig);
6567
}
6668

69+
public String invokeUrl(
70+
final ViolationsLogger violationsLogger,
71+
final String url,
72+
final Method method,
73+
final String postContent,
74+
final CertificateConfig certificateConfig,
75+
final ProxyConfig proxyConfig) {
76+
77+
this.certificateConfig = certificateConfig;
78+
return this.doInvokeUrl(
79+
violationsLogger, url, method, postContent, "", proxyConfig);
80+
}
81+
6782
private String doInvokeUrl(
6883
final ViolationsLogger violationsLogger,
6984
final String url,
@@ -106,6 +121,10 @@ private String doInvokeUrl(
106121

107122
final HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
108123
proxyConfig.addTo(httpClientBuilder);
124+
if(certificateConfig != null){
125+
certificateConfig.addTo(httpClientBuilder);
126+
}
127+
109128
final HttpClient httpClient = httpClientBuilder.build();
110129

111130
// Execute the request and get the response
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package se.bjurr.violations.comments.bitbucketserver.lib.client;
2+
3+
import org.apache.http.impl.client.HttpClientBuilder;
4+
import org.apache.http.ssl.SSLContexts;
5+
6+
import javax.net.ssl.SSLContext;
7+
import java.io.FileInputStream;
8+
import java.io.IOException;
9+
import java.security.*;
10+
import java.security.cert.CertificateException;
11+
12+
13+
public class CertificateConfig {
14+
private final String keyStorePath;
15+
private final String keyStorePass;
16+
17+
public CertificateConfig(String keyStorePath, String keyStorePass) {
18+
this.keyStorePath = keyStorePath;
19+
this.keyStorePass = keyStorePass;
20+
}
21+
22+
public HttpClientBuilder addTo(HttpClientBuilder builder) throws KeyStoreException,
23+
NoSuchAlgorithmException, CertificateException,
24+
IOException, UnrecoverableKeyException, KeyManagementException {
25+
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
26+
keyStore.load(new FileInputStream(this.keyStorePath),
27+
null);
28+
29+
SSLContext sslContext = SSLContexts.custom()
30+
.loadKeyMaterial(keyStore, keyStorePass.toCharArray())
31+
.build();
32+
builder.setSSLContext(sslContext);
33+
return builder;
34+
}
35+
}

0 commit comments

Comments
 (0)