Repository navigation
Credentials as placeholders, put on by the proxy for bound hosts only - #42
Merged
Merged
Conversation
`--credential NAME=HOST[/path]` and `[[credentials]]` hand the command a placeholder, porta-cred-NAME-<random>, instead of the key. The real value, read from porta's environment, stays in porta. A credential turns the proxy on; for a bound host the proxy terminates the command's TLS with a certificate from a CA made for this run, puts the value where the placeholder is (request line, query, headers), and sends the request on over its own TLS connection verified against the webpki roots. The same placeholder on a path it is not bound to is refused with 403 before anything is sent. Substitutions and refusals are recorded by name, never by value. Hosts no credential names are tunnelled as before. The command trusts the CA through SSL_CERT_FILE, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE and GIT_SSL_CAINFO (system roots plus the CA) and NODE_EXTRA_CA_CERTS (the CA alone). The CA lives for a week, in memory; its files are removed when the proxy stops. rustls and rcgen on ring, the provider reqwest already builds: no second crypto library and no OpenSSL. PORTA_TEST_UPSTREAM(_CA) lets the integration suite send a CONNECT to a local server; it is read from porta's own environment. Closes #37 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
CI's code-quality floor (90) failed at 89: credential_broker.rs was one 488-line file with a deeply nested body copier and five-parameter functions, http_proxy.rs had passed 300 lines, and so had cli.almd. - credential_broker.rs keeps the credentials and where each may go; credential_broker/tls.rs makes the run's CA, its leaves, the trust bundle and the upstream verifier; credential_broker/exchange.rs carries one intercepted request; the unit tests move to credential_broker/tests.rs. A Target (host, port) replaces the separate arguments. - The tunnel and wt_is_host_allowed move beside the dial in proxy_egress.rs; the proxy's setup with credentials is one function. - The TOML quoting helpers move to util.almd; --credential parsing and the saved [[credentials]] tables to proxy.almd. No behaviour change: 163 Almide tests, 5 broker unit tests, the whole integration suite and escapes.py pass as before; codopsy grades 90 (A). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This was referenced Sep 28, 2026
O6lvl4
added a commit
to O6lvl4/comide
that referenced
this pull request
Sep 28, 2026
onogoro's default hands golemide placeholders through porta's credential broker, which needs porta with --credential (almide/porta#42) and an Almide whose HTTP client honours HTTPS_PROXY and a proxy's CA (almide/almide#2833). Neither is released, so the bundle names the commits. porta's develop is rustls only, so the sed for #35 goes; the build checks --credential is there. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This was referenced Sep 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #37.
What it does
--credential NAME=HOST[,HOST](repeatable) and[[credentials]]in porta.toml (name,from = { env = "..." },hosts = ["host[:443][/path]"]). The command'sNAMEisporta-cred-NAME-<random>, minted per run. The real value is read from porta's environment and never enters the child's environment or any log.--proxy-allow, every host is reachable through it.HTTPS_PROXYas today.Authorization: Bearer …andx-api-keyboth work, and sends the request on over its own TLS connection verified against the webpki roots.substituteanddenydecisions go to stderr and the--proxy-auditJSONL with the credential's name, never its value.SSL_CERT_FILE,REQUESTS_CA_BUNDLE,CURL_CA_BUNDLEandGIT_SSL_CAINFOpoint at a bundle holding the system roots plus the run CA, because those variables replace the trust store.NODE_EXTRA_CA_CERTSpoints at the CA alone./tmp/porta-credentials-*are removed when the proxy stops.explain --savewrites[[credentials]]tables: where each credential goes and which variable it comes from, never the value.Design notes
native/credential_broker.rsholds the placeholders and bindings, the head rewrite, the CA and leaf minting, and the intercept/forward loop.rustls0.23 andrcgen0.13 run onring, the provider reqwest's rustls already builds. There is no second crypto library and no OpenSSL.Connection: closeand closes the client's side after the response, so it never has to find response boundaries. ALPN offershttp/1.1only.PORTA_TEST_UPSTREAM=host=127.0.0.1:port,...andPORTA_TEST_UPSTREAM_CAare read from porta's own environment, not the child's. They let the integration suite send a CONNECT to a local TLS server past the address guard. They are documented at the function.Left for later
headerfield that puts the key on a named header even when the request does not carry the placeholder.binaries = [...], issue item 5).Verified (macOS, Apple silicon, pinned Almide 0.63.0)
almide test: 163 tests in 9 files pass, including new proxy/CLI tests (a credential enables the proxy,--credentialparsing,explain --saveoutput).cargo test credential_brokerin the generated crate): 5 passed. They cover binding parsing and the non-443 refusal, bound/unbound substitution, pass-through with no placeholder, the outgoing head and framing, and date arithmetic.scripts/integration.py: 29 PASS, and 1 SKIP that is not new (the WASI component test skips when.tools/almideis absent from the copy). The new end-to-end test covers:/admingets 403 and never reaches the server;substituteanddenylines, and the value appears in neither the audit, stderr nor stdout;scripts/escapes.py: every attempt held./usr/bin/curlthrough--credential BOGUS_KEY=api.anthropic.comgot 401 from Anthropic, meaning the placeholder was replaced and upstream TLS was verified;https://example.comin the same run was tunnelled and verified (200);porta upwith a[[credentials]]table works, and the CA directory is gone afterwards.No OpenSSL linked, unit tests, integration, escapes, monkey, and the code-quality floor, now 90 (A). The first push fell to 89; the second commit splits the broker intocredential_broker/{tls,exchange,tests}.rswith no change in behaviour.🤖 Generated with Claude Code