Skip to content

Commit 9b65758

Browse files
Vladimir Rusnakwaiet
authored andcommitted
Enable JVM proxy system properties in Key Vault JCA
1 parent 36dceca commit 9b65758

3 files changed

Lines changed: 95 additions & 3 deletions

File tree

  • sdk/keyvault/azure-security-keyvault-jca

sdk/keyvault/azure-security-keyvault-jca/README.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,24 @@ az role assignment create \
544544
-J-Dazure.keyvault.client-secret=${CLIENT_SECRET}
545545
```
546546

547+
If you run `jarsigner` behind a proxy, pass the standard JVM proxy system properties with `-J`:
548+
```bash
549+
jarsigner -keystore NONE -storetype AzureKeyVault \
550+
-signedjar signerjar.jar ${PARAM_YOUR_JAR_FILE_PATH} "${CERT_NAME}" \
551+
-verbose -storepass "" \
552+
-providerName AzureKeyVault \
553+
-providerClass com.azure.security.keyvault.jca.KeyVaultJcaProvider \
554+
-J-Dazure.keyvault.uri=${KEYVAULT_URL} \
555+
-J-Dazure.keyvault.tenant-id=${TENANT} \
556+
-J-Dazure.keyvault.client-id=${CLIENT_ID} \
557+
-J-Dazure.keyvault.client-secret=${CLIENT_SECRET} \
558+
-J-Dhttps.proxyHost=proxy.company.local \
559+
-J-Dhttps.proxyPort=8080 \
560+
'-J-Dhttp.nonProxyHosts=169.254.169.254|localhost|127.*'
561+
```
562+
`http.nonProxyHosts` may be needed for local or managed identity endpoints, such as `169.254.169.254`,
563+
that should bypass the proxy.
564+
547565
replace ${PARAM_YOUR_JAR_FILE_PATH} with the path of your jar file, replace ${PARAM_JCA_PROVIDER_JAR_PATH} with the path of the jca provider jar.
548566

549567
Check your output, if you see the `jar signed` message, it means the jar is signed successfully.
@@ -681,5 +699,3 @@ This project has adopted the [Microsoft Open Source Code of Conduct][microsoft_c
681699
[jca_reference_guide]: https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html
682700
[microsoft_code_of_conduct]: https://opensource.microsoft.com/codeofconduct/
683701
[non-exportable]: https://learn.microsoft.com/azure/key-vault/certificates/about-certificates#exportable-or-non-exportable-key
684-
685-

sdk/keyvault/azure-security-keyvault-jca/src/main/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ private static CloseableHttpClient buildClient() {
186186
.register("https", sslConnectionSocketFactory)
187187
.build());
188188

189-
return HttpClients.custom().setConnectionManager(manager).build();
189+
return HttpClients.custom().useSystemProperties().setConnectionManager(manager).build();
190190
}
191191

192192
public static String validateUri(String uri, String propertyName) {

sdk/keyvault/azure-security-keyvault-jca/src/test/java/com/azure/security/keyvault/jca/implementation/utils/HttpUtilTest.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66
import org.junit.jupiter.api.Disabled;
77
import org.junit.jupiter.api.Test;
88

9+
import java.io.BufferedReader;
10+
import java.io.InputStreamReader;
11+
import java.io.OutputStream;
12+
import java.net.ServerSocket;
13+
import java.net.Socket;
14+
import java.nio.charset.StandardCharsets;
15+
import java.util.concurrent.CountDownLatch;
16+
import java.util.concurrent.TimeUnit;
17+
import java.util.concurrent.atomic.AtomicReference;
18+
919
import static com.azure.security.keyvault.jca.implementation.utils.HttpUtil.DEFAULT_USER_AGENT_VALUE_PREFIX;
1020
import static com.azure.security.keyvault.jca.implementation.utils.HttpUtil.VERSION;
1121
import static org.junit.jupiter.api.Assertions.*;
@@ -18,6 +28,39 @@ public void getUserAgentPrefixTest() {
1828
assertEquals(DEFAULT_USER_AGENT_VALUE_PREFIX + VERSION, HttpUtil.USER_AGENT_VALUE);
1929
}
2030

31+
@Test
32+
public void getUsesJvmProxySystemProperties() throws Exception {
33+
String previousProxyHost = System.getProperty("http.proxyHost");
34+
String previousProxyPort = System.getProperty("http.proxyPort");
35+
String previousNonProxyHosts = System.getProperty("http.nonProxyHosts");
36+
37+
try (ServerSocket proxyServer = new ServerSocket(0)) {
38+
CountDownLatch requestReceived = new CountDownLatch(1);
39+
AtomicReference<String> requestLine = new AtomicReference<>();
40+
AtomicReference<Exception> proxyFailure = new AtomicReference<>();
41+
42+
Thread proxyThread
43+
= new Thread(() -> handleProxyRequest(proxyServer, requestLine, requestReceived, proxyFailure));
44+
proxyThread.setDaemon(true);
45+
proxyThread.start();
46+
47+
System.setProperty("http.proxyHost", "localhost");
48+
System.setProperty("http.proxyPort", String.valueOf(proxyServer.getLocalPort()));
49+
System.clearProperty("http.nonProxyHosts");
50+
51+
String response = HttpUtil.get("http://azure-keyvault-jca-proxy-test.invalid/path", null);
52+
53+
assertTrue(requestReceived.await(5, TimeUnit.SECONDS), "Expected proxy server to receive the request.");
54+
assertNull(proxyFailure.get(), "Proxy server failed while handling the request.");
55+
assertEquals("proxied", response);
56+
assertEquals("GET http://azure-keyvault-jca-proxy-test.invalid/path HTTP/1.1", requestLine.get());
57+
} finally {
58+
restoreProperty("http.proxyHost", previousProxyHost);
59+
restoreProperty("http.proxyPort", previousProxyPort);
60+
restoreProperty("http.nonProxyHosts", previousNonProxyHosts);
61+
}
62+
}
63+
2164
@Test
2265
@Disabled("Disable this because it will cause pipeline failure: https://dev.azure.com/azure-sdk/internal/_build/results?buildId=1196171&view=logs&j=4a83f3be-c53d-53dd-7954-86872056fb11&t=54174aae-5a55-579d-08e2-94fb446f7b77&l=29")
2366
public void testHttpUtilGet() {
@@ -35,4 +78,37 @@ public void testHttpUtilGet1() {
3578
assertNotNull(result);
3679
assertFalse(result.isEmpty());
3780
}
81+
82+
private static void handleProxyRequest(ServerSocket proxyServer, AtomicReference<String> requestLine,
83+
CountDownLatch requestReceived, AtomicReference<Exception> proxyFailure) {
84+
try (Socket socket = proxyServer.accept();
85+
BufferedReader reader = new BufferedReader(
86+
new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
87+
OutputStream outputStream = socket.getOutputStream()) {
88+
89+
requestLine.set(reader.readLine());
90+
String line;
91+
while ((line = reader.readLine()) != null && !line.isEmpty()) {
92+
// Consume request headers before writing the response.
93+
}
94+
95+
byte[] body = "proxied".getBytes(StandardCharsets.UTF_8);
96+
outputStream.write(("HTTP/1.1 200 OK\r\nContent-Length: " + body.length + "\r\n\r\n")
97+
.getBytes(StandardCharsets.UTF_8));
98+
outputStream.write(body);
99+
outputStream.flush();
100+
requestReceived.countDown();
101+
} catch (Exception e) {
102+
proxyFailure.set(e);
103+
requestReceived.countDown();
104+
}
105+
}
106+
107+
private static void restoreProperty(String name, String value) {
108+
if (value == null) {
109+
System.clearProperty(name);
110+
} else {
111+
System.setProperty(name, value);
112+
}
113+
}
38114
}

0 commit comments

Comments
 (0)