Skip to content

Commit 307a2df

Browse files
authored
SSL-enabled WorkflowClient with CA cert as param and overriding authority name (#448)
* Ssl enabled worker custom CA and authority name * Update README.md * rebase to main branch * update readme
1 parent 80c0669 commit 307a2df

2 files changed

Lines changed: 175 additions & 3 deletions

File tree

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,60 @@
11
# Workflow execution with mTLS
22

3-
43
This example shows how to secure your Temporal application with [mTLS](https://docs.temporal.io/security/#encryption-in-transit-with-mtls).
54
This is required to connect with Temporal Cloud or any production Temporal deployment.
65

76

87
## Export env variables
8+
99
Before running the example you need to export the following env variables:
1010

1111
- TEMPORAL_ENDPOINT: grpc endpoint, for Temporal Cloud would like `${namespace}.tmprl.cloud:7233`.
1212
- TEMPORAL_NAMESPACE: Namespace.
1313
- TEMPORAL_CLIENT_CERT: For Temporal Cloud see requirements [here](https://docs.temporal.io/cloud/how-to-manage-certificates-in-temporal-cloud#end-entity-certificates).
1414
- TEMPORAL_CLIENT_KEY: For Temporal Cloud see requirements [here](https://docs.temporal.io/cloud/how-to-manage-certificates-in-temporal-cloud#end-entity-certificates).
1515

16-
17-
1816
## Running this sample
1917

2018
```bash
2119
./gradlew -q execute -PmainClass=io.temporal.samples.ssl.Starter
2220
```
21+
22+
## Run SslEnabledWorkerCustomCA Sample
23+
24+
This sample shows how to start a worker that connects to a temporal cluster with mTLS enabled; created by ([tls-simple sample](https://github.com/temporalio/samples-server/tree/main/tls/tls-simple));
25+
26+
SslEnabledWorkerCustomCA demonstrates:
27+
28+
- Passing a custom CA certificate file as parameter
29+
- Overriding the authority name used for TLS handshakes (if needed)
30+
31+
1.Start a temporal cluster with tls
32+
33+
Please follow the temporal server-sample to start simple Temporal mTLS cluster locally: [tls-simple](https://github.com/temporalio/samples-server/tree/main/tls/tls-simple)
34+
35+
2.Set environment variables
36+
37+
```bash
38+
# Environment variables
39+
# paths to ca cert, client cert and client key come from the previous step
40+
export TEMPORAL_CLIENT_CERT="</path/to/client.pem>"
41+
export TEMPORAL_CLIENT_KEY="</path/to/client.key>"
42+
export TEMPORAL_CA_CERT="</path/to/ca.cert>"
43+
export TEMPORAL_ENDPOINT="localhost:7233" # Temporal grpc endpoint
44+
export TEMPORAL_NAMESPACE="default" # Temporal namespace
45+
export TEMPORAL_SERVER_HOSTNAME="tls-sample" # Temporal server host name
46+
```
47+
48+
3.Start the Worker
49+
50+
```bash
51+
./gradlew -q execute -PmainClass="io.temporal.samples.ssl.SslEnabledWorkerCustomCA"
52+
```
53+
54+
4.Expected result
55+
56+
```text
57+
[main] INFO i.t.s.WorkflowServiceStubsImpl - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=localhost:7233}}
58+
[main] INFO io.temporal.internal.worker.Poller - start: Poller{name=Workflow Poller taskQueue="MyTaskQueue", namespace="default"}
59+
Workflow completed:done
60+
```
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (c) 2020 Temporal Technologies, Inc. All Rights Reserved
3+
*
4+
* Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5+
*
6+
* Modifications copyright (C) 2017 Uber Technologies, Inc.
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not
9+
* use this file except in compliance with the License. A copy of the License is
10+
* located at
11+
*
12+
* http://aws.amazon.com/apache2.0
13+
*
14+
* or in the "license" file accompanying this file. This file is distributed on
15+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
16+
* express or implied. See the License for the specific language governing
17+
* permissions and limitations under the License.
18+
*/
19+
20+
package io.temporal.samples.ssl;
21+
22+
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
23+
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;
24+
import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder;
25+
import io.temporal.client.WorkflowClient;
26+
import io.temporal.client.WorkflowClientOptions;
27+
import io.temporal.client.WorkflowOptions;
28+
import io.temporal.serviceclient.WorkflowServiceStubs;
29+
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
30+
import io.temporal.worker.Worker;
31+
import io.temporal.worker.WorkerFactory;
32+
import java.io.FileInputStream;
33+
import java.io.InputStream;
34+
35+
public class SslEnabledWorkerCustomCA {
36+
37+
static final String TASK_QUEUE = "MyTaskQueue";
38+
39+
public static void main(String[] args) throws Exception {
40+
41+
// Load your client certificate, which should look like:
42+
// -----BEGIN CERTIFICATE-----
43+
// ...
44+
// -----END CERTIFICATE-----
45+
InputStream clientCert = new FileInputStream(System.getenv("TEMPORAL_CLIENT_CERT"));
46+
47+
// PKCS8 client key, which should look like:
48+
// -----BEGIN PRIVATE KEY-----
49+
// ...
50+
// -----END PRIVATE KEY-----
51+
InputStream clientKey = new FileInputStream(System.getenv("TEMPORAL_CLIENT_KEY"));
52+
53+
// Load your Certification Authority certificate, which should look like:
54+
// -----BEGIN CERTIFICATE-----
55+
// ...
56+
// -----END CERTIFICATE-----
57+
InputStream caCert = new FileInputStream(System.getenv("TEMPORAL_CA_CERT"));
58+
59+
// For temporal cloud this would likely be ${namespace}.tmprl.cloud:7233
60+
String targetEndpoint = System.getenv("TEMPORAL_ENDPOINT");
61+
62+
// Your registered namespace.
63+
String namespace = System.getenv("TEMPORAL_NAMESPACE");
64+
65+
// Create an SSL Context using the client certificate and key based on the implementation
66+
// SimpleSslContextBuilder
67+
// https://github.com/temporalio/sdk-java/blob/master/temporal-serviceclient/src/main/java/io/temporal/serviceclient/SimpleSslContextBuilder.java
68+
SslContext sslContext =
69+
GrpcSslContexts.configure(
70+
SslContextBuilder.forClient()
71+
.keyManager(clientCert, clientKey)
72+
.trustManager(caCert))
73+
.build();
74+
75+
// Create SSL enabled client by passing SslContext, created by
76+
// SimpleSslContextBuilder.
77+
WorkflowServiceStubs service =
78+
WorkflowServiceStubs.newServiceStubs(
79+
WorkflowServiceStubsOptions.newBuilder()
80+
.setSslContext(sslContext)
81+
.setTarget(targetEndpoint)
82+
// Override the authority name used for TLS handshakes
83+
.setChannelInitializer(
84+
c -> c.overrideAuthority(System.getenv("TEMPORAL_SERVER_HOSTNAME")))
85+
.build());
86+
87+
// Now setup and start workflow worker, which uses SSL enabled gRPC service to
88+
// communicate with backend. client that can be used to start and signal workflows.
89+
WorkflowClient client =
90+
WorkflowClient.newInstance(
91+
service, WorkflowClientOptions.newBuilder().setNamespace(namespace).build());
92+
93+
// worker factory that can be used to create workers for specific task queues
94+
WorkerFactory factory = WorkerFactory.newInstance(client);
95+
96+
/*
97+
* Define the workflow worker. Workflow workers listen to a defined task queue and process
98+
* workflows and activities.
99+
*/
100+
Worker worker = factory.newWorker(TASK_QUEUE);
101+
102+
/*
103+
* Register our workflow implementation with the worker.
104+
* Workflow implementations must be known to the worker at runtime in
105+
* order to dispatch workflow tasks.
106+
*/
107+
worker.registerWorkflowImplementationTypes(MyWorkflowImpl.class);
108+
109+
/*
110+
* Start all the workers registered for a specific task queue.
111+
* The started workers then start polling for workflows and activities.
112+
*/
113+
factory.start();
114+
115+
// Create the workflow client stub. It is used to start our workflow execution.
116+
MyWorkflow workflow =
117+
client.newWorkflowStub(
118+
MyWorkflow.class,
119+
WorkflowOptions.newBuilder()
120+
.setWorkflowId("WORKFLOW_ID")
121+
.setTaskQueue(TASK_QUEUE)
122+
.build());
123+
124+
/*
125+
* Execute our workflow and wait for it to complete. The call to our execute method is
126+
* synchronous.
127+
*/
128+
String greeting = workflow.execute();
129+
130+
// Display workflow execution results
131+
System.out.println("Workflow completed:" + greeting);
132+
System.exit(0);
133+
}
134+
}

0 commit comments

Comments
 (0)