Add audit log target and move related syslog messages (https://github.com/opnsense/core/issues/4925)

o add new "audit" log target
o move user auth log entries into the new scope
o send config changes to audit log including message if provided
o add messages in user and group administration
This commit is contained in:
Ad Schellevis 2021-04-19 18:04:35 +02:00
parent 253a888c26
commit cfb84fe8e9
7 changed files with 49 additions and 6 deletions

View File

@ -244,6 +244,7 @@ function core_syslog()
{
$logfacilities = array();
$logfacilities['audit'] = array('facility' => array('audit'));
$logfacilities['configd'] = array('facility' => array('configd.py'));
$logfacilities['dhcpd'] = array('facility' => array('dhcpd', 'dhcrelay'));
$logfacilities['filter'] = array('facility' => array('filterlog'));

View File

@ -187,6 +187,7 @@ class AuthenticationFactory
*/
public function authenticate($service_name, $username, $password)
{
openlog("audit", LOG_ODELAY, LOG_AUTH);
$service = $this->getService($service_name);
if ($service !== null) {
$service->setUserName($username);
@ -203,6 +204,7 @@ class AuthenticationFactory
get_class($service),
get_class($authenticator)
));
closelog();
return true;
} else {
// since checkConstraints() is defined on the service, who doesn't know about the
@ -214,6 +216,7 @@ class AuthenticationFactory
get_class($service),
get_class($authenticator)
));
closelog();
return false;
}
} else {
@ -229,12 +232,13 @@ class AuthenticationFactory
}
}
syslog(LOG_WARNING, sprintf(
"user %s could not authenticate for %s. [using %s + %s]\n",
"user %s could not authenticate for %s. [using %s + %s]",
$username,
$service_name,
!empty($service) ? get_class($service) : '-',
!empty($authenticator) ? get_class($authenticator) : '-'
));
closelog();
return false;
}

View File

@ -463,6 +463,27 @@ class Config extends Singleton
}
}
/**
* send config change to audit log including the context we currently know of.
*/
private function auditLogChange($backup_filename, $revision=null)
{
openlog("audit", LOG_ODELAY, LOG_AUTH);
$append_message = "";
if (is_array($revision) && !empty($revision['description'])) {
$append_message = sprintf(" [%s]", $revision['description']);
}
syslog(LOG_NOTICE, sprintf(
"user %s%s changed configuration to %s in %s%s",
!empty($_SESSION["Username"]) ? $_SESSION["Username"] : "(system)",
!empty($_SERVER['REMOTE_ADDR']) ? "@" . $_SERVER['REMOTE_ADDR'] : "",
$backup_filename,
!empty($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['SCRIPT_NAME'],
$append_message
));
closelog();
}
/**
* backup current config
* @return string target filename
@ -626,6 +647,7 @@ class Config extends Singleton
fflush($this->config_file_handle);
$backup_filename = $backup ? $this->backup() : null;
if ($backup_filename) {
$this->auditLogChange($backup_filename, $revision);
// use syslog to trigger a new configd event, which should signal a syshook config (in batch).
// Althought we include the backup filename, the event handler is responsible to determine the
// last processed event itself. (it's merely added for debug purposes)

View File

@ -90,6 +90,7 @@
</Trust>
<Wizard url="/wizard.php?xml=system" cssClass="fa fa-magic fa-fw"/>
<LogFiles order="150" VisibleName="Log Files" cssClass="fa fa-eye fa-fw">
<Audit url="/ui/diagnostics/log/core/audit"/>
<Backend url="/ui/diagnostics/log/core/configd"/>
<General url="/ui/diagnostics/log/core/system"/>
<WebGUI VisibleName="Web GUI" url="/ui/diagnostics/log/core/lighttpd"/>

View File

@ -0,0 +1,6 @@
###################################################################
# Local syslog-ng configuration filter definition [audit].
###################################################################
filter f_local_audit {
program("audit") or facility(auth);
};

View File

@ -155,8 +155,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
}
}
}
write_config();
if (isset($id) && $a_group[$id]) {
$audit_msg = sprintf("group \"%s\" changed", $group['name']);
} else {
$audit_msg = sprintf("group \"%s\" created", $group['name']);
}
write_config($audit_msg);
// XXX: signal backend which users have changed.
// core_user_changed_groups() would change local group assignments in that case as well.
$new_members = !empty($group['member']) ? $group['member'] : array();

View File

@ -181,7 +181,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
local_user_del($a_user[$id]);
$userdeleted = $a_user[$id]['name'];
unset($a_user[$id]);
write_config();
write_config(sprintf('The user "%s" was successfully removed.', $userdeleted));
$savemsg = sprintf(gettext('The user "%s" was successfully removed.'), $userdeleted);
header(url_safe('Location: /system_usermanager.php?savemsg=%s', array($savemsg)));
exit;
@ -191,7 +191,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$certdeleted = lookup_cert($a_user[$id]['cert'][$pconfig['certid']]);
$certdeleted = $certdeleted['descr'];
unset($a_user[$id]['cert'][$pconfig['certid']]);
write_config();
write_config(sprintf('The certificate association "%s" was successfully removed.', $certdeleted));
$savemsg = sprintf(gettext('The certificate association "%s" was successfully removed.'), $certdeleted);
header(url_safe('Location: /system_usermanager.php?savemsg=%s&act=edit&userid=%d', array($savemsg, $id)));
exit;
@ -385,7 +385,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
local_user_set_groups($userent, $pconfig['groups']);
local_user_set($userent);
write_config();
if (isset($id)) {
$audit_msg = sprintf("user \"%s\" changed", $userent['name']);
} else {
$audit_msg = sprintf("user \"%s\" created", $userent['name']);
}
write_config($audit_msg);
// XXX: signal backend that the user has changed.
configdp_run('auth user changed', [$userent['name']]);