Skip to content

Commit 95fa16c

Browse files
committed
Add TLS utilities
This patch adds utilities under the temporal.tls namespace to assist with connecting clients to TLS enabled Temporal backends. Signed-off-by: Greg Haskins <[email protected]>
1 parent d6724d1 commit 95fa16c

File tree

7 files changed

+145
-2
lines changed

7 files changed

+145
-2
lines changed

project.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
:profiles {:dev {:dependencies [[org.clojure/tools.namespace "1.4.4"]
3131
[eftest "0.6.0"]
32-
[io.temporal/temporal-opentracing "1.22.3"]]}}
32+
[io.temporal/temporal-opentracing "1.22.3"]]
33+
:resource-paths ["test/temporal/test/resources"]}}
3334
:cloverage {:runner :eftest
3435
:runner-opts {:multithread? false
3536
:fail-fast? true}

src/temporal/client/core.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Arguments:
6464
| :data-converter | Overrides the data converter used to serialize arguments and results. | [DataConverter](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/converter/DataConverter.html) | |
6565
| :interceptors | Collection of interceptors used to intercept workflow client calls. | [WorkflowClientInterceptor](https://javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/interceptors/WorkflowClientInterceptor.html) | |
6666
| :channel | Sets gRPC channel to use. Exclusive with target and sslContext | [ManagedChannel](https://grpc.github.io/grpc-java/javadoc/io/grpc/ManagedChannel.html) | |
67-
| :ssl-context | Sets gRPC SSL Context to use | [SslContext](https://netty.io/4.0/api/io/netty/handler/ssl/SslContext.html) | |
67+
| :ssl-context | Sets gRPC SSL Context to use (See [[temporal.tls/new-ssl-context]]) | [SslContext](https://netty.io/4.0/api/io/netty/handler/ssl/SslContext.html) | |
6868
| :enable-https | Sets option to enable SSL/TLS/HTTPS for gRPC | boolean | false |
6969
| :rpc-timeout | Sets the rpc timeout value for non query and non long poll calls | [Duration](https://docs.oracle.com/javase/8/docs/api//java/time/Duration.html) | 10s |
7070
| :rpc-long-poll-timeout | Sets the rpc timeout value | [Duration](https://docs.oracle.com/javase/8/docs/api//java/time/Duration.html) | 60s |

src/temporal/tls.clj

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
;; Copyright © Manetu, Inc. All rights reserved
2+
3+
(ns temporal.tls
4+
"Utilities for connecting to TLS enabled Temporal clusters"
5+
(:require [clojure.java.io :as io])
6+
(:import [java.security KeyStore]
7+
[java.security.cert CertificateFactory X509Certificate]
8+
[javax.net.ssl TrustManagerFactory]
9+
[io.grpc.netty.shaded.io.grpc.netty GrpcSslContexts]
10+
[io.grpc.netty.shaded.io.netty.handler.ssl SslContext]))
11+
12+
(defn- new-ca
13+
^X509Certificate [certpath]
14+
(let [cf (CertificateFactory/getInstance "X.509")]
15+
(with-open [is (io/input-stream certpath)]
16+
(.generateCertificate cf is))))
17+
18+
(defn- new-keystore
19+
^KeyStore [certpath]
20+
(let [ca (new-ca certpath)
21+
ks-type (KeyStore/getDefaultType)]
22+
(doto (KeyStore/getInstance ks-type)
23+
(.load nil nil)
24+
(.setCertificateEntry "ca" ca))))
25+
26+
(defn- new-trustmanagerfactory
27+
^TrustManagerFactory [certpath]
28+
(let [alg (TrustManagerFactory/getDefaultAlgorithm)
29+
ks (new-keystore certpath)]
30+
(doto (TrustManagerFactory/getInstance alg)
31+
(.init ks))))
32+
33+
(defn new-ssl-context
34+
"
35+
Creates a new gRPC [SslContext](https://netty.io/4.0/api/io/netty/handler/ssl/SslContext.html) suitable for passing to the :ssl-context option of [[temporal.client.core/create-client]]
36+
37+
Arguments:
38+
39+
- `ca-path`: The path to a PEM encoded x509 Certificate Authority root certificate for validating the Temporal server.
40+
- `cert-path`: The path to a PEM encoded x509 Certificate representing this client's identity, used for mutual TLS authentication.
41+
- 'key-path': The path to a PEM encoded private key representing this client's identity, used for mutual TLS authentication.
42+
43+
"
44+
^SslContext [{:keys [ca-path cert-path key-path] :as args}]
45+
(-> (GrpcSslContexts/forClient)
46+
(cond->
47+
(some? ca-path) (.trustManager (new-trustmanagerfactory ca-path))
48+
(and (some? cert-path) (some? key-path)) (.keyManager (io/file cert-path) (io/file key-path)))
49+
(.build)))

test/temporal/test/resources/ca.crt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDDjCCAfagAwIBAgIQLLzSA48U8GQtqMFMgazHjzANBgkqhkiG9w0BAQsFADAh
3+
MR8wHQYDVQQDExZZdWdhYnl0ZSBTZWxmc2lnbmVkIENBMB4XDTIzMTIyOTIwMzM0
4+
N1oXDTI0MDMyODIwMzM0N1owITEfMB0GA1UEAxMWWXVnYWJ5dGUgU2VsZnNpZ25l
5+
ZCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANJGsOx6lyoQfP2f
6+
ByK6LAN1/CTdPoNNVMok7ibP3XKiqE0Dyrv9I/66pZqQrP1HYnv+uVXFDBPMqhXa
7+
Bw5MyW0kjWQzruh2nTDWljZLl129XsvbPR4zkR+UH+6AoHxLIsfS1//jwE+y7OC8
8+
2vpE5PAsBsR2hPXGYPqWeZWscjDW0A0QpYI2b0q8UUnY36cr2fBv0tG/ZwDnhEBe
9+
9E2kTnL4NIcRxoOZXN85NusRBN5oueGOhyVeSBNz2ym1o8D8mMT1L3YHZXsTMDBA
10+
OTYpzCx+hgVtrp3cQUWWGp8R8G3FtrWDvJGxf34X5k/4txlRlaGrQ98w3AM8JdMr
11+
0irWANMCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMBAf8w
12+
HQYDVR0OBBYEFBWjvPFAs3z0xzL+LSwcskkw1rcxMA0GCSqGSIb3DQEBCwUAA4IB
13+
AQBXvO40RJ0Gy4Mcmn1R7CWDBKfRdqvSVoZdQwI0ZNQ0HXWzln4OksprohWRQJNJ
14+
yqvw6DG7LroyfGEn8sfO1fzLcROymGK1akSu4PT0QSHMfmS377OPJvS6licFSvMB
15+
2aFiD2pmQRlNa9mHAxAvGMPnAgrWhNALEPfePpVo9eR+06cJj17WXU/LGA3Fey1N
16+
fAZ7W/LPpFBPPs98gbgJvhUIOJ8IvxPbNTG/21kQK8CfJ2dBnkNZOcm/FI5z+eu1
17+
O5swP6MRHuybvkHhyrhbU67f3iACpCgGzg1YUSjuXm9W+c4LB6qsGiZ/yGc2jJ8v
18+
sbxxhViVNVJ58wbJ63C3OimS
19+
-----END CERTIFICATE-----

test/temporal/test/resources/tls.crt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDBTCCAe2gAwIBAgIRAJHL+sXVDe5KtY39RLUHnZAwDQYJKoZIhvcNAQELBQAw
3+
ITEfMB0GA1UEAxMWWXVnYWJ5dGUgU2VsZnNpZ25lZCBDQTAeFw0yMzEyMjkyMDMz
4+
NTFaFw0yNDAzMjgyMDMzNTFaMBMxETAPBgNVBAMTCHl1Z2FieXRlMIIBIjANBgkq
5+
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Im+0RuHFVA1X7j1XNnr4B68ognJN1Dr
6+
+/YtSiiN14QMRHENjlhUwi8pdvDwOvozyjQnufLchoOY7FpFlOgm99j5JjTD0F52
7+
vBhL1Xe0XB3NrI1e6FizqoOzv7WfBwTepptuF3p1U8RIiqHtxVHUUFsX3LrwKRqD
8+
QgNGvQA4YJOdlOzAdpYmH/MDehFIrX0iZRfLc/Eb4uOc+CZxOHboMi8lAlNdnSFj
9+
8coLYYI7PUSsc1l/XNwvm4p09cWmuDpwaEHMmVOfLh2WBChojDgzYbRcSBbX+VS4
10+
pW6EEnGthNx8/DyFXkiVKSBWMIhDHWhcsiG6PP3mlfuGqYOLSDZGbwIDAQABo0Yw
11+
RDATBgNVHSUEDDAKBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaA
12+
FBWjvPFAs3z0xzL+LSwcskkw1rcxMA0GCSqGSIb3DQEBCwUAA4IBAQBCqRpJz0c/
13+
2bYVaUiH8bk+ubW0iDQH3kCpHS5uTLWNO/gsWE7H+Gp93AZueb3dWoiuZWAlahNL
14+
qLLgKhwM0P527nnoEhBcCYlA3fEfArTWIq4CAE6SX4jUPYsVp4ZUMfQTICsivtPw
15+
uL0lcupDnrpmmiDCYCiCcmT/kXuzUrSyO4Qu8pbznfvhHBa6fxdJdQ6bBFZ1zBox
16+
jJe0UnS7emCFAUzv4yNPw1yFyMqMIwfwN2arVxcz1WQhbM1uLenK6gVjBglnnFDT
17+
9ZsM/ZZXGUvqiIIRvGrREES9Ljuic2j2q/keUXJFg9917dy3ep884+5vv7cxoha1
18+
RNY6CYw4pDlU
19+
-----END CERTIFICATE-----

test/temporal/test/resources/tls.key

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDYib7RG4cVUDVf
3+
uPVc2evgHryiCck3UOv79i1KKI3XhAxEcQ2OWFTCLyl28PA6+jPKNCe58tyGg5js
4+
WkWU6Cb32PkmNMPQXna8GEvVd7RcHc2sjV7oWLOqg7O/tZ8HBN6mm24XenVTxEiK
5+
oe3FUdRQWxfcuvApGoNCA0a9ADhgk52U7MB2liYf8wN6EUitfSJlF8tz8Rvi45z4
6+
JnE4dugyLyUCU12dIWPxygthgjs9RKxzWX9c3C+binT1xaa4OnBoQcyZU58uHZYE
7+
KGiMODNhtFxIFtf5VLilboQSca2E3Hz8PIVeSJUpIFYwiEMdaFyyIbo8/eaV+4ap
8+
g4tINkZvAgMBAAECggEBAMilQppSzqXyL7LmGP2TtJx0/seLF9dY9YIAh9DaqSxV
9+
YGSe+Te4I7nXp61d7sxHgWvRTipgnvVJxY7kyusC/vDULXG4nOVcUttSDBrek9Jz
10+
j1xfltznLHxJE2sF6TjAy2tIRQgeYc9f5vQGveMEQx6+eer/kYAU4CFwFcEWDid1
11+
jGHFuk68CTn/lRACUTIGGzbmevbdzhmtYhU5q8KZO4s1xfGQE+e+Ikw9KNVcBI2l
12+
ox4gzhgfcNsE+RUjhUfACB45aBDGfWLY1uC7opIM5lT0I03TBHwhe7y/24qRtnZ3
13+
3J4kajfssf4rDvHm4MKroTVf3OM4ZM6q2rKDWFMGJaECgYEA4UYE8P6YNO704AtW
14+
/O3kLMjno2q44YXO/HG34cyoPHRk5E60CDbeZ4JX2DlhsVWioGkZg6VVfedtwrlS
15+
j8sFO/2wpnhF591kWwaa5AK6lhhb8bPfjSZG6kffDzKRP1PEN41hq2EqmofpfuLF
16+
7YsSFE+6TeGxVq/SCiXPOpU9UlECgYEA9hK02iDECo1dkQBojPH9RtlCt9uWPW0h
17+
qaQQdKr5RM638IhLZA24tMkfU0XrVp179c7aRdkrIsn6pGzmp2bufjetrLLGkrj8
18+
mujV0nwP4qAHTZjSgCAtoVEUaSYv+WcBsB3shHycB5ffTLZWAOY0WzCrDpsXpd7W
19+
N/NaoRjlHL8CgYEA2DEpZtr+2bYF/coENoJbe3tnilZOjeirp2u/TAzr2/DcLps1
20+
fbiionXdth4DmnuTshyLJuMR892ZYcoW6Pau1E74LBq7A/VdbVoeZfoUdR11h7XX
21+
Mg/s+MP21w/xgvPyGFovxJhgmaMbu/EIgJr5w9Jr+nhBh+7+RUzZ3uAA1LECgYEA
22+
gCb/3vXfgytaRlDzIixI3qP5di07EmSKeoHCPDBqvyX1b6RbtxDaV/TChqjMRoCf
23+
9UU0MdpG98g+63D3sskNfdhbb6xvdCw5Cigma4dG8pyrEQN85VNc0D2cpqJHq9i0
24+
bVc4PUt0KxQyLA5tvewl6jPvchzddPoXkG4BjhKcB5sCgYAVA1rHQy6kMaJuInRs
25+
YPQ+jpKKoxSbDfRvXuhBGaAyisJy5lfI6qHDpl9t2QNHV2tnHq1R5AW8rkAGKVdF
26+
dh/t5DvgfC20ZMVZlJcoPnfwdVaOvu0tnLPk1pes1pInH/TbBGNm6ngZTBdXVu3J
27+
4qnsF0nRAwBqxlv1ldLOF/9i4w==
28+
-----END PRIVATE KEY-----

test/temporal/test/tls.clj

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
;; Copyright © Manetu, Inc. All rights reserved
2+
3+
(ns temporal.test.tls
4+
(:require [clojure.test :refer :all]
5+
[clojure.java.io :as io]
6+
[temporal.tls :as tls]))
7+
8+
;;-----------------------------------------------------------------------------
9+
;; Tests
10+
;;-----------------------------------------------------------------------------
11+
12+
(deftest positive-tests
13+
(testing "Verify that we can create a default SSL context"
14+
(let [ctx (tls/new-ssl-context {})]
15+
(is (some? ctx))))
16+
(testing "Verify that we can create an SSL context with only a CA"
17+
(let [ctx (tls/new-ssl-context {:ca-path (io/resource "ca.crt")})]
18+
(is (some? ctx))))
19+
(testing "Verify that we can create an SSL context with only mTLS cert"
20+
(let [ctx (tls/new-ssl-context {:cert-path (io/resource "tls.crt") :key-path (io/resource "tls.key")})]
21+
(is (some? ctx)))))
22+
23+
(deftest negative-tests
24+
(testing "Verify that we cannot create an SSL context with a bogus CA"
25+
(is (thrown? java.io.FileNotFoundException (tls/new-ssl-context {:ca-path "invalid"}))))
26+
(testing "Verify that we cannot create an SSL context with a bogus Cert"
27+
(is (thrown? java.lang.IllegalArgumentException (tls/new-ssl-context {:cert-path "invalid" :key-path "invalid"})))))

0 commit comments

Comments
 (0)