intersystems-community / intersystems-community/iris-agentic-dev
Trust the OS cert store for Atelier TLS, not just bundled roots
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 40
- Forks
- 14
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 7
Description
Summary
Connecting to an IRIS instance whose web gateway serves HTTPS with a
locally-issued certificate (e.g. mkcert, which automatically adds to
the system trust) fails at the TLS handshake, with no config path in
.iris-agentic-dev.toml to accept it. The only workaround is to publish
a second, plain-HTTP port on the gateway and connect over that
instead - undesirable for a stack that's otherwise HTTPS-only by
design.
What I found
reqwest is pinned to the rustls-tls feature (bundled webpki roots,
never reads the OS trust store):
# Cargo.toml
reqwest = { version = "0.12", features = ["json", "rustls-tls", "cookies"], default-features = false }
tokio-tungstenite, a few lines away in the same crate, already asks
for native roots instead:
tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "connect", "handshake"], default-features = false }
So the websocket client already trusts a locally-issued cert; the
Atelier REST client (reqwest) doesn't. IRIS_INSECURE / IRIS_TLS_VERIFY
env vars exist as a workaround, disabling cert validation entirely
(connection.rs, danger_accept_invalid_certs):
pub fn http_client() -> anyhow::Result<reqwest::Client> {
let insecure = std::env::var("IRIS_INSECURE")
.ok()
.map(|v| v == "true" || v == "1")
.unwrap_or_else(|| {
std::env::var("IRIS_TLS_VERIFY")
.map(|v| v == "false" || v == "0")
.unwrap_or(false)
});
...
}
But neither variable appears in docs/connecting.md's "Environment
variables" table, and WorkspaceConfig (workspace_config.rs) has no
corresponding field, so there's no way to set this per-project in
.iris-agentic-dev.toml either - only via process environment, which
doesn't compose with a project-local config file the way every other
connection setting does.
Suggested fix
- Give reqwest the same
rustls-tls-native-rootsfeature
tokio-tungstenite already uses, so it trusts the OS certificate
store the way curl and browsers do. mkcert's CA (and any other
locally-trusted CA) is already in that store - no user action
needed, and no need to disable validation at all. IRIS_INSECURE/IRIS_TLS_VERIFYare a blunter existing workaround -
document them in docs/connecting.md's env var table regardless, but
the native-roots fix above should make them unnecessary for this
case.
Repro
Verified this against a real Web Gateway container - no IRIS instance
behind it is even needed, since the failure happens before any HTTP
request completes. A bare container = "..." config wouldn't have
discovered this setup either: the IRIS container itself publishes no
web port of its own, only the gateway does, so docker-based
auto-discovery has nothing to find.
-
Issue a cert with mkcert, which installs its root CA into the OS
trust store automatically:mkcert -cert-file cert/webcert.pem -key-file cert/webkey.pem localhost 127.0.0.1 -
Run a Web Gateway container terminating TLS with it:
docker run -d -p 9443:443 \ -v ./cert/webcert.pem:/irissys/tls/webgateway/tls.crt \ -v ./cert/webkey.pem:/irissys/tls/webgateway/tls.key \ containers.intersystems.com/intersystems/webgateway:2025.2 --ssl -
.iris-agentic-dev.toml:host = "localhost" web_port = 9443 scheme = "https" -
curl -v https://localhost:9443/api/atelier/completes the TLS
handshake cleanly (cert verified, TLS 1.3) and only times out
afterward, waiting on a response nothing is configured to send.
iris-agentic-dev tool iris_info --args '{"what":"namespace"}'
fails immediately instead (~35ms):error: HTTP error: error sending request for url (https://localhost:9443/api/atelier/v1/USER)Setting
IRIS_INSECURE=truechanges that failure into the same
hang curl gets - confirming the difference is exactly the TLS
trust step, not anything HTTP-level. (check_configwon't show
this either way - it makes no network calls, so it reports
whatever config resolved without ever testing reachability.)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reqwest feature declaration in Cargo.toml and the http_client implementation in connection.rs, then inspect WorkspaceConfig in workspace_config.rs and the environment-variable table in docs/connecting.md. Confirm that the REST client trusts OS roots like the websocket client, while the existing IRIS_INSECURE and IRIS_TLS_VERIFY workarounds are documented; verify the change against the mkcert HTTPS reproduction described here.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend, security
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100