99import io .dapr .durabletask .implementation .protobuf .TaskHubSidecarServiceGrpc .*;
1010
1111import io .grpc .*;
12+ import io .grpc .netty .shaded .io .grpc .netty .GrpcSslContexts ;
13+ import io .grpc .netty .shaded .io .grpc .netty .NettyChannelBuilder ;
14+ import io .grpc .netty .shaded .io .netty .handler .ssl .util .InsecureTrustManagerFactory ;
15+ import java .io .FileInputStream ;
16+ import java .io .InputStream ;
1217
1318import javax .annotation .Nullable ;
1419import java .time .Duration ;
1722import java .util .concurrent .TimeUnit ;
1823import java .util .concurrent .TimeoutException ;
1924import java .util .logging .Logger ;
25+ import java .io .IOException ;
2026
2127/**
2228 * Durable Task client implementation that uses gRPC to connect to a remote "sidecar" process.
2329 */
2430public final class DurableTaskGrpcClient extends DurableTaskClient {
2531 private static final int DEFAULT_PORT = 4001 ;
2632 private static final Logger logger = Logger .getLogger (DurableTaskGrpcClient .class .getPackage ().getName ());
33+ private static final String GRPC_TLS_CA_PATH = "DAPR_GRPC_TLS_CA_PATH" ;
34+ private static final String GRPC_TLS_CERT_PATH = "DAPR_GRPC_TLS_CERT_PATH" ;
35+ private static final String GRPC_TLS_KEY_PATH = "DAPR_GRPC_TLS_KEY_PATH" ;
36+ private static final String GRPC_TLS_INSECURE = "DAPR_GRPC_TLS_INSECURE" ;
2737
2838 private final DataConverter dataConverter ;
2939 private final ManagedChannel managedSidecarChannel ;
@@ -44,11 +54,60 @@ public final class DurableTaskGrpcClient extends DurableTaskClient {
4454 port = builder .port ;
4555 }
4656
57+ String endpoint = "localhost:" + port ;
58+ ManagedChannelBuilder <?> channelBuilder ;
59+
60+ // Get TLS configuration from builder or environment variables
61+ String tlsCaPath = builder .tlsCaPath != null ? builder .tlsCaPath : System .getenv (GRPC_TLS_CA_PATH );
62+ String tlsCertPath = builder .tlsCertPath != null ? builder .tlsCertPath : System .getenv (GRPC_TLS_CERT_PATH );
63+ String tlsKeyPath = builder .tlsKeyPath != null ? builder .tlsKeyPath : System .getenv (GRPC_TLS_KEY_PATH );
64+ boolean insecure = builder .insecure || Boolean .parseBoolean (System .getenv (GRPC_TLS_INSECURE ));
65+
66+ if (insecure ) {
67+ // Insecure mode - uses TLS but doesn't verify certificates
68+ try {
69+ channelBuilder = NettyChannelBuilder .forTarget (endpoint )
70+ .sslContext (GrpcSslContexts .forClient ()
71+ .trustManager (InsecureTrustManagerFactory .INSTANCE )
72+ .build ());
73+ } catch (Exception e ) {
74+ throw new RuntimeException ("Failed to create insecure TLS credentials" , e );
75+ }
76+ } else if (tlsCertPath != null && tlsKeyPath != null ) {
77+ // mTLS case - using client cert and key, with optional CA cert for server authentication
78+ try (
79+ InputStream clientCertInputStream = new FileInputStream (tlsCertPath );
80+ InputStream clientKeyInputStream = new FileInputStream (tlsKeyPath );
81+ InputStream caCertInputStream = tlsCaPath != null ? new FileInputStream (tlsCaPath ) : null
82+ ) {
83+ TlsChannelCredentials .Builder tlsBuilder = TlsChannelCredentials .newBuilder ()
84+ .keyManager (clientCertInputStream , clientKeyInputStream ); // For client authentication
85+ if (caCertInputStream != null ) {
86+ tlsBuilder .trustManager (caCertInputStream ); // For server authentication
87+ }
88+ ChannelCredentials credentials = tlsBuilder .build ();
89+ channelBuilder = Grpc .newChannelBuilder (endpoint , credentials );
90+ } catch (IOException e ) {
91+ throw new RuntimeException ("Failed to create mTLS credentials" +
92+ (tlsCaPath != null ? " with CA cert" : "" ), e );
93+ }
94+ } else if (tlsCaPath != null ) {
95+ // Simple TLS case - using CA cert only for server authentication
96+ try (InputStream caCertInputStream = new FileInputStream (tlsCaPath )) {
97+ ChannelCredentials credentials = TlsChannelCredentials .newBuilder ()
98+ .trustManager (caCertInputStream )
99+ .build ();
100+ channelBuilder = Grpc .newChannelBuilder (endpoint , credentials );
101+ } catch (IOException e ) {
102+ throw new RuntimeException ("Failed to create TLS credentials with CA cert" , e );
103+ }
104+ } else {
105+ // No TLS config provided, use plaintext
106+ channelBuilder = ManagedChannelBuilder .forTarget (endpoint ).usePlaintext ();
107+ }
108+
47109 // Need to keep track of this channel so we can dispose it on close()
48- this .managedSidecarChannel = ManagedChannelBuilder
49- .forAddress ("localhost" , port )
50- .usePlaintext ()
51- .build ();
110+ this .managedSidecarChannel = channelBuilder .build ();
52111 sidecarGrpcChannel = this .managedSidecarChannel ;
53112 }
54113
0 commit comments