5
0
mirror of git://git.proxmox.com/git/proxmox-backup.git synced 2025-02-09 09:57:40 +03:00

adapt to rest-server 0.3 and http 0.8 changes

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2023-01-25 12:06:49 +01:00 committed by Thomas Lamprecht
parent 26f03f9e53
commit 5aeeb44a32
11 changed files with 160 additions and 335 deletions

View File

@ -59,12 +59,12 @@ proxmox-async = "0.4"
proxmox-borrow = "1"
proxmox-compression = "0.1.1"
proxmox-fuse = "0.1.3"
proxmox-http = { version = "0.7", features = [ "client", "http-helpers", "websocket" ] } # see below
proxmox-http = { version = "0.8.0", features = [ "client", "http-helpers", "websocket" ] } # see below
proxmox-io = "1.0.1" # tools and client use "tokio" feature
proxmox-lang = "1.1"
proxmox-ldap = "0.1"
proxmox-metrics = "0.2"
proxmox-rest-server = "0.2.2"
proxmox-rest-server = { version = "0.3.0", features = [ "templates" ] }
# some use "cli", some use "cli" and "server", pbs-config uses nothing
proxmox-router = { version = "1.3.1", default_features = false }
# everything but pbs-config and pbs-client ues "api-macro"
@ -204,12 +204,12 @@ zstd.workspace = true
proxmox-async.workspace = true
proxmox-compression.workspace = true
proxmox-http = { workspace = true, features = [ "client-trait", "proxmox-async" ] } # pbs-client doesn't use these
proxmox-http = { workspace = true, features = [ "client-trait", "proxmox-async", "rate-limited-stream" ] } # pbs-client doesn't use these
proxmox-io.workspace = true
proxmox-lang.workspace = true
proxmox-ldap.workspace = true
proxmox-metrics.workspace = true
proxmox-rest-server.workspace = true
proxmox-rest-server = { workspace = true, features = [ "rate-limited-stream" ] }
proxmox-router = { workspace = true, features = [ "cli", "server"] }
proxmox-schema = { workspace = true, features = [ "api-macro" ] }
proxmox-section-config.workspace = true
@ -243,25 +243,28 @@ proxmox-rrd.workspace = true
# NOTE: You must run `cargo update` after changing this for it to take effect!
[patch.crates-io]
#proxmox-acme-rs = { path = "../proxmox-acme-rs" }
#proxmox-apt = { path = "../proxmox-apt" }
#proxmox-async = { path = "../proxmox/proxmox-async" }
#proxmox-compression = { path = "../proxmox/proxmox-compression" }
#proxmox-borrow = { path = "../proxmox/proxmox-borrow" }
#proxmox-compression = { path = "../proxmox/proxmox-compression" }
#proxmox-fuse = { path = "../proxmox-fuse" }
#proxmox-http = { path = "../proxmox/proxmox-http" }
#proxmox-io = { path = "../proxmox/proxmox-io" }
#proxmox-lang = { path = "../proxmox/proxmox-lang" }
#proxmox-openid = { path = "../proxmox-openid-rs" }
#proxmox-router = { path = "../proxmox/proxmox-rest-server" }
#proxmox-rest-server = { path = "../proxmox/proxmox-rest-server" }
#proxmox-router = { path = "../proxmox/proxmox-router" }
#proxmox-schema = { path = "../proxmox/proxmox-schema" }
#proxmox-section-config = { path = "../proxmox/proxmox-section-config" }
#proxmox-shared-memory = { path = "../proxmox/proxmox-shared-memory" }
#proxmox-sys = { path = "../proxmox/proxmox-sys" }
#proxmox-serde = { path = "../proxmox/proxmox-serde" }
#proxmox-shared-memory = { path = "../proxmox/proxmox-shared-memory" }
#proxmox-subscription = { path = "../proxmox/proxmox-subscription" }
#proxmox-sys = { path = "../proxmox/proxmox-sys" }
#proxmox-tfa = { path = "../proxmox/proxmox-tfa" }
#proxmox-time = { path = "../proxmox/proxmox-time" }
#proxmox-uuid = { path = "../proxmox/proxmox-uuid" }
#proxmox-apt = { path = "../proxmox-apt" }
#proxmox-openid = { path = "../proxmox-openid-rs" }
#pxar = { path = "../pxar" }
[features]

18
debian/control vendored
View File

@ -47,19 +47,23 @@ Build-Depends: debhelper (>= 12),
librust-proxmox-borrow-1+default-dev,
librust-proxmox-compression-0.1+default-dev (>= 0.1.1-~~),
librust-proxmox-fuse-0.1+default-dev (>= 0.1.3-~~),
librust-proxmox-http-0.7+client-dev,
librust-proxmox-http-0.7+client-trait-dev,
librust-proxmox-http-0.7+default-dev,
librust-proxmox-http-0.7+http-helpers-dev,
librust-proxmox-http-0.7+proxmox-async-dev,
librust-proxmox-http-0.7+websocket-dev,
librust-proxmox-http-0.8+client-dev,
librust-proxmox-http-0.8+client-trait-dev,
librust-proxmox-http-0.8+default-dev,
librust-proxmox-http-0.8+http-helpers-dev,
librust-proxmox-http-0.8+proxmox-async-dev,
librust-proxmox-http-0.8+rate-limited-stream-dev,
librust-proxmox-http-0.8+rate-limiter-dev,
librust-proxmox-http-0.8+websocket-dev,
librust-proxmox-io-1+default-dev (>= 1.0.1-~~),
librust-proxmox-io-1+tokio-dev (>= 1.0.1-~~),
librust-proxmox-lang-1+default-dev (>= 1.1-~~),
librust-proxmox-ldap-0.1+default-dev,
librust-proxmox-metrics-0.2+default-dev,
librust-proxmox-openid-0.9+default-dev (>= 0.9.9-~~),
librust-proxmox-rest-server-0.2+default-dev (>= 0.2.2-~~),
librust-proxmox-rest-server-0.3+default-dev,
librust-proxmox-rest-server-0.3+rate-limited-stream-dev,
librust-proxmox-rest-server-0.3+templates-dev,
librust-proxmox-router-1+cli-dev (>= 1.3.1-~~),
librust-proxmox-router-1+default-dev (>= 1.3.1-~~),
librust-proxmox-router-1+server-dev (>= 1.3.1-~~),

View File

@ -35,7 +35,7 @@ pathpatterns.workspace = true
proxmox-async.workspace = true
proxmox-compression.workspace = true
proxmox-http.workspace = true
proxmox-http = { workspace = true, features = [ "rate-limiter" ] }
proxmox-io = { workspace = true, features = [ "tokio" ] }
proxmox-lang.workspace = true
proxmox-router = { workspace = true, features = [ "cli", "server" ] }

View File

@ -22,9 +22,9 @@ use proxmox_sys::fs::{file_get_json, replace_file, CreateOptions};
use proxmox_sys::linux::tty;
use proxmox_async::broadcast_future::BroadcastFuture;
use proxmox_http::client::{HttpsConnector, RateLimiter};
use proxmox_http::client::HttpsConnector;
use proxmox_http::uri::{build_authority, json_object_to_query};
use proxmox_http::ProxyConfig;
use proxmox_http::{ProxyConfig, RateLimiter};
use pbs_api_types::percent_encoding::DEFAULT_ENCODE_SET;
use pbs_api_types::{Authid, RateLimitConfig, Userid};

View File

@ -107,10 +107,13 @@ async fn run() -> Result<(), Error> {
}
};
let adaptor = StaticAuthAdapter::new()
.map_err(|err| format_err!("reading ticket file failed: {}", err))?;
let ticket =
auth::read_ticket().map_err(|err| format_err!("reading ticket file failed: {}", err))?;
let config = ApiConfig::new("", &ROUTER, RpcEnvironmentType::PUBLIC, adaptor)?;
let config = ApiConfig::new("", RpcEnvironmentType::PUBLIC)
.default_api2_handler(&ROUTER)
.index_handler_func(|_, _| auth::get_index())
.auth_handler_func(move |h, m| Box::pin(auth::check_auth(Arc::clone(&ticket), h, m)));
let rest_server = RestServer::new(config);
let vsock_fd = get_vsock_fd()?;

View File

@ -3,15 +3,15 @@ use std::fs::File;
use std::future::Future;
use std::io::prelude::*;
use std::pin::Pin;
use std::sync::Arc;
use anyhow::{bail, format_err, Error};
use http::request::Parts;
use http::HeaderMap;
use hyper::{Body, Method, Response, StatusCode};
use proxmox_router::UserInformation;
use proxmox_rest_server::{AuthError, RestEnvironment, ServerAdapter};
use proxmox_rest_server::AuthError;
const TICKET_FILE: &str = "/ticket";
@ -29,61 +29,49 @@ impl UserInformation for SimpleUserInformation {
}
}
pub struct StaticAuthAdapter {
ticket: String,
}
impl StaticAuthAdapter {
pub fn new() -> Result<Self, Error> {
let mut ticket_file = File::open(TICKET_FILE)?;
let mut ticket = String::new();
let len = ticket_file.read_to_string(&mut ticket)?;
if len == 0 {
bail!("invalid ticket: cannot be empty");
}
Ok(StaticAuthAdapter { ticket })
pub fn read_ticket() -> Result<Arc<str>, Error> {
let mut ticket_file = File::open(TICKET_FILE)?;
let mut ticket = String::new();
let len = ticket_file.read_to_string(&mut ticket)?;
if len == 0 {
bail!("invalid ticket: cannot be empty");
}
Ok(ticket.into())
}
impl ServerAdapter for StaticAuthAdapter {
fn check_auth<'a>(
&'a self,
headers: &'a HeaderMap,
_method: &'a Method,
) -> Pin<
Box<
dyn Future<Output = Result<(String, Box<dyn UserInformation + Sync + Send>), AuthError>>
+ Send
+ 'a,
>,
> {
Box::pin(async move {
match headers.get(hyper::header::AUTHORIZATION) {
Some(header) if header.to_str().unwrap_or("") == self.ticket => {
let user_info: Box<dyn UserInformation + Send + Sync> =
Box::new(SimpleUserInformation {});
Ok((String::from("root@pam"), user_info))
}
_ => Err(AuthError::Generic(format_err!(
"invalid file restore ticket provided"
))),
pub fn check_auth<'a>(
ticket: Arc<str>,
headers: &'a HeaderMap,
_method: &'a Method,
) -> Pin<
Box<
dyn Future<Output = Result<(String, Box<dyn UserInformation + Sync + Send>), AuthError>>
+ Send
+ 'a,
>,
> {
Box::pin(async move {
match headers.get(hyper::header::AUTHORIZATION) {
Some(header) if header.to_str().unwrap_or("") == &*ticket => {
let user_info: Box<dyn UserInformation + Send + Sync> =
Box::new(SimpleUserInformation {});
Ok((String::from("root@pam"), user_info))
}
})
}
fn get_index(
&self,
_env: RestEnvironment,
_parts: Parts,
) -> Pin<Box<dyn Future<Output = http::Response<Body>> + Send>> {
Box::pin(async move {
let index = "<center><h1>Proxmox Backup Restore Daemon/h1></center>";
Response::builder()
.status(StatusCode::OK)
.header(hyper::header::CONTENT_TYPE, "text/html")
.body(index.into())
.unwrap()
})
}
_ => Err(AuthError::Generic(format_err!(
"invalid file restore ticket provided"
))),
}
})
}
pub fn get_index() -> Pin<Box<dyn Future<Output = http::Response<Body>> + Send>> {
Box::pin(async move {
let index = "<center><h1>Proxmox Backup Restore Daemon/h1></center>";
Response::builder()
.status(StatusCode::OK)
.header(hyper::header::CONTENT_TYPE, "text/html")
.body(index.into())
.unwrap()
})
}

View File

@ -3,18 +3,14 @@ use std::pin::Pin;
use anyhow::{bail, Error};
use futures::*;
use http::request::Parts;
use http::HeaderMap;
use http::Response;
use hyper::{Body, Method, StatusCode};
use hyper::{Body, StatusCode};
use proxmox_lang::try_block;
use proxmox_router::{RpcEnvironmentType, UserInformation};
use proxmox_router::RpcEnvironmentType;
use proxmox_sys::fs::CreateOptions;
use proxmox_rest_server::{
daemon, ApiConfig, AuthError, RestEnvironment, RestServer, ServerAdapter,
};
use proxmox_rest_server::{daemon, ApiConfig, RestServer};
use proxmox_backup::auth_helpers::*;
use proxmox_backup::config;
@ -31,38 +27,16 @@ fn main() {
}
}
struct ProxmoxBackupApiAdapter;
fn get_index() -> Pin<Box<dyn Future<Output = Response<Body>> + Send>> {
Box::pin(async move {
let index = "<center><h1>Proxmox Backup API Server</h1></center>";
impl ServerAdapter for ProxmoxBackupApiAdapter {
fn get_index(
&self,
_env: RestEnvironment,
_parts: Parts,
) -> Pin<Box<dyn Future<Output = Response<Body>> + Send>> {
Box::pin(async move {
let index = "<center><h1>Proxmox Backup API Server</h1></center>";
Response::builder()
.status(StatusCode::OK)
.header(hyper::header::CONTENT_TYPE, "text/html")
.body(index.into())
.unwrap()
})
}
fn check_auth<'a>(
&'a self,
headers: &'a HeaderMap,
method: &'a Method,
) -> Pin<
Box<
dyn Future<Output = Result<(String, Box<dyn UserInformation + Sync + Send>), AuthError>>
+ Send
+ 'a,
>,
> {
Box::pin(async move { check_pbs_auth(headers, method).await })
}
Response::builder()
.status(StatusCode::OK)
.header(hyper::header::CONTENT_TYPE, "text/html")
.body(index.into())
.unwrap()
})
}
async fn run() -> Result<(), Error> {
@ -97,13 +71,6 @@ async fn run() -> Result<(), Error> {
}
let _ = csrf_secret(); // load with lazy_static
let mut config = ApiConfig::new(
pbs_buildcfg::JS_DIR,
&proxmox_backup::api2::ROUTER,
RpcEnvironmentType::PRIVILEGED,
ProxmoxBackupApiAdapter,
)?;
let backup_user = pbs_config::backup_user()?;
let mut commando_sock = proxmox_rest_server::CommandSocket::new(
proxmox_rest_server::our_ctrl_sock(),
@ -117,19 +84,22 @@ async fn run() -> Result<(), Error> {
.owner(backup_user.uid)
.group(backup_user.gid);
config.enable_access_log(
pbs_buildcfg::API_ACCESS_LOG_FN,
Some(dir_opts.clone()),
Some(file_opts.clone()),
&mut commando_sock,
)?;
config.enable_auth_log(
pbs_buildcfg::API_AUTH_LOG_FN,
Some(dir_opts.clone()),
Some(file_opts.clone()),
&mut commando_sock,
)?;
let config = ApiConfig::new(pbs_buildcfg::JS_DIR, RpcEnvironmentType::PRIVILEGED)
.index_handler_func(|_, _| get_index())
.auth_handler_func(|h, m| Box::pin(check_pbs_auth(h, m)))
.default_api2_handler(&proxmox_backup::api2::ROUTER)
.enable_access_log(
pbs_buildcfg::API_ACCESS_LOG_FN,
Some(dir_opts.clone()),
Some(file_opts.clone()),
&mut commando_sock,
)?
.enable_auth_log(
pbs_buildcfg::API_AUTH_LOG_FN,
Some(dir_opts.clone()),
Some(file_opts.clone()),
&mut commando_sock,
)?;
let rest_server = RestServer::new(config);
proxmox_rest_server::init_worker_tasks(

View File

@ -1,7 +1,4 @@
use std::future::Future;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use anyhow::{bail, format_err, Error};
@ -12,28 +9,22 @@ use hyper::header;
use hyper::{Body, StatusCode};
use url::form_urlencoded;
use http::{HeaderMap, Method};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use openssl::ssl::SslAcceptor;
use serde_json::{json, Value};
use tokio_stream::wrappers::ReceiverStream;
use proxmox_http::client::RateLimitedStream;
use proxmox_lang::try_block;
use proxmox_metrics::MetricsData;
use proxmox_router::{RpcEnvironment, RpcEnvironmentType, UserInformation};
use proxmox_router::{RpcEnvironment, RpcEnvironmentType};
use proxmox_sys::fs::{CreateOptions, FileSystemInformation};
use proxmox_sys::linux::{
procfs::{Loadavg, ProcFsMemInfo, ProcFsNetDev, ProcFsStat},
socket::set_tcp_keepalive,
};
use proxmox_sys::linux::procfs::{Loadavg, ProcFsMemInfo, ProcFsNetDev, ProcFsStat};
use proxmox_sys::logrotate::LogRotate;
use proxmox_sys::{task_log, task_warn};
use pbs_datastore::DataStore;
use proxmox_rest_server::{
cleanup_old_tasks, cookie_from_header, rotate_task_log_archive, ApiConfig, AuthError,
RestEnvironment, RestServer, ServerAdapter, WorkerTask,
cleanup_old_tasks, cookie_from_header, rotate_task_log_archive, ApiConfig, RestEnvironment,
RestServer, WorkerTask,
};
use proxmox_backup::rrd_cache::{
@ -89,32 +80,6 @@ fn main() -> Result<(), Error> {
proxmox_async::runtime::main(run())
}
struct ProxmoxBackupProxyAdapter;
impl ServerAdapter for ProxmoxBackupProxyAdapter {
fn get_index(
&self,
env: RestEnvironment,
parts: Parts,
) -> Pin<Box<dyn Future<Output = Response<Body>> + Send>> {
Box::pin(get_index_future(env, parts))
}
fn check_auth<'a>(
&'a self,
headers: &'a HeaderMap,
method: &'a Method,
) -> Pin<
Box<
dyn Future<Output = Result<(String, Box<dyn UserInformation + Sync + Send>), AuthError>>
+ Send
+ 'a,
>,
> {
Box::pin(async move { check_pbs_auth(headers, method).await })
}
}
/// check for a cookie with the user-preferred language, fallback to the config one if not set or
/// not existing
fn get_language(headers: &http::HeaderMap) -> String {
@ -217,29 +182,28 @@ async fn run() -> Result<(), Error> {
let rrd_cache = initialize_rrd_cache()?;
rrd_cache.apply_journal()?;
let mut config = ApiConfig::new(
pbs_buildcfg::JS_DIR,
&proxmox_backup::api2::ROUTER,
RpcEnvironmentType::PUBLIC,
ProxmoxBackupProxyAdapter,
)?;
config.add_alias("novnc", "/usr/share/novnc-pve");
config.add_alias("extjs", "/usr/share/javascript/extjs");
config.add_alias("qrcodejs", "/usr/share/javascript/qrcodejs");
config.add_alias("fontawesome", "/usr/share/fonts-font-awesome");
config.add_alias("xtermjs", "/usr/share/pve-xtermjs");
config.add_alias("locale", "/usr/share/pbs-i18n");
config.add_alias(
"widgettoolkit",
"/usr/share/javascript/proxmox-widget-toolkit",
);
config.add_alias("docs", "/usr/share/doc/proxmox-backup/html");
let mut indexpath = PathBuf::from(pbs_buildcfg::JS_DIR);
indexpath.push("index.hbs");
config.register_template("index", &indexpath)?;
config.register_template("console", "/usr/share/pve-xtermjs/index.html.hbs")?;
let mut config = ApiConfig::new(pbs_buildcfg::JS_DIR, RpcEnvironmentType::PUBLIC)
.index_handler_func(|e, p| Box::pin(get_index_future(e, p)))
.auth_handler_func(|h, m| Box::pin(check_pbs_auth(h, m)))
.register_template("index", &indexpath)?
.register_template("console", "/usr/share/pve-xtermjs/index.html.hbs")?
.default_api2_handler(&proxmox_backup::api2::ROUTER)
.aliases([
("novnc", "/usr/share/novnc-pve"),
("extjs", "/usr/share/javascript/extjs"),
("qrcodejs", "/usr/share/javascript/qrcodejs"),
("fontawesome", "/usr/share/fonts-font-awesome"),
("xtermjs", "/usr/share/pve-xtermjs"),
("locale", "/usr/share/pbs-i18n"),
(
"widgettoolkit",
"/usr/share/javascript/proxmox-widget-toolkit",
),
("docs", "/usr/share/doc/proxmox-backup/html"),
]);
let backup_user = pbs_config::backup_user()?;
let mut commando_sock = proxmox_rest_server::CommandSocket::new(
@ -254,19 +218,19 @@ async fn run() -> Result<(), Error> {
.owner(backup_user.uid)
.group(backup_user.gid);
config.enable_access_log(
pbs_buildcfg::API_ACCESS_LOG_FN,
Some(dir_opts.clone()),
Some(file_opts.clone()),
&mut commando_sock,
)?;
config.enable_auth_log(
pbs_buildcfg::API_AUTH_LOG_FN,
Some(dir_opts.clone()),
Some(file_opts.clone()),
&mut commando_sock,
)?;
config = config
.enable_access_log(
pbs_buildcfg::API_ACCESS_LOG_FN,
Some(dir_opts.clone()),
Some(file_opts.clone()),
&mut commando_sock,
)?
.enable_auth_log(
pbs_buildcfg::API_AUTH_LOG_FN,
Some(dir_opts.clone()),
Some(file_opts.clone()),
&mut commando_sock,
)?;
let rest_server = RestServer::new(config);
proxmox_rest_server::init_worker_tasks(
@ -304,11 +268,14 @@ async fn run() -> Result<(), Error> {
Ok(Value::Null)
})?;
let connections = proxmox_rest_server::connection::AcceptBuilder::with_acceptor(acceptor)
.debug(debug)
.rate_limiter_lookup(Arc::new(lookup_rate_limiter))
.tcp_keepalive_time(PROXMOX_BACKUP_TCP_KEEPALIVE_TIME);
let server = daemon::create_daemon(
([0, 0, 0, 0, 0, 0, 0, 0], 8007).into(),
move |listener| {
let connections = accept_connections(listener, acceptor, debug);
let connections = hyper::server::accept::from_stream(ReceiverStream::new(connections));
let connections = connections.accept(listener);
Ok(async {
daemon::systemd_notify(daemon::SystemdNotify::Ready)?;
@ -368,128 +335,18 @@ fn make_tls_acceptor() -> Result<SslAcceptor, Error> {
let ciphers_tls_1_3 = config.ciphers_tls_1_3;
let ciphers_tls_1_2 = config.ciphers_tls_1_2;
let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
let mut acceptor = proxmox_rest_server::connection::TlsAcceptorBuilder::new()
.certificate_paths_pem(key_path, cert_path);
//let mut acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
if let Some(ciphers) = ciphers_tls_1_3.as_deref() {
acceptor.set_ciphersuites(ciphers)?;
acceptor = acceptor.cipher_suites(ciphers.to_string());
}
if let Some(ciphers) = ciphers_tls_1_2.as_deref() {
acceptor.set_cipher_list(ciphers)?;
acceptor = acceptor.cipher_list(ciphers.to_string());
}
acceptor
.set_private_key_file(key_path, SslFiletype::PEM)
.map_err(|err| format_err!("unable to read proxy key {key_path} - {err}"))?;
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);
acceptor.check_private_key().unwrap();
Ok(acceptor.build())
}
type ClientStreamResult = Result<
std::pin::Pin<Box<tokio_openssl::SslStream<RateLimitedStream<tokio::net::TcpStream>>>>,
Error,
>;
const MAX_PENDING_ACCEPTS: usize = 1024;
fn accept_connections(
listener: tokio::net::TcpListener,
acceptor: Arc<Mutex<openssl::ssl::SslAcceptor>>,
debug: bool,
) -> tokio::sync::mpsc::Receiver<ClientStreamResult> {
let (sender, receiver) = tokio::sync::mpsc::channel(MAX_PENDING_ACCEPTS);
tokio::spawn(accept_connection(listener, acceptor, debug, sender));
receiver
}
async fn accept_connection(
listener: tokio::net::TcpListener,
acceptor: Arc<Mutex<openssl::ssl::SslAcceptor>>,
debug: bool,
sender: tokio::sync::mpsc::Sender<ClientStreamResult>,
) {
let accept_counter = Arc::new(());
let mut shutdown_future = proxmox_rest_server::shutdown_future().fuse();
loop {
let (sock, peer) = select! {
res = listener.accept().fuse() => match res {
Ok(conn) => conn,
Err(err) => {
eprintln!("error accepting tcp connection: {err}");
continue;
}
},
_ = shutdown_future => break,
};
sock.set_nodelay(true).unwrap();
let _ = set_tcp_keepalive(sock.as_raw_fd(), PROXMOX_BACKUP_TCP_KEEPALIVE_TIME);
let sock =
RateLimitedStream::with_limiter_update_cb(sock, move || lookup_rate_limiter(peer));
let ssl = {
// limit acceptor_guard scope
// Acceptor can be reloaded using the command socket "reload-certificate" command
let acceptor_guard = acceptor.lock().unwrap();
match openssl::ssl::Ssl::new(acceptor_guard.context()) {
Ok(ssl) => ssl,
Err(err) => {
eprintln!("failed to create Ssl object from Acceptor context - {err}");
continue;
}
}
};
let stream = match tokio_openssl::SslStream::new(ssl, sock) {
Ok(stream) => stream,
Err(err) => {
eprintln!("failed to create SslStream using ssl and connection socket - {err}");
continue;
}
};
let mut stream = Box::pin(stream);
let sender = sender.clone();
if Arc::strong_count(&accept_counter) > MAX_PENDING_ACCEPTS {
eprintln!("connection rejected - to many open connections");
continue;
}
let accept_counter = Arc::clone(&accept_counter);
tokio::spawn(async move {
let accept_future =
tokio::time::timeout(Duration::new(10, 0), stream.as_mut().accept());
let result = accept_future.await;
match result {
Ok(Ok(())) => {
if sender.send(Ok(stream)).await.is_err() && debug {
eprintln!("detect closed connection channel");
}
}
Ok(Err(err)) => {
if debug {
eprintln!("https handshake failed - {err}");
}
}
Err(_) => {
if debug {
eprintln!("https handshake timeout");
}
}
}
drop(accept_counter); // decrease reference count
});
}
acceptor.build()
}
fn start_stat_generator() {

View File

@ -11,7 +11,7 @@ use proxmox_schema::{api, ApiType, ParameterSchema, Schema};
use pbs_api_types::PROXMOX_UPID_REGEX;
use pbs_client::view_task_result;
use proxmox_rest_server::normalize_uri_path;
use proxmox_rest_server::normalize_path_with_components;
use proxmox_backup::client_helpers::connect_to_localhost;
@ -94,7 +94,7 @@ async fn get_child_links(
path: &str,
rpcenv: &mut dyn RpcEnvironment,
) -> Result<Vec<String>, Error> {
let (path, components) = normalize_uri_path(path)?;
let (path, components) = normalize_path_with_components(path)?;
let info = &proxmox_backup::api2::ROUTER
.find_route(&components, &mut HashMap::new())
@ -132,7 +132,7 @@ fn get_api_method(
_ => unreachable!(),
};
let mut uri_param = HashMap::new();
let (path, components) = normalize_uri_path(path)?;
let (path, components) = normalize_path_with_components(path)?;
if let Some(method) =
&proxmox_backup::api2::ROUTER.find_method(&components, method.clone(), &mut uri_param)
{
@ -384,7 +384,7 @@ async fn get_api_children(
let mut res = Vec::new();
for link in get_child_links(&path, rpcenv).await? {
let path = format!("{}/{}", path, link);
let (path, _) = normalize_uri_path(&path)?;
let (path, _) = normalize_path_with_components(&path)?;
let mut cap = String::new();
if get_child_links(&path, rpcenv).await.is_ok() {

View File

@ -7,7 +7,7 @@ use nix::sys::stat::Mode;
use proxmox_sys::fs::{create_path, CreateOptions};
use proxmox_http::client::{RateLimit, RateLimiter, ShareableRateLimit};
use proxmox_http::{RateLimit, RateLimiter, ShareableRateLimit};
use proxmox_shared_memory::{check_subtype, initialize_subtype};
use proxmox_shared_memory::{Init, SharedMemory, SharedMutex};

View File

@ -8,7 +8,7 @@ use std::time::Instant;
use anyhow::Error;
use cidr::IpInet;
use proxmox_http::client::{RateLimiter, ShareableRateLimit};
use proxmox_http::{RateLimiter, ShareableRateLimit};
use proxmox_section_config::SectionConfigData;
use proxmox_time::{parse_daily_duration, DailyDuration, TmEditor};