diff --git a/.dockerignore b/.dockerignore index 1801971..7b2bf09 100644 --- a/.dockerignore +++ b/.dockerignore @@ -34,3 +34,5 @@ server_key users.db* screenshot.png recipe.json +cert.pem +key.pem diff --git a/.gitignore b/.gitignore index 4aa8d9d..5bdca21 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ server_key .env recipe.json lldap_config.toml +cert.pem +key.pem diff --git a/Cargo.lock b/Cargo.lock index 7f2d3f3..d9c1cad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -633,35 +633,43 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.0-beta.4" +version = "3.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcd70aa5597dbc42f7217a543f9ef2768b2ef823ba29036072d30e1d88e98406" +checksum = "85a35a599b11c089a7f49105658d089b8f2cf0882993c17daf6de15285c2c35d" dependencies = [ "atty", "bitflags", "clap_derive", + "clap_lex", "indexmap", "lazy_static", - "os_str_bytes", "strsim", "termcolor", - "textwrap", - "vec_map", + "textwrap 0.15.0", ] [[package]] name = "clap_derive" -version = "3.0.0-beta.4" +version = "3.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5bb0d655624a0b8770d1c178fb8ffcb1f91cc722cb08f451e3dc72465421ac" +checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" dependencies = [ - "heck", + "heck 0.4.0", "proc-macro-error", "proc-macro2", "quote", "syn", ] +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "combine" version = "3.8.1" @@ -1378,7 +1386,7 @@ checksum = "b4bf9cd823359d74ad3d3ecf1afd4a975f4ff2f891cdf9a66744606daf52de8c" dependencies = [ "graphql-introspection-query", "graphql-parser 0.2.3", - "heck", + "heck 0.3.3", "lazy_static", "proc-macro2", "quote", @@ -1450,6 +1458,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -2396,9 +2410,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "3.1.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6acbef58a60fe69ab50510a55bc8cdd4d6cf2283d27ad338f54cb52747a9cf2d" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" [[package]] name = "parking_lot" @@ -2778,7 +2792,7 @@ checksum = "f7f8e70d25cbc5d14d73c4f0c313ef505450a7c2a39b7e2ca421bc456a4574f6" dependencies = [ "bitflags", "crossterm", - "textwrap", + "textwrap 0.14.2", "unicode-segmentation", ] @@ -2922,7 +2936,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f30d6681c05300d4d92aa3dce08585b52c775735d632bb1f16f9f68f29c832d" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn", @@ -3247,7 +3261,7 @@ dependencies = [ "dotenv", "either", "futures", - "heck", + "heck 0.3.3", "proc-macro2", "quote", "sha2", @@ -3419,6 +3433,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "thiserror" version = "1.0.28" @@ -3840,12 +3860,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.3" diff --git a/lldap_config.docker_template.toml b/lldap_config.docker_template.toml index 3dbc6e0..8dccb5d 100644 --- a/lldap_config.docker_template.toml +++ b/lldap_config.docker_template.toml @@ -3,6 +3,10 @@ ## with "LLDAP_". For instance, "ldap_port" can be overridden with the ## "LLDAP_LDAP_PORT" variable. +## Tune the logging to be more verbose by setting this to be true. +## You can set it with the LLDAP_VERBOSE environment variable. +# verbose=false + ## The port on which to have the LDAP server. #ldap_port = 3890 @@ -96,6 +100,15 @@ key_file = "/data/private_key" ## Same for reply-to, optional. #reply_to="Do not reply " -## Tune the logging to be more verbose by setting this to be true. -## You can set it with the LLDAP_VERBOSE environment variable. -# verbose=false +## Options to configure LDAPS. +## To set these options from environment variables, use the following format +## (example with "port"): LLDAP_LDAPS_OPTIONS__PORT +#[ldaps_options] +## Whether to enable LDAPS. +#enabled=true +## Port on which to listen. +#port=6360 +## Certificate file. +#cert_file="/data/cert.pem" +## Certificate key file. +#key_file="/data/key.pem" diff --git a/server/Cargo.toml b/server/Cargo.toml index 6efbf12..bde60c4 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -18,7 +18,7 @@ async-trait = "0.1" base64 = "0.13" bincode = "1.3" chrono = { version = "*", features = [ "serde" ]} -clap = "3.0.0-beta.4" +clap = { version = "3.1.15", features = [ "std", "color", "suggestions", "derive", "env" ] } cron = "*" derive_builder = "0.10.2" futures = "*" diff --git a/server/src/infra/cli.rs b/server/src/infra/cli.rs index bd7293a..4472304 100644 --- a/server/src/infra/cli.rs +++ b/server/src/infra/cli.rs @@ -1,8 +1,8 @@ -use clap::Clap; +use clap::Parser; use lettre::message::Mailbox; /// lldap is a lightweight LDAP server -#[derive(Debug, Clap, Clone)] +#[derive(Debug, Parser, Clone)] #[clap(version, author)] pub struct CLIOpts { /// Export @@ -11,7 +11,7 @@ pub struct CLIOpts { } #[allow(clippy::large_enum_variant)] -#[derive(Debug, Clap, Clone)] +#[derive(Debug, Parser, Clone)] pub enum Command { /// Export the GraphQL schema to *.graphql. #[clap(name = "export_graphql_schema")] @@ -24,7 +24,7 @@ pub enum Command { SendTestEmail(TestEmailOpts), } -#[derive(Debug, Clap, Clone)] +#[derive(Debug, Parser, Clone)] pub struct GeneralConfigOpts { /// Change config file name. #[clap( @@ -40,7 +40,7 @@ pub struct GeneralConfigOpts { pub verbose: bool, } -#[derive(Debug, Clap, Clone)] +#[derive(Debug, Parser, Clone)] pub struct RunOpts { #[clap(flatten)] pub general_config: GeneralConfigOpts, @@ -54,10 +54,6 @@ pub struct RunOpts { #[clap(long, env = "LLDAP_LDAP_PORT")] pub ldap_port: Option, - /// Change ldap ssl port. Default: 6360 - #[clap(long, env = "LLDAP_LDAPS_PORT")] - pub ldaps_port: Option, - /// Change HTTP API port. Default: 17170 #[clap(long, env = "LLDAP_HTTP_PORT")] pub http_port: Option, @@ -68,9 +64,12 @@ pub struct RunOpts { #[clap(flatten)] pub smtp_opts: SmtpOpts, + + #[clap(flatten)] + pub ldaps_opts: LdapsOpts, } -#[derive(Debug, Clap, Clone)] +#[derive(Debug, Parser, Clone)] pub struct TestEmailOpts { #[clap(flatten)] pub general_config: GeneralConfigOpts, @@ -83,10 +82,30 @@ pub struct TestEmailOpts { pub smtp_opts: SmtpOpts, } -#[derive(Debug, Clap, Clone)] +#[derive(Debug, Parser, Clone)] +#[clap(next_help_heading = Some("LDAPS"), setting = clap::AppSettings::DeriveDisplayOrder)] +pub struct LdapsOpts { + /// Enable LDAPS. Default: false. + #[clap(long, env = "LLDAP_LDAPS_OPTIONS__ENABLED")] + pub ldaps_enabled: Option, + + /// Change ldap ssl port. Default: 6360 + #[clap(long, env = "LLDAP_LDAPS_OPTIONS__PORT")] + pub ldaps_port: Option, + + /// Ldaps certificate file. Default: cert.pem + #[clap(long, env = "LLDAP_LDAPS_OPTIONS__CERT_FILE")] + pub ldaps_cert_file: Option, + + /// Ldaps certificate key file. Default: key.pem + #[clap(long, env = "LLDAP_LDAPS_OPTIONS__KEY_FILE")] + pub ldaps_key_file: Option, +} + +#[derive(Debug, Parser, Clone)] +#[clap(next_help_heading = Some("SMTP"), setting = clap::AppSettings::DeriveDisplayOrder)] pub struct SmtpOpts { /// Sender email address. - #[clap(long)] #[clap(long, env = "LLDAP_SMTP_OPTIONS__FROM")] pub smtp_from: Option, @@ -115,7 +134,7 @@ pub struct SmtpOpts { pub smtp_tls_required: Option, } -#[derive(Debug, Clap, Clone)] +#[derive(Debug, Parser, Clone)] pub struct ExportGraphQLSchemaOpts { /// Output to a file. If not specified, the config is printed to the standard output. #[clap(short, long)] diff --git a/server/src/infra/configuration.rs b/server/src/infra/configuration.rs index ad9cc45..224ad2c 100644 --- a/server/src/infra/configuration.rs +++ b/server/src/infra/configuration.rs @@ -1,6 +1,6 @@ use crate::{ domain::handler::UserId, - infra::cli::{GeneralConfigOpts, RunOpts, SmtpOpts, TestEmailOpts}, + infra::cli::{GeneralConfigOpts, LdapsOpts, RunOpts, SmtpOpts, TestEmailOpts}, }; use anyhow::{Context, Result}; use figment::{ @@ -39,13 +39,30 @@ impl std::default::Default for MailOptions { } } +#[derive(Clone, Debug, Deserialize, Serialize, derive_builder::Builder)] +#[builder(pattern = "owned")] +pub struct LdapsOptions { + #[builder(default = "false")] + pub enabled: bool, + #[builder(default = "6360")] + pub port: u16, + #[builder(default = r#"String::from("cert.pem")"#)] + pub cert_file: String, + #[builder(default = r#"String::from("key.pem")"#)] + pub key_file: String, +} + +impl std::default::Default for LdapsOptions { + fn default() -> Self { + LdapsOptionsBuilder::default().build().unwrap() + } +} + #[derive(Clone, Debug, Deserialize, Serialize, derive_builder::Builder)] #[builder(pattern = "owned", build_fn(name = "private_build"))] pub struct Configuration { #[builder(default = "3890")] pub ldap_port: u16, - #[builder(default = "6360")] - pub ldaps_port: u16, #[builder(default = "17170")] pub http_port: u16, #[builder(default = r#"SecUtf8::from("secretjwtsecret")"#)] @@ -64,6 +81,8 @@ pub struct Configuration { pub key_file: String, #[builder(default)] pub smtp_options: MailOptions, + #[builder(default)] + pub ldaps_options: LdapsOptions, #[builder(default = r#"String::from("http://localhost")"#)] pub http_url: String, #[serde(skip)] @@ -144,10 +163,6 @@ impl ConfigOverrider for RunOpts { config.ldap_port = port; } - if let Some(port) = self.ldaps_port { - config.ldaps_port = port; - } - if let Some(port) = self.http_port { config.http_port = port; } @@ -156,6 +171,7 @@ impl ConfigOverrider for RunOpts { config.http_url = url.to_string(); } self.smtp_opts.override_config(config); + self.ldaps_opts.override_config(config); } } @@ -166,6 +182,23 @@ impl ConfigOverrider for TestEmailOpts { } } +impl ConfigOverrider for LdapsOpts { + fn override_config(&self, config: &mut Configuration) { + if let Some(enabled) = self.ldaps_enabled { + config.ldaps_options.enabled = enabled; + } + if let Some(port) = self.ldaps_port { + config.ldaps_options.port = port; + } + if let Some(path) = self.ldaps_cert_file.as_ref() { + config.ldaps_options.cert_file = path.clone(); + } + if let Some(path) = self.ldaps_key_file.as_ref() { + config.ldaps_options.key_file = path.clone(); + } + } +} + impl ConfigOverrider for GeneralConfigOpts { fn override_config(&self, config: &mut Configuration) { if self.verbose {