diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 58e986dd4b..186370aae3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -15,6 +15,35 @@ on:
- release-*
jobs:
+ test:
+ name: "Unit tests"
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ continue-on-error: false
+ env:
+ JDK_VER: 17
+ steps:
+ - uses: actions/checkout@v5
+ - name: Set up OpenJDK ${{ env.JDK_VER }}
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: ${{ env.JDK_VER }}
+ - name: Run tests
+ run: ./mvnw clean install -B -q
+ - name: Codecov
+ uses: codecov/codecov-action@v5.5.0
+ - name: Upload test report for sdk
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-dapr-java-sdk-jdk${{ env.JDK_VER }}
+ path: sdk/target/jacoco-report/
+ - name: Upload test report for sdk-actors
+ uses: actions/upload-artifact@v4
+ with:
+ name: report-dapr-java-sdk-actors-jdk${{ env.JDK_VER }}
+ path: sdk-actors/target/jacoco-report/
+
build:
name: "Build jdk:${{ matrix.java }} sb:${{ matrix.spring-boot-display-version }} exp:${{ matrix.experimental }}"
runs-on: ubuntu-latest
@@ -114,27 +143,11 @@ jobs:
/home/runner/.local/bin/toxiproxy-server --version
- name: Clean up and install sdk
run: ./mvnw clean install -B -q -DskipTests
- - name: Unit tests
- run: ./mvnw test # making it temporarily verbose.
- env:
- DOCKER_HOST: ${{steps.setup_docker.outputs.sock}}
- - name: Codecov
- uses: codecov/codecov-action@v5.5.0
- name: Integration tests using spring boot version ${{ matrix.spring-boot-version }}
id: integration_tests
run: PRODUCT_SPRING_BOOT_VERSION=${{ matrix.spring-boot-version }} ./mvnw -B -Pintegration-tests verify
env:
DOCKER_HOST: ${{steps.setup_docker.outputs.sock}}
- - name: Upload test report for sdk
- uses: actions/upload-artifact@v4
- with:
- name: report-dapr-java-sdk-jdk${{ matrix.java }}-sb${{ matrix.spring-boot-version }}
- path: sdk/target/jacoco-report/
- - name: Upload test report for sdk-actors
- uses: actions/upload-artifact@v4
- with:
- name: report-dapr-java-sdk-actors-jdk${{ matrix.java }}-sb${{ matrix.spring-boot-version }}
- path: sdk-actors/target/jacoco-report/
- name: Upload failsafe test report for sdk-tests on failure
if: ${{ failure() && steps.integration_tests.conclusion == 'failure' }}
uses: actions/upload-artifact@v4
@@ -150,7 +163,7 @@ jobs:
publish:
runs-on: ubuntu-latest
- needs: build
+ needs: [ build, test ]
timeout-minutes: 30
env:
JDK_VER: 17
diff --git a/sdk/pom.xml b/sdk/pom.xml
index 57154623c8..af01cfa88b 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -132,18 +132,6 @@
assertj-core
${assertj.version}
-
- org.bouncycastle
- bcprov-jdk15on
- 1.70
- test
-
-
- org.bouncycastle
- bcpkix-jdk15on
- 1.70
- test
-
io.grpc
grpc-netty-shaded
diff --git a/sdk/src/test/java/io/dapr/utils/NetworkUtilsTest.java b/sdk/src/test/java/io/dapr/utils/NetworkUtilsTest.java
index 3823bef3bd..a8bd189e30 100644
--- a/sdk/src/test/java/io/dapr/utils/NetworkUtilsTest.java
+++ b/sdk/src/test/java/io/dapr/utils/NetworkUtilsTest.java
@@ -27,20 +27,9 @@
import org.junit.jupiter.api.condition.OS;
import java.io.File;
-import java.nio.file.Files;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.cert.X509Certificate;
-import java.util.Date;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.ArrayList;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
-import org.bouncycastle.cert.X509v3CertificateBuilder;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class NetworkUtilsTest {
private final int defaultGrpcPort = 50001;
@@ -48,47 +37,6 @@ public class NetworkUtilsTest {
private ManagedChannel channel;
private static final List channels = new ArrayList<>();
- // Helper method to generate a self-signed certificate for testing
- private static KeyPair generateKeyPair() throws Exception {
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
- keyPairGenerator.initialize(2048);
- return keyPairGenerator.generateKeyPair();
- }
-
- private static X509Certificate generateCertificate(KeyPair keyPair) throws Exception {
- X500Name issuer = new X500Name("CN=Test Certificate");
- X500Name subject = new X500Name("CN=Test Certificate");
- Date notBefore = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000);
- Date notAfter = new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000L);
- SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded());
- X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
- issuer,
- java.math.BigInteger.valueOf(System.currentTimeMillis()),
- notBefore,
- notAfter,
- subject,
- publicKeyInfo
- );
-
- ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").build(keyPair.getPrivate());
- X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certBuilder.build(signer));
- return cert;
- }
-
- private static void writeCertificateToFile(X509Certificate cert, File file) throws Exception {
- String certPem = "-----BEGIN CERTIFICATE-----\n" +
- java.util.Base64.getEncoder().encodeToString(cert.getEncoded()) +
- "\n-----END CERTIFICATE-----";
- Files.write(file.toPath(), certPem.getBytes());
- }
-
- private static void writePrivateKeyToFile(KeyPair keyPair, File file) throws Exception {
- String keyPem = "-----BEGIN PRIVATE KEY-----\n" +
- java.util.Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()) +
- "\n-----END PRIVATE KEY-----";
- Files.write(file.toPath(), keyPem.getBytes());
- }
-
@AfterEach
public void tearDown() {
if (channel != null && !channel.isShutdown()) {
@@ -157,56 +105,35 @@ public void testBuildGrpcManagedChannel_httpsEndpointWithPort() {
@Test
public void testBuildGrpcManagedChannelWithTls() throws Exception {
- // Generate test certificate and key
- KeyPair keyPair = generateKeyPair();
- X509Certificate cert = generateCertificate(keyPair);
-
- File certFile = File.createTempFile("test-cert", ".pem");
- File keyFile = File.createTempFile("test-key", ".pem");
- try {
- writeCertificateToFile(cert, certFile);
- writePrivateKeyToFile(keyPair, keyFile);
+ File certFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
+ File keyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
- var properties = new Properties(Map.of(
+ var properties = new Properties(Map.of(
Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath()
));
- channel = NetworkUtils.buildGrpcManagedChannel(properties);
- channels.add(channel);
- String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
- Assertions.assertEquals(expectedAuthority, channel.authority());
- } finally {
- certFile.delete();
- keyFile.delete();
- }
+ channel = NetworkUtils.buildGrpcManagedChannel(properties);
+ channels.add(channel);
+ String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
+ Assertions.assertEquals(expectedAuthority, channel.authority());
+
}
@Test
public void testBuildGrpcManagedChannelWithTlsAndEndpoint() throws Exception {
- // Generate test certificate and key
- KeyPair keyPair = generateKeyPair();
- X509Certificate cert = generateCertificate(keyPair);
-
- File certFile = File.createTempFile("test-cert", ".pem");
- File keyFile = File.createTempFile("test-key", ".pem");
- try {
- writeCertificateToFile(cert, certFile);
- writePrivateKeyToFile(keyPair, keyFile);
+ File certFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
+ File keyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
- var properties = new Properties(Map.of(
- Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
- Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
- Properties.GRPC_ENDPOINT.getName(), "https://example.com:443"
- ));
+ var properties = new Properties(Map.of(
+ Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
+ Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
+ Properties.GRPC_ENDPOINT.getName(), "https://example.com:443"
+ ));
- channel = NetworkUtils.buildGrpcManagedChannel(properties);
- channels.add(channel);
- Assertions.assertEquals("example.com:443", channel.authority());
- } finally {
- certFile.delete();
- keyFile.delete();
- }
+ channel = NetworkUtils.buildGrpcManagedChannel(properties);
+ channels.add(channel);
+ Assertions.assertEquals("example.com:443", channel.authority());
}
@Test
@@ -229,49 +156,32 @@ public void testBuildGrpcManagedChannelWithTlsAndUnixSocket() throws Exception {
System.getProperty("os.name").toLowerCase().contains("mac"));
// Generate test certificate and key
- KeyPair keyPair = generateKeyPair();
- X509Certificate cert = generateCertificate(keyPair);
-
- File certFile = File.createTempFile("test-cert", ".pem");
- File keyFile = File.createTempFile("test-key", ".pem");
- try {
- writeCertificateToFile(cert, certFile);
- writePrivateKeyToFile(keyPair, keyFile);
+ File certFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
+ File keyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
- var properties = new Properties(Map.of(
- Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
- Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
- Properties.GRPC_ENDPOINT.getName(), "unix:/tmp/test.sock"
- ));
+ var properties = new Properties(Map.of(
+ Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
+ Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
+ Properties.GRPC_ENDPOINT.getName(), "unix:/tmp/test.sock"
+ ));
- // For Unix sockets, we expect an exception if the platform doesn't support it
- try {
- channel = NetworkUtils.buildGrpcManagedChannel(properties);
- channels.add(channel);
- // If we get here, Unix sockets are supported
- Assertions.assertNotNull(channel.authority(), "Channel authority should not be null");
- } catch (Exception e) {
- // If we get here, Unix sockets are not supported
- Assertions.assertTrue(e.getMessage().contains("DomainSocketAddress"));
- }
- } finally {
- certFile.delete();
- keyFile.delete();
+ // For Unix sockets, we expect an exception if the platform doesn't support it
+ try {
+ channel = NetworkUtils.buildGrpcManagedChannel(properties);
+ channels.add(channel);
+ // If we get here, Unix sockets are supported
+ Assertions.assertNotNull(channel.authority(), "Channel authority should not be null");
+ } catch (Exception e) {
+ // If we get here, Unix sockets are not supported
+ Assertions.assertTrue(e.getMessage().contains("DomainSocketAddress"));
}
+
}
@Test
public void testBuildGrpcManagedChannelWithTlsAndDnsAuthority() throws Exception {
- // Generate test certificate and key
- KeyPair keyPair = generateKeyPair();
- X509Certificate cert = generateCertificate(keyPair);
-
- File certFile = File.createTempFile("test-cert", ".pem");
- File keyFile = File.createTempFile("test-key", ".pem");
- try {
- writeCertificateToFile(cert, certFile);
- writePrivateKeyToFile(keyPair, keyFile);
-
+ File certFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
+ File keyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CERT_PATH.getName(), certFile.getAbsolutePath(),
Properties.GRPC_TLS_KEY_PATH.getName(), keyFile.getAbsolutePath(),
@@ -281,44 +191,26 @@ public void testBuildGrpcManagedChannelWithTlsAndDnsAuthority() throws Exception
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertEquals("example.com:443", channel.authority());
- } finally {
- certFile.delete();
- keyFile.delete();
- }
+
}
@Test
public void testBuildGrpcManagedChannelWithTlsAndCaCert() throws Exception {
- // Generate test CA certificate
- KeyPair caKeyPair = generateKeyPair();
- X509Certificate caCert = generateCertificate(caKeyPair);
-
- File caCertFile = File.createTempFile("test-ca-cert", ".pem");
- try {
- writeCertificateToFile(caCert, caCertFile);
+ File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
- var properties = new Properties(Map.of(
- Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath()
- ));
+ var properties = new Properties(Map.of(
+ Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath()
+ ));
- channel = NetworkUtils.buildGrpcManagedChannel(properties);
- channels.add(channel);
- String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
- Assertions.assertEquals(expectedAuthority, channel.authority());
- } finally {
- caCertFile.delete();
- }
+ channel = NetworkUtils.buildGrpcManagedChannel(properties);
+ channels.add(channel);
+ String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
+ Assertions.assertEquals(expectedAuthority, channel.authority());
}
@Test
public void testBuildGrpcManagedChannelWithTlsAndCaCertAndEndpoint() throws Exception {
- // Generate test CA certificate
- KeyPair caKeyPair = generateKeyPair();
- X509Certificate caCert = generateCertificate(caKeyPair);
-
- File caCertFile = File.createTempFile("test-ca-cert", ".pem");
- try {
- writeCertificateToFile(caCert, caCertFile);
+ File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
var properties = new Properties(Map.of(
Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
@@ -328,9 +220,7 @@ public void testBuildGrpcManagedChannelWithTlsAndCaCertAndEndpoint() throws Exce
channel = NetworkUtils.buildGrpcManagedChannel(properties);
channels.add(channel);
Assertions.assertEquals("example.com:443", channel.authority());
- } finally {
- caCertFile.delete();
- }
+
}
@Test
@@ -346,37 +236,22 @@ public void testBuildGrpcManagedChannelWithInvalidCaCert() {
@Test
public void testBuildGrpcManagedChannelWithMtlsAndCaCert() throws Exception {
- // Generate test certificates
- KeyPair caKeyPair = generateKeyPair();
- X509Certificate caCert = generateCertificate(caKeyPair);
- KeyPair clientKeyPair = generateKeyPair();
- X509Certificate clientCert = generateCertificate(clientKeyPair);
-
- File caCertFile = File.createTempFile("test-ca-cert", ".pem");
- File clientCertFile = File.createTempFile("test-client-cert", ".pem");
- File clientKeyFile = File.createTempFile("test-client-key", ".pem");
- try {
- writeCertificateToFile(caCert, caCertFile);
- writeCertificateToFile(clientCert, clientCertFile);
- writePrivateKeyToFile(clientKeyPair, clientKeyFile);
+ File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
+ File clientCertFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
+ File clientKeyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
- // Test mTLS with both client certs and CA cert
- var properties = new Properties(Map.of(
- Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
- Properties.GRPC_TLS_CERT_PATH.getName(), clientCertFile.getAbsolutePath(),
- Properties.GRPC_TLS_KEY_PATH.getName(), clientKeyFile.getAbsolutePath()
- ));
+ // Test mTLS with both client certs and CA cert
+ var properties = new Properties(Map.of(
+ Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
+ Properties.GRPC_TLS_CERT_PATH.getName(), clientCertFile.getAbsolutePath(),
+ Properties.GRPC_TLS_KEY_PATH.getName(), clientKeyFile.getAbsolutePath()
+ ));
- channel = NetworkUtils.buildGrpcManagedChannel(properties);
- channels.add(channel);
- String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
- Assertions.assertEquals(expectedAuthority, channel.authority());
- Assertions.assertFalse(channel.isTerminated(), "Channel should be active");
- } finally {
- caCertFile.delete();
- clientCertFile.delete();
- clientKeyFile.delete();
- }
+ channel = NetworkUtils.buildGrpcManagedChannel(properties);
+ channels.add(channel);
+ String expectedAuthority = String.format("%s:%s", defaultSidecarIP, defaultGrpcPort);
+ Assertions.assertEquals(expectedAuthority, channel.authority());
+ Assertions.assertFalse(channel.isTerminated(), "Channel should be active");
}
@Test
@@ -463,57 +338,40 @@ private static void testGrpcEndpointParsingErrorScenario(String grpcEndpointEnvV
@Test
public void testBuildGrpcManagedChannelWithCaCertAndUnixSocket() throws Exception {
// Skip test if Unix domain sockets are not supported
- Assumptions.assumeTrue(System.getProperty("os.name").toLowerCase().contains("linux") ||
- System.getProperty("os.name").toLowerCase().contains("mac"));
+ Assumptions.assumeTrue(System.getProperty("os.name").toLowerCase().contains("linux") ||
+ System.getProperty("os.name").toLowerCase().contains("mac"));
- // Generate test CA certificate
- KeyPair caKeyPair = generateKeyPair();
- X509Certificate caCert = generateCertificate(caKeyPair);
-
- File caCertFile = File.createTempFile("test-ca-cert", ".pem");
- try {
- writeCertificateToFile(caCert, caCertFile);
+ File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
- var properties = new Properties(Map.of(
- Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
- Properties.GRPC_ENDPOINT.getName(), "unix:/tmp/test.sock"
- ));
+ var properties = new Properties(Map.of(
+ Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
+ Properties.GRPC_ENDPOINT.getName(), "unix:/tmp/test.sock"
+ ));
- // For Unix sockets, we expect an exception if the platform doesn't support it
- try {
- channel = NetworkUtils.buildGrpcManagedChannel(properties);
- channels.add(channel);
- Assertions.assertNotNull(channel.authority(), "Channel authority should not be null");
- } catch (Exception e) {
- // If we get here, Unix sockets are not supported
- Assertions.assertTrue(e.getMessage().contains("DomainSocketAddress"));
- }
- } finally {
- caCertFile.delete();
+ // For Unix sockets, we expect an exception if the platform doesn't support it
+ try {
+ channel = NetworkUtils.buildGrpcManagedChannel(properties);
+ channels.add(channel);
+ Assertions.assertNotNull(channel.authority(), "Channel authority should not be null");
+ } catch (Exception e) {
+ // If we get here, Unix sockets are not supported
+ Assertions.assertTrue(e.getMessage().contains("DomainSocketAddress"));
}
+
}
@Test
public void testBuildGrpcManagedChannelWithCaCertAndDnsAuthority() throws Exception {
- // Generate test CA certificate
- KeyPair caKeyPair = generateKeyPair();
- X509Certificate caCert = generateCertificate(caKeyPair);
-
- File caCertFile = File.createTempFile("test-ca-cert", ".pem");
- try {
- writeCertificateToFile(caCert, caCertFile);
+ File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
- var properties = new Properties(Map.of(
- Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
- Properties.GRPC_ENDPOINT.getName(), "dns://authority:53/example.com:443"
- ));
+ var properties = new Properties(Map.of(
+ Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
+ Properties.GRPC_ENDPOINT.getName(), "dns://authority:53/example.com:443"
+ ));
- channel = NetworkUtils.buildGrpcManagedChannel(properties);
- channels.add(channel);
- Assertions.assertEquals("example.com:443", channel.authority());
- } finally {
- caCertFile.delete();
- }
+ channel = NetworkUtils.buildGrpcManagedChannel(properties);
+ channels.add(channel);
+ Assertions.assertEquals("example.com:443", channel.authority());
}
@Test
@@ -536,43 +394,28 @@ public void testBuildGrpcManagedChannelWithInsecureTls() throws Exception {
@Test
public void testBuildGrpcManagedChannelWithInsecureTlsAndMtls() throws Exception {
- // Generate test certificates
- KeyPair caKeyPair = generateKeyPair();
- X509Certificate caCert = generateCertificate(caKeyPair);
- KeyPair clientKeyPair = generateKeyPair();
- X509Certificate clientCert = generateCertificate(clientKeyPair);
-
- File caCertFile = File.createTempFile("test-ca-cert", ".pem");
- File clientCertFile = File.createTempFile("test-client-cert", ".pem");
- File clientKeyFile = File.createTempFile("test-client-key", ".pem");
- try {
- writeCertificateToFile(caCert, caCertFile);
- writeCertificateToFile(clientCert, clientCertFile);
- writePrivateKeyToFile(clientKeyPair, clientKeyFile);
+ File caCertFile = new File(this.getClass().getResource("/certs/test-ca-cert.pem").getFile());
+ File clientCertFile = new File(this.getClass().getResource("/certs/test-cert.pem").getFile());
+ File clientKeyFile = new File(this.getClass().getResource("/certs/test-cert.key").getFile());
- // Test that insecure TLS still works with mTLS settings
- // The client certs should be ignored since we're using InsecureTrustManagerFactory
- var properties = new Properties(Map.of(
- Properties.GRPC_TLS_INSECURE.getName(), "true",
- Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
- Properties.GRPC_TLS_CERT_PATH.getName(), clientCertFile.getAbsolutePath(),
- Properties.GRPC_TLS_KEY_PATH.getName(), clientKeyFile.getAbsolutePath(),
- Properties.GRPC_ENDPOINT.getName(), "dns:///example.com:443?tls=true"
- ));
+ // Test that insecure TLS still works with mTLS settings
+ // The client certs should be ignored since we're using InsecureTrustManagerFactory
+ var properties = new Properties(Map.of(
+ Properties.GRPC_TLS_INSECURE.getName(), "true",
+ Properties.GRPC_TLS_CA_PATH.getName(), caCertFile.getAbsolutePath(),
+ Properties.GRPC_TLS_CERT_PATH.getName(), clientCertFile.getAbsolutePath(),
+ Properties.GRPC_TLS_KEY_PATH.getName(), clientKeyFile.getAbsolutePath(),
+ Properties.GRPC_ENDPOINT.getName(), "dns:///example.com:443?tls=true"
+ ));
- channel = NetworkUtils.buildGrpcManagedChannel(properties);
- channels.add(channel);
-
- // Verify the channel is created with the correct authority
- Assertions.assertEquals("example.com:443", channel.authority());
-
- // Verify the channel is active and using TLS (not plaintext)
- Assertions.assertFalse(channel.isTerminated(), "Channel should be active");
- } finally {
- caCertFile.delete();
- clientCertFile.delete();
- clientKeyFile.delete();
- }
+ channel = NetworkUtils.buildGrpcManagedChannel(properties);
+ channels.add(channel);
+
+ // Verify the channel is created with the correct authority
+ Assertions.assertEquals("example.com:443", channel.authority());
+
+ // Verify the channel is active and using TLS (not plaintext)
+ Assertions.assertFalse(channel.isTerminated(), "Channel should be active");
}
@Test
diff --git a/sdk/src/test/resources/certs/test-ca-cert.key b/sdk/src/test/resources/certs/test-ca-cert.key
new file mode 100644
index 0000000000..eac281d7aa
--- /dev/null
+++ b/sdk/src/test/resources/certs/test-ca-cert.key
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+fg8QEv831uJb0uItcjDy5Yr0TEYMqg==
+-----END PRIVATE KEY-----
diff --git a/sdk/src/test/resources/certs/test-ca-cert.pem b/sdk/src/test/resources/certs/test-ca-cert.pem
new file mode 100644
index 0000000000..087998d230
--- /dev/null
+++ b/sdk/src/test/resources/certs/test-ca-cert.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFUzCCAzugAwIBAgIUFHmlZNi1305lvonC4ePOulB207UwDQYJKoZIhvcNAQEL
+BQAwOTENMAsGA1UECgwEREFQUjENMAsGA1UECwwEREFQUjEZMBcGA1UEAwwQVEVT
+VCBDRVJUSUZJQ0FURTAeFw0yNTA4MjgxNTI4MTlaFw0yNzA4MjgxNTI4MTlaMDkx
+DTALBgNVBAoMBERBUFIxDTALBgNVBAsMBERBUFIxGTAXBgNVBAMMEFRFU1QgQ0VS
+VElGSUNBVEUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDbzg+ow2pe
++tWKSISVIF6kFi9VYReq0sJ8gJ+mQRkBK7Hs8G0WD9KS+Ebg15CTEulNbyp3sqPa
+28tD1bq69ST8aMjUxD8NyWyYd7NQSd7pWHuR+NMDsh908W+JDyTxGgonXFaU5s8m
++FAS25nC8dzEgolxrQlVraXld1ZxMVW/OnOdl4dlSsXpGR4Zwv2S4BrppQvGhGTK
+aURuOI1mot0IZVnV4acg5iK+2wPvDD2UJp6fMR6PplKrgb8dV2SqEEEVPwsXY0nb
+idRb3yJ6VRtibkbu7u987BpEEaNeSmsC0BOIeHj90Jc+ilDQEgVRkMvP9zSPh6yY
+4kOuMevof2J86FTRZWo7b9u1BG/2WoLeOPk00kAzN2jmk4hnytknWz1G0dxVZSJr
+OcLHv9tWKk4TI3l54DrKw+n3pQA2Qs22P97n6d151mi3Yr45YtypmQhn4f4tsLxT
+16mp2Vs/D4vU1M4jldpi9vDin+R4wIgDxXThUUd3c6NqrhyRiLteRaZVVsWeudi/
+jZt7H676S5lVdLTsU1jmOxef1mTzJxNAhw7VClq8YXeq8Z65Mj84fARxEh+WgN31
+5+JlIE6gPdYz7A+h5pupDVXJdhOViafQMBsAkUWautz4n47F5X+oB53rKEvRjjgV
+sSVNB3oLBWCoXPxfpANQjNXky9QRb2Ib1wIDAQABo1MwUTAdBgNVHQ4EFgQUnBy0
+t/3jxb0LK0SWaKjOlRlebmowHwYDVR0jBBgwFoAUnBy0t/3jxb0LK0SWaKjOlRle
+bmowDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAh/5qDtYaiTWN
+3cX0H/ucdsT1fzVCiWmniRBrvGgLOJ4VfBpcGAeyt3nTOCGBpLIHi6M47mv6+DA8
+GVA+k4FgAbFRWgSR5zDsOOC0/jTTEMpcrz13DgpCeh/Jj0MdNe3nzkC+eAT2bp07
+ZYLrO++N+IEpDEuDz3YlqIpgKpEREoGKWXrXcCEdsAUbIjOSWBfLBTuF8x11IVi7
+V4y3UUVTg6aA8ILmtWStoBuVroOH/HY/8RuQztUejjtd3PIEzPRgITekpWEDxI1D
+Ycc7ZgdxEYmzXTvRAmLkIAoSPR5U61i09SSHmCs9hoWUGQGxSsxBFloTH6IoJFls
+VDeWw3Shzu1PSPP5NedGgdRC8GKjOVDAgXzYPSoTYab5mGHTbL3HtRELthCmQSaC
+SrNwKjd1MmhJ6yrjxKruE9mpSHUu50IDIP+PyMokWMRf504eGvPJstvD6+I4sUS3
+/Owu0eGM3incgG/ulAWpRDCXRq49JpAoq7evbyBQyzDfrCSN0U6sgjBVlJuoEuXD
+t1cNmvPxf0730HxQYrq1nYahdt5Mi9+Pv8ublylKuGeYiWqiSeSE6wRRTktL7Xmf
+BotM8yvJBhpY00GAPSxXQ2Kl+OielJq9QSCOgtQkMCMzKMsfbO+YA+WvMICe+GNJ
+sfrgLw0imYT1npKJbNtg/vRxTZFj9hc=
+-----END CERTIFICATE-----
diff --git a/sdk/src/test/resources/certs/test-cert.key b/sdk/src/test/resources/certs/test-cert.key
new file mode 100644
index 0000000000..87b958ab6d
--- /dev/null
+++ b/sdk/src/test/resources/certs/test-cert.key
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+mfPgTPwyRZiGKrz43GpgD0Zg/eytPw==
+-----END PRIVATE KEY-----
diff --git a/sdk/src/test/resources/certs/test-cert.pem b/sdk/src/test/resources/certs/test-cert.pem
new file mode 100644
index 0000000000..00a8155f78
--- /dev/null
+++ b/sdk/src/test/resources/certs/test-cert.pem
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFUzCCAzugAwIBAgIUbPytgC1pfbqeBSbdOok03mPcoU8wDQYJKoZIhvcNAQEL
+BQAwOTENMAsGA1UECgwEREFQUjENMAsGA1UECwwEREFQUjEZMBcGA1UEAwwQVGVz
+dCBDZXJ0aWZpY2F0ZTAeFw0yNTA4MjgxNTIzMzJaFw0yNzA4MjgxNTIzMzJaMDkx
+DTALBgNVBAoMBERBUFIxDTALBgNVBAsMBERBUFIxGTAXBgNVBAMMEFRlc3QgQ2Vy
+dGlmaWNhdGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCX9WC+9qfC
+u7LhLTkm1XpYnIFowqlIAARHxWv08xbOIm/4bUtruuy0nOEVzzYiu8fdRP2LsBp9
+iKuRJzBw6QOeASeepCorOFnU24bG3oAdjPHp7Bj76tM1GW5H8izOlln22My4asaO
+P4kxC+LQt7aolF1Ca7A9J3TNEBxSaowUpCCDtwNnBTPoFa28vhFjga32BnNEZCTP
+WCrn97WfDKj4trb+lQIt77jSBpPmwBJIqsOaM02uIlnF8MElX2TEUfMFGWAzDBml
+lB80cZHybC2Ic2nrYKuuHtpZrtMM6atGstxiHDt002p6yxUUEbcXE1SvB6ZGuBDw
+9frpF7J5xnRQ7PAaKl17hXinnOPG/b3xtvOrx2rewWHHUxfCDzzaDcr1+31zfoW8
+3wcwfcuuS8E9iO4mIIYKoB+3C0430IMlqv61BVlHB9FajSEXhg8KIRDB8dZZGX4Y
+95teRGv4s69Wr0gFFrPG5XJ0m4gS7mpkJeYwTrvtgb2Rm+D7vjxKR4xW8zSRnj4W
+644YSpBI9n/fCw3wmWAvs+2wt1m6JcvXyOFJPY96BQWE3eIGV052OCc69rXUhEV/
+vFRVNn4UJMCGptpJZiTM+/jvC94YEY2GzMu0jfuBYrnzeeasRnnVh6gfFKXui3xK
+GApmMoqfd/2DogdmMXilZQ4SHinS6Bj0yQIDAQABo1MwUTAdBgNVHQ4EFgQUuj4S
+u+I/pBSJFGVoCK4y+QvGm/QwHwYDVR0jBBgwFoAUuj4Su+I/pBSJFGVoCK4y+QvG
+m/QwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAR18zFnyf22+h
+bLT8ab0fD6pLQUW0/yr0PpsNNrsnNbTMr+tgOQDZgi/jpnG8eQmyA5aVjBxgxBNq
+BhXFMixVputyafbb+fCIGvwWAMGtKL3Jf2yYfn6IhMftMB2e3xp4hUNBfRC92fVT
+McypKFf/bWPxk7ZDeZGwNK0CViB2XNDCPWvR+RxQI4stilpN47/fAQdpnAmcDVi6
+wVljILTaPhgpWj0Q3c6ccdgFE8ETRQK46dDW6C2KstIjqOxP4Go5HQw5bGTQVRPw
+bX2v7kadLfFDJJDwmCRUNzQJfWM+8qROy8YgexFe5rBUkOOFCz2Wd2I0LjiN8SrP
+aY3iEoZQO/bIUPJsi3qtLgb9HDZ6iXeB1SHEXnn/l0b1zpb2kumdhiNif2s1NXsw
+LQV7xai3xrdT96fnWElqD39gHunLO2hCE4ra7YJ3yZnXyi21EdErhpCaD1aPo96d
+0m/2rbIfafrBZFdcu4hvS56qtnVajOfXaN5bCKyRsByA8Ebv2XlWWWCRDii5ft/W
+RYrRDZhC6t9dZNv1ObhDLzx/2FNq82lxhi4VCwlAy6Qdc8kY7uh92IWUUQoLonQB
+QI0QuROI9W9Vc/DUJFvts/qCKWtD0XdoTVlZc/1B2WFbiwZ5U04x5inFBtudvyEL
+ZEyQNL0MVlOgpxK3igY4xKM8r+m4bi4=
+-----END CERTIFICATE-----