mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 00:01:55 +00:00
feat(otel-tracing-proxy): trust internal endpoints with untrusted CAs (#10139)
* [ee] feat(otel-tracing-proxy): trust internal endpoints with untrusted CAs Add `insecure_upstream_hosts` and `upstream_ca_certs` to the HTTP Request Tracing settings so the OTEL tracing proxy can reach internal endpoints with untrusted or private-CA certificates while keeping them traced. Wires the two settings through the worker config and live reload, adds the inputs to the instance settings UI, and pulls in the rustls upstream-client deps (hyper-rustls/tokio-rustls/rustls/ rustls-native-certs/rustls-pemfile; hyper-http-proxy switched to its rustls feature). The proxy-side implementation lives in the companion EE PR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump ee-repo-ref to otel_ca companion commit Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(otel-tracing-proxy): expose new fields in declarative config; bump ee-ref Addresses code-review findings: - Add `insecure_upstream_hosts` and `upstream_ca_certs` to the declarative `OtelTracingProxySettings` in instance_config.rs so operator/GitOps-managed installs can set them and reconciliation no longer drops values saved via the UI. - Restore the trailing newline on ee-repo-ref.txt and bump it to the companion EE commit carrying the strict host-matching / port-ordering fixes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 51e50629f48dbc4f5520a787b4bdfb76f4cd38d3 This commit updates the EE repository reference after PR #665 was merged in windmill-ee-private. Previous ee-repo-ref: 49f458e4446395e98915c220baa757ab3b2ed2d8 New ee-repo-ref: 51e50629f48dbc4f5520a787b4bdfb76f4cd38d3 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
Generated
+5
-4
@@ -5814,12 +5814,9 @@ dependencies = [
|
||||
"http 1.4.2",
|
||||
"hyper 1.10.1",
|
||||
"hyper-rustls 0.27.9",
|
||||
"hyper-tls",
|
||||
"hyper-util",
|
||||
"native-tls",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tower-service",
|
||||
]
|
||||
@@ -15747,7 +15744,7 @@ dependencies = [
|
||||
"hmac",
|
||||
"hudsucker",
|
||||
"hyper-http-proxy",
|
||||
"hyper-tls",
|
||||
"hyper-rustls 0.27.9",
|
||||
"hyper-util",
|
||||
"itertools 0.14.0",
|
||||
"jsonwebtoken 8.3.0",
|
||||
@@ -15777,6 +15774,9 @@ dependencies = [
|
||||
"reqwest-middleware",
|
||||
"rsa",
|
||||
"rust_decimal",
|
||||
"rustls 0.23.35",
|
||||
"rustls-native-certs 0.8.4",
|
||||
"rustls-pemfile 2.2.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.9",
|
||||
@@ -15786,6 +15786,7 @@ dependencies = [
|
||||
"tiberius",
|
||||
"tokio",
|
||||
"tokio-postgres",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
|
||||
+4
-1
@@ -681,5 +681,8 @@ rumqttc = { version = "0.24.0", features = ["use-native-tls"]}
|
||||
strum = { version = "0.27", features = ["derive"] }
|
||||
strum_macros = "0.27"
|
||||
hudsucker = { version = "0.22", features = ["rcgen-ca", "native-tls-client"] }
|
||||
hyper-http-proxy = { version = "1", default-features = false, features = ["native-tls"] }
|
||||
hyper-http-proxy = { version = "1", default-features = false, features = ["rustls-tls-native-roots"] }
|
||||
hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "ring", "tls12"] }
|
||||
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] }
|
||||
rustls-native-certs = "0.8"
|
||||
rcgen = "0.13"
|
||||
|
||||
@@ -1 +1 @@
|
||||
e19948fa2974a7d89bec12957fc6d9fa0a421da8
|
||||
51e50629f48dbc4f5520a787b4bdfb76f4cd38d3
|
||||
|
||||
@@ -1061,12 +1061,16 @@ pub async fn reload_otel_tracing_proxy_setting(conn: &Connection) {
|
||||
if current.enabled != new_settings.enabled
|
||||
|| current.enabled_languages != new_settings.enabled_languages
|
||||
|| current.no_proxy_hosts != new_settings.no_proxy_hosts
|
||||
|| current.insecure_upstream_hosts != new_settings.insecure_upstream_hosts
|
||||
|| current.upstream_ca_certs != new_settings.upstream_ca_certs
|
||||
{
|
||||
tracing::info!(
|
||||
"OTEL tracing proxy settings changed: enabled={}, languages={:?}, no_proxy_hosts={:?}",
|
||||
"OTEL tracing proxy settings changed: enabled={}, languages={:?}, no_proxy_hosts={:?}, insecure_upstream_hosts={:?}, upstream_ca_certs={}",
|
||||
new_settings.enabled,
|
||||
new_settings.enabled_languages,
|
||||
new_settings.no_proxy_hosts,
|
||||
new_settings.insecure_upstream_hosts,
|
||||
if new_settings.upstream_ca_certs.as_deref().unwrap_or("").trim().is_empty() { "unset" } else { "set" },
|
||||
);
|
||||
*current = new_settings;
|
||||
}
|
||||
|
||||
@@ -641,6 +641,15 @@ pub struct OtelTracingProxySettings {
|
||||
/// pin their own CA (kubectl, helm, terraform providers, aws cli for EKS, etc.).
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub no_proxy_hosts: Option<String>,
|
||||
/// Comma-separated host/IP patterns for which the MITM proxy skips upstream TLS
|
||||
/// verification. Unlike `no_proxy_hosts` the hosts stay traced — only the proxy's own
|
||||
/// upstream certificate check is disabled.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub insecure_upstream_hosts: Option<String>,
|
||||
/// Extra CA certificates (PEM bundle) added to the MITM proxy's upstream trust store,
|
||||
/// on top of the system roots, so internal endpoints signed by a private CA verify.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub upstream_ca_certs: Option<String>,
|
||||
}
|
||||
|
||||
/// Script language identifier (for instance config use).
|
||||
|
||||
@@ -13,7 +13,7 @@ default = []
|
||||
private = ["windmill-worker-volumes/private", "windmill-queue/private", "windmill-common/private", "windmill-dep-map/private", "windmill-runtime-nativets?/private"]
|
||||
mcp = ["windmill-ai/mcp", "dep:windmill-mcp"]
|
||||
prometheus = ["dep:prometheus", "windmill-common/prometheus"]
|
||||
enterprise = ["windmill-queue/enterprise", "windmill-git-sync/enterprise", "windmill-common/enterprise", "windmill-worker-volumes/enterprise", "windmill-runtime-nativets?/enterprise", "dep:pem", "dep:rsa", "dep:tokio-util", "dep:opentelemetry-proto", "dep:prost", "dep:hudsucker", "dep:rcgen", "dep:hyper-http-proxy", "dep:hyper-tls", "dep:hyper-util"]
|
||||
enterprise = ["windmill-queue/enterprise", "windmill-git-sync/enterprise", "windmill-common/enterprise", "windmill-worker-volumes/enterprise", "windmill-runtime-nativets?/enterprise", "dep:pem", "dep:rsa", "dep:tokio-util", "dep:opentelemetry-proto", "dep:prost", "dep:hudsucker", "dep:rcgen", "dep:hyper-http-proxy", "dep:hyper-rustls", "dep:tokio-rustls", "dep:rustls", "dep:rustls-native-certs", "dep:rustls-pemfile", "dep:hyper-util"]
|
||||
mssql = ["dep:tiberius"]
|
||||
mssql-kerberos = ["mssql", "tiberius/integrated-auth-gssapi"] # Linux/Unix integrated auth
|
||||
mssql-winauth = ["mssql", "tiberius/winauth"] # Windows integrated auth
|
||||
@@ -144,7 +144,11 @@ bollard = { workspace = true, optional = true }
|
||||
oracle = { workspace = true, optional = true }
|
||||
hudsucker = { workspace = true, optional = true }
|
||||
hyper-http-proxy = { workspace = true, optional = true }
|
||||
hyper-tls = { workspace = true, optional = true }
|
||||
hyper-rustls = { workspace = true, optional = true }
|
||||
tokio-rustls = { workspace = true, optional = true }
|
||||
rustls = { workspace = true, optional = true }
|
||||
rustls-native-certs = { workspace = true, optional = true }
|
||||
rustls-pemfile = { workspace = true, optional = true }
|
||||
hyper-util = { workspace = true, optional = true }
|
||||
rcgen = { workspace = true, optional = true }
|
||||
|
||||
|
||||
@@ -283,6 +283,17 @@ pub struct OtelTracingProxySettings {
|
||||
pub enabled_languages: HashSet<ScriptLang>,
|
||||
#[serde(default)]
|
||||
pub no_proxy_hosts: Option<String>,
|
||||
/// Comma-separated host/IP patterns for which the MITM proxy skips upstream TLS
|
||||
/// verification. Unlike `no_proxy_hosts` (which bypasses the proxy entirely, so the
|
||||
/// request goes untraced), these hosts stay traced — only the proxy's own upstream
|
||||
/// certificate check is disabled. Same suffix-matching semantics as `no_proxy_hosts`.
|
||||
#[serde(default)]
|
||||
pub insecure_upstream_hosts: Option<String>,
|
||||
/// Extra CA certificates (PEM bundle) added to the MITM proxy's upstream trust store,
|
||||
/// on top of the system roots. Lets the proxy verify internal endpoints signed by a
|
||||
/// private CA without disabling verification.
|
||||
#[serde(default)]
|
||||
pub upstream_ca_certs: Option<String>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "prometheus")]
|
||||
|
||||
@@ -753,6 +753,51 @@
|
||||
upstream relay (e.g. through a corporate proxy).
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label
|
||||
for="otel_tracing_proxy_insecure_upstream_hosts"
|
||||
class="block text-xs font-semibold text-emphasis"
|
||||
>
|
||||
Insecure upstream hosts (skip TLS verification)
|
||||
</label>
|
||||
<TextInput
|
||||
inputProps={{
|
||||
type: 'text',
|
||||
placeholder: '10.0.0.5,*.internal,git.corp.example',
|
||||
id: 'otel_tracing_proxy_insecure_upstream_hosts',
|
||||
disabled: !$enterpriseLicense
|
||||
}}
|
||||
bind:value={$values[setting.key].insecure_upstream_hosts}
|
||||
/>
|
||||
<p class="text-xs text-tertiary">
|
||||
Comma-separated host/IP patterns the proxy still traces but for which it skips
|
||||
upstream TLS certificate verification. Use for internal endpoints with
|
||||
self-signed or otherwise untrusted certificates — unlike NO_PROXY above, these
|
||||
requests stay traced. Same matching as NO_PROXY (<code>example.com</code> matches
|
||||
subdomains; <code>.example.com</code> matches subdomains only).
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label
|
||||
for="otel_tracing_proxy_upstream_ca_certs"
|
||||
class="block text-xs font-semibold text-emphasis"
|
||||
>
|
||||
Upstream CA certificates (PEM)
|
||||
</label>
|
||||
<textarea
|
||||
id="otel_tracing_proxy_upstream_ca_certs"
|
||||
disabled={!$enterpriseLicense}
|
||||
rows="4"
|
||||
placeholder={'-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----'}
|
||||
bind:value={$values[setting.key].upstream_ca_certs}
|
||||
></textarea>
|
||||
<p class="text-xs text-tertiary">
|
||||
Extra CA certificates added to the proxy's upstream trust store, on top of the
|
||||
system roots. Use this to trace internal endpoints signed by a private CA while
|
||||
keeping certificate verification enabled — preferred over the insecure list above
|
||||
when you have the CA.
|
||||
</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if setting.fieldType == 'object_store_config'}
|
||||
|
||||
Reference in New Issue
Block a user