1919
2020package io .temporal .samples .nexus .options ;
2121
22+ import io .grpc .Metadata ;
2223import io .grpc .netty .shaded .io .grpc .netty .GrpcSslContexts ;
2324import io .grpc .netty .shaded .io .netty .handler .ssl .SslContextBuilder ;
2425import io .grpc .netty .shaded .io .netty .handler .ssl .util .InsecureTrustManagerFactory ;
26+ import io .grpc .stub .MetadataUtils ;
2527import io .temporal .client .WorkflowClient ;
2628import io .temporal .client .WorkflowClientOptions ;
2729import io .temporal .serviceclient .WorkflowServiceStubs ;
@@ -47,14 +49,23 @@ public static WorkflowClient getWorkflowClient(String[] args) {
4749 serverRootCaOption .setRequired (false );
4850 options .addOption (serverRootCaOption );
4951
50- Option clientCertOption = new Option ("client-cert" , true , "Optional path to client cert" );
52+ Option clientCertOption =
53+ new Option (
54+ "client-cert" , true , "Optional path to client cert, mutually exclusive with API key" );
5155 clientCertOption .setRequired (false );
5256 options .addOption (clientCertOption );
5357
54- Option clientKeyOption = new Option ("client-key" , true , "Optional path to client key" );
58+ Option clientKeyOption =
59+ new Option (
60+ "client-key" , true , "Optional path to client key, mutually exclusive with API key" );
5561 clientKeyOption .setRequired (false );
5662 options .addOption (clientKeyOption );
5763
64+ Option apiKeyOption =
65+ new Option ("api-key" , true , "Optional API key, mutually exclusive with cert/key" );
66+ apiKeyOption .setRequired (false );
67+ options .addOption (apiKeyOption );
68+
5869 Option serverNameOption =
5970 new Option (
6071 "server-name" , true , "Server name to use for verifying the server's certificate" );
@@ -89,9 +100,15 @@ public static WorkflowClient getWorkflowClient(String[] args) {
89100 String clientKey = cmd .getOptionValue ("client-key" , "" );
90101 String serverName = cmd .getOptionValue ("server-name" , "" );
91102 boolean insecureSkipVerify = cmd .hasOption ("insecure-skip-verify" );
103+ String apiKey = cmd .getOptionValue ("api-key" , "" );
92104
105+ // API key and client cert/key are mutually exclusive
106+ if (!apiKey .isEmpty () && (!clientCert .isEmpty () || !clientKey .isEmpty ())) {
107+ throw new IllegalArgumentException ("API key and client cert/key are mutually exclusive" );
108+ }
93109 WorkflowServiceStubsOptions .Builder serviceStubOptionsBuilder =
94110 WorkflowServiceStubsOptions .newBuilder ().setTarget (targetHost );
111+ // Configure TLS if client cert and key are provided
95112 if (!clientCert .isEmpty () || !clientKey .isEmpty ()) {
96113 if (clientCert .isEmpty () || clientKey .isEmpty ()) {
97114 throw new IllegalArgumentException ("Both client-cert and client-key must be provided" );
@@ -112,10 +129,24 @@ public static WorkflowClient getWorkflowClient(String[] args) {
112129 } catch (FileNotFoundException e ) {
113130 throw new RuntimeException (e );
114131 }
132+ if (serverName != null && !serverName .isEmpty ()) {
133+ serviceStubOptionsBuilder .setChannelInitializer (c -> c .overrideAuthority (serverName ));
134+ }
115135 }
116- if (serverName != null && !serverName .isEmpty ()) {
117- serviceStubOptionsBuilder .setChannelInitializer (c -> c .overrideAuthority (serverName ));
136+ // Configure API key if provided
137+ if (!apiKey .isEmpty ()) {
138+ serviceStubOptionsBuilder .setEnableHttps (true );
139+ serviceStubOptionsBuilder .addApiKey (() -> apiKey );
140+ Metadata .Key <String > TEMPORAL_NAMESPACE_HEADER_KEY =
141+ Metadata .Key .of ("temporal-namespace" , Metadata .ASCII_STRING_MARSHALLER );
142+ Metadata metadata = new Metadata ();
143+ metadata .put (TEMPORAL_NAMESPACE_HEADER_KEY , namespace );
144+ serviceStubOptionsBuilder .setChannelInitializer (
145+ (channel ) -> {
146+ channel .intercept (MetadataUtils .newAttachHeadersInterceptor (metadata ));
147+ });
118148 }
149+
119150 WorkflowServiceStubs service =
120151 WorkflowServiceStubs .newServiceStubs (serviceStubOptionsBuilder .build ());
121152 return WorkflowClient .newInstance (
0 commit comments