]> git.proxmox.com Git - proxmox-backup.git/commitdiff
api: factor out auth logger and use for all API authentication failures
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 4 Nov 2020 15:12:13 +0000 (16:12 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 4 Nov 2020 16:26:34 +0000 (17:26 +0100)
we have information here not available in the access log, especially
if the /api2/extjs formatter is used, which encapsulates errors in a
200 response.

So keep the auth log for now, but extend it use from create ticket
calls to all authentication failures for API calls, this ensures one
can also fail2ban tokens.

Do that logging in a central place, which makes it simple but means
that we do not have the user ID information available to include in
the log.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
debian/postinst
src/api2/access.rs
src/buildcfg.rs
src/server/rest.rs

index 300fdf46f29489539b08d6b12fe9c7f9b1e4bbb0..af5ee097f820dfbad7efd8b169e1879b4c4ee8bc 100644 (file)
@@ -25,6 +25,9 @@ case "$1" in
                                    sed -i '/^\s\+verify-schedule /d' /etc/proxmox-backup/datastore.cfg || true
                        fi
                fi
+               if dpkg --compare-versions "$2" 'le' '0.9.5-1'; then
+                       chown --quiet backup:backup /var/log/proxmox-backup/api/auth.log || true
+               fi
        fi
        # FIXME: Remove in future version once we're sure no broken entries remain in anyone's files
        if grep -q -e ':termproxy::[^@]\+: ' /var/log/proxmox-backup/tasks/active; then
index 9b9e85c0456cceb03a8975c7c079663696c0b480..3b59b3d3db2a6cd861cda719666a15ed591fd18a 100644 (file)
@@ -12,7 +12,6 @@ use proxmox::{http_err, list_subdirs_api_method};
 use crate::tools::ticket::{self, Empty, Ticket};
 use crate::auth_helpers::*;
 use crate::api2::types::*;
-use crate::tools::{FileLogOptions, FileLogger};
 
 use crate::config::acl as acl_config;
 use crate::config::acl::{PRIVILEGES, PRIV_SYS_AUDIT, PRIV_PERMISSIONS_MODIFY};
@@ -144,20 +143,13 @@ fn create_ticket(
     port: Option<u16>,
     rpcenv: &mut dyn RpcEnvironment,
 ) -> Result<Value, Error> {
-    let logger_options = FileLogOptions {
-        append: true,
-        prefix_time: true,
-        ..Default::default()
-    };
-    let mut auth_log = FileLogger::new("/var/log/proxmox-backup/api/auth.log", logger_options)?;
-
     match authenticate_user(&username, &password, path, privs, port) {
         Ok(true) => {
             let ticket = Ticket::new("PBS", &username)?.sign(private_auth_key(), None)?;
 
             let token = assemble_csrf_prevention_token(csrf_secret(), &username);
 
-            auth_log.log(format!("successful auth for user '{}'", username));
+            crate::server::rest::auth_logger()?.log(format!("successful auth for user '{}'", username));
 
             Ok(json!({
                 "username": username,
@@ -180,7 +172,7 @@ fn create_ticket(
                 username,
                 err.to_string()
             );
-            auth_log.log(&msg);
+            crate::server::rest::auth_logger()?.log(&msg);
             log::error!("{}", msg);
 
             Err(http_err!(UNAUTHORIZED, "permission check failed."))
index 402f2c9d33abbcfb6dbb8a15f1db5d46d304d7b1..c7e65032b542357057aff7aa4c3a088e63648a04 100644 (file)
@@ -16,9 +16,14 @@ pub const PROXMOX_BACKUP_RUN_DIR: &str = PROXMOX_BACKUP_RUN_DIR_M!();
 /// namespaced directory for persistent logging
 pub const PROXMOX_BACKUP_LOG_DIR: &str = PROXMOX_BACKUP_LOG_DIR_M!();
 
-/// logfile for all API reuests handled by the proxy and privileged API daemons
+/// logfile for all API reuests handled by the proxy and privileged API daemons. Note that not all
+/// failed logins can be logged here with full information, use the auth log for that.
 pub const API_ACCESS_LOG_FN: &str = concat!(PROXMOX_BACKUP_LOG_DIR_M!(), "/api/access.log");
 
+/// logfile for any failed authentication, via ticket or via token, and new successfull ticket
+/// creations. This file can be useful for fail2ban.
+pub const API_AUTH_LOG_FN: &str = concat!(PROXMOX_BACKUP_LOG_DIR_M!(), "/api/auth.log");
+
 /// the PID filename for the unprivileged proxy daemon
 pub const PROXMOX_BACKUP_PROXY_PID_FN: &str = concat!(PROXMOX_BACKUP_RUN_DIR_M!(), "/proxy.pid");
 
index 0749b891869d7e8f05f0675a8c327ef30caa3d3f..ea87c9c8fa0d2418ea9fbeb044368f9061b5f5e2 100644 (file)
@@ -164,6 +164,15 @@ fn log_response(
             ));
     }
 }
+pub fn auth_logger() -> Result<FileLogger, Error> {
+    let logger_options = tools::FileLogOptions {
+        append: true,
+        prefix_time: true,
+        owned_by_backup: true,
+        ..Default::default()
+    };
+    FileLogger::new(crate::buildcfg::API_AUTH_LOG_FN, logger_options)
+}
 
 fn get_proxied_peer(headers: &HeaderMap) -> Option<std::net::SocketAddr> {
     lazy_static! {
@@ -687,6 +696,10 @@ async fn handle_request(
                 match auth_result {
                     Ok(authid) => rpcenv.set_auth_id(Some(authid.to_string())),
                     Err(err) => {
+                        let peer = peer.ip();
+                        auth_logger()?
+                            .log(format!("authentication failure; rhost={} msg={}", peer, err));
+
                         // always delay unauthorized calls by 3 seconds (from start of request)
                         let err = http_err!(UNAUTHORIZED, "authentication failed - {}", err);
                         tokio::time::delay_until(Instant::from_std(delay_unauth_time)).await;