From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 7E8BC60EAB for ; Fri, 14 Jan 2022 11:51:02 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 6D9EC28ABD for ; Fri, 14 Jan 2022 11:50:32 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 8BD4F28AB2 for ; Fri, 14 Jan 2022 11:50:31 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 5FCFE4399F for ; Fri, 14 Jan 2022 11:50:31 +0100 (CET) From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= To: pbs-devel@lists.proxmox.com Date: Fri, 14 Jan 2022 11:50:25 +0100 Message-Id: <20220114105025.3339247-1-f.gruenbichler@proxmox.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.222 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pbs-devel] [PATCH proxmox-backup] node.cfg/proxy: add tls min/max protocol version X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Jan 2022 10:51:02 -0000 in a new 'tls' config key for future extensibility. Signed-off-by: Fabian Grünbichler --- pbs-api-types/src/lib.rs | 39 +++++++++++++++++++++++++++++++++ src/api2/node/config.rs | 4 ++++ src/bin/proxmox-backup-proxy.rs | 22 +++++++++++++++++-- src/config/node.rs | 10 ++++++++- 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/pbs-api-types/src/lib.rs b/pbs-api-types/src/lib.rs index 754e7b22..caf68ebf 100644 --- a/pbs-api-types/src/lib.rs +++ b/pbs-api-types/src/lib.rs @@ -359,6 +359,45 @@ pub enum NodePowerCommand { Shutdown, } +#[api()] +#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)] +/// TLS protocol version ('tls-1.2' or 'tls-1.3'). +pub enum TlsVersion { + /// TLS version 1.2 + #[serde(rename = "tls-1.2")] + Tls1_2, + /// TLS version 1.3 + #[serde(rename = "tls-1.3")] + Tls1_3, +} + +#[api( + properties: { + "min-ver": { + type: TlsVersion, + optional: true, + }, + "max-ver": { + type: TlsVersion, + optional: true, + }, + }, +)] +#[derive(Clone, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +/// TLS settings +pub struct TlsSettings { + /// Minimum TLS protocol version (requires proxy restart to take effect) + pub min_ver: Option, + /// Maximum TLS protocol version (requires proxy restart to take effect) + pub max_ver: Option, +} + +pub const TLS_SETTINGS_STRING_SCHEMA: Schema = StringSchema::new( + "TLS settings") + .format(&ApiStringFormat::PropertyString(&TlsSettings::API_SCHEMA)) + .schema(); + #[api()] #[derive(Eq, PartialEq, Debug, Serialize, Deserialize)] diff --git a/src/api2/node/config.rs b/src/api2/node/config.rs index c4af7b92..710e9ebc 100644 --- a/src/api2/node/config.rs +++ b/src/api2/node/config.rs @@ -62,6 +62,8 @@ pub enum DeletableProperty { /// Delete the ciphers-tls-1.2 property. #[serde(rename="ciphers-tls-1.2")] ciphers_tls_1_2, + /// Delete the tls property + tls, } #[api( @@ -121,6 +123,7 @@ pub fn update_node_config( DeletableProperty::email_from => { config.email_from = None; }, DeletableProperty::ciphers_tls_1_3 => { config.ciphers_tls_1_3 = None; }, DeletableProperty::ciphers_tls_1_2 => { config.ciphers_tls_1_2 = None; }, + DeletableProperty::tls => { config.tls = None; }, } } } @@ -135,6 +138,7 @@ pub fn update_node_config( if update.email_from.is_some() { config.email_from = update.email_from; } if update.ciphers_tls_1_3.is_some() { config.ciphers_tls_1_3 = update.ciphers_tls_1_3; } if update.ciphers_tls_1_2.is_some() { config.ciphers_tls_1_2 = update.ciphers_tls_1_2; } + if update.tls.is_some() { config.tls = update.tls; } crate::config::node::save_config(&config)?; diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs index 523966cf..eadfb2de 100644 --- a/src/bin/proxmox-backup-proxy.rs +++ b/src/bin/proxmox-backup-proxy.rs @@ -12,7 +12,7 @@ use hyper::{Body, StatusCode}; use hyper::header; use url::form_urlencoded; -use openssl::ssl::{SslMethod, SslAcceptor, SslFiletype}; +use openssl::ssl::{SslMethod, SslAcceptor, SslFiletype, SslVersion}; use tokio_stream::wrappers::ReceiverStream; use serde_json::{json, Value}; use http::{Method, HeaderMap}; @@ -22,6 +22,7 @@ use proxmox_sys::fs::CreateOptions; use proxmox_lang::try_block; use proxmox_router::{RpcEnvironment, RpcEnvironmentType, UserInformation}; use proxmox_http::client::{RateLimitedStream, ShareableRateLimit}; +use proxmox_schema::ApiType; use proxmox_sys::{task_log, task_warn}; use proxmox_sys::logrotate::LogRotate; @@ -51,7 +52,7 @@ use proxmox_time::CalendarEvent; use pbs_api_types::{ Authid, TapeBackupJobConfig, VerificationJobConfig, SyncJobConfig, DataStoreConfig, - PruneOptions, + PruneOptions, TlsVersion, TlsSettings, }; use proxmox_rest_server::daemon; @@ -358,6 +359,23 @@ fn make_tls_acceptor() -> Result { acceptor.set_certificate_chain_file(cert_path) .map_err(|err| format_err!("unable to read proxy cert {} - {}", cert_path, err))?; acceptor.set_options(openssl::ssl::SslOptions::NO_RENEGOTIATION); + + if let Some(tls_settings) = config.tls { + if let Ok(value) = TlsSettings::API_SCHEMA.parse_property_string(&tls_settings) { + if let Ok(settings) = serde_json::from_value::(value) { + let convert = |version: Option| { + version.map(|version| match version { + TlsVersion::Tls1_2 => SslVersion::TLS1_2, + TlsVersion::Tls1_3 => SslVersion::TLS1_3, + }) + }; + + acceptor.set_min_proto_version(convert(settings.min_ver))?; + acceptor.set_max_proto_version(convert(settings.max_ver))?; + } + } + } + acceptor.check_private_key().unwrap(); Ok(acceptor.build()) diff --git a/src/config/node.rs b/src/config/node.rs index 40d7b220..d96a0911 100644 --- a/src/config/node.rs +++ b/src/config/node.rs @@ -8,7 +8,7 @@ use proxmox_schema::{api, ApiStringFormat, ApiType, Updater}; use proxmox_http::ProxyConfig; -use pbs_api_types::{EMAIL_SCHEMA, OPENSSL_CIPHERS_TLS_1_2_SCHEMA, OPENSSL_CIPHERS_TLS_1_3_SCHEMA}; +use pbs_api_types::{EMAIL_SCHEMA, OPENSSL_CIPHERS_TLS_1_2_SCHEMA, OPENSSL_CIPHERS_TLS_1_3_SCHEMA, TLS_SETTINGS_STRING_SCHEMA}; use pbs_buildcfg::configdir; use pbs_config::{open_backup_lockfile, BackupLockGuard}; @@ -100,6 +100,10 @@ pub struct AcmeConfig { schema: OPENSSL_CIPHERS_TLS_1_2_SCHEMA, optional: true, }, + "tls": { + schema: TLS_SETTINGS_STRING_SCHEMA, + optional: true, + }, }, )] #[derive(Deserialize, Serialize, Updater)] @@ -138,6 +142,10 @@ pub struct NodeConfig { /// List of TLS ciphers for TLS <= 1.2 that will be used by the proxy. (Proxy has to be restarted for changes to take effect) #[serde(skip_serializing_if = "Option::is_none", rename="ciphers-tls-1.2")] pub ciphers_tls_1_2: Option, + + /// TLS protocol settings that will be used by the proxy. (Proxy has to be restarted for changes to take effect) + #[serde(skip_serializing_if = "Option::is_none")] + pub tls: Option, } impl NodeConfig { -- 2.30.2