feat: add optional native-tls support as alternative to rustls (#8037)
Signed-off-by: Rodolfo Olivieri <rolivier@redhat.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -97,9 +97,6 @@ jobs:
|
|||||||
export CARGO_INCREMENTAL=0
|
export CARGO_INCREMENTAL=0
|
||||||
cargo clippy --workspace --all-targets --exclude v8 -- -D warnings
|
cargo clippy --workspace --all-targets --exclude v8 -- -D warnings
|
||||||
|
|
||||||
- name: Check for banned TLS crates
|
|
||||||
run: ./scripts/check-no-native-tls.sh
|
|
||||||
|
|
||||||
openapi-schema-check:
|
openapi-schema-check:
|
||||||
name: Check OpenAPI Schema is Up-to-Date
|
name: Check OpenAPI Schema is Up-to-Date
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
Generated
+279
-11
@@ -164,7 +164,7 @@ version = "1.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -175,7 +175,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"once_cell_polyfill",
|
"once_cell_polyfill",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -823,10 +823,13 @@ dependencies = [
|
|||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"hyper 1.8.1",
|
"hyper 1.8.1",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
|
"openssl",
|
||||||
|
"openssl-sys",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-openssl",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
@@ -852,6 +855,12 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base16ct"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base32"
|
name = "base32"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -2330,6 +2339,18 @@ version = "0.2.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-bigint"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@@ -2371,6 +2392,33 @@ dependencies = [
|
|||||||
"libloading 0.9.0",
|
"libloading 0.9.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek"
|
||||||
|
version = "4.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures 0.2.17",
|
||||||
|
"curve25519-dalek-derive",
|
||||||
|
"digest",
|
||||||
|
"fiat-crypto",
|
||||||
|
"rustc_version",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "curve25519-dalek-derive"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.20.11"
|
version = "0.20.11"
|
||||||
@@ -3075,7 +3123,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users 0.5.2",
|
"redox_users 0.5.2",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3215,6 +3263,20 @@ dependencies = [
|
|||||||
"cipher",
|
"cipher",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ecdsa"
|
||||||
|
version = "0.16.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
|
||||||
|
dependencies = [
|
||||||
|
"der",
|
||||||
|
"digest",
|
||||||
|
"elliptic-curve",
|
||||||
|
"rfc6979",
|
||||||
|
"signature",
|
||||||
|
"spki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ecow"
|
name = "ecow"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
@@ -3224,6 +3286,30 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ed25519"
|
||||||
|
version = "2.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
||||||
|
dependencies = [
|
||||||
|
"pkcs8",
|
||||||
|
"signature",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ed25519-dalek"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
|
||||||
|
dependencies = [
|
||||||
|
"curve25519-dalek",
|
||||||
|
"ed25519",
|
||||||
|
"serde",
|
||||||
|
"sha2",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
@@ -3233,6 +3319,27 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "elliptic-curve"
|
||||||
|
version = "0.13.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"crypto-bigint",
|
||||||
|
"digest",
|
||||||
|
"ff",
|
||||||
|
"generic-array",
|
||||||
|
"group",
|
||||||
|
"hkdf",
|
||||||
|
"pem-rfc7468",
|
||||||
|
"pkcs8",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"sec1",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "email_address"
|
name = "email_address"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
@@ -3325,7 +3432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3472,6 +3579,22 @@ dependencies = [
|
|||||||
"simd-adler32",
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ff"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fiat-crypto"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filetime"
|
name = "filetime"
|
||||||
version = "0.2.27"
|
version = "0.2.27"
|
||||||
@@ -4073,6 +4196,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
"version_check",
|
"version_check",
|
||||||
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4226,6 +4350,9 @@ dependencies = [
|
|||||||
"opentelemetry_sdk",
|
"opentelemetry_sdk",
|
||||||
"pastey",
|
"pastey",
|
||||||
"pctx_code_mode",
|
"pctx_code_mode",
|
||||||
|
"pem",
|
||||||
|
"pkcs1",
|
||||||
|
"pkcs8",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rayon",
|
"rayon",
|
||||||
@@ -4235,6 +4362,7 @@ dependencies = [
|
|||||||
"rubato",
|
"rubato",
|
||||||
"sacp",
|
"sacp",
|
||||||
"schemars 1.2.1",
|
"schemars 1.2.1",
|
||||||
|
"sec1",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
@@ -4428,6 +4556,7 @@ dependencies = [
|
|||||||
"goose-mcp",
|
"goose-mcp",
|
||||||
"hex",
|
"hex",
|
||||||
"http 1.4.0",
|
"http 1.4.0",
|
||||||
|
"openssl",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
"reqwest 0.13.2",
|
"reqwest 0.13.2",
|
||||||
@@ -4475,6 +4604,17 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "group"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
||||||
|
dependencies = [
|
||||||
|
"ff",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gzip-header"
|
name = "gzip-header"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@@ -4811,6 +4951,22 @@ dependencies = [
|
|||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-tls"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper 1.8.1",
|
||||||
|
"hyper-util",
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.20"
|
version = "0.1.20"
|
||||||
@@ -5282,7 +5438,7 @@ dependencies = [
|
|||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
"portable-atomic-util",
|
"portable-atomic-util",
|
||||||
"serde_core",
|
"serde_core",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5479,11 +5635,18 @@ checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
"ed25519-dalek",
|
||||||
"getrandom 0.2.17",
|
"getrandom 0.2.17",
|
||||||
|
"hmac",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
"p256",
|
||||||
|
"p384",
|
||||||
"pem",
|
"pem",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"rsa",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"signature",
|
"signature",
|
||||||
"simple_asn1",
|
"simple_asn1",
|
||||||
]
|
]
|
||||||
@@ -5958,6 +6121,23 @@ dependencies = [
|
|||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "native-tls"
|
||||||
|
version = "0.2.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"openssl",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"security-framework 3.7.0",
|
||||||
|
"security-framework-sys",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk-context"
|
name = "ndk-context"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -6070,7 +6250,7 @@ version = "0.50.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6518,6 +6698,30 @@ version = "0.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e"
|
checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p256"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
|
||||||
|
dependencies = [
|
||||||
|
"ecdsa",
|
||||||
|
"elliptic-curve",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "p384"
|
||||||
|
version = "0.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6"
|
||||||
|
dependencies = [
|
||||||
|
"ecdsa",
|
||||||
|
"elliptic-curve",
|
||||||
|
"primeorder",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "par-core"
|
name = "par-core"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@@ -7051,6 +7255,15 @@ dependencies = [
|
|||||||
"num-integer",
|
"num-integer",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "primeorder"
|
||||||
|
version = "0.13.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
|
||||||
|
dependencies = [
|
||||||
|
"elliptic-curve",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@@ -7630,9 +7843,11 @@ dependencies = [
|
|||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper 1.8.1",
|
"hyper 1.8.1",
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
|
"hyper-tls",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
|
"native-tls",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn",
|
"quinn",
|
||||||
@@ -7643,6 +7858,7 @@ dependencies = [
|
|||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
@@ -7674,11 +7890,13 @@ dependencies = [
|
|||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper 1.8.1",
|
"hyper 1.8.1",
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
|
"hyper-tls",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"mime",
|
"mime",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
|
"native-tls",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn",
|
"quinn",
|
||||||
@@ -7690,6 +7908,7 @@ dependencies = [
|
|||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tower",
|
"tower",
|
||||||
@@ -7712,6 +7931,16 @@ dependencies = [
|
|||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rfc6979"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
|
||||||
|
dependencies = [
|
||||||
|
"hmac",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rgb"
|
name = "rgb"
|
||||||
version = "0.8.53"
|
version = "0.8.53"
|
||||||
@@ -7909,7 +8138,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.12.1",
|
"linux-raw-sys 0.12.1",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7968,7 +8197,7 @@ dependencies = [
|
|||||||
"security-framework 3.7.0",
|
"security-framework 3.7.0",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -8180,6 +8409,20 @@ version = "3.0.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
|
checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sec1"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"der",
|
||||||
|
"generic-array",
|
||||||
|
"pkcs8",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.11.1"
|
version = "2.11.1"
|
||||||
@@ -8759,7 +9002,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
|
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -8852,6 +9095,7 @@ dependencies = [
|
|||||||
"indexmap 2.13.0",
|
"indexmap 2.13.0",
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
"native-tls",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rustls",
|
"rustls",
|
||||||
@@ -9897,7 +10141,7 @@ dependencies = [
|
|||||||
"getrandom 0.4.2",
|
"getrandom 0.4.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.1.4",
|
"rustix 1.1.4",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -10304,6 +10548,27 @@ dependencies = [
|
|||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-native-tls"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||||
|
dependencies = [
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-openssl"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59df6849caa43bb7567f9a36f863c447d95a11d5903c9cc334ba32576a27eadd"
|
||||||
|
dependencies = [
|
||||||
|
"openssl",
|
||||||
|
"openssl-sys",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-rustls"
|
name = "tokio-rustls"
|
||||||
version = "0.26.4"
|
version = "0.26.4"
|
||||||
@@ -10333,10 +10598,12 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"log",
|
"log",
|
||||||
|
"native-tls",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
]
|
]
|
||||||
@@ -10785,6 +11052,7 @@ dependencies = [
|
|||||||
"http 1.4.0",
|
"http 1.4.0",
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
|
"native-tls",
|
||||||
"rand 0.9.2",
|
"rand 0.9.2",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@@ -11462,7 +11730,7 @@ version = "0.1.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -11,8 +11,6 @@ check-everything:
|
|||||||
cargo fmt --all
|
cargo fmt --all
|
||||||
@echo " → Running clippy linting..."
|
@echo " → Running clippy linting..."
|
||||||
cargo clippy --all-targets -- -D warnings
|
cargo clippy --all-targets -- -D warnings
|
||||||
@echo " → Checking for banned TLS crates..."
|
|
||||||
./scripts/check-no-native-tls.sh
|
|
||||||
@echo " → Checking UI code formatting..."
|
@echo " → Checking UI code formatting..."
|
||||||
cd ui/desktop && pnpm run lint:check
|
cd ui/desktop && pnpm run lint:check
|
||||||
@echo " → Validating OpenAPI schema..."
|
@echo " → Validating OpenAPI schema..."
|
||||||
|
|||||||
@@ -16,15 +16,17 @@ name = "generate-acp-schema"
|
|||||||
path = "src/bin/generate_acp_schema.rs"
|
path = "src/bin/generate_acp_schema.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["code-mode"]
|
default = ["code-mode", "rustls-tls"]
|
||||||
code-mode = ["goose/code-mode"]
|
code-mode = ["goose/code-mode"]
|
||||||
|
rustls-tls = ["goose/rustls-tls", "goose-mcp/rustls-tls"]
|
||||||
|
native-tls = ["goose/native-tls", "goose-mcp/native-tls"]
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
goose = { path = "../goose", default-features = false }
|
goose = { path = "../goose", default-features = false }
|
||||||
goose-mcp = { path = "../goose-mcp" }
|
goose-mcp = { path = "../goose-mcp", default-features = false }
|
||||||
rmcp = { workspace = true }
|
rmcp = { workspace = true }
|
||||||
sacp = { workspace = true, features = ["unstable"] }
|
sacp = { workspace = true, features = ["unstable"] }
|
||||||
agent-client-protocol-schema = { workspace = true }
|
agent-client-protocol-schema = { workspace = true }
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ async-trait = { workspace = true }
|
|||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
tar = "0.4.45"
|
tar = "0.4.45"
|
||||||
reqwest = { workspace = true, features = ["blocking", "rustls"], default-features = false }
|
reqwest = { workspace = true, features = ["blocking"], default-features = false }
|
||||||
zip = { workspace = true }
|
zip = { workspace = true }
|
||||||
bzip2 = "0.5"
|
bzip2 = "0.5"
|
||||||
webbrowser = { workspace = true }
|
webbrowser = { workspace = true }
|
||||||
@@ -62,19 +62,31 @@ urlencoding = { workspace = true }
|
|||||||
clap_complete = "4.5.62"
|
clap_complete = "4.5.62"
|
||||||
comfy-table = "7.2.2"
|
comfy-table = "7.2.2"
|
||||||
sha2 = { workspace = true }
|
sha2 = { workspace = true }
|
||||||
sigstore-verify = { version = "0.6", default-features = false, features = ["rustls"] }
|
sigstore-verify = { version = "0.6", default-features = false }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { workspace = true }
|
winapi = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["code-mode", "local-inference", "aws-providers"]
|
default = ["code-mode", "local-inference", "aws-providers", "rustls-tls"]
|
||||||
code-mode = ["goose/code-mode", "goose-acp/code-mode"]
|
code-mode = ["goose/code-mode", "goose-acp/code-mode"]
|
||||||
local-inference = ["goose/local-inference"]
|
local-inference = ["goose/local-inference"]
|
||||||
aws-providers = ["goose/aws-providers"]
|
aws-providers = ["goose/aws-providers"]
|
||||||
cuda = ["goose/cuda", "local-inference"]
|
cuda = ["goose/cuda", "local-inference"]
|
||||||
# disables the update command
|
# disables the update command
|
||||||
disable-update = []
|
disable-update = []
|
||||||
|
rustls-tls = [
|
||||||
|
"reqwest/rustls",
|
||||||
|
"sigstore-verify/rustls",
|
||||||
|
"goose/rustls-tls",
|
||||||
|
"goose-mcp/rustls-tls",
|
||||||
|
]
|
||||||
|
native-tls = [
|
||||||
|
"reqwest/native-tls",
|
||||||
|
"sigstore-verify/native-tls",
|
||||||
|
"goose/native-tls",
|
||||||
|
"goose-mcp/native-tls",
|
||||||
|
]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))]
|
||||||
|
compile_error!("At least one of `rustls-tls` or `native-tls` features must be enabled");
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rustls-tls", feature = "native-tls"))]
|
||||||
|
compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive");
|
||||||
|
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ description.workspace = true
|
|||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
rustls-tls = ["reqwest/rustls"]
|
||||||
|
native-tls = ["reqwest/native-tls"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rmcp = { workspace = true, features = ["server", "client", "transport-io", "macros"] }
|
rmcp = { workspace = true, features = ["server", "client", "transport-io", "macros"] }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
@@ -23,7 +27,7 @@ serde = { workspace = true }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
schemars = { workspace = true }
|
schemars = { workspace = true }
|
||||||
indoc = { workspace = true }
|
indoc = { workspace = true }
|
||||||
reqwest = { workspace = true, features = ["json", "rustls", "system-proxy"], default-features = false }
|
reqwest = { workspace = true, features = ["json", "system-proxy"], default-features = false }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
etcetera = { workspace = true }
|
etcetera = { workspace = true }
|
||||||
tempfile = { workspace = true }
|
tempfile = { workspace = true }
|
||||||
|
|||||||
@@ -11,11 +11,28 @@ description.workspace = true
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["code-mode", "local-inference", "aws-providers"]
|
default = ["code-mode", "local-inference", "aws-providers", "rustls-tls"]
|
||||||
code-mode = ["goose/code-mode"]
|
code-mode = ["goose/code-mode"]
|
||||||
local-inference = ["goose/local-inference"]
|
local-inference = ["goose/local-inference"]
|
||||||
aws-providers = ["goose/aws-providers"]
|
aws-providers = ["goose/aws-providers"]
|
||||||
cuda = ["goose/cuda", "local-inference"]
|
cuda = ["goose/cuda", "local-inference"]
|
||||||
|
rustls-tls = [
|
||||||
|
"reqwest/rustls",
|
||||||
|
"tokio-tungstenite/rustls-tls-native-roots",
|
||||||
|
"axum-server/tls-rustls",
|
||||||
|
"dep:rustls",
|
||||||
|
"dep:aws-lc-rs",
|
||||||
|
"goose/rustls-tls",
|
||||||
|
"goose-mcp/rustls-tls",
|
||||||
|
]
|
||||||
|
native-tls = [
|
||||||
|
"reqwest/native-tls",
|
||||||
|
"tokio-tungstenite/native-tls",
|
||||||
|
"axum-server/tls-openssl",
|
||||||
|
"dep:openssl",
|
||||||
|
"goose/native-tls",
|
||||||
|
"goose-mcp/native-tls",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
goose = { path = "../goose", default-features = false }
|
goose = { path = "../goose", default-features = false }
|
||||||
@@ -41,21 +58,22 @@ thiserror = { workspace = true }
|
|||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
serde_yaml = { workspace = true }
|
serde_yaml = { workspace = true }
|
||||||
utoipa = { workspace = true, features = ["axum_extras", "chrono"] }
|
utoipa = { workspace = true, features = ["axum_extras", "chrono"] }
|
||||||
reqwest = { workspace = true, features = ["json", "rustls", "blocking", "multipart", "system-proxy"], default-features = false }
|
reqwest = { workspace = true, features = ["json", "blocking", "multipart", "system-proxy"], default-features = false }
|
||||||
tokio-util = { workspace = true }
|
tokio-util = { workspace = true }
|
||||||
serde_path_to_error = "0.1.20"
|
serde_path_to_error = "0.1.20"
|
||||||
tokio-tungstenite = { version = "0.28.0", features = ["rustls-tls-native-roots"] }
|
tokio-tungstenite = { version = "0.28.0" }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
subtle = "2.6"
|
subtle = "2.6"
|
||||||
socket2 = "0.6.1"
|
socket2 = "0.6.1"
|
||||||
fs2 = { workspace = true }
|
fs2 = { workspace = true }
|
||||||
rustls = { version = "0.23", features = ["aws_lc_rs"] }
|
rustls = { version = "0.23", features = ["aws_lc_rs"], optional = true }
|
||||||
uuid = { workspace = true }
|
uuid = { workspace = true }
|
||||||
rcgen = "0.13"
|
rcgen = "0.13"
|
||||||
axum-server = { version = "0.8.0", features = ["tls-rustls"] }
|
axum-server = { version = "0.8.0" }
|
||||||
aws-lc-rs = "1.16.0"
|
aws-lc-rs = { version = "1.16.0", optional = true }
|
||||||
|
openssl = { version = "0.10", optional = true }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winreg = { version = "0.55.0" }
|
winreg = { version = "0.55.0" }
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use anyhow::Result;
|
|||||||
use axum::middleware;
|
use axum::middleware;
|
||||||
use axum_server::Handle;
|
use axum_server::Handle;
|
||||||
use goose_server::auth::check_token;
|
use goose_server::auth::check_token;
|
||||||
|
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
|
||||||
use goose_server::tls::self_signed_config;
|
use goose_server::tls::self_signed_config;
|
||||||
use tower_http::cors::{Any, CorsLayer};
|
use tower_http::cors::{Any, CorsLayer};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
@@ -31,6 +32,7 @@ pub async fn run() -> Result<()> {
|
|||||||
// gateways, etc.) try to open TLS connections. Both `ring` and `aws-lc-rs`
|
// gateways, etc.) try to open TLS connections. Both `ring` and `aws-lc-rs`
|
||||||
// features are enabled on rustls (via different transitive deps), so rustls
|
// features are enabled on rustls (via different transitive deps), so rustls
|
||||||
// cannot auto-detect a provider — we must pick one explicitly.
|
// cannot auto-detect a provider — we must pick one explicitly.
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||||
|
|
||||||
crate::logging::setup_logging(Some("goosed"))?;
|
crate::logging::setup_logging(Some("goosed"))?;
|
||||||
@@ -74,21 +76,39 @@ pub async fn run() -> Result<()> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if settings.tls {
|
if settings.tls {
|
||||||
let tls_setup = self_signed_config().await?;
|
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
|
||||||
|
{
|
||||||
|
let tls_setup = self_signed_config().await?;
|
||||||
|
|
||||||
let handle = Handle::new();
|
let handle = Handle::new();
|
||||||
let shutdown_handle = handle.clone();
|
let shutdown_handle = handle.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
shutdown_signal().await;
|
shutdown_signal().await;
|
||||||
shutdown_handle.graceful_shutdown(None);
|
shutdown_handle.graceful_shutdown(None);
|
||||||
});
|
});
|
||||||
|
|
||||||
info!("listening on https://{}", addr);
|
info!("listening on https://{}", addr);
|
||||||
|
|
||||||
axum_server::bind_rustls(addr, tls_setup.config)
|
#[cfg(feature = "rustls-tls")]
|
||||||
.handle(handle)
|
axum_server::bind_rustls(addr, tls_setup.config)
|
||||||
.serve(app.into_make_service())
|
.handle(handle)
|
||||||
.await?;
|
.serve(app.into_make_service())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
#[cfg(feature = "native-tls")]
|
||||||
|
axum_server::bind_openssl(addr, tls_setup.config)
|
||||||
|
.handle(handle)
|
||||||
|
.serve(app.into_make_service())
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))]
|
||||||
|
{
|
||||||
|
anyhow::bail!(
|
||||||
|
"TLS was requested but no TLS backend is enabled. \
|
||||||
|
Enable the `rustls-tls` or `native-tls` feature."
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let listener = tokio::net::TcpListener::bind(addr).await?;
|
let listener = tokio::net::TcpListener::bind(addr).await?;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))]
|
||||||
|
compile_error!("At least one of `rustls-tls` or `native-tls` features must be enabled");
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rustls-tls", feature = "native-tls"))]
|
||||||
|
compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive");
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod configuration;
|
pub mod configuration;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
@@ -5,6 +11,7 @@ pub mod openapi;
|
|||||||
pub mod routes;
|
pub mod routes;
|
||||||
pub mod session_event_bus;
|
pub mod session_event_bus;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
|
||||||
pub mod tls;
|
pub mod tls;
|
||||||
pub mod tunnel;
|
pub mod tunnel;
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,31 @@
|
|||||||
|
//! TLS configuration for the goose server.
|
||||||
|
//!
|
||||||
|
//! Two TLS backends are supported for the HTTPS listener via `axum-server`:
|
||||||
|
//!
|
||||||
|
//! - **`rustls-tls`** (enabled by default) – uses `axum-server/tls-rustls` with
|
||||||
|
//! the `aws-lc-rs` crypto provider.
|
||||||
|
//! - **`native-tls`** – uses `axum-server/tls-openssl`, which links against the
|
||||||
|
//! platform's OpenSSL (or a compatible fork such as LibreSSL / BoringSSL).
|
||||||
|
//! On Linux this *is* the platform-native TLS stack; on macOS/Windows the
|
||||||
|
//! `native-tls` crate used by the HTTP *client* delegates to Security.framework
|
||||||
|
//! / SChannel respectively, but `axum-server` does not offer those backends so
|
||||||
|
//! the server listener always uses OpenSSL when this feature is active.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use aws_lc_rs::digest;
|
|
||||||
use axum_server::tls_rustls::RustlsConfig;
|
|
||||||
use rcgen::{CertificateParams, DnType, KeyPair, SanType};
|
use rcgen::{CertificateParams, DnType, KeyPair, SanType};
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
pub type TlsConfig = axum_server::tls_rustls::RustlsConfig;
|
||||||
|
|
||||||
|
#[cfg(feature = "native-tls")]
|
||||||
|
pub type TlsConfig = axum_server::tls_openssl::OpenSSLConfig;
|
||||||
|
|
||||||
pub struct TlsSetup {
|
pub struct TlsSetup {
|
||||||
pub config: RustlsConfig,
|
pub config: TlsConfig,
|
||||||
pub fingerprint: String,
|
pub fingerprint: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a self-signed TLS certificate for localhost (127.0.0.1) and
|
fn generate_self_signed_cert() -> Result<(rcgen::Certificate, KeyPair)> {
|
||||||
/// return a [`TlsSetup`] containing the rustls config and the SHA-256
|
|
||||||
/// fingerprint of the generated certificate (colon-separated hex).
|
|
||||||
///
|
|
||||||
/// The fingerprint is printed to stdout so the parent process (e.g. Electron)
|
|
||||||
/// can pin it and reject connections from any other certificate.
|
|
||||||
pub async fn self_signed_config() -> Result<TlsSetup> {
|
|
||||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
|
||||||
|
|
||||||
let mut params = CertificateParams::default();
|
let mut params = CertificateParams::default();
|
||||||
params
|
params
|
||||||
.distinguished_name
|
.distinguished_name
|
||||||
@@ -28,22 +37,62 @@ pub async fn self_signed_config() -> Result<TlsSetup> {
|
|||||||
|
|
||||||
let key_pair = KeyPair::generate()?;
|
let key_pair = KeyPair::generate()?;
|
||||||
let cert = params.self_signed(&key_pair)?;
|
let cert = params.self_signed(&key_pair)?;
|
||||||
|
Ok((cert, key_pair))
|
||||||
|
}
|
||||||
|
|
||||||
let cert_der = cert.der();
|
fn sha256_fingerprint(der: &[u8]) -> String {
|
||||||
let sha256 = digest::digest(&digest::SHA256, cert_der);
|
#[cfg(feature = "rustls-tls")]
|
||||||
let fingerprint = sha256
|
{
|
||||||
.as_ref()
|
let sha256 = aws_lc_rs::digest::digest(&aws_lc_rs::digest::SHA256, der);
|
||||||
.iter()
|
sha256
|
||||||
.map(|b| format!("{b:02X}"))
|
.as_ref()
|
||||||
.collect::<Vec<_>>()
|
.iter()
|
||||||
.join(":");
|
.map(|b| format!("{b:02X}"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(":")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "native-tls")]
|
||||||
|
{
|
||||||
|
use openssl::hash::MessageDigest;
|
||||||
|
let digest =
|
||||||
|
openssl::hash::hash(MessageDigest::sha256(), der).expect("SHA-256 hash failed");
|
||||||
|
digest
|
||||||
|
.iter()
|
||||||
|
.map(|b| format!("{b:02X}"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(":")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a self-signed TLS certificate for localhost (127.0.0.1) and
|
||||||
|
/// return a [`TlsSetup`] containing the server config and the SHA-256
|
||||||
|
/// fingerprint of the generated certificate (colon-separated hex).
|
||||||
|
///
|
||||||
|
/// The fingerprint is printed to stdout so the parent process (e.g. Electron)
|
||||||
|
/// can pin it and reject connections from any other certificate.
|
||||||
|
pub async fn self_signed_config() -> Result<TlsSetup> {
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||||
|
|
||||||
|
let (cert, key_pair) = generate_self_signed_cert()?;
|
||||||
|
|
||||||
|
let fingerprint = sha256_fingerprint(cert.der());
|
||||||
println!("GOOSED_CERT_FINGERPRINT={fingerprint}");
|
println!("GOOSED_CERT_FINGERPRINT={fingerprint}");
|
||||||
|
|
||||||
let cert_pem = cert.pem();
|
let cert_pem = cert.pem();
|
||||||
let key_pem = key_pair.serialize_pem();
|
let key_pem = key_pair.serialize_pem();
|
||||||
|
|
||||||
let config = RustlsConfig::from_pem(cert_pem.into_bytes(), key_pem.into_bytes()).await?;
|
#[cfg(feature = "rustls-tls")]
|
||||||
|
let config = axum_server::tls_rustls::RustlsConfig::from_pem(
|
||||||
|
cert_pem.into_bytes(),
|
||||||
|
key_pem.into_bytes(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
#[cfg(feature = "native-tls")]
|
||||||
|
let config =
|
||||||
|
axum_server::tls_openssl::OpenSSLConfig::from_pem(cert_pem.as_bytes(), key_pem.as_bytes())?;
|
||||||
|
|
||||||
Ok(TlsSetup {
|
Ok(TlsSetup {
|
||||||
config,
|
config,
|
||||||
|
|||||||
@@ -485,6 +485,7 @@ async fn run_single_connection(
|
|||||||
scheme: String,
|
scheme: String,
|
||||||
restart_tx: mpsc::Sender<()>,
|
restart_tx: mpsc::Sender<()>,
|
||||||
) {
|
) {
|
||||||
|
#[cfg(feature = "rustls-tls")]
|
||||||
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
|
||||||
|
|
||||||
let worker_url = get_worker_url();
|
let worker_url = get_worker_url();
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
use goose_server::tls::{self_signed_config, TlsConfig};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "native-tls"))]
|
||||||
|
#[test]
|
||||||
|
fn default_tls_config_is_rustls() {
|
||||||
|
fn assert_type<T>(_: &T) {}
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
let setup = rt.block_on(self_signed_config()).unwrap();
|
||||||
|
// Proves TlsConfig resolves to RustlsConfig when native-tls is disabled.
|
||||||
|
let _: &axum_server::tls_rustls::RustlsConfig = &setup.config;
|
||||||
|
assert_type::<TlsConfig>(&setup.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "native-tls")]
|
||||||
|
#[test]
|
||||||
|
fn native_tls_config_is_openssl() {
|
||||||
|
fn assert_type<T>(_: &T) {}
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
let setup = rt.block_on(self_signed_config()).unwrap();
|
||||||
|
// Proves TlsConfig resolves to OpenSSLConfig when native-tls is enabled.
|
||||||
|
let _: &axum_server::tls_openssl::OpenSSLConfig = &setup.config;
|
||||||
|
assert_type::<TlsConfig>(&setup.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn self_signed_config_produces_valid_fingerprint() {
|
||||||
|
let setup = self_signed_config().await.unwrap();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
!setup.fingerprint.is_empty(),
|
||||||
|
"fingerprint must not be empty"
|
||||||
|
);
|
||||||
|
|
||||||
|
let parts: Vec<&str> = setup.fingerprint.split(':').collect();
|
||||||
|
assert_eq!(
|
||||||
|
parts.len(),
|
||||||
|
32,
|
||||||
|
"SHA-256 fingerprint must have 32 hex pairs"
|
||||||
|
);
|
||||||
|
|
||||||
|
for part in &parts {
|
||||||
|
assert_eq!(
|
||||||
|
part.len(),
|
||||||
|
2,
|
||||||
|
"each fingerprint segment must be 2 hex chars"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
part.chars().all(|c| c.is_ascii_hexdigit()),
|
||||||
|
"fingerprint segment '{}' must be valid hex",
|
||||||
|
part
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn self_signed_config_returns_usable_tls_config() {
|
||||||
|
use axum::routing::get;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
let setup = self_signed_config().await.unwrap();
|
||||||
|
|
||||||
|
let app = axum::Router::new().route("/health", get(|| async { "ok" }));
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], 0));
|
||||||
|
|
||||||
|
#[cfg(not(feature = "native-tls"))]
|
||||||
|
let server = axum_server::bind_rustls(addr, setup.config);
|
||||||
|
|
||||||
|
#[cfg(feature = "native-tls")]
|
||||||
|
let server = axum_server::bind_openssl(addr, setup.config);
|
||||||
|
|
||||||
|
let handle = axum_server::Handle::new();
|
||||||
|
let shutdown_handle = handle.clone();
|
||||||
|
|
||||||
|
let server_handle = tokio::spawn({
|
||||||
|
let handle = handle.clone();
|
||||||
|
async move {
|
||||||
|
server
|
||||||
|
.handle(handle)
|
||||||
|
.serve(app.into_make_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for the server to start listening.
|
||||||
|
let listening_addr = loop {
|
||||||
|
if let Some(addr) = handle.listening().await {
|
||||||
|
break addr;
|
||||||
|
}
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
|
||||||
|
};
|
||||||
|
|
||||||
|
let client = reqwest::Client::builder()
|
||||||
|
.danger_accept_invalid_certs(true)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let resp = client
|
||||||
|
.get(format!("https://{}/health", listening_addr))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(resp.status(), 200);
|
||||||
|
assert_eq!(resp.text().await.unwrap(), "ok");
|
||||||
|
|
||||||
|
shutdown_handle.graceful_shutdown(None);
|
||||||
|
let _ = server_handle.await;
|
||||||
|
}
|
||||||
+28
-6
@@ -8,7 +8,7 @@ repository.workspace = true
|
|||||||
description.workspace = true
|
description.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["code-mode", "local-inference", "aws-providers"]
|
default = ["code-mode", "local-inference", "aws-providers", "rustls-tls"]
|
||||||
code-mode = ["dep:pctx_code_mode"]
|
code-mode = ["dep:pctx_code_mode"]
|
||||||
local-inference = [
|
local-inference = [
|
||||||
"dep:candle-core",
|
"dep:candle-core",
|
||||||
@@ -27,6 +27,26 @@ aws-providers = [
|
|||||||
"dep:aws-sdk-sagemakerruntime",
|
"dep:aws-sdk-sagemakerruntime",
|
||||||
]
|
]
|
||||||
cuda = ["local-inference", "candle-core/cuda", "candle-nn/cuda", "llama-cpp-2/cuda"]
|
cuda = ["local-inference", "candle-core/cuda", "candle-nn/cuda", "llama-cpp-2/cuda"]
|
||||||
|
rustls-tls = [
|
||||||
|
"reqwest/rustls",
|
||||||
|
"rmcp/reqwest",
|
||||||
|
"sqlx/runtime-tokio-rustls",
|
||||||
|
"jsonwebtoken/aws_lc_rs",
|
||||||
|
"oauth2/reqwest",
|
||||||
|
"oauth2/rustls-tls",
|
||||||
|
]
|
||||||
|
native-tls = [
|
||||||
|
"dep:pem",
|
||||||
|
"dep:pkcs1",
|
||||||
|
"dep:pkcs8",
|
||||||
|
"dep:sec1",
|
||||||
|
"reqwest/native-tls",
|
||||||
|
"rmcp/reqwest-native-tls",
|
||||||
|
"sqlx/runtime-tokio-native-tls",
|
||||||
|
"jsonwebtoken/rust_crypto",
|
||||||
|
"oauth2/reqwest",
|
||||||
|
"oauth2/native-tls",
|
||||||
|
]
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
@@ -35,17 +55,16 @@ workspace = true
|
|||||||
lru = { workspace = true }
|
lru = { workspace = true }
|
||||||
rmcp = { workspace = true, features = [
|
rmcp = { workspace = true, features = [
|
||||||
"client",
|
"client",
|
||||||
"reqwest",
|
|
||||||
"transport-child-process",
|
"transport-child-process",
|
||||||
"transport-streamable-http-client",
|
"transport-streamable-http-client",
|
||||||
"transport-streamable-http-client-reqwest",
|
"transport-streamable-http-client-reqwest",
|
||||||
] }
|
] }
|
||||||
oauth2 = "5.0"
|
oauth2 = { version = "5.0", default-features = false }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
reqwest = { workspace = true, features = ["rustls", "json", "cookies", "gzip", "brotli", "deflate", "zstd", "charset", "http2", "stream", "blocking", "multipart", "system-proxy"], default-features = false }
|
reqwest = { workspace = true, features = ["json", "cookies", "gzip", "brotli", "deflate", "zstd", "charset", "http2", "stream", "blocking", "multipart", "system-proxy"], default-features = false }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
@@ -94,7 +113,6 @@ tokio-cron-scheduler = "0.14.0"
|
|||||||
urlencoding = { workspace = true }
|
urlencoding = { workspace = true }
|
||||||
v_htmlescape = "0.15"
|
v_htmlescape = "0.15"
|
||||||
sqlx = { version = "0.8", default-features = false, features = [
|
sqlx = { version = "0.8", default-features = false, features = [
|
||||||
"runtime-tokio-rustls",
|
|
||||||
"sqlite",
|
"sqlite",
|
||||||
"chrono",
|
"chrono",
|
||||||
"json",
|
"json",
|
||||||
@@ -111,7 +129,7 @@ aws-sdk-bedrockruntime = { version = "=1.120.0", default-features = false, featu
|
|||||||
aws-sdk-sagemakerruntime = { version = "1.62.0", default-features = false, features = ["default-https-client", "rt-tokio"], optional = true }
|
aws-sdk-sagemakerruntime = { version = "1.62.0", default-features = false, features = ["default-https-client", "rt-tokio"], optional = true }
|
||||||
|
|
||||||
# For GCP Vertex AI provider auth
|
# For GCP Vertex AI provider auth
|
||||||
jsonwebtoken = { version = "10.3.0", features = ["aws_lc_rs"] }
|
jsonwebtoken = { version = "10.3.0", default-features = false, features = ["use_pem"] }
|
||||||
|
|
||||||
blake3 = "1.5"
|
blake3 = "1.5"
|
||||||
fs2 = { workspace = true }
|
fs2 = { workspace = true }
|
||||||
@@ -160,6 +178,10 @@ llama-cpp-2 = { version = "0.1.137", features = ["sampler"], optional = true }
|
|||||||
encoding_rs = "0.8.35"
|
encoding_rs = "0.8.35"
|
||||||
pastey = "0.2.1"
|
pastey = "0.2.1"
|
||||||
shell-words = { workspace = true }
|
shell-words = { workspace = true }
|
||||||
|
pem = { version = "3", optional = true }
|
||||||
|
pkcs1 = { version = "0.7", default-features = false, features = ["pkcs8"], optional = true }
|
||||||
|
pkcs8 = { version = "0.10", default-features = false, features = ["alloc"], optional = true }
|
||||||
|
sec1 = { version = "0.7", default-features = false, features = ["der", "pkcs8"], optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { workspace = true }
|
winapi = { workspace = true }
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))]
|
||||||
|
compile_error!("At least one of `rustls-tls` or `native-tls` features must be enabled");
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rustls-tls", feature = "native-tls"))]
|
||||||
|
compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive");
|
||||||
|
|
||||||
pub mod acp;
|
pub mod acp;
|
||||||
pub mod action_required_manager;
|
pub mod action_required_manager;
|
||||||
pub mod agents;
|
pub mod agents;
|
||||||
|
|||||||
@@ -119,12 +119,21 @@ impl TlsConfig {
|
|||||||
let key_pem = read_to_string(&cert_key_pair.key_path)
|
let key_pem = read_to_string(&cert_key_pair.key_path)
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to read client private key: {}", e))?;
|
.map_err(|e| anyhow::anyhow!("Failed to read client private key: {}", e))?;
|
||||||
|
|
||||||
// Create a combined PEM file with certificate and private key
|
#[cfg(not(feature = "native-tls"))]
|
||||||
let combined_pem = format!("{}\n{}", cert_pem, key_pem);
|
let identity = {
|
||||||
|
let combined_pem = format!("{}\n{}", cert_pem, key_pem);
|
||||||
|
Identity::from_pem(combined_pem.as_bytes()).map_err(|e| {
|
||||||
|
anyhow::anyhow!("Failed to create identity from cert and key: {}", e)
|
||||||
|
})?
|
||||||
|
};
|
||||||
|
|
||||||
let identity = Identity::from_pem(combined_pem.as_bytes()).map_err(|e| {
|
#[cfg(feature = "native-tls")]
|
||||||
anyhow::anyhow!("Failed to create identity from cert and key: {}", e)
|
let identity = {
|
||||||
})?;
|
let pkcs8_key_pem = convert_key_to_pkcs8_pem(&key_pem)?;
|
||||||
|
Identity::from_pkcs8_pem(cert_pem.as_bytes(), pkcs8_key_pem.as_bytes()).map_err(
|
||||||
|
|e| anyhow::anyhow!("Failed to create identity from cert and key: {}", e),
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Some(identity))
|
Ok(Some(identity))
|
||||||
} else {
|
} else {
|
||||||
@@ -154,6 +163,71 @@ impl Default for TlsConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert a PEM private key from any format (PKCS#1, SEC1, PKCS#8) to PKCS#8 PEM.
|
||||||
|
///
|
||||||
|
/// `reqwest::Identity::from_pkcs8_pem` (native-tls) only accepts PKCS#8
|
||||||
|
/// (`-----BEGIN PRIVATE KEY-----`), but private keys in the wild come in three formats:
|
||||||
|
///
|
||||||
|
/// - **PKCS#1** (`-----BEGIN RSA PRIVATE KEY-----`): Legacy RSA-specific format.
|
||||||
|
/// Generated by default with `openssl genrsa`. Very common in older setups, tutorials,
|
||||||
|
/// and CA-issued key files.
|
||||||
|
/// - **SEC1** (`-----BEGIN EC PRIVATE KEY-----`): Legacy EC-specific format.
|
||||||
|
/// Generated by default with `openssl ecparam -genkey`. Common with EC certificates.
|
||||||
|
/// - **PKCS#8** (`-----BEGIN PRIVATE KEY-----`): Generic, algorithm-agnostic wrapper.
|
||||||
|
/// This is the only format native-tls accepts.
|
||||||
|
///
|
||||||
|
/// Without this conversion, users with legacy-format keys (Kubernetes secrets, corporate
|
||||||
|
/// PKI, etc.) would get a cryptic "Failed to create identity" error and need to manually
|
||||||
|
/// run `openssl pkey -in key.pem -out key-pkcs8.pem`.
|
||||||
|
///
|
||||||
|
/// Note: the rustls code path (`Identity::from_pem`) accepts all formats natively,
|
||||||
|
/// so this conversion is only needed for native-tls.
|
||||||
|
#[cfg(feature = "native-tls")]
|
||||||
|
fn convert_key_to_pkcs8_pem(key_pem_str: &str) -> Result<String> {
|
||||||
|
use pkcs8::der::{Decode, Encode};
|
||||||
|
|
||||||
|
let parsed =
|
||||||
|
pem::parse(key_pem_str).map_err(|e| anyhow::anyhow!("Failed to parse PEM key: {}", e))?;
|
||||||
|
|
||||||
|
match parsed.tag() {
|
||||||
|
"PRIVATE KEY" => Ok(key_pem_str.to_string()),
|
||||||
|
"RSA PRIVATE KEY" => {
|
||||||
|
let info = pkcs8::PrivateKeyInfo::new(pkcs1::ALGORITHM_ID, parsed.contents());
|
||||||
|
let der_bytes = info
|
||||||
|
.to_der()
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to encode PKCS#8: {}", e))?;
|
||||||
|
Ok(pem::encode(&pem::Pem::new("PRIVATE KEY", der_bytes)))
|
||||||
|
}
|
||||||
|
"EC PRIVATE KEY" => {
|
||||||
|
let ec_key = sec1::EcPrivateKey::from_der(parsed.contents())
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to parse EC key: {}", e))?;
|
||||||
|
let curve_oid = ec_key
|
||||||
|
.parameters
|
||||||
|
.and_then(|p| p.named_curve())
|
||||||
|
.ok_or_else(|| {
|
||||||
|
anyhow::anyhow!(
|
||||||
|
"EC key missing curve parameters. Convert to PKCS#8: \
|
||||||
|
openssl pkey -in key.pem -out key-pkcs8.pem"
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let algorithm = pkcs8::AlgorithmIdentifierRef {
|
||||||
|
oid: sec1::ALGORITHM_OID,
|
||||||
|
parameters: Some((&curve_oid).into()),
|
||||||
|
};
|
||||||
|
let info = pkcs8::PrivateKeyInfo::new(algorithm, parsed.contents());
|
||||||
|
let der_bytes = info
|
||||||
|
.to_der()
|
||||||
|
.map_err(|e| anyhow::anyhow!("Failed to encode PKCS#8: {}", e))?;
|
||||||
|
Ok(pem::encode(&pem::Pem::new("PRIVATE KEY", der_bytes)))
|
||||||
|
}
|
||||||
|
tag => Err(anyhow::anyhow!(
|
||||||
|
"Unsupported key format '{}'. Expected PKCS#8, PKCS#1, or SEC1. \
|
||||||
|
Convert with: openssl pkey -in key.pem -out key-pkcs8.pem",
|
||||||
|
tag
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct OAuthConfig {
|
pub struct OAuthConfig {
|
||||||
pub host: String,
|
pub host: String,
|
||||||
pub client_id: String,
|
pub client_id: String,
|
||||||
@@ -440,6 +514,127 @@ impl fmt::Debug for ApiClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, feature = "native-tls"))]
|
||||||
|
mod native_tls_tests {
|
||||||
|
use super::convert_key_to_pkcs8_pem;
|
||||||
|
|
||||||
|
const PKCS8_RSA_KEY: &str = "\
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzmc7SPaB07+gK
|
||||||
|
p/VETtmayzNASEaaGIEKO5eOrlrKfIMdmSyB38Ia4dCyxb8WKAROeBtaev8AXfKh
|
||||||
|
5sPRPi42SNF77d171QWKU4WKXRWWpO2UWwzrXc/BaCNr0Ey9S4ej3v0DmdPkW+pY
|
||||||
|
PZ5lzHUT6wTutGwJsceCN+/lgPmazaZvfnTdLlRChLyPFjwGkGFwmu7YZACdbIqd
|
||||||
|
CW5oIs+weAK2L9+HZaLi0TWcnJrnONs00GHTm2DwLkl8ulKRn6+XygWZLpY4owE6
|
||||||
|
/x4v4CrTKStvfJlPiErcR/t13vZ+kZq3XxcgIY5V0HEz+AT57/MvvGomQXyMmQnN
|
||||||
|
bQrmdbvRAgMBAAECggEABd6knqSmuDeogeOmHYzFqhxSwRqzmwDqw7i5ne9HFpfN
|
||||||
|
6bNaO+biF0KS0Wrq0Tiu1lkwzKrZJ2wKnF24P+AMPtgvp4EZRF0sjI4o/sIGzPj4
|
||||||
|
LklxAUa8Pd4PTUxeG7Aqn1GP+5SFEzEpVieyY/GUEHn1e+8v2jvCEViOabXmwndA
|
||||||
|
tGHScHwMA0qW1smCOLj12mfFJJjJjlj7QveJFSJ94wo8XjdZvzLDonQoAf4vN99f
|
||||||
|
rf40zgAx8VQk1UmOPYgc7mqN3JerjWX3rG820UWilLnAA35rrVxjzeV9yfAbgpVC
|
||||||
|
qHPaOaN4tBVTb3z9w94wK/uDjd4Px26Qq0Yipi4xGQKBgQD7RXE6hNlx1hW7pdWw
|
||||||
|
hrxdH9ofptBzJfQwYnO0cq6KFF6+QQYzJcMAZAKEytDzfjkH1iHURtBFA1ndKBSI
|
||||||
|
B1G8iR7Jie4szDghJ+zS9QHHhXLRprSqyamRefnLe/614YlaP7i9wq/sHg8KKm5b
|
||||||
|
g+S49EfuKctAenMx8sDPDG7Y2QKBgQC2+xOZTE5uPPitOyR8eMUF1ye9zeONzyJ2
|
||||||
|
l2rjEZuIOWd12wsrgGVTRXoecpqFNIxcmK2mnBtrWCJ/A5xFXjQjIZ1huJ/oNm+t
|
||||||
|
bI/GtlM5BknfEP6m8NVtMx5ubzqDIlsgRpXCWco3ytaKZJtdnJhZAOmBogAKUiPr
|
||||||
|
NL2afWbfuQKBgA722MJybPzBkjPFsY88xvUI05W0+o8RAJTtGBT0C37/rZDJEJR1
|
||||||
|
OELKsfe0mHMX3k+gKg2ZVgf2JiDspSRgwzZmOCYqh7u1QdZ/qTP7EWsPgIIJ2pKd
|
||||||
|
RfL6/6xlqwqr7uEoEFmEwbNfKughFMdweGunaK0/YfJqGHguC9uI0wUpAoGBAKDM
|
||||||
|
U5TLscC+Y+oXpyCbIMjZIltxqx7bf/Wnao7Q0lUL3Rd8vnwkAOcEjyRiodedLhvR
|
||||||
|
MAjR9maGtQnZKmLrPfYBfER78komTE2isVZ2svvRwuj8Dky2J1gnK/7wUAMdFedv
|
||||||
|
H/wC2+nbnl1PvBivnFHas1jv/AkV1erEFjrFKLpBAoGABQ29M3xsVv7++/ivl0JM
|
||||||
|
lNzUZwWbG4GI9Yx/zBMJpjiPi9Bkbe2Iu7EgLuiaTnktLSzm9hwVEIxd6a6X/wRA
|
||||||
|
cGr4L/FDExxjHQPzYpeGQ5fA9HlDWZzQ7Ou+nZ/O+OwXuvnmjXTXyB0djVJHOmLU
|
||||||
|
gOfZqLKYsL5zn6pefvXu0dU=
|
||||||
|
-----END PRIVATE KEY-----";
|
||||||
|
|
||||||
|
const PKCS1_RSA_KEY: &str = "\
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEowIBAAKCAQEAs5nO0j2gdO/oCqf1RE7ZmsszQEhGmhiBCjuXjq5aynyDHZks
|
||||||
|
gd/CGuHQssW/FigETngbWnr/AF3yoebD0T4uNkjRe+3de9UFilOFil0VlqTtlFsM
|
||||||
|
613PwWgja9BMvUuHo979A5nT5FvqWD2eZcx1E+sE7rRsCbHHgjfv5YD5ms2mb350
|
||||||
|
3S5UQoS8jxY8BpBhcJru2GQAnWyKnQluaCLPsHgCti/fh2Wi4tE1nJya5zjbNNBh
|
||||||
|
05tg8C5JfLpSkZ+vl8oFmS6WOKMBOv8eL+Aq0ykrb3yZT4hK3Ef7dd72fpGat18X
|
||||||
|
ICGOVdBxM/gE+e/zL7xqJkF8jJkJzW0K5nW70QIDAQABAoIBAAXepJ6kprg3qIHj
|
||||||
|
ph2MxaocUsEas5sA6sO4uZ3vRxaXzemzWjvm4hdCktFq6tE4rtZZMMyq2SdsCpxd
|
||||||
|
uD/gDD7YL6eBGURdLIyOKP7CBsz4+C5JcQFGvD3eD01MXhuwKp9Rj/uUhRMxKVYn
|
||||||
|
smPxlBB59XvvL9o7whFYjmm15sJ3QLRh0nB8DANKltbJgji49dpnxSSYyY5Y+0L3
|
||||||
|
iRUifeMKPF43Wb8yw6J0KAH+LzffX63+NM4AMfFUJNVJjj2IHO5qjdyXq41l96xv
|
||||||
|
NtFFopS5wAN+a61cY83lfcnwG4KVQqhz2jmjeLQVU298/cPeMCv7g43eD8dukKtG
|
||||||
|
IqYuMRkCgYEA+0VxOoTZcdYVu6XVsIa8XR/aH6bQcyX0MGJztHKuihRevkEGMyXD
|
||||||
|
AGQChMrQ8345B9Yh1EbQRQNZ3SgUiAdRvIkeyYnuLMw4ISfs0vUBx4Vy0aa0qsmp
|
||||||
|
kXn5y3v+teGJWj+4vcKv7B4PCipuW4PkuPRH7inLQHpzMfLAzwxu2NkCgYEAtvsT
|
||||||
|
mUxObjz4rTskfHjFBdcnvc3jjc8idpdq4xGbiDlnddsLK4BlU0V6HnKahTSMXJit
|
||||||
|
ppwba1gifwOcRV40IyGdYbif6DZvrWyPxrZTOQZJ3xD+pvDVbTMebm86gyJbIEaV
|
||||||
|
wlnKN8rWimSbXZyYWQDpgaIAClIj6zS9mn1m37kCgYAO9tjCcmz8wZIzxbGPPMb1
|
||||||
|
CNOVtPqPEQCU7RgU9At+/62QyRCUdThCyrH3tJhzF95PoCoNmVYH9iYg7KUkYMM2
|
||||||
|
ZjgmKoe7tUHWf6kz+xFrD4CCCdqSnUXy+v+sZasKq+7hKBBZhMGzXyroIRTHcHhr
|
||||||
|
p2itP2Hyahh4LgvbiNMFKQKBgQCgzFOUy7HAvmPqF6cgmyDI2SJbcase23/1p2qO
|
||||||
|
0NJVC90XfL58JADnBI8kYqHXnS4b0TAI0fZmhrUJ2Spi6z32AXxEe/JKJkxNorFW
|
||||||
|
drL70cLo/A5MtidYJyv+8FADHRXnbx/8Atvp255dT7wYr5xR2rNY7/wJFdXqxBY6
|
||||||
|
xSi6QQKBgAUNvTN8bFb+/vv4r5dCTJTc1GcFmxuBiPWMf8wTCaY4j4vQZG3tiLux
|
||||||
|
IC7omk55LS0s5vYcFRCMXemul/8EQHBq+C/xQxMcYx0D82KXhkOXwPR5Q1mc0Ozr
|
||||||
|
vp2fzvjsF7r55o1018gdHY1SRzpi1IDn2aiymLC+c5+qXn717tHV
|
||||||
|
-----END RSA PRIVATE KEY-----";
|
||||||
|
|
||||||
|
const SEC1_EC_KEY: &str = "\
|
||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIIQyP9q8dmPTyzxgCAF22fS5w6GJP7lVrkq3gdG216TtoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAEAxC2ZMkrbwEImb3S2BD8qA9rquFbozW6d7VrhVk1tOqnIuM+vXkz
|
||||||
|
ShGoCNbfNS+COlPMRAujyDlATZcLs9p4tA==
|
||||||
|
-----END EC PRIVATE KEY-----";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pkcs8_key_passthrough() {
|
||||||
|
let result = convert_key_to_pkcs8_pem(PKCS8_RSA_KEY).unwrap();
|
||||||
|
assert_eq!(result, PKCS8_RSA_KEY.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pkcs1_rsa_key_conversion() {
|
||||||
|
let result = convert_key_to_pkcs8_pem(PKCS1_RSA_KEY).unwrap();
|
||||||
|
assert!(result.contains("-----BEGIN PRIVATE KEY-----"));
|
||||||
|
assert!(result.contains("-----END PRIVATE KEY-----"));
|
||||||
|
assert!(!result.contains("RSA PRIVATE KEY"));
|
||||||
|
// Verify the result is valid PKCS#8 by re-parsing
|
||||||
|
let re_parsed = pem::parse(&result).unwrap();
|
||||||
|
assert_eq!(re_parsed.tag(), "PRIVATE KEY");
|
||||||
|
use pkcs8::der::Decode;
|
||||||
|
pkcs8::PrivateKeyInfo::from_der(re_parsed.contents()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sec1_ec_key_conversion() {
|
||||||
|
let result = convert_key_to_pkcs8_pem(SEC1_EC_KEY).unwrap();
|
||||||
|
assert!(result.contains("-----BEGIN PRIVATE KEY-----"));
|
||||||
|
assert!(result.contains("-----END PRIVATE KEY-----"));
|
||||||
|
assert!(!result.contains("EC PRIVATE KEY"));
|
||||||
|
// Verify the result is valid PKCS#8 by re-parsing
|
||||||
|
let re_parsed = pem::parse(&result).unwrap();
|
||||||
|
assert_eq!(re_parsed.tag(), "PRIVATE KEY");
|
||||||
|
use pkcs8::der::Decode;
|
||||||
|
pkcs8::PrivateKeyInfo::from_der(re_parsed.contents()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_unsupported_key_format() {
|
||||||
|
let bad_pem =
|
||||||
|
"-----BEGIN DSA PRIVATE KEY-----\nMIIBuwIBAAKB\n-----END DSA PRIVATE KEY-----";
|
||||||
|
let result = convert_key_to_pkcs8_pem(bad_pem);
|
||||||
|
assert!(result.is_err());
|
||||||
|
assert!(result
|
||||||
|
.unwrap_err()
|
||||||
|
.to_string()
|
||||||
|
.contains("Unsupported key format"),);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_pem() {
|
||||||
|
let result = convert_key_to_pkcs8_pem("not a pem");
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Prevent native-tls/OpenSSL from being added to the dependency tree.
|
|
||||||
# These cause Linux compatibility issues with OpenSSL version mismatches.
|
|
||||||
# See: https://github.com/block/goose/issues/6034
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
BANNED_CRATES=("native-tls" "openssl-sys" "openssl")
|
|
||||||
FOUND_BANNED=0
|
|
||||||
|
|
||||||
for crate in "${BANNED_CRATES[@]}"; do
|
|
||||||
if cargo tree -i "$crate" 2>/dev/null | grep -q "$crate"; then
|
|
||||||
echo "ERROR: Found banned crate '$crate' in dependency tree"
|
|
||||||
echo "This causes Linux compatibility issues with OpenSSL versions."
|
|
||||||
echo "Use rustls-based alternatives instead (e.g., rustls-tls-native-roots)."
|
|
||||||
echo ""
|
|
||||||
echo "Dependency chain:"
|
|
||||||
cargo tree -i "$crate"
|
|
||||||
echo ""
|
|
||||||
FOUND_BANNED=1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $FOUND_BANNED -eq 1 ]; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✓ No banned TLS crates found (native-tls, openssl, openssl-sys)"
|
|
||||||
Reference in New Issue
Block a user