From 501884382df06fa00584bc9f05fc170ddf0b656a Mon Sep 17 00:00:00 2001 From: WxNzEMof <143541718+WxNzEMof@users.noreply.github.com> Date: Mon, 22 Jul 2024 23:30:50 +0000 Subject: [PATCH 1/2] Add TLS support --- Cargo.lock | 128 +++++++++++++++++++++++++++++++++++++++++ README.md | 2 + harmonia/Cargo.toml | 3 +- harmonia/src/config.rs | 4 ++ harmonia/src/main.rs | 17 ++++-- 5 files changed, 148 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05bd3a86..0d69302d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,6 +51,7 @@ dependencies = [ "actix-codec", "actix-rt", "actix-service", + "actix-tls", "actix-utils", "ahash", "base64", @@ -60,6 +61,7 @@ dependencies = [ "derive_more", "encoding_rs", "futures-core", + "h2", "http", "httparse", "httpdate", @@ -140,6 +142,25 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "actix-tls" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac453898d866cdbecdbc2334fe1738c747b4eba14a677261f2b768ba05329389" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "impl-more", + "openssl", + "pin-project-lite", + "tokio", + "tokio-openssl", + "tokio-util", + "tracing", +] + [[package]] name = "actix-utils" version = "3.0.1" @@ -163,6 +184,7 @@ dependencies = [ "actix-rt", "actix-server", "actix-service", + "actix-tls", "actix-utils", "actix-web-codegen", "ahash", @@ -566,6 +588,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -632,6 +669,25 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "harmonia" version = "0.8.0" @@ -646,6 +702,7 @@ dependencies = [ "libnixstore", "log", "mime", + "openssl", "percent-encoding", "serde", "serde_json", @@ -706,6 +763,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "impl-more" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206ca75c9c03ba3d4ace2460e57b189f39f43de612c2f85836e65c929701bb2d" + [[package]] name = "indexmap" version = "2.1.0" @@ -858,6 +921,44 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -1139,6 +1240,15 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.11.2" @@ -1271,6 +1381,18 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "tokio-openssl" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ffab79df67727f6acf57f1ff743091873c24c579b1e2ce4d8f53e47ded4d63d" +dependencies = [ + "futures-util", + "openssl", + "openssl-sys", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.15" @@ -1415,6 +1537,12 @@ version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" diff --git a/README.md b/README.md index a672e37a..9d029f8a 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,8 @@ is `info,actix_web=debug`. To only log errors use the following `RUST_LOG=error` and to only disable access logging, use `RUST_LOG=info,actix_web::middleware=error` +To enable TLS on the HTTP server, specify `tls_cert_path` and `tls_key_path`. + ## Build ### Whole application diff --git a/harmonia/Cargo.toml b/harmonia/Cargo.toml index 9373ca3a..1474b395 100644 --- a/harmonia/Cargo.toml +++ b/harmonia/Cargo.toml @@ -13,7 +13,8 @@ repository = "https://github.com/nix-community/harmonia.git" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -actix-web = { version = "4", default-features = false, features = ["macros", "compress-zstd", "cookies"] } +actix-web = { version = "4", default-features = false, features = ["macros", "compress-zstd", "cookies", "openssl"] } +openssl = { version = "0.10" } actix-files = "0.6.6" log = "0.4" env_logger = "0.11" diff --git a/harmonia/src/config.rs b/harmonia/src/config.rs index ba298c28..ac477c7f 100644 --- a/harmonia/src/config.rs +++ b/harmonia/src/config.rs @@ -36,6 +36,10 @@ pub(crate) struct Config { pub(crate) sign_key_path: Option, #[serde(default)] pub(crate) sign_key_paths: Vec, + #[serde(default)] + pub(crate) tls_cert_path: Option, + #[serde(default)] + pub(crate) tls_key_path: Option, #[serde(skip, default)] pub(crate) secret_keys: Vec, diff --git a/harmonia/src/main.rs b/harmonia/src/main.rs index 0265b33c..3fa4f427 100644 --- a/harmonia/src/main.rs +++ b/harmonia/src/main.rs @@ -1,6 +1,7 @@ use std::{fmt::Display, time::Duration}; use actix_web::{http, web, App, HttpResponse, HttpServer}; +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; mod buildlog; mod cacheinfo; @@ -109,7 +110,7 @@ async fn main() -> std::io::Result<()> { let config_data = c.clone(); log::info!("listening on {}", c.bind); - HttpServer::new(move || { + let mut server = HttpServer::new(move || { App::new() .app_data(config_data.clone()) .route("/", web::get().to(root::get)) @@ -140,8 +141,14 @@ async fn main() -> std::io::Result<()> { // default is 5 seconds, which is too small when doing mass requests on slow machines .client_request_timeout(Duration::from_secs(30)) .workers(c.workers) - .max_connection_rate(c.max_connection_rate) - .bind(c.bind.clone())? - .run() - .await + .max_connection_rate(c.max_connection_rate); + if c.tls_cert_path.is_some() || c.tls_key_path.is_some() { + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls())?; + builder.set_private_key_file(c.tls_key_path.clone().unwrap(), SslFiletype::PEM)?; + builder.set_certificate_chain_file(c.tls_cert_path.clone().unwrap())?; + server = server.bind_openssl(c.bind.clone(), builder)?; + } else { + server = server.bind(c.bind.clone())?; + } + server.run().await } From 558f9c6bbf63b2bb70f47e0d4f79e4fa9df8978b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 25 Jul 2024 14:56:17 +0200 Subject: [PATCH 2/2] add test for tls --- flake.nix | 1 + tests/t04-tls.nix | 15 +++++++++++++++ tests/tls-cert.pem | 20 ++++++++++++++++++++ tests/tls-csr.pem | 17 +++++++++++++++++ tests/tls-key.pem | 28 ++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 tests/t04-tls.nix create mode 100644 tests/tls-cert.pem create mode 100644 tests/tls-csr.pem create mode 100644 tests/tls-key.pem diff --git a/flake.nix b/flake.nix index 0ecee5ff..96f75587 100644 --- a/flake.nix +++ b/flake.nix @@ -44,6 +44,7 @@ t01-signing = import ./tests/t01-signing.nix testArgs; t02-varnish = import ./tests/t02-varnish.nix testArgs; t03-chroot = import ./tests/t03-chroot.nix testArgs; + t04-tls = import ./tests/t04-tls.nix testArgs; } // { clippy = config.packages.harmonia.override ({ enableClippy = true; diff --git a/tests/t04-tls.nix b/tests/t04-tls.nix new file mode 100644 index 00000000..4ee5d5a0 --- /dev/null +++ b/tests/t04-tls.nix @@ -0,0 +1,15 @@ +(import ./lib.nix) { + name = "t04-tls"; + + nodes.harmonia = { + imports = [ ../module.nix ]; + + services.harmonia-dev.enable = true; + services.harmonia-dev.settings.tls_cert_path = ./tls-cert.pem; + services.harmonia-dev.settings.tls_key_path = ./tls-key.pem; + }; + + testScript = '' + harmonia.wait_until_succeeds("curl --cacert ${./tls-cert.pem} https://localhost:5000/version") + ''; +} diff --git a/tests/tls-cert.pem b/tests/tls-cert.pem new file mode 100644 index 00000000..e61798a4 --- /dev/null +++ b/tests/tls-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOTCCAiECFAc5lyBrKjhrcgYBeGP7LA7nGzQiMA0GCSqGSIb3DQEBCwUAMFkx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yNDA3 +MjUxMjQ3MTNaFw0yNTA3MjUxMjQ3MTNaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQI +DApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQx +EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKB6EDoExUqUIX5ANiA2VRNS6Q5otiecHpg7aL/0fkXKUm/iqmvLdib6AlrB +GDo0GHNfKrJatSFTDtaaVh6RgwoWFxZbml46NdMfzNy7h2E2YEtyuHO7bpuh+vKC +73jK9Z9estGkg2xYrgubGcaiZGO5KF97MGrB6mf3xM214SJDU+0znvH7Xbtwkl8D +kOjf7WmuWopBKCeoj/x1CFURHF1rr2fPaOh01qnRDCZQDpeKv41K0EFbTue7yKtj +Y54/y0rY1rdrNA/DU2MhHNxy/CjvO+tkliM9gieD4S6J60lIDSrp5UW6shPLXX2C +GAC1fKZTNNWOVgWi/pfZVXTaTCUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAZ8WP +Th+RS/FAC5ms5Ed/TdrwN3JVzZsUwDlVm2L7oohHh4y49dVSsznFOxCzn9IhYepS +ZVIL5LiHYYXnFSoM/e4hVn1QD59Hws4IL/UlHMNg8wLb/GnwjRrPa5dXrEADj/Pr +nJMzYcCPkQVdaQQLuLVvLTe9U6skVsLjKyu9y7CC+C2mQ4c0G5H8SLh19nZFFBmT +djWL1Qdxyn2VFf406u7GheJo+hRg+4IL643eRCNH6AK5YHtgVnceoMTJVKT650mH +iOCHCmgsUpypdi1++BYc4k7xnxP5BGdrVf8/uGiYtk5N9MaRyjd+tU1d6EYLHeaN +C+eX1d5j/cM+i2qj4w== +-----END CERTIFICATE----- diff --git a/tests/tls-csr.pem b/tests/tls-csr.pem new file mode 100644 index 00000000..5965aba4 --- /dev/null +++ b/tests/tls-csr.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICnjCCAYYCAQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9j +YWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoHoQOgTFSpQh +fkA2IDZVE1LpDmi2J5wemDtov/R+RcpSb+Kqa8t2JvoCWsEYOjQYc18qslq1IVMO +1ppWHpGDChYXFluaXjo10x/M3LuHYTZgS3K4c7tum6H68oLveMr1n16y0aSDbFiu +C5sZxqJkY7koX3swasHqZ/fEzbXhIkNT7TOe8ftdu3CSXwOQ6N/taa5aikEoJ6iP +/HUIVREcXWuvZ89o6HTWqdEMJlAOl4q/jUrQQVtO57vIq2Njnj/LStjWt2s0D8NT +YyEc3HL8KO8762SWIz2CJ4PhLonrSUgNKunlRbqyE8tdfYIYALV8plM01Y5WBaL+ +l9lVdNpMJQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBACjz0ki1Nm7wf9VrZopz +JxLv0ZCvcdXUWLMUqd4MKcDO2y0EoGfMeG9LJyvoB5Ptyi3gMLHgHZcBMwF0oeu6 +zs9lBVOXFVtVq+qw7iBj4/RQCBdr4757Po2iiinDXqHHkqskuHhyY4uHfajSyy7G +zdFCdsxy1yI8Om6qMarkXt31LwqF8XTGaFJna4x00Xg3tRNlDBCWbYQ9nuafEz4w +OdHFnud7OU13BnV2PNHWJfmY/smZ6mum28suxYlXUZx+fuSUklRqMFD8hbp5fuWO +2XEPAorbTL3xobYxF6et9UhcIUgJqNlIZNIxlY68t/KjpDmCRYJuuK72NFWLIItg +7Og= +-----END CERTIFICATE REQUEST----- diff --git a/tests/tls-key.pem b/tests/tls-key.pem new file mode 100644 index 00000000..c12e031b --- /dev/null +++ b/tests/tls-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCgehA6BMVKlCF+ +QDYgNlUTUukOaLYnnB6YO2i/9H5FylJv4qpry3Ym+gJawRg6NBhzXyqyWrUhUw7W +mlYekYMKFhcWW5peOjXTH8zcu4dhNmBLcrhzu26bofrygu94yvWfXrLRpINsWK4L +mxnGomRjuShfezBqwepn98TNteEiQ1PtM57x+127cJJfA5Do3+1prlqKQSgnqI/8 +dQhVERxda69nz2jodNap0QwmUA6Xir+NStBBW07nu8irY2OeP8tK2Na3azQPw1Nj +IRzccvwo7zvrZJYjPYIng+EuietJSA0q6eVFurITy119ghgAtXymUzTVjlYFov6X +2VV02kwlAgMBAAECggEAEDkcIta7SzV7x/5IeoEuS0HP0GZtjnDjTD3VR8fjwWfE +EGONxE/7+ydoeDGaeBKEK5sB/1Mu3yuSYxzpz9/4q1sIV85IO3ZkXUToZPg1phzl +Jzt1wjK/P885m1f5SvDZsT7Vkl6wmpIXJj02dzTmM96oDN8F9K+d5DImxypilB/+ +hb8BBee1i06K5plhynQfJuxg0Rwv9cstVoBrVY4S8G/Tb4hFMLTc3+DkY6lKFn3F +Fgf45jCKpTfknB6ZvCXoKm9pX8DqabszXZNnPbSxPpjuQgBRvlKwB/tU6fiRuugs +CBqE2exLy6uXcFNk5oXoemGJzzyxHjauOmk7DBoVEQKBgQDdmshrk0YMVFk3cT66 +S/wOCqKzzcFZeq7KsATEMtcwHzVYr3fyrudFJjc87uVqBHKB235mBPh1psg/kW1x +BV6CkN8xvN7v7JnXfVP59jOyy7v6g1nmOwl4Qcf0Fca7b61q36st12My5RFZNpME +HseQbET6HPFvXVFqtql3mr9u1wKBgQC5Ym8Ph2Fc05Z4qbNo4gG+R/ujiUAJVM7J +GQF638NouE86QTBHdX5pgaBXkSZqQ1keymJGWKqICumSvCykIUQI4XSTwIAGG9Xg +iV8cXXc5x/eqfut56mbmgOI41Nqjyfi/2v0YbM2q306vRfLXvJ+0DzdwA4dM90ET +CfWyRD4pYwKBgAV1/gBgpbZCEdzC5qfSnYh/DJlftacN1ebaxZNMKW9fJYJk+JC7 +bKmQkoXm4TJmn6fBj/DVqIXFsWOXotnJJxYSmd1w6RGChBwCU6JyRb3fNWer+vgo +dkhHXrUOIFKYIu7iSiacCy7C5FWNebv9Qi+161E6i1ySMSJvE+gFoTgLAoGAdM41 +pfYp/X//xiU+uq30ZT0bq23WIEsEQ6byzMXibL/8g3sBfXTlYnrfWW1GZBvtMj5Y +b3R8dl1R0DeqdPvUzzem6VWYFMFDIEfN2qR1c72wKgfwPI/ZqBC6+Q38eMjQZ6oG +YHZlm+05uav8F7xsb9pKltRSUsdThDh5S4o+FHsCgYBX6fv/GvvDDYkYtDKEcj4O +AA3bTzOX5SvfN0Wi438zI8c8R6GajimLVmJciHAlFGsCXQjUH799wo08qdSIR00m +uZhX/sevoOw8c8HQVKHzdtjxjKCfwwmxi0Wd+JtXRve5XXoni51jqNconhMBjKWz +4sCtAFYiGENU+vEgo+ON0A== +-----END PRIVATE KEY-----