report: replace boolean --sign with signing modes
Turn --sign=BOOL into --sign=no|best-effort|require-one|require-all, making the multi-signer aggregation policy explicit: best-effort never fails on signing, require-one requires at least one signature, and require-all requires every signer to succeed (an empty reply, i.e. a signer opting out, counts as failure). Signed reports are always emitted as a JSON-SEQ stream. The mode is also exposed as an input to the io.systemd.Report.GenerateSigned Varlink method. Signed-off-by: Paul Meyer <katexochen0@gmail.com>
This commit is contained in:
@@ -107,6 +107,19 @@ CHANGES WITH 262:
|
||||
upgraded, and the existing "anchor secret" stored in /var/lib and the
|
||||
ESP/XBOOTLDR will be removed.
|
||||
|
||||
Changes in systemd-report:
|
||||
|
||||
* The "generate" and "upload" commands of systemd-report can now
|
||||
cryptographically sign the reports they produce. Signatures are
|
||||
acquired from backend Varlink signers linked into
|
||||
/run/systemd/report.sign/. The new "--sign=" option selects the
|
||||
signing policy: "no" (the default) emits an unsigned report;
|
||||
"best-effort" attaches whatever signatures can be acquired but never
|
||||
fails; "require-one" requires at least one signature; and
|
||||
"require-all" requires every available signer to succeed. A signed
|
||||
report is emitted as a JSON-SEQ stream: the report object followed by
|
||||
one signature object per acquired signature.
|
||||
|
||||
CHANGES WITH 261:
|
||||
|
||||
Announcements of Future Feature Removals and Incompatible Changes:
|
||||
|
||||
+49
-7
@@ -199,14 +199,56 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--sign=<replaceable>BOOL</replaceable></option></term>
|
||||
<term><option>--sign=<replaceable>MODE</replaceable></option></term>
|
||||
|
||||
<listitem><para>If enabled, the report generated by <command>generate</command> or uploaded by
|
||||
<command>upload</command> is cryptographically signed. In this mode the report is emitted as a
|
||||
JSON-SEQ stream: the report object comes first, followed by one or more signature objects that
|
||||
cover the precise binary representation of the report object. Signatures are acquired by calling
|
||||
<function>io.systemd.Report.Signer.Sign()</function> on any sockets found under
|
||||
<filename>/run/systemd/report.sign/</filename>. Defaults to off.</para>
|
||||
<listitem><para>Controls whether and how the report generated by <command>generate</command> or
|
||||
uploaded by <command>upload</command> is cryptographically signed. Signatures are acquired by calling
|
||||
<function>io.systemd.Report.Signer.Sign()</function> on each socket found under
|
||||
<filename>/run/systemd/report.sign/</filename>.</para>
|
||||
|
||||
<para>When signing is requested (any value other than <option>no</option>) the report is emitted as a
|
||||
JSON-SEQ stream: the report object comes first, followed by one signature object per acquired signature
|
||||
(possibly none, in <option>best-effort</option> mode), each covering the precise binary representation
|
||||
of the report object. With <option>no</option> the report is emitted as a single plain JSON object.
|
||||
Takes one of the following values:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>no</option></term>
|
||||
<listitem><para>Do not sign the report; it is emitted as a single plain JSON object. This is the
|
||||
default.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>best-effort</option></term>
|
||||
<listitem><para>Never fail because of signing. Any acquired signatures are included. The operation
|
||||
succeeds even if none could be acquired, in which case the JSON-SEQ stream simply contains no
|
||||
signature objects.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>require-one</option></term>
|
||||
<listitem><para>Require at least one signature. Individual signers that fail or return no signature
|
||||
are tolerated, but the operation fails if not a single signature could be acquired.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>require-all</option></term>
|
||||
<listitem><para>Require every signer to succeed with at least one signature. The operation fails
|
||||
if no signer is present, if any signer returns an error, or if any signer returns no signature.
|
||||
</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>Defaults to <option>no</option>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -51,8 +51,8 @@ int context_generate_report(Context *context) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_sign) {
|
||||
r = context_sign_report(context, report, arg_json_format_flags, /* output= */ NULL);
|
||||
if (arg_sign_mode != REPORT_SIGN_NO) {
|
||||
r = context_sign_report(context, report, arg_sign_mode, arg_json_format_flags, /* output= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
|
||||
+78
-25
@@ -12,12 +12,22 @@
|
||||
#include "report.h"
|
||||
#include "report-sign.h"
|
||||
#include "sha256.h"
|
||||
#include "string-table.h"
|
||||
#include "time-util.h"
|
||||
#include "varlink-util.h"
|
||||
|
||||
#define REPORT_SIGN_DIR "/run/systemd/report.sign"
|
||||
#define REPORT_SIGN_TIMEOUT_USEC USEC_PER_MINUTE
|
||||
|
||||
static const char* const report_sign_mode_table[_REPORT_SIGN_MODE_MAX] = {
|
||||
[REPORT_SIGN_NO] = "no",
|
||||
[REPORT_SIGN_BEST_EFFORT] = "best-effort",
|
||||
[REPORT_SIGN_REQUIRE_ONE] = "require-one",
|
||||
[REPORT_SIGN_REQUIRE_ALL] = "require-all",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(report_sign_mode, ReportSignMode);
|
||||
|
||||
typedef struct Signature {
|
||||
char *mechanism;
|
||||
sd_json_variant *data;
|
||||
@@ -26,7 +36,11 @@ typedef struct Signature {
|
||||
typedef struct SignatureList {
|
||||
Signature *signatures;
|
||||
size_t n_signatures;
|
||||
int result;
|
||||
|
||||
size_t n_replies; /* replies received (one per contacted socket) */
|
||||
size_t n_errors; /* replies that were errors */
|
||||
size_t n_empty; /* replies OK but with zero signatures (opt-out) */
|
||||
int fatal_error; /* first unrecoverable errno (e.g. OOM); fails every mode */
|
||||
} SignatureList;
|
||||
|
||||
static void signature_done(Signature *s) {
|
||||
@@ -58,18 +72,23 @@ static int execute_dir_reply(
|
||||
|
||||
assert(link);
|
||||
|
||||
sl->n_replies++;
|
||||
|
||||
/* Get the socket name */
|
||||
const char *p = ASSERT_PTR(sd_varlink_get_description(link));
|
||||
|
||||
_cleanup_free_ char *sn = NULL;
|
||||
r = path_extract_filename(p, &sn);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract service name from '%s': %m", p);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to extract service name from '%s': %m", p);
|
||||
sl->n_errors++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (error_id) {
|
||||
r = sd_varlink_error_to_errno(error_id, reply);
|
||||
RET_GATHER(sl->result, r);
|
||||
return log_error_errno(r, "Signing via Varlink service '%s' failed: %s", p, error_id);
|
||||
log_warning("Signing via Varlink service '%s' failed: %s", p, error_id);
|
||||
sl->n_errors++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *array = NULL;
|
||||
@@ -80,21 +99,28 @@ static int execute_dir_reply(
|
||||
};
|
||||
|
||||
r = sd_json_dispatch(reply, dispatch_table, /* flags= */ 0, &array);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to dispatch method reply: %m");
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to parse reply from Varlink service '%s': %m", p);
|
||||
sl->n_errors++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t n = 0;
|
||||
if (array) {
|
||||
sd_json_variant *s;
|
||||
JSON_VARIANT_ARRAY_FOREACH(s, array) {
|
||||
if (!GREEDY_REALLOC(sl->signatures, sl->n_signatures + 1))
|
||||
return log_oom();
|
||||
if (!GREEDY_REALLOC(sl->signatures, sl->n_signatures + 1)) {
|
||||
RET_GATHER(sl->fatal_error, log_oom());
|
||||
return 0;
|
||||
}
|
||||
|
||||
Signature *i = sl->signatures + sl->n_signatures;
|
||||
|
||||
i->mechanism = strdup(sn);
|
||||
if (!i->mechanism)
|
||||
return log_oom();
|
||||
if (!i->mechanism) {
|
||||
RET_GATHER(sl->fatal_error, log_oom());
|
||||
return 0;
|
||||
}
|
||||
|
||||
i->data = sd_json_variant_ref(s);
|
||||
sl->n_signatures++;
|
||||
@@ -103,9 +129,10 @@ static int execute_dir_reply(
|
||||
}
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
if (n == 0) {
|
||||
sl->n_empty++;
|
||||
log_info("Mechanism '%s' succeeded, but returned no signatures.", p);
|
||||
else
|
||||
} else
|
||||
log_info("Successfully acquired %zu signatures from '%s'", n, p);
|
||||
|
||||
return 0;
|
||||
@@ -114,6 +141,7 @@ static int execute_dir_reply(
|
||||
int context_sign_report(
|
||||
Context *context,
|
||||
sd_json_variant *report,
|
||||
ReportSignMode mode,
|
||||
sd_json_format_flags_t format_flags,
|
||||
FILE *output) {
|
||||
int r;
|
||||
@@ -121,6 +149,9 @@ int context_sign_report(
|
||||
assert(context);
|
||||
assert(report);
|
||||
|
||||
if (mode == REPORT_SIGN_NO)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Refusing to sign report with signing disabled.");
|
||||
|
||||
/* When generating a signed report we switch to JSON-SEQ. We'll put the report as first object in the
|
||||
* stream, and then signature objects after it, that cover the precise binary representation of the
|
||||
* first object. We normalize the report JSON first, but this is not load bearing, as the signature
|
||||
@@ -156,17 +187,38 @@ int context_sign_report(
|
||||
REPORT_SIGN_TIMEOUT_USEC,
|
||||
execute_dir_reply,
|
||||
/* userdata= */ &sl);
|
||||
if (jobs < 0)
|
||||
/* A missing signer directory (-ENOENT) just means no signing backends are installed; that is benign
|
||||
* and surfaces below as "no signatures acquired". Any other enumeration failure is fatal. */
|
||||
if (jobs < 0 && jobs != -ENOENT)
|
||||
return log_error_errno(jobs, "Failed to execute signing via '%s': %m", REPORT_SIGN_DIR);
|
||||
if (jobs == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOPKG),
|
||||
"No signing mechanism found via '%s'.", REPORT_SIGN_DIR);
|
||||
if (sl.result < 0)
|
||||
/* The details were printed at error level by execute_dir_reply above. */
|
||||
return log_debug_errno(sl.result, "Signing via '%s' failed: %m", REPORT_SIGN_DIR);
|
||||
if (sl.n_signatures == 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOPKG),
|
||||
"No signatures acquired via '%s'.", REPORT_SIGN_DIR);
|
||||
|
||||
if (sl.fatal_error < 0)
|
||||
return log_error_errno(sl.fatal_error, "Failed to collect signatures: %m");
|
||||
|
||||
switch (mode) {
|
||||
case REPORT_SIGN_REQUIRE_ALL:
|
||||
if (sl.n_errors > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Signing mode '%s' requested, but %zu of %zu signing mechanisms failed.",
|
||||
report_sign_mode_to_string(mode), sl.n_errors, sl.n_replies);
|
||||
if (sl.n_empty > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOPKG),
|
||||
"Signing mode '%s' requested, but %zu of %zu signing mechanisms produced no signature.",
|
||||
report_sign_mode_to_string(mode), sl.n_empty, sl.n_replies);
|
||||
_fallthrough_;
|
||||
case REPORT_SIGN_REQUIRE_ONE:
|
||||
if (sl.n_signatures == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOPKG),
|
||||
"Signing mode '%s' requested, but no signatures could be acquired via '%s'.",
|
||||
report_sign_mode_to_string(mode), REPORT_SIGN_DIR);
|
||||
break;
|
||||
|
||||
case REPORT_SIGN_BEST_EFFORT:
|
||||
break; /* never fails; may emit zero signatures */
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
if (fputs(text, output) == EOF)
|
||||
return log_error_errno(errno, "Failed to write report: %m");
|
||||
@@ -202,6 +254,7 @@ int context_sign_report(
|
||||
int context_sign_report_as_string(
|
||||
Context *context,
|
||||
sd_json_variant *report,
|
||||
ReportSignMode mode,
|
||||
sd_json_format_flags_t format_flags,
|
||||
char **ret) {
|
||||
|
||||
@@ -217,7 +270,7 @@ int context_sign_report_as_string(
|
||||
if (!f)
|
||||
return log_oom();
|
||||
|
||||
r = context_sign_report(context, report, format_flags, f);
|
||||
r = context_sign_report(context, report, mode, format_flags, f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
|
||||
#include "report.h"
|
||||
|
||||
int context_sign_report(Context *context, sd_json_variant *report, sd_json_format_flags_t format_flags, FILE *output);
|
||||
DECLARE_STRING_TABLE_LOOKUP(report_sign_mode, ReportSignMode);
|
||||
|
||||
int context_sign_report_as_string(Context *context, sd_json_variant *report, sd_json_format_flags_t format_flags, char **ret);
|
||||
int context_sign_report(
|
||||
Context *context,
|
||||
sd_json_variant *report,
|
||||
ReportSignMode mode,
|
||||
sd_json_format_flags_t format_flags,
|
||||
FILE *output);
|
||||
|
||||
int context_sign_report_as_string(
|
||||
Context *context,
|
||||
sd_json_variant *report,
|
||||
ReportSignMode mode,
|
||||
sd_json_format_flags_t format_flags,
|
||||
char **ret);
|
||||
|
||||
@@ -68,11 +68,12 @@ static int http_upload_report(Context *context, sd_json_variant *report) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Upload a JSON report in text form as a single JSON object, instead of a JSON-SEQ list. */
|
||||
/* Upload the report in text form: a single JSON object when unsigned, or a JSON-SEQ stream (the
|
||||
* report followed by zero or more signature objects) when signing is enabled. */
|
||||
|
||||
_cleanup_free_ char *text = NULL;
|
||||
if (arg_sign) {
|
||||
r = context_sign_report_as_string(context, report, /* format_flags= */ 0, &text);
|
||||
if (arg_sign_mode != REPORT_SIGN_NO) {
|
||||
r = context_sign_report_as_string(context, report, arg_sign_mode, /* format_flags= */ 0, &text);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
@@ -232,10 +233,10 @@ static int varlink_upload_report(Context *context, sd_json_variant *report) {
|
||||
assert(report);
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *params = NULL;
|
||||
if (arg_sign) {
|
||||
if (arg_sign_mode != REPORT_SIGN_NO) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
|
||||
r = context_sign_report_as_string(context, report, /* format_flags= */ 0, &buf);
|
||||
r = context_sign_report_as_string(context, report, arg_sign_mode, /* format_flags= */ 0, &buf);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
+47
-11
@@ -10,6 +10,7 @@
|
||||
#include "dlopen-note.h"
|
||||
#include "format-table.h"
|
||||
#include "help-util.h"
|
||||
#include "json-util.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "options.h"
|
||||
@@ -23,6 +24,7 @@
|
||||
#include "runtime-scope.h"
|
||||
#include "set.h"
|
||||
#include "sort-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
@@ -46,7 +48,7 @@ char *arg_cert = NULL;
|
||||
char *arg_trust = NULL;
|
||||
char **arg_extra_headers = NULL;
|
||||
usec_t arg_network_timeout_usec = TIMEOUT_USEC;
|
||||
bool arg_sign = false;
|
||||
ReportSignMode arg_sign_mode = REPORT_SIGN_NO;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_url, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_key, freep);
|
||||
@@ -779,6 +781,28 @@ static int verb_list_sources(int argc, char *argv[], uintptr_t _data, void *user
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* String table mapping the io.systemd.Report SignMode enum values (camelCase, per Varlink conventions) onto
|
||||
* ReportSignMode. This is an explicit allowlist of the modes valid for GenerateSigned: unlike the CLI's
|
||||
* report_sign_mode_from_string() it deliberately omits "no" (use the Generate method for unsigned reports). */
|
||||
static const char* const report_sign_varlink_mode_table[_REPORT_SIGN_MODE_MAX] = {
|
||||
[REPORT_SIGN_BEST_EFFORT] = "bestEffort",
|
||||
[REPORT_SIGN_REQUIRE_ONE] = "requireOne",
|
||||
[REPORT_SIGN_REQUIRE_ALL] = "requireAll",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(report_sign_varlink_mode, ReportSignMode);
|
||||
|
||||
static JSON_DISPATCH_ENUM_DEFINE(json_dispatch_report_sign_varlink_mode, ReportSignMode, report_sign_varlink_mode_from_string);
|
||||
|
||||
typedef struct GenerateParameters {
|
||||
char **matches;
|
||||
ReportSignMode sign_mode;
|
||||
} GenerateParameters;
|
||||
|
||||
static void generate_parameters_done(GenerateParameters *p) {
|
||||
strv_free(p->matches);
|
||||
}
|
||||
|
||||
static int vl_method_generate_internal(
|
||||
sd_varlink *link,
|
||||
sd_json_variant *parameters,
|
||||
@@ -789,14 +813,21 @@ static int vl_method_generate_internal(
|
||||
assert(link);
|
||||
assert(parameters);
|
||||
|
||||
_cleanup_strv_free_ char **input_matches = NULL;
|
||||
_cleanup_(generate_parameters_done) GenerateParameters p = {
|
||||
.sign_mode = _REPORT_SIGN_MODE_INVALID,
|
||||
};
|
||||
|
||||
static const sd_json_dispatch_field dispatch_table[] = {
|
||||
{ "matches", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, 0, 0 },
|
||||
static const sd_json_dispatch_field dispatch_table_unsigned[] = {
|
||||
{ "matches", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, voffsetof(p, matches), SD_JSON_NULLABLE },
|
||||
{}
|
||||
};
|
||||
static const sd_json_dispatch_field dispatch_table_signed[] = {
|
||||
{ "matches", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, voffsetof(p, matches), SD_JSON_NULLABLE },
|
||||
{ "mode", SD_JSON_VARIANT_STRING, json_dispatch_report_sign_varlink_mode, voffsetof(p, sign_mode), SD_JSON_NULLABLE },
|
||||
{}
|
||||
};
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &input_matches);
|
||||
r = sd_varlink_dispatch(link, parameters, sign ? dispatch_table_signed : dispatch_table_unsigned, &p);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
@@ -804,7 +835,7 @@ static int vl_method_generate_internal(
|
||||
.action = ACTION_GENERATE,
|
||||
};
|
||||
|
||||
r = parse_metrics_matches(input_matches, &context.matches);
|
||||
r = parse_metrics_matches(p.matches, &context.matches);
|
||||
if (r < 0)
|
||||
return sd_varlink_error_invalid_parameter_name(link, "matches");
|
||||
|
||||
@@ -822,10 +853,14 @@ static int vl_method_generate_internal(
|
||||
return r;
|
||||
|
||||
if (sign) {
|
||||
/* Supply the default when 'mode' was absent. */
|
||||
if (p.sign_mode < 0)
|
||||
p.sign_mode = REPORT_SIGN_REQUIRE_ONE;
|
||||
|
||||
/* Use compact JSON formatting (no pretty/color/seq flags), matching the on-the-wire format
|
||||
* used for uploads. context_sign_report() adds the JSON-SEQ record separators itself. */
|
||||
_cleanup_free_ char *s = NULL;
|
||||
r = context_sign_report_as_string(&context, report, /* format_flags= */ 0, &s);
|
||||
r = context_sign_report_as_string(&context, report, p.sign_mode, /* format_flags= */ 0, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1007,10 +1042,11 @@ static int parse_argv(int argc, char *argv[], char ***ret_args) {
|
||||
return log_oom();
|
||||
break;
|
||||
|
||||
OPTION_LONG("sign", "BOOL", "Sign the generated report."):
|
||||
r = parse_boolean_argument("--sign", opts.arg, &arg_sign);
|
||||
if (r < 0)
|
||||
return r;
|
||||
OPTION_LONG("sign", "MODE",
|
||||
"Sign the report: no, best-effort, require-one, require-all"):
|
||||
arg_sign_mode = report_sign_mode_from_string(opts.arg);
|
||||
if (arg_sign_mode < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse --sign= mode '%s'.", opts.arg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -9,11 +9,20 @@
|
||||
#define REPORT_CERT_FILE CERTIFICATE_ROOT "/certs/systemd-report.pem"
|
||||
#define REPORT_TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem"
|
||||
|
||||
typedef enum ReportSignMode {
|
||||
REPORT_SIGN_NO,
|
||||
REPORT_SIGN_BEST_EFFORT,
|
||||
REPORT_SIGN_REQUIRE_ONE,
|
||||
REPORT_SIGN_REQUIRE_ALL,
|
||||
_REPORT_SIGN_MODE_MAX,
|
||||
_REPORT_SIGN_MODE_INVALID = -EINVAL,
|
||||
} ReportSignMode;
|
||||
|
||||
extern sd_json_format_flags_t arg_json_format_flags;
|
||||
extern char *arg_url, *arg_key, *arg_cert, *arg_trust;
|
||||
extern char **arg_extra_headers;
|
||||
extern usec_t arg_network_timeout_usec;
|
||||
extern bool arg_sign;
|
||||
extern ReportSignMode arg_sign_mode;
|
||||
|
||||
typedef enum Action {
|
||||
ACTION_LIST_METRICS,
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
#include "varlink-io.systemd.Report.h"
|
||||
|
||||
static SD_VARLINK_DEFINE_ENUM_TYPE(
|
||||
SignMode,
|
||||
SD_VARLINK_FIELD_COMMENT("Emit whatever signatures are available, never fail on signing."),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(bestEffort),
|
||||
SD_VARLINK_FIELD_COMMENT("Require at least one signature; tolerate individual signer failures. (Default.)"),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(requireOne),
|
||||
SD_VARLINK_FIELD_COMMENT("Require every signing mechanism to succeed with a signature."),
|
||||
SD_VARLINK_DEFINE_ENUM_VALUE(requireAll));
|
||||
|
||||
static SD_VARLINK_DEFINE_METHOD(
|
||||
Generate,
|
||||
SD_VARLINK_FIELD_COMMENT("Selects which metrics to include in the report, as an array of metric family names or prefixes thereof. If unset or empty all available metrics are included. This matches the [MATCH…] arguments of the systemd-report command line tool."),
|
||||
@@ -13,6 +22,8 @@ static SD_VARLINK_DEFINE_METHOD(
|
||||
GenerateSigned,
|
||||
SD_VARLINK_FIELD_COMMENT("Selects which metrics to include in the report, as an array of metric family names or prefixes thereof. If unset or empty all available metrics are included. This matches the [MATCH…] arguments of the systemd-report command line tool."),
|
||||
SD_VARLINK_DEFINE_INPUT(matches, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("How to handle multiple signers. Defaults to requireOne if unset."),
|
||||
SD_VARLINK_DEFINE_INPUT_BY_TYPE(mode, SignMode, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("The generated, signed report in Base64. A precise binary formatting of the JSON data is important to authenticate the signature. This data contains a JSON-SEQ compliant stream of objects, the first being the report, the following ones signature objects."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(reportData, SD_VARLINK_STRING, 0));
|
||||
|
||||
@@ -20,6 +31,8 @@ SD_VARLINK_DEFINE_INTERFACE(
|
||||
io_systemd_Report,
|
||||
"io.systemd.Report",
|
||||
SD_VARLINK_INTERFACE_COMMENT("Frontend API for generating system reports. This interface is implemented by systemd-report, which aggregates the metrics exposed by the io.systemd.Metrics services linked into /run/systemd/report/."),
|
||||
SD_VARLINK_SYMBOL_COMMENT("Policy for how multiple signers are aggregated."),
|
||||
&vl_type_SignMode,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Generate a report and return it as a JSON object."),
|
||||
&vl_method_Generate,
|
||||
SD_VARLINK_SYMBOL_COMMENT("Generate a signed report and return it Base64 encoded."),
|
||||
|
||||
Reference in New Issue
Block a user