Skip to content

Commit b729086

Browse files
committed
Allow overriding origin for core connections (#528)
* Override origin and therefore host/authority header when TLS domain override is set * Allow overriding origin specifically
1 parent 653f4ab commit b729086

File tree

3 files changed

+39
-30
lines changed

3 files changed

+39
-30
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ src/protos/*.rs
1414
/machine_coverage/
1515
/bindings/
1616
/core/machine_coverage/
17+
/.cloud_certs/

client/src/lib.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use crate::{
3333
workflow_handle::UntypedWorkflowHandle,
3434
};
3535
use backoff::{exponential, ExponentialBackoff, SystemClock};
36-
use http::uri::InvalidUri;
36+
use http::{uri::InvalidUri, Uri};
3737
use once_cell::sync::OnceCell;
3838
use parking_lot::RwLock;
3939
use std::{
@@ -114,6 +114,14 @@ pub struct ClientOptions {
114114
/// Retry configuration for the server client. Default is [RetryConfig::default]
115115
#[builder(default)]
116116
pub retry_config: RetryConfig,
117+
118+
/// If set, override the origin used when connecting. May be useful in rare situations where tls
119+
/// verification needs to use a different name from what should be set as the `:authority`
120+
/// header. If [TlsConfig::domain] is set, and this is not, this will be set to
121+
/// `https://<domain>`, effectively making the `:authority` header consistent with the domain
122+
/// override.
123+
#[builder(default)]
124+
pub override_origin: Option<Uri>,
117125
}
118126

119127
/// Configuration options for TLS
@@ -310,6 +318,11 @@ impl ClientOptions {
310318
{
311319
let channel = Channel::from_shared(self.target_url.to_string())?;
312320
let channel = self.add_tls_to_channel(channel).await?;
321+
let channel = if let Some(origin) = self.override_origin.clone() {
322+
channel.origin(origin)
323+
} else {
324+
channel
325+
};
313326
let channel = channel.connect().await?;
314327
let service = ServiceBuilder::new()
315328
.layer_fn(|channel| GrpcMetricSvc {
@@ -347,10 +360,7 @@ impl ClientOptions {
347360

348361
/// If TLS is configured, set the appropriate options on the provided channel and return it.
349362
/// Passes it through if TLS options not set.
350-
async fn add_tls_to_channel(
351-
&self,
352-
channel: Endpoint,
353-
) -> Result<Endpoint, tonic::transport::Error> {
363+
async fn add_tls_to_channel(&self, mut channel: Endpoint) -> Result<Endpoint, ClientInitError> {
354364
if let Some(tls_cfg) = &self.tls_cfg {
355365
let mut tls = tonic::transport::ClientTlsConfig::new();
356366

@@ -361,6 +371,13 @@ impl ClientOptions {
361371

362372
if let Some(domain) = &tls_cfg.domain {
363373
tls = tls.domain_name(domain);
374+
375+
// This song and dance ultimately is just to make sure the `:authority` header ends
376+
// up correct on requests while we use TLS. Setting the header directly in our
377+
// interceptor doesn't work since seemingly it is overridden at some point by
378+
// something lower level.
379+
let uri: Uri = format!("https://{}", domain).parse()?;
380+
channel = channel.origin(uri);
364381
}
365382

366383
if let Some(client_opts) = &tls_cfg.client_tls_config {
@@ -369,7 +386,7 @@ impl ClientOptions {
369386
tls = tls.identity(client_identity);
370387
}
371388

372-
return channel.tls_config(tls);
389+
return channel.tls_config(tls).map_err(Into::into);
373390
}
374391
Ok(channel)
375392
}

tests/main.rs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mod integ_tests {
2525
use temporal_sdk_core_api::worker::WorkerConfigBuilder;
2626
use temporal_sdk_core_protos::temporal::api::workflowservice::v1::ListNamespacesRequest;
2727
use temporal_sdk_core_test_utils::{
28-
get_integ_server_options, get_integ_telem_options, NAMESPACE,
28+
get_integ_server_options, get_integ_telem_options, init_integ_telem,
2929
};
3030
use url::Url;
3131

@@ -58,35 +58,23 @@ mod integ_tests {
5858
.await;
5959
}
6060

61-
// TODO: Currently ignored because starting up the docker image with TLS requires some hoop
62-
// jumping. We should upgrade CI to be able to do that but this was manually run against
63-
// https://github.com/temporalio/customization-samples/tree/master/tls/tls-simple
61+
// Manually run to verify tls works against cloud. You will need certs in place in the
62+
// indicated directory.
6463
#[tokio::test]
6564
#[ignore]
6665
async fn tls_test() {
67-
// Load certs/keys
68-
let root = tokio::fs::read(
69-
"/home/sushi/dev/temporal/customization-samples/tls/tls-simple/certs/ca.cert",
70-
)
71-
.await
72-
.unwrap();
73-
let client_cert = tokio::fs::read(
74-
"/home/sushi/dev/temporal/customization-samples/tls/tls-simple/certs/client.pem",
75-
)
76-
.await
77-
.unwrap();
78-
let client_private_key = tokio::fs::read(
79-
"/home/sushi/dev/temporal/customization-samples/tls/tls-simple/certs/client.key",
80-
)
81-
.await
82-
.unwrap();
66+
init_integ_telem();
67+
let root = tokio::fs::read("../.cloud_certs/ca.pem").await.unwrap();
68+
let client_cert = tokio::fs::read("../.cloud_certs/client.pem").await.unwrap();
69+
let client_private_key = tokio::fs::read("../.cloud_certs/client.key").await.unwrap();
8370
let sgo = ClientOptionsBuilder::default()
84-
.target_url(Url::from_str("https://localhost:7233").unwrap())
71+
.target_url(Url::from_str("https://spencer.temporal-dev.tmprl.cloud:7233").unwrap())
8572
.client_name("tls_tester")
8673
.client_version("clientver")
8774
.tls_cfg(TlsConfig {
8875
server_root_ca_cert: Some(root),
89-
domain: Some("tls-sample".to_string()),
76+
// Not necessary, but illustrates functionality for people using proxies, etc.
77+
domain: Some("spencer.temporal-dev.tmprl.cloud".to_string()),
9078
client_tls_config: Some(ClientTlsConfig {
9179
client_cert,
9280
client_private_key,
@@ -95,9 +83,12 @@ mod integ_tests {
9583
.build()
9684
.unwrap();
9785
let con = sgo
98-
.connect(NAMESPACE.to_string(), None, None)
86+
.connect("spencer.temporal-dev".to_string(), None, None)
9987
.await
10088
.unwrap();
101-
con.list_namespaces().await.unwrap();
89+
dbg!(con
90+
.list_workflow_executions(100, vec![], "".to_string())
91+
.await
92+
.unwrap());
10293
}
10394
}

0 commit comments

Comments
 (0)