From 448fa45059564e5374c3bed738755650a4f07de4 Mon Sep 17 00:00:00 2001 From: Aymalla Date: Fri, 19 May 2023 19:08:02 +0100 Subject: [PATCH 1/4] Ssl enabled worker custom CA and authority name --- .../java/io/temporal/samples/ssl/README.md | 88 +++++++++++++++++ .../samples/ssl/SslEnabledWorkerCustomCA.java | 96 +++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 src/main/java/io/temporal/samples/ssl/README.md create mode 100644 src/main/java/io/temporal/samples/ssl/SslEnabledWorkerCustomCA.java diff --git a/src/main/java/io/temporal/samples/ssl/README.md b/src/main/java/io/temporal/samples/ssl/README.md new file mode 100644 index 00000000..0acf49d9 --- /dev/null +++ b/src/main/java/io/temporal/samples/ssl/README.md @@ -0,0 +1,88 @@ +# SslEnabledWorker + +This sample shows how to start a worker with SSL enabled + +## SslEnabledWorker + +This sample demonstrates how to start SSL enabled worker using the `client certificate` that is issued by a trusted CA (Certificate Authority). + +***Assumptions:*** + - CA's certificate must be installed to the JVM or machine's X509 Default TrustManager. + - Client certificate authority name matches the temporal sever host name. + +**1. Set environment variables** + +```bash +# Environment variables +export TEMPORAL_CLIENT_CERT="" +export TEMPORAL_CLIENT_KEY="" +export TEMPORAL_ENDPOINT="" +export TEMPORAL_NAMESPACE="" +``` + +**2. Start the Worker** + +```bash +./gradlew -q execute -PmainClass=io.temporal.samples.ssl.SslEnabledWorker +``` + +**3. Expected result** + +``` +[main] INFO i.t.s.WorkflowServiceStubsImpl - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=temporal-host-name:7233}} +``` + +## SslEnabledWorkerCustomCA + +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)); + +SslEnabledWorkerCustomCA demonstrates: +- Passing a custom CA certificate file as parameter +- Overriding the authority name used for TLS handshakes (if needed) + +**1. Start a temporal cluster with tls** + +```bash +# 1. clone the samples-server repository +git clone https://github.com/temporalio/samples-server.git + +# 2. change `tls/tls-simple/docker-compose.yml` +#replace: "SKIP_DEFAULT_NAMESPACE_CREATION=true" +#with: "SKIP_DEFAULT_NAMESPACE_CREATION=false" + +# 3. follow the readme to generate certificates and start temporal cluster +# https://github.com/temporalio/samples-server/tree/main/tls/tls-simple +cd samples-server/tls/tls-simple + +# generate certificates +./generate-test-certs.sh + +# start temporal cluster +./start-temporal.sh +``` + +**2. Set environment variables** + +```bash +# Environment variables +# paths to ca cert, client cert and client key come from the previous step +export TEMPORAL_CLIENT_CERT="" +export TEMPORAL_CLIENT_KEY="" +export TEMPORAL_CA_CERT="" +export TEMPORAL_ENDPOINT="localhost:7233" +export TEMPORAL_NAMESPACE="default" +export TEMPORAL_SERVER_HOSTNAME="tls-sample" +``` + +**2. Start the Worker** + +```bash +./gradlew -q execute -PmainClass=io.temporal.samples.ssl.SslEnabledWorkerCustomCA +``` + +**3. Expected result** + +``` +[main] INFO i.t.s.WorkflowServiceStubsImpl - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=temporal-host-name:7233}} +``` + diff --git a/src/main/java/io/temporal/samples/ssl/SslEnabledWorkerCustomCA.java b/src/main/java/io/temporal/samples/ssl/SslEnabledWorkerCustomCA.java new file mode 100644 index 00000000..a9f41527 --- /dev/null +++ b/src/main/java/io/temporal/samples/ssl/SslEnabledWorkerCustomCA.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020 Temporal Technologies, Inc. All Rights Reserved + * + * Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Modifications copyright (C) 2017 Uber Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"). You may not + * use this file except in compliance with the License. A copy of the License is + * located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package io.temporal.samples.ssl; + +import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.shaded.io.netty.handler.ssl.SslContext; +import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder; +import io.temporal.client.WorkflowClient; +import io.temporal.client.WorkflowClientOptions; +import io.temporal.serviceclient.WorkflowServiceStubs; +import io.temporal.serviceclient.WorkflowServiceStubsOptions; +import io.temporal.worker.WorkerFactory; +import java.io.FileInputStream; +import java.io.InputStream; + +public class SslEnabledWorkerCustomCA { + + static final String TASK_QUEUE = "MyTaskQueue"; + + public static void main(String[] args) throws Exception { + + // Load your client certificate + InputStream clientCert = new FileInputStream(System.getenv("TEMPORAL_CLIENT_CERT")); + + // PKCS8 client key + InputStream clientKey = new FileInputStream(System.getenv("TEMPORAL_CLIENT_KEY")); + + // Certification Authority certificate + InputStream caCert = new FileInputStream(System.getenv("TEMPORAL_CA_CERT")); + + // For temporal cloud this would likely be ${namespace}.tmprl.cloud:7233 + String targetEndpoint = System.getenv("TEMPORAL_ENDPOINT"); + + // Your registered namespace. + String namespace = System.getenv("TEMPORAL_NAMESPACE"); + + // Create an SSL Context using the client certificate and key based on the implementation + // SimpleSslContextBuilder + // https://github.com/temporalio/sdk-java/blob/master/temporal-serviceclient/src/main/java/io/temporal/serviceclient/SimpleSslContextBuilder.java + SslContext sslContext = + GrpcSslContexts.configure( + SslContextBuilder.forClient() + .keyManager(clientCert, clientKey) + .trustManager(caCert)) + .build(); + + // Create SSL enabled client by passing SslContext, created by + // SimpleSslContextBuilder. + WorkflowServiceStubs service = + WorkflowServiceStubs.newServiceStubs( + WorkflowServiceStubsOptions.newBuilder() + .setSslContext(sslContext) + .setTarget(targetEndpoint) + // Override the authority name used for TLS handshakes + .setChannelInitializer( + c -> c.overrideAuthority(System.getenv("TEMPORAL_SERVER_HOSTNAME"))) + .build()); + + // Now setup and start workflow worker, which uses SSL enabled gRPC service to + // communicate with + // backend. + // client that can be used to start and signal workflows. + WorkflowClient client = + WorkflowClient.newInstance( + service, WorkflowClientOptions.newBuilder().setNamespace(namespace).build()); + + // worker factory that can be used to create workers for specific task queues + WorkerFactory factory = WorkerFactory.newInstance(client); + + // Worker that listens on a task queue and hosts both workflow and activity + // implementations. + factory.newWorker(TASK_QUEUE); + + // TODO: now register your workflow types and activity implementations. + // worker.registerWorkflowImplementationTypes(...); + // worker.registerActivitiesImplementations(...); + factory.start(); + } +} From c5fddaad438a144250f3498f86e6b3bc82508e8f Mon Sep 17 00:00:00 2001 From: Aymalla Date: Mon, 22 May 2023 14:41:09 +0100 Subject: [PATCH 2/4] Update README.md --- src/main/java/io/temporal/samples/ssl/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/temporal/samples/ssl/README.md b/src/main/java/io/temporal/samples/ssl/README.md index 0acf49d9..f5e62fcd 100644 --- a/src/main/java/io/temporal/samples/ssl/README.md +++ b/src/main/java/io/temporal/samples/ssl/README.md @@ -1,6 +1,6 @@ -# SslEnabledWorker +# Ssl enabled WorkflowClient -This sample shows how to start a worker with SSL enabled +These samples demonstrate how to start a workflow client (worker) with SSL enabled. ## SslEnabledWorker From 04401059b991316c281d093fad9006ca924f6850 Mon Sep 17 00:00:00 2001 From: Aymalla Date: Tue, 20 Jun 2023 16:06:12 +0100 Subject: [PATCH 3/4] rebase to main branch --- .../java/io/temporal/samples/ssl/README.md | 44 ++++++++++++- .../samples/ssl/SslEnabledWorkerCustomCA.java | 64 +++++++++++++++---- 2 files changed, 92 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/io/temporal/samples/ssl/README.md b/core/src/main/java/io/temporal/samples/ssl/README.md index 187b5cc4..ec62ce37 100644 --- a/core/src/main/java/io/temporal/samples/ssl/README.md +++ b/core/src/main/java/io/temporal/samples/ssl/README.md @@ -1,11 +1,11 @@ # Workflow execution with mTLS - This example shows how to secure your Temporal application with [mTLS](https://docs.temporal.io/security/#encryption-in-transit-with-mtls). This is required to connect with Temporal Cloud or any production Temporal deployment. ## Export env variables + Before running the example you need to export the following env variables: - TEMPORAL_ENDPOINT: grpc endpoint, for Temporal Cloud would like `${namespace}.tmprl.cloud:7233`. @@ -13,10 +13,48 @@ Before running the example you need to export the following env variables: - TEMPORAL_CLIENT_CERT: For Temporal Cloud see requirements [here](https://docs.temporal.io/cloud/how-to-manage-certificates-in-temporal-cloud#end-entity-certificates). - TEMPORAL_CLIENT_KEY: For Temporal Cloud see requirements [here](https://docs.temporal.io/cloud/how-to-manage-certificates-in-temporal-cloud#end-entity-certificates). - - ## Running this sample ```bash ./gradlew -q execute -PmainClass=io.temporal.samples.ssl.Starter ``` + +## Run SslEnabledWorkerCustomCA Sample + +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)); + +SslEnabledWorkerCustomCA demonstrates: + +- Passing a custom CA certificate file as parameter +- Overriding the authority name used for TLS handshakes (if needed) + +1.Start a temporal cluster with tls + +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) + +2.Set environment variables + +```bash +# Environment variables +# paths to ca cert, client cert and client key come from the previous step +export TEMPORAL_CLIENT_CERT="" +export TEMPORAL_CLIENT_KEY="" +export TEMPORAL_CA_CERT="" +export TEMPORAL_ENDPOINT="localhost:7233" # Temporal grpc endpoint +export TEMPORAL_NAMESPACE="default" # Temporal namespace +export TEMPORAL_SERVER_HOSTNAME="tls-sample" # Temporal server host name +``` + +3.Start the Worker + +```bash +gradle -q execute -PmainClass=io.temporal.samples.ssl.SslEnabledWorkerCustomCA +``` + +4.Expected result + +```text +[main] INFO i.t.s.WorkflowServiceStubsImpl - Created WorkflowServiceStubs for channel: ManagedChannelOrphanWrapper{delegate=ManagedChannelImpl{logId=1, target=localhost:7233}} +[main] INFO io.temporal.internal.worker.Poller - start: Poller{name=Workflow Poller taskQueue="MyTaskQueue", namespace="default"} +Workflow completed:done +``` diff --git a/core/src/main/java/io/temporal/samples/ssl/SslEnabledWorkerCustomCA.java b/core/src/main/java/io/temporal/samples/ssl/SslEnabledWorkerCustomCA.java index a9f41527..165737ff 100644 --- a/core/src/main/java/io/temporal/samples/ssl/SslEnabledWorkerCustomCA.java +++ b/core/src/main/java/io/temporal/samples/ssl/SslEnabledWorkerCustomCA.java @@ -24,8 +24,10 @@ import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder; import io.temporal.client.WorkflowClient; import io.temporal.client.WorkflowClientOptions; +import io.temporal.client.WorkflowOptions; import io.temporal.serviceclient.WorkflowServiceStubs; import io.temporal.serviceclient.WorkflowServiceStubsOptions; +import io.temporal.worker.Worker; import io.temporal.worker.WorkerFactory; import java.io.FileInputStream; import java.io.InputStream; @@ -36,13 +38,22 @@ public class SslEnabledWorkerCustomCA { public static void main(String[] args) throws Exception { - // Load your client certificate + // Load your client certificate, which should look like: + // -----BEGIN CERTIFICATE----- + // ... + // -----END CERTIFICATE----- InputStream clientCert = new FileInputStream(System.getenv("TEMPORAL_CLIENT_CERT")); - // PKCS8 client key + // PKCS8 client key, which should look like: + // -----BEGIN PRIVATE KEY----- + // ... + // -----END PRIVATE KEY----- InputStream clientKey = new FileInputStream(System.getenv("TEMPORAL_CLIENT_KEY")); - // Certification Authority certificate + // Load your Certification Authority certificate, which should look like: + // -----BEGIN CERTIFICATE----- + // ... + // -----END CERTIFICATE----- InputStream caCert = new FileInputStream(System.getenv("TEMPORAL_CA_CERT")); // For temporal cloud this would likely be ${namespace}.tmprl.cloud:7233 @@ -74,9 +85,7 @@ public static void main(String[] args) throws Exception { .build()); // Now setup and start workflow worker, which uses SSL enabled gRPC service to - // communicate with - // backend. - // client that can be used to start and signal workflows. + // communicate with backend. client that can be used to start and signal workflows. WorkflowClient client = WorkflowClient.newInstance( service, WorkflowClientOptions.newBuilder().setNamespace(namespace).build()); @@ -84,13 +93,42 @@ public static void main(String[] args) throws Exception { // worker factory that can be used to create workers for specific task queues WorkerFactory factory = WorkerFactory.newInstance(client); - // Worker that listens on a task queue and hosts both workflow and activity - // implementations. - factory.newWorker(TASK_QUEUE); - - // TODO: now register your workflow types and activity implementations. - // worker.registerWorkflowImplementationTypes(...); - // worker.registerActivitiesImplementations(...); + /* + * Define the workflow worker. Workflow workers listen to a defined task queue and process + * workflows and activities. + */ + Worker worker = factory.newWorker(TASK_QUEUE); + + /* + * Register our workflow implementation with the worker. + * Workflow implementations must be known to the worker at runtime in + * order to dispatch workflow tasks. + */ + worker.registerWorkflowImplementationTypes(MyWorkflowImpl.class); + + /* + * Start all the workers registered for a specific task queue. + * The started workers then start polling for workflows and activities. + */ factory.start(); + + // Create the workflow client stub. It is used to start our workflow execution. + MyWorkflow workflow = + client.newWorkflowStub( + MyWorkflow.class, + WorkflowOptions.newBuilder() + .setWorkflowId("WORKFLOW_ID") + .setTaskQueue(TASK_QUEUE) + .build()); + + /* + * Execute our workflow and wait for it to complete. The call to our execute method is + * synchronous. + */ + String greeting = workflow.execute(); + + // Display workflow execution results + System.out.println("Workflow completed:" + greeting); + System.exit(0); } } From 06ed719acc9896cb1c23a42c74300eaefb0b8ece Mon Sep 17 00:00:00 2001 From: Ayman Date: Tue, 20 Jun 2023 17:09:25 +0100 Subject: [PATCH 4/4] update readme --- core/src/main/java/io/temporal/samples/ssl/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/io/temporal/samples/ssl/README.md b/core/src/main/java/io/temporal/samples/ssl/README.md index ec62ce37..a48d7aed 100644 --- a/core/src/main/java/io/temporal/samples/ssl/README.md +++ b/core/src/main/java/io/temporal/samples/ssl/README.md @@ -48,7 +48,7 @@ export TEMPORAL_SERVER_HOSTNAME="tls-sample" # Temporal server host name 3.Start the Worker ```bash -gradle -q execute -PmainClass=io.temporal.samples.ssl.SslEnabledWorkerCustomCA +./gradlew -q execute -PmainClass="io.temporal.samples.ssl.SslEnabledWorkerCustomCA" ``` 4.Expected result