From 366c53a3fc6ab47cbd5ea0a8e3115ed6b818abb7 Mon Sep 17 00:00:00 2001 From: Ben Standefer <benstandefer@gmail.com> Date: Tue, 4 Feb 2025 02:11:36 -0800 Subject: [PATCH] Add mTLS with Temporal Cloud instructions The "out of the box" SSL instructions didn't work for me because I used the option to create my own CA certificate and end-end entity certificates. I added a section to Authentication that makes it easy for people following along with the Temporal Cloud setup. If you create your own CA certificate, including the root certificate in the constructor of GRPC::Core::ChannelCredentials.new leads to auth failures, but the tests of that function ensure that it's okay to pass `nil` as that value, which is needed for people following the Temporal Cloud instructions. For developer happiness, I think it's also reasonable for this library to include Temporal Cloud-friendly instructions. (not a spokesperson!) :D --- README.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/README.md b/README.md index a64c1159..c5aee29d 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,52 @@ Temporal.configure do |config| end ``` +### mTLS with Temporal Cloud + +Temporal Cloud recommends mTLS and gives instructions on how to issue root CA and end-entity certificates. +To create and use these certificates, install the [tcld](https://docs.temporal.io/cloud/tcld) CLI and then run: + +```bash +mkdir temporal-certs +cd temporal-certs +tcld gen ca --org temporal -d 1y --ca-cert ca.pem --ca-key ca.key +``` + +The contents of the generated ca.pem should be pasted into the "CA Certificates" section of your Namespace settings +page in the Temporal Cloud UI. The namespace must be configured to allow mTLS auth for the authentication section +to appear. + +Then create an end-entity certificate that your app will use via temporal-ruby to talk to Temporal Cloud: + +```bash +tcld gen leaf --org temporal -d 364d --ca-cert ca.pem --ca-key ca.key --cert client.pem --key client.key +``` + +With these files, client.key and client.pem alone can be used to auth: + +```ruby +Temporal.configure do |config| + config.host = "myapp-staging.b948c.tmprl.cloud" + config.port = 7233 + config.namespace = "myapp-staging.b948c" + config.task_queue = "default" + + # Load certificates + client_key = File.read("/tmp/temporal-certs-staging/client.key") + client_cert = File.read("/tmp/temporal-certs-staging/client.pem") + + # Configure GRPC credentials + config.credentials = GRPC::Core::ChannelCredentials.new( + # "can be constructed with nil server roots" - https://github.com/grpc/grpc/blob/master/src/ruby/spec/channel_credentials_spec.rb#L45 + nil, + client_key, + client_cert + ) +end +``` + +In a production app you probably want to store the contents of client.key/client.pem in ENV variables, a secure keychain, Rails credentials files, etc. + ### OAuth2 Token Use gRPC Call Credentials to add OAuth2 token to gRPC calls: