2
0
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:
Todd C. Miller 2024-03-08 16:31:39 -07:00
parent b3ade1c5f9
commit 1debad3bec
12 changed files with 180 additions and 46 deletions

View File

@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" 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
.if n .ad l
.SH "NAME"
@ -682,15 +682,48 @@ Defaults to
.TP 6n
log_format = string
The event log format.
Supported log formats are
\(lqsudo\(rq
for traditional sudo-style logs and
\(lqjson\(rq
for JSON-format logs.
Supported log formats are:
.PP
.RS 6n
.PD 0
.TP 6n
json
Log events in JSON format.
The JSON log entries contain the full contents of the accept, reject, exit
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
\fIsudo\fR.
.RE
.SS "syslog"
The
\fIsyslog\fR

View File

@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd January 16, 2023
.Dd March 8, 2024
.Dt SUDO_LOGSRVD.CONF @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -611,13 +611,40 @@ Defaults to
.Em false .
.It log_format = string
The event log format.
Supported log formats are
.Dq sudo
for traditional sudo-style logs and
.Dq json
for JSON-format logs.
Supported log formats are:
.Bl -tag -width 4n
.It json
Log events in JSON format.
The JSON log entries contain the full contents of the accept, reject, exit
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
.Em sudo .
.El

View File

@ -25,7 +25,7 @@
.nr BA @BAMAN@
.nr LC @LCMAN@
.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
.if n .ad l
.SH "NAME"
@ -5381,18 +5381,35 @@ Supported log formats are:
.PD 0
.TP 6n
json
Logs in JSON format.
Log events in JSON format.
JSON log entries contain the full user details as well as the execution
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
\fIsyslog\fR
may be truncated.
.PD
.TP 6n
sudo
Traditional sudo-style logs, see
Log events in traditional sudo-style format, see
\fIEVENT LOGGING\fR
for a description of the log file format.
for details.
.PP
This setting affects logs sent via
syslog(3)

View File

@ -25,7 +25,7 @@
.nr BA @BAMAN@
.nr LC @LCMAN@
.nr PS @PSMAN@
.Dd December 19, 2023
.Dd March 8, 2024
.Dt SUDOERS @mansectform@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
@ -5054,16 +5054,32 @@ The event log format.
Supported log formats are:
.Bl -tag -width 4n
.It json
Logs in JSON format.
Log events in JSON format.
JSON log entries contain the full user details as well as the execution
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
.Em syslog
may be truncated.
.It sudo
Traditional sudo-style logs, see
Log events in traditional sudo-style format, see
.Sx "EVENT LOGGING"
for a description of the log file format.
for details.
.El
.Pp
This setting affects logs sent via

View File

@ -43,7 +43,8 @@ enum event_type {
/* Supported eventlog formats. */
enum eventlog_format {
EVLOG_SUDO,
EVLOG_JSON
EVLOG_JSON,
EVLOG_JSON_COMPACT
};
/* Eventlog flag values. */

View File

@ -1131,6 +1131,7 @@ do_syslog(int event_type, int flags, struct eventlog_args *args,
ret = do_syslog_sudo(pri, lbuf.buf, evlog);
break;
case EVLOG_JSON:
case EVLOG_JSON_COMPACT:
ret = do_syslog_json(pri, event_type, args, evlog);
break;
default:
@ -1205,11 +1206,12 @@ done:
}
static bool
do_logfile_json(int event_type, struct eventlog_args *args,
const struct eventlog *evlog)
do_logfile_json(enum eventlog_format format, int event_type,
struct eventlog_args *args, const struct eventlog *evlog)
{
const struct eventlog_config *evl_conf = eventlog_getconf();
const char *logfile = evl_conf->logpath;
const bool compact = format == EVLOG_JSON_COMPACT;
struct stat sb;
char *json_str;
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)
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)
goto done;
@ -1229,25 +1231,32 @@ do_logfile_json(int event_type, struct eventlog_args *args,
goto done;
}
/* Note: assumes file ends in "\n}\n" */
if (fstat(fileno(fp), &sb) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
"unable to stat %s", logfile);
goto done;
}
if (sb.st_size == 0) {
/* New file */
putc('{', fp);
} else if (fseeko(fp, -3, SEEK_END) == 0) {
/* Continue file, overwrite the final "\n}\n" */
putc(',', fp);
if (!compact) {
/* Note: assumes file ends in "\n}\n" */
if (fstat(fileno(fp), &sb) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
"unable to stat %s", logfile);
goto done;
}
if (sb.st_size == 0) {
/* New file */
putc('{', fp);
} else if (fseeko(fp, -3, SEEK_END) == 0) {
/* 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 {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
"unable to seek %s", logfile);
goto done;
/* Compact (minified) JSON records, one per line. */
putc('{', fp);
fputs(json_str, fp);
fputs("}\n", fp);
}
fputs(json_str, fp);
fputs("\n}\n", fp); /* close JSON */
fflush(fp);
/* 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);
break;
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;
default:
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,

View File

@ -903,6 +903,8 @@ cb_eventlog_format(struct logsrvd_config *config, const char *str, size_t offset
if (strcmp(str, "json") == 0)
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)
config->eventlog.log_format = EVLOG_SUDO;
else

View File

@ -41,6 +41,7 @@ static struct def_values def_data_timestamp_type[] = {
static struct def_values def_data_log_format[] = {
{ "sudo", sudo },
{ "json", json },
{ "json_compact", json_compact },
{ NULL, 0 },
};

View File

@ -338,6 +338,7 @@ enum def_tuple {
kernel,
sudo,
json,
json_compact,
dso,
trace
};

View File

@ -426,7 +426,7 @@ runchroot
log_format
T_TUPLE
"The format of logs to produce: %s"
sudo json
sudo json json_compact
selinux
T_FLAG
"Enable SELinux RBAC support"

View File

@ -1132,16 +1132,29 @@ sudoers_log_close(int type, FILE *fp)
void
init_eventlog_config(void)
{
enum eventlog_format format;
int logtype = 0;
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)
logtype |= EVLOG_SYSLOG;
if (def_logfile)
logtype |= EVLOG_FILE;
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_rejectpri(def_syslog_badpri);
eventlog_set_syslog_alertpri(def_syslog_badpri);

View File

@ -228,9 +228,22 @@ static bool
cb_log_format(struct sudoers_context *ctx, const char *file,
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);
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);
}