From bbcfe33fe7967684c99b84f6c9d52a7163245909 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 15 Mar 2023 09:32:23 +0800 Subject: [PATCH] fix: request fail caused by certificate issue --- Cargo.lock | 205 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 11 ++- cert/cert.pem | 31 ++++++ cert/csr.sh | 28 ++++++ cert/key.pem | 52 ++++++++++ cert/pem.sh | 6 ++ configuration/local.yaml | 2 +- src/application.rs | 27 +++++- src/lib.rs | 1 + src/self_signed.rs | 29 ++++++ tests/api/test_server.rs | 6 +- 11 files changed, 392 insertions(+), 6 deletions(-) create mode 100644 cert/cert.pem create mode 100644 cert/csr.sh create mode 100644 cert/key.pem create mode 100644 cert/pem.sh create mode 100644 src/self_signed.rs diff --git a/Cargo.lock b/Cargo.lock index 92537f51..2491706f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,7 @@ dependencies = [ "actix-codec", "actix-rt", "actix-service", + "actix-tls", "actix-utils", "ahash 0.8.3", "base64 0.21.0", @@ -195,6 +196,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "actix-tls" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fde0cf292f7cdc7f070803cb9a0d45c018441321a78b1042ffbbb81ec333297" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "log", + "openssl", + "pin-project-lite", + "tokio-openssl", + "tokio-util", +] + [[package]] name = "actix-utils" version = "3.0.1" @@ -218,6 +237,7 @@ dependencies = [ "actix-rt", "actix-server", "actix-service", + "actix-tls", "actix-utils", "actix-web-codegen", "ahash 0.7.6", @@ -434,7 +454,9 @@ dependencies = [ "jsonwebtoken", "lazy_static", "once_cell", + "openssl", "rand", + "rcgen", "reqwest", "secrecy", "serde", @@ -470,6 +492,45 @@ dependencies = [ "password-hash", ] +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time 0.3.20", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-stream" version = "0.3.4" @@ -912,6 +973,26 @@ dependencies = [ "parking_lot_core 0.9.7", ] +[[package]] +name = "data-encoding" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" + +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -956,6 +1037,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dotenvy" version = "0.15.6" @@ -1493,6 +1585,21 @@ dependencies = [ "simple_asn1", ] +[[package]] +name = "jwt" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f" +dependencies = [ + "base64 0.13.1", + "crypto-common", + "digest", + "hmac", + "serde", + "serde_json", + "sha2", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -1710,6 +1817,15 @@ dependencies = [ "libc", ] +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -1979,6 +2095,19 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rcgen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +dependencies = [ + "pem", + "ring", + "time 0.3.20", + "x509-parser", + "yasna", +] + [[package]] name = "redis" version = "0.21.7" @@ -2113,6 +2242,15 @@ dependencies = [ "semver", ] +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + [[package]] name = "rustix" version = "0.36.9" @@ -2497,6 +2635,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tempfile" version = "3.4.0" @@ -2602,6 +2752,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "token" +version = "0.1.0" +dependencies = [ + "jsonwebtoken", + "jwt", + "serde", +] + [[package]] name = "tokio" version = "1.26.0" @@ -2643,6 +2802,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-openssl" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08f9ffb7809f1b20c1b398d92acf4cc719874b3b2b2d9ea2f09b4a80350878a" +dependencies = [ + "futures-util", + "openssl", + "openssl-sys", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.23.4" @@ -2836,6 +3007,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "unicode_categories" version = "0.1.1" @@ -3160,6 +3337,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs", + "base64 0.13.1", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "ring", + "rusticata-macros", + "thiserror", + "time 0.3.20", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -3169,6 +3365,15 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yasna" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aed2e7a52e3744ab4d0c05c20aa065258e84c49fd4226f5191b2ed29712710b4" +dependencies = [ + "time 0.3.20", +] + [[package]] name = "zeroize" version = "1.5.7" diff --git a/Cargo.toml b/Cargo.toml index 45e1b66a..1af0a570 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] actix = "0.13" -actix-web = "4.3.1" +actix-web = { version = "4.3.1", features = ["openssl"] } actix-http = "3.3.1" actix-rt = "2" actix-web-actors = { version = "4.2.0" } @@ -16,6 +16,7 @@ actix-identity = "0.5.2" actix-cors = "0.6.4" actix-web-flash-messages = { version = "0.4", features = ["cookies"] } actix-session = { version = "0.7", features = ["redis-rs-tls-session"] } +openssl = "0.10.45" # serde serde_json = "1.0" @@ -50,6 +51,7 @@ validator = "0.16.0" bytes = "1.4.0" bincode = "1.3.3" dashmap = "5.4" +rcgen = { version = "0.10.0", features = ["pem", "x509-parser"] } # tracing tracing = { version = "0.1.37" } @@ -69,4 +71,9 @@ path = "src/main.rs" [lib] -path = "src/lib.rs" \ No newline at end of file +path = "src/lib.rs" + +[workspace] +members = [ + "crates/token", +] \ No newline at end of file diff --git a/cert/cert.pem b/cert/cert.pem new file mode 100644 index 00000000..10514d9d --- /dev/null +++ b/cert/cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFRDCCAywCCQDXwkFioxoJ2TANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJV +UzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU3Vubnl2YWxlMRYwFAYD +VQQKDA1BcHBGbG93eSxJbmMuMRQwEgYDVQQDDAthcHBmbG93eS5pbzAeFw0yMzAz +MTUwMDUxNDVaFw0yNDAzMTQwMDUxNDVaMGQxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApDYWxpZm9ybmlhMRIwEAYDVQQHDAlTdW5ueXZhbGUxFjAUBgNVBAoMDUFwcEZs +b3d5LEluYy4xFDASBgNVBAMMC2FwcGZsb3d5LmlvMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA09v/ouq4r7+oLOWqVscYpW5QRLR5O6OYZprocIARAtWA +qBkywhPku/SZq27dtPD7Pi3soSPkMhYDFALai4idgELCFxxkTuHWNm3J+Y8PcMq2 +RX325/pQVpOMTkChqaUzh93ynYqv89x3lT9z4saknBde/WO2yOJ6sfED9w+ezYgm +34LV5Z0cofQTDEiTX58KV3MmG5hRMdBwCaDg1jUb3jKr5lBrF4+EHbAN5PWH282V +JdyOTvZp/CF5TcnAMONkYENjURpnSXJes34ufYHkmr0eDa+2pfc3TI5wlB3tPQyN +p+B5TsDCDofv0Zme5Ur42TWcwsG0WRvtDw2KZ98wBtGaIv8UEQjXipNQVzeCv5Yv +zeykjdDhOJ/OZFzsm2vtl55t52M43xYMo3QPmjHMiVYz9KVvPqrVo+O5PI7B7uwY +JxWQIJosUa6AeKfkCAQd8mlNqYylqV8Utqs8b4zee8Vf7hzaCYNKxyDvqsd3yDwE +umh5zVuxJitLchDFT4mv1v3yLHocusV2lwjfEk66R/o5BBDdviycxeAM5Q1lyi7M +RywHAt/eVQNaBq0HSa2vbIm5yTZNQYwuhnNgv035hf8vpu+tFOGepTqgy/CrYpPm +VnsClJVrmxd4LfUZ0aZODiKCVx6psfeBvTXu1r7/SjsmbvYE4ubfM66optyFc3cC +AwEAATANBgkqhkiG9w0BAQsFAAOCAgEAfhSUTP91rBP+8zvsoxomKdeClVFURczr +HO/VuXVmBoKLASFqFcT84usRhb5T6XB7o2GcCYSo0VFJw99UM6nLsZ7c0MKaAjT6 +/9VeyLtDfhCDkffGGxpeYhme+0PY8TXIU5aO0ZhQwzXUOiC7t3Ac3AzHTPGrGqOK +aAGhMo7V2bQXcNR6NFhsUlJOtVE59MxL1K5Ug1oMn/H+NUF6/st+KzohruQJSSWG +GcbqVor0zZbFJSvRJ5P3ngw2cg2SIj9w6RwUWMp+a5kOx10fOYrQEHGyTHFlVDy0 +yOCU4eVO3EVTm7Se1XVwmG3kNKQaLFJf1voMuYD2sFbZ0nhGJDSZOcGUrchUXPQB +C9MwU52OeNm5VwE/41wLoFvOkJ/I/Ak7vccl1YJXpefa6qjNOFm5X0jA7D4egDfC +IVs5m30qa6Birx0xS6RUuuvxLJyNzgLSzsC1eFwjR2uwIUrGpYo3YI4+bMxp2Wnk +6qtm5G8D1giWg6z0RLw+GSj4QfcJEBP+zyiH/MdB5te9kXVYLKyS+DGgTTatLi1l +MBBK5b7dvfwo08J/sksK+mPHHBsV9TPAkqMp9vuZw25pRAEnvjEOUPfi3X9EZDw7 +A3LElN9KDks3IioioAOm0vPvHrlfziSljt5IMkuZLT3lUe6B3cs69caLO0S/ZDTz +yqGwLIqHYos= +-----END CERTIFICATE----- diff --git a/cert/csr.sh b/cert/csr.sh new file mode 100644 index 00000000..fde21e0e --- /dev/null +++ b/cert/csr.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Generate key file +openssl genpkey -algorithm RSA \ + -pkeyopt rsa_keygen_bits:4096 \ + -pkeyopt rsa_keygen_pubexp:65537 | \ + # pkcs8 + # PKCS (Public-Key Cryptography Standards) is a series of standards developed by RSA + # Laboratories that define formats for cryptographic objects, including private keys, + # public keys, certificates, and messages. + #-topk8 + # option specifies that the output should be in PKCS#8 format + openssl pkcs8 -topk8 -nocrypt -outform pem -out appflowy.io.key + +# Generate CSR file +#https://www.digicert.com/kb/csr-creation.htm +#https://www.digicert.com/kb/ssl-support/openssl-quick-reference-guide.htm +openssl req -subj "/C=US/ST=California/L=Sunnyvale/O=AppFlowy,Inc./CN=appflowy.io"\ + -new -days 3650 -key appflowy.io.key -out appflowy.io.csr + +# Generate self-sign file +openssl x509 -req -days 365 -in appflowy.io.csr -signkey appflowy.io.key -out appflowy.io.crt + +# Verify certificate signing request +openssl req -text -noout -verify -in appflowy.io.csr + +# verify certificate +openssl x509 -text -noout -in appflowy.io.crt diff --git a/cert/key.pem b/cert/key.pem new file mode 100644 index 00000000..d403fc71 --- /dev/null +++ b/cert/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +Oi+igzFlcelWDZ/eQ8CpDkSpAqtwwx97 +-----END PRIVATE KEY----- diff --git a/cert/pem.sh b/cert/pem.sh new file mode 100644 index 00000000..983083df --- /dev/null +++ b/cert/pem.sh @@ -0,0 +1,6 @@ +#!/bin/bash +openssl req -x509 -newkey rsa:4096 \ + -keyout key.pem -out cert.pem \ + -days 365 -nodes -subj "/C=US/ST=California/L=Sunnyvale/O=AppFlowy,Inc./CN=appflowy.io" \ + +openssl x509 -in cert.pem -text -noout \ No newline at end of file diff --git a/configuration/local.yaml b/configuration/local.yaml index d7f541e2..2667baa6 100644 --- a/configuration/local.yaml +++ b/configuration/local.yaml @@ -1,5 +1,5 @@ application: host: 127.0.0.1 - base_url: "http://127.0.0.1" + base_url: "https://127.0.0.1" database: require_ssl: false diff --git a/src/application.rs b/src/application.rs index 731c1799..eac95db8 100644 --- a/src/application.rs +++ b/src/application.rs @@ -2,13 +2,16 @@ use crate::api::{token_scope, user_scope, ws_scope}; use crate::component::auth::HEADER_TOKEN; use crate::config::config::{Config, DatabaseSetting}; use crate::middleware::cors::default_cors; +use crate::self_signed::create_certificate; use crate::state::State; use actix_identity::IdentityMiddleware; - use actix_session::storage::RedisSessionStore; use actix_session::SessionMiddleware; use actix_web::cookie::Key; use actix_web::{dev::Server, web, web::Data, App, HttpServer}; + +use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; +use openssl::x509::X509; use secrecy::{ExposeSecret, Secret}; use sqlx::{postgres::PgPoolOptions, PgPool}; use std::net::TcpListener; @@ -51,6 +54,7 @@ pub async fn run( secret_key: Secret, redis_uri: Secret, ) -> Result { + let (cert, _server_key) = create_certificate()?; let redis_store = RedisSessionStore::new(redis_uri.expose_secret()).await?; let server = HttpServer::new(move || { let secret_key = Key::from(secret_key.expose_secret().as_bytes()); @@ -70,7 +74,7 @@ pub async fn run( .service(ws_scope()) .app_data(Data::new(state.clone())) }) - .listen(listener)? + .listen_openssl(listener, make_ssl_acceptor_builder(cert))? .run(); Ok(server) } @@ -97,3 +101,22 @@ pub async fn get_connection_pool(setting: &DatabaseSetting) -> Result SslAcceptorBuilder { + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + let x509_cert = X509::from_pem(cert.as_bytes()).unwrap(); + builder.set_certificate(&x509_cert).unwrap(); + builder + .set_private_key_file("./cert/key.pem", SslFiletype::PEM) + .unwrap(); + builder + .set_certificate_chain_file("./cert/cert.pem") + .unwrap(); + builder + .set_min_proto_version(Some(openssl::ssl::SslVersion::TLS1_2)) + .unwrap(); + builder + .set_max_proto_version(Some(openssl::ssl::SslVersion::TLS1_3)) + .unwrap(); + builder +} diff --git a/src/lib.rs b/src/lib.rs index e406b561..8eec845d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,5 +4,6 @@ pub mod component; pub mod config; pub mod domain; pub mod middleware; +mod self_signed; pub mod state; pub mod telemetry; diff --git a/src/self_signed.rs b/src/self_signed.rs new file mode 100644 index 00000000..396adecf --- /dev/null +++ b/src/self_signed.rs @@ -0,0 +1,29 @@ +use rcgen::{Certificate, CertificateParams, KeyPair, RcgenError, SanType}; + +pub const CA_CRT: &str = include_str!("../cert/cert.pem"); +pub const CA_KEY: &str = include_str!("../cert/key.pem"); + +pub fn create_certificate() -> Result<(String, String), RcgenError> { + let key = KeyPair::from_pem(CA_KEY)?; + let params = CertificateParams::from_ca_cert_pem(CA_CRT, key)?; + let ca_cert = Certificate::from_params(params)?; + + let mut params = CertificateParams::default(); + params + .subject_alt_names + .push(SanType::IpAddress("127.0.0.1".parse().unwrap())); + params + .subject_alt_names + .push(SanType::IpAddress("0.0.0.0".parse().unwrap())); + params + .subject_alt_names + .push(SanType::DnsName("localhost".to_string())); + + // Generate a certificate that's valid for: + // 1. localhost + // 2. 127.0.0.1 + let gen_cert = Certificate::from_params(params)?; + let server_crt = gen_cert.serialize_pem_with_signer(&ca_cert)?; + let server_key = gen_cert.serialize_private_key_pem(); + Ok((server_crt, server_key)) +} diff --git a/tests/api/test_server.rs b/tests/api/test_server.rs index 4ecf1c75..3e01b62b 100644 --- a/tests/api/test_server.rs +++ b/tests/api/test_server.rs @@ -3,6 +3,7 @@ use appflowy_server::config::config::{get_configuration, DatabaseSetting}; use appflowy_server::state::State; use appflowy_server::telemetry::{get_subscriber, init_subscriber}; use once_cell::sync::Lazy; +use reqwest::Certificate; use appflowy_server::component::auth::{RegisterResponse, HEADER_TOKEN}; use sqlx::types::Uuid; @@ -99,14 +100,17 @@ pub async fn spawn_server() -> TestServer { .expect("Failed to build application"); let port = application.port(); - let address = format!("http://localhost:{}", port); + let address = format!("https://localhost:{}", port); let _ = tokio::spawn(async { let _ = application.run_until_stopped().await; }); let api_client = reqwest::Client::builder() + .add_root_certificate(Certificate::from_pem(include_bytes!("../../cert/cert.pem")).unwrap()) .redirect(reqwest::redirect::Policy::none()) + .danger_accept_invalid_certs(true) .cookie_store(true) + .no_proxy() .build() .unwrap();