mirror of
https://github.com/sudo-project/sudo.git
synced 2025-08-22 09:57:41 +00:00
Add json_compact log type for compact/minified JSON.
The "json_compact" log type logs one event per line in compact/minified JSON format. GitHub issue #357.
This commit is contained in:
parent
b3ade1c5f9
commit
1debad3bec
@ -16,7 +16,7 @@
|
|||||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.TH "SUDO_LOGSRVD.CONF" "@mansectform@" "January 16, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
.TH "SUDO_LOGSRVD.CONF" "@mansectform@" "March 8, 2024" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||||
.nh
|
.nh
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
@ -682,15 +682,48 @@ Defaults to
|
|||||||
.TP 6n
|
.TP 6n
|
||||||
log_format = string
|
log_format = string
|
||||||
The event log format.
|
The event log format.
|
||||||
Supported log formats are
|
Supported log formats are:
|
||||||
\(lqsudo\(rq
|
.PP
|
||||||
for traditional sudo-style logs and
|
.RS 6n
|
||||||
\(lqjson\(rq
|
.PD 0
|
||||||
for JSON-format logs.
|
.TP 6n
|
||||||
|
json
|
||||||
|
Log events in JSON format.
|
||||||
The JSON log entries contain the full contents of the accept, reject, exit
|
The JSON log entries contain the full contents of the accept, reject, exit
|
||||||
and alert messages.
|
and alert messages.
|
||||||
|
When logging to a file, the entire file is treated as a single JSON
|
||||||
|
object consisting of multiple events, each event spanning multiple lines.
|
||||||
|
When logging via
|
||||||
|
\fIsyslog\fR,
|
||||||
|
events are stored in compact (minified) format, described below.
|
||||||
|
.PD
|
||||||
|
.TP 6n
|
||||||
|
json_compact
|
||||||
|
Log events in compact (minified) JSON format.
|
||||||
|
Each event is written as a separate JSON object on single line without
|
||||||
|
extraneous white space.
|
||||||
|
When logging via
|
||||||
|
\fIsyslog\fR,
|
||||||
|
there is no difference between the
|
||||||
|
\fIjson\fR
|
||||||
|
and
|
||||||
|
\fIjson_compact\fR
|
||||||
|
formats.
|
||||||
|
Due to limitations of the protocol, JSON events sent via
|
||||||
|
\fIsyslog\fR
|
||||||
|
may be truncated.
|
||||||
|
.TP 6n
|
||||||
|
sudo
|
||||||
|
Log events in traditional sudo-style log format.
|
||||||
|
See the
|
||||||
|
\fIEVENT LOGGING\fR
|
||||||
|
section in
|
||||||
|
sudoers(@mansectform@)
|
||||||
|
for details.
|
||||||
|
.PP
|
||||||
The default value is
|
The default value is
|
||||||
\fIsudo\fR.
|
\fIsudo\fR.
|
||||||
|
.RE
|
||||||
.SS "syslog"
|
.SS "syslog"
|
||||||
The
|
The
|
||||||
\fIsyslog\fR
|
\fIsyslog\fR
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.Dd January 16, 2023
|
.Dd March 8, 2024
|
||||||
.Dt SUDO_LOGSRVD.CONF @mansectform@
|
.Dt SUDO_LOGSRVD.CONF @mansectform@
|
||||||
.Os Sudo @PACKAGE_VERSION@
|
.Os Sudo @PACKAGE_VERSION@
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -611,13 +611,40 @@ Defaults to
|
|||||||
.Em false .
|
.Em false .
|
||||||
.It log_format = string
|
.It log_format = string
|
||||||
The event log format.
|
The event log format.
|
||||||
Supported log formats are
|
Supported log formats are:
|
||||||
.Dq sudo
|
.Bl -tag -width 4n
|
||||||
for traditional sudo-style logs and
|
.It json
|
||||||
.Dq json
|
Log events in JSON format.
|
||||||
for JSON-format logs.
|
|
||||||
The JSON log entries contain the full contents of the accept, reject, exit
|
The JSON log entries contain the full contents of the accept, reject, exit
|
||||||
and alert messages.
|
and alert messages.
|
||||||
|
When logging to a file, the entire file is treated as a single JSON
|
||||||
|
object consisting of multiple events, each event spanning multiple lines.
|
||||||
|
When logging via
|
||||||
|
.Em syslog ,
|
||||||
|
events are stored in compact (minified) format, described below.
|
||||||
|
.It json_compact
|
||||||
|
Log events in compact (minified) JSON format.
|
||||||
|
Each event is written as a separate JSON object on single line without
|
||||||
|
extraneous white space.
|
||||||
|
When logging via
|
||||||
|
.Em syslog ,
|
||||||
|
there is no difference between the
|
||||||
|
.Em json
|
||||||
|
and
|
||||||
|
.Em json_compact
|
||||||
|
formats.
|
||||||
|
Due to limitations of the protocol, JSON events sent via
|
||||||
|
.Em syslog
|
||||||
|
may be truncated.
|
||||||
|
.It sudo
|
||||||
|
Log events in traditional sudo-style log format.
|
||||||
|
See the
|
||||||
|
.Em "EVENT LOGGING"
|
||||||
|
section in
|
||||||
|
.Xr sudoers @mansectform@
|
||||||
|
for details.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
The default value is
|
The default value is
|
||||||
.Em sudo .
|
.Em sudo .
|
||||||
.El
|
.El
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
.nr BA @BAMAN@
|
.nr BA @BAMAN@
|
||||||
.nr LC @LCMAN@
|
.nr LC @LCMAN@
|
||||||
.nr PS @PSMAN@
|
.nr PS @PSMAN@
|
||||||
.TH "SUDOERS" "@mansectform@" "December 19, 2023" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
.TH "SUDOERS" "@mansectform@" "March 8, 2024" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
|
||||||
.nh
|
.nh
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
@ -5381,18 +5381,35 @@ Supported log formats are:
|
|||||||
.PD 0
|
.PD 0
|
||||||
.TP 6n
|
.TP 6n
|
||||||
json
|
json
|
||||||
Logs in JSON format.
|
Log events in JSON format.
|
||||||
JSON log entries contain the full user details as well as the execution
|
JSON log entries contain the full user details as well as the execution
|
||||||
environment if the command was allowed.
|
environment if the command was allowed.
|
||||||
|
When logging to a file, the entire file is treated as a single JSON
|
||||||
|
object consisting of multiple events, each event spanning multiple lines.
|
||||||
|
When logging via
|
||||||
|
\fIsyslog\fR,
|
||||||
|
events are stored in compact (minified) format, described below.
|
||||||
|
.PD
|
||||||
|
.TP 6n
|
||||||
|
json_compact
|
||||||
|
Log events in compact (minified) JSON format.
|
||||||
|
Each event is written as a separate JSON object on single line without
|
||||||
|
extraneous white space.
|
||||||
|
When logging via
|
||||||
|
\fIsyslog\fR,
|
||||||
|
there is no difference between the
|
||||||
|
\fIjson\fR
|
||||||
|
and
|
||||||
|
\fIjson_compact\fR
|
||||||
|
formats.
|
||||||
Due to limitations of the protocol, JSON events sent via
|
Due to limitations of the protocol, JSON events sent via
|
||||||
\fIsyslog\fR
|
\fIsyslog\fR
|
||||||
may be truncated.
|
may be truncated.
|
||||||
.PD
|
|
||||||
.TP 6n
|
.TP 6n
|
||||||
sudo
|
sudo
|
||||||
Traditional sudo-style logs, see
|
Log events in traditional sudo-style format, see
|
||||||
\fIEVENT LOGGING\fR
|
\fIEVENT LOGGING\fR
|
||||||
for a description of the log file format.
|
for details.
|
||||||
.PP
|
.PP
|
||||||
This setting affects logs sent via
|
This setting affects logs sent via
|
||||||
syslog(3)
|
syslog(3)
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
.nr BA @BAMAN@
|
.nr BA @BAMAN@
|
||||||
.nr LC @LCMAN@
|
.nr LC @LCMAN@
|
||||||
.nr PS @PSMAN@
|
.nr PS @PSMAN@
|
||||||
.Dd December 19, 2023
|
.Dd March 8, 2024
|
||||||
.Dt SUDOERS @mansectform@
|
.Dt SUDOERS @mansectform@
|
||||||
.Os Sudo @PACKAGE_VERSION@
|
.Os Sudo @PACKAGE_VERSION@
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -5054,16 +5054,32 @@ The event log format.
|
|||||||
Supported log formats are:
|
Supported log formats are:
|
||||||
.Bl -tag -width 4n
|
.Bl -tag -width 4n
|
||||||
.It json
|
.It json
|
||||||
Logs in JSON format.
|
Log events in JSON format.
|
||||||
JSON log entries contain the full user details as well as the execution
|
JSON log entries contain the full user details as well as the execution
|
||||||
environment if the command was allowed.
|
environment if the command was allowed.
|
||||||
|
When logging to a file, the entire file is treated as a single JSON
|
||||||
|
object consisting of multiple events, each event spanning multiple lines.
|
||||||
|
When logging via
|
||||||
|
.Em syslog ,
|
||||||
|
events are stored in compact (minified) format, described below.
|
||||||
|
.It json_compact
|
||||||
|
Log events in compact (minified) JSON format.
|
||||||
|
Each event is written as a separate JSON object on single line without
|
||||||
|
extraneous white space.
|
||||||
|
When logging via
|
||||||
|
.Em syslog ,
|
||||||
|
there is no difference between the
|
||||||
|
.Em json
|
||||||
|
and
|
||||||
|
.Em json_compact
|
||||||
|
formats.
|
||||||
Due to limitations of the protocol, JSON events sent via
|
Due to limitations of the protocol, JSON events sent via
|
||||||
.Em syslog
|
.Em syslog
|
||||||
may be truncated.
|
may be truncated.
|
||||||
.It sudo
|
.It sudo
|
||||||
Traditional sudo-style logs, see
|
Log events in traditional sudo-style format, see
|
||||||
.Sx "EVENT LOGGING"
|
.Sx "EVENT LOGGING"
|
||||||
for a description of the log file format.
|
for details.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
This setting affects logs sent via
|
This setting affects logs sent via
|
||||||
|
@ -43,7 +43,8 @@ enum event_type {
|
|||||||
/* Supported eventlog formats. */
|
/* Supported eventlog formats. */
|
||||||
enum eventlog_format {
|
enum eventlog_format {
|
||||||
EVLOG_SUDO,
|
EVLOG_SUDO,
|
||||||
EVLOG_JSON
|
EVLOG_JSON,
|
||||||
|
EVLOG_JSON_COMPACT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Eventlog flag values. */
|
/* Eventlog flag values. */
|
||||||
|
@ -1131,6 +1131,7 @@ do_syslog(int event_type, int flags, struct eventlog_args *args,
|
|||||||
ret = do_syslog_sudo(pri, lbuf.buf, evlog);
|
ret = do_syslog_sudo(pri, lbuf.buf, evlog);
|
||||||
break;
|
break;
|
||||||
case EVLOG_JSON:
|
case EVLOG_JSON:
|
||||||
|
case EVLOG_JSON_COMPACT:
|
||||||
ret = do_syslog_json(pri, event_type, args, evlog);
|
ret = do_syslog_json(pri, event_type, args, evlog);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1205,11 +1206,12 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
do_logfile_json(int event_type, struct eventlog_args *args,
|
do_logfile_json(enum eventlog_format format, int event_type,
|
||||||
const struct eventlog *evlog)
|
struct eventlog_args *args, const struct eventlog *evlog)
|
||||||
{
|
{
|
||||||
const struct eventlog_config *evl_conf = eventlog_getconf();
|
const struct eventlog_config *evl_conf = eventlog_getconf();
|
||||||
const char *logfile = evl_conf->logpath;
|
const char *logfile = evl_conf->logpath;
|
||||||
|
const bool compact = format == EVLOG_JSON_COMPACT;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
char *json_str;
|
char *json_str;
|
||||||
int ret = false;
|
int ret = false;
|
||||||
@ -1219,7 +1221,7 @@ do_logfile_json(int event_type, struct eventlog_args *args,
|
|||||||
if ((fp = evl_conf->open_log(EVLOG_FILE, logfile)) == NULL)
|
if ((fp = evl_conf->open_log(EVLOG_FILE, logfile)) == NULL)
|
||||||
debug_return_bool(false);
|
debug_return_bool(false);
|
||||||
|
|
||||||
json_str = format_json(event_type, args, evlog, false);
|
json_str = format_json(event_type, args, evlog, compact);
|
||||||
if (json_str == NULL)
|
if (json_str == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@ -1229,25 +1231,32 @@ do_logfile_json(int event_type, struct eventlog_args *args,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: assumes file ends in "\n}\n" */
|
if (!compact) {
|
||||||
if (fstat(fileno(fp), &sb) == -1) {
|
/* Note: assumes file ends in "\n}\n" */
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
|
if (fstat(fileno(fp), &sb) == -1) {
|
||||||
"unable to stat %s", logfile);
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
|
||||||
goto done;
|
"unable to stat %s", logfile);
|
||||||
}
|
goto done;
|
||||||
if (sb.st_size == 0) {
|
}
|
||||||
/* New file */
|
if (sb.st_size == 0) {
|
||||||
putc('{', fp);
|
/* New file */
|
||||||
} else if (fseeko(fp, -3, SEEK_END) == 0) {
|
putc('{', fp);
|
||||||
/* Continue file, overwrite the final "\n}\n" */
|
} else if (fseeko(fp, -3, SEEK_END) == 0) {
|
||||||
putc(',', fp);
|
/* Continue file, overwrite the final "\n}\n" */
|
||||||
|
putc(',', fp);
|
||||||
|
} else {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
|
||||||
|
"unable to seek %s", logfile);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
fputs(json_str, fp);
|
||||||
|
fputs("\n}\n", fp); /* close JSON */
|
||||||
} else {
|
} else {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
|
/* Compact (minified) JSON records, one per line. */
|
||||||
"unable to seek %s", logfile);
|
putc('{', fp);
|
||||||
goto done;
|
fputs(json_str, fp);
|
||||||
|
fputs("}\n", fp);
|
||||||
}
|
}
|
||||||
fputs(json_str, fp);
|
|
||||||
fputs("\n}\n", fp); /* close JSON */
|
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
/* XXX - check for file error and recover */
|
/* XXX - check for file error and recover */
|
||||||
|
|
||||||
@ -1294,7 +1303,8 @@ do_logfile(int event_type, int flags, struct eventlog_args *args,
|
|||||||
args->event_time);
|
args->event_time);
|
||||||
break;
|
break;
|
||||||
case EVLOG_JSON:
|
case EVLOG_JSON:
|
||||||
ret = do_logfile_json(event_type, args, evlog);
|
case EVLOG_JSON_COMPACT:
|
||||||
|
ret = do_logfile_json(evl_conf->format, event_type, args, evlog);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
|
@ -903,6 +903,8 @@ cb_eventlog_format(struct logsrvd_config *config, const char *str, size_t offset
|
|||||||
|
|
||||||
if (strcmp(str, "json") == 0)
|
if (strcmp(str, "json") == 0)
|
||||||
config->eventlog.log_format = EVLOG_JSON;
|
config->eventlog.log_format = EVLOG_JSON;
|
||||||
|
else if (strcmp(str, "json_compact") == 0)
|
||||||
|
config->eventlog.log_format = EVLOG_JSON_COMPACT;
|
||||||
else if (strcmp(str, "sudo") == 0)
|
else if (strcmp(str, "sudo") == 0)
|
||||||
config->eventlog.log_format = EVLOG_SUDO;
|
config->eventlog.log_format = EVLOG_SUDO;
|
||||||
else
|
else
|
||||||
|
@ -41,6 +41,7 @@ static struct def_values def_data_timestamp_type[] = {
|
|||||||
static struct def_values def_data_log_format[] = {
|
static struct def_values def_data_log_format[] = {
|
||||||
{ "sudo", sudo },
|
{ "sudo", sudo },
|
||||||
{ "json", json },
|
{ "json", json },
|
||||||
|
{ "json_compact", json_compact },
|
||||||
{ NULL, 0 },
|
{ NULL, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -338,6 +338,7 @@ enum def_tuple {
|
|||||||
kernel,
|
kernel,
|
||||||
sudo,
|
sudo,
|
||||||
json,
|
json,
|
||||||
|
json_compact,
|
||||||
dso,
|
dso,
|
||||||
trace
|
trace
|
||||||
};
|
};
|
||||||
|
@ -426,7 +426,7 @@ runchroot
|
|||||||
log_format
|
log_format
|
||||||
T_TUPLE
|
T_TUPLE
|
||||||
"The format of logs to produce: %s"
|
"The format of logs to produce: %s"
|
||||||
sudo json
|
sudo json json_compact
|
||||||
selinux
|
selinux
|
||||||
T_FLAG
|
T_FLAG
|
||||||
"Enable SELinux RBAC support"
|
"Enable SELinux RBAC support"
|
||||||
|
@ -1132,16 +1132,29 @@ sudoers_log_close(int type, FILE *fp)
|
|||||||
void
|
void
|
||||||
init_eventlog_config(void)
|
init_eventlog_config(void)
|
||||||
{
|
{
|
||||||
|
enum eventlog_format format;
|
||||||
int logtype = 0;
|
int logtype = 0;
|
||||||
debug_decl(init_eventlog_config, SUDOERS_DEBUG_LOGGING);
|
debug_decl(init_eventlog_config, SUDOERS_DEBUG_LOGGING);
|
||||||
|
|
||||||
|
switch (def_log_format) {
|
||||||
|
case json:
|
||||||
|
format = EVLOG_JSON;
|
||||||
|
break;
|
||||||
|
case json_compact:
|
||||||
|
format = EVLOG_JSON_COMPACT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
format = EVLOG_SUDO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (def_syslog)
|
if (def_syslog)
|
||||||
logtype |= EVLOG_SYSLOG;
|
logtype |= EVLOG_SYSLOG;
|
||||||
if (def_logfile)
|
if (def_logfile)
|
||||||
logtype |= EVLOG_FILE;
|
logtype |= EVLOG_FILE;
|
||||||
|
|
||||||
eventlog_set_type(logtype);
|
eventlog_set_type(logtype);
|
||||||
eventlog_set_format(def_log_format == sudo ? EVLOG_SUDO : EVLOG_JSON);
|
eventlog_set_format(format);
|
||||||
eventlog_set_syslog_acceptpri(def_syslog_goodpri);
|
eventlog_set_syslog_acceptpri(def_syslog_goodpri);
|
||||||
eventlog_set_syslog_rejectpri(def_syslog_badpri);
|
eventlog_set_syslog_rejectpri(def_syslog_badpri);
|
||||||
eventlog_set_syslog_alertpri(def_syslog_badpri);
|
eventlog_set_syslog_alertpri(def_syslog_badpri);
|
||||||
|
@ -228,9 +228,22 @@ static bool
|
|||||||
cb_log_format(struct sudoers_context *ctx, const char *file,
|
cb_log_format(struct sudoers_context *ctx, const char *file,
|
||||||
int line, int column, const union sudo_defs_val *sd_un, int op)
|
int line, int column, const union sudo_defs_val *sd_un, int op)
|
||||||
{
|
{
|
||||||
|
enum eventlog_format format;
|
||||||
debug_decl(cb_log_format, SUDOERS_DEBUG_PLUGIN);
|
debug_decl(cb_log_format, SUDOERS_DEBUG_PLUGIN);
|
||||||
|
|
||||||
eventlog_set_format(sd_un->tuple == sudo ? EVLOG_SUDO : EVLOG_JSON);
|
switch (sd_un->tuple) {
|
||||||
|
case json:
|
||||||
|
format = EVLOG_JSON;
|
||||||
|
break;
|
||||||
|
case json_compact:
|
||||||
|
format = EVLOG_JSON_COMPACT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
format = EVLOG_SUDO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventlog_set_format(format);
|
||||||
|
|
||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user