systemd-id128: a new tool to print machine/boot/invocation/app-specific ids

The raison d'etre for this program is printing machine-app-specific IDs. We
provide a library function for that, but not a convenient API. We can hardly
ask people to quickly hack their own C programs or call libsystemd through CFFI
in python or another scripting language if they just want to print an ID.

Verb 'new' was already available as 'journalctl --new-id128', but this makes
it more discoverable.

v2:
- rename binary to systemd-id128
- make --app-specific= into a switch that applies to boot-id and machine-id
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2018-08-21 16:08:48 +02:00
parent 65d410c7ca
commit 0d1d512f7f
6 changed files with 201 additions and 9 deletions

View File

@ -78,7 +78,7 @@
<function>sd_id128_get_machine()</function> when passing an ID to untrusted environments, in order to make sure
that the original machine ID may not be determined externally. This way, the ID used by the application remains
stable on a given machine, but cannot be easily correlated with IDs used in other applications on the same
machine. The application-specific ID should be generated via a tool like <command>journalctl --new-id128</command>,
machine. The application-specific ID should be generated via a tool like <command>systemd-id128 new</command>,
and may be compiled into the application. This function will return the same application-specific ID for each
combination of machine ID and application ID. Internally, this function calculates HMAC-SHA256 of the application
ID, keyed by the machine ID.</para>
@ -145,6 +145,7 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-id128</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-id128</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,

View File

@ -2323,6 +2323,14 @@ executable('systemd-cgroups-agent',
install : true,
install_dir : rootlibexecdir)
exe = executable('systemd-id128',
'src/id128/id128.c',
include_directories : includes,
link_with : [libshared],
install_rpath : rootlibexecdir,
install : true)
public_programs += exe
exe = executable('systemd-path',
'src/path/path.c',
include_directories : includes,

167
src/id128/id128.c Normal file
View File

@ -0,0 +1,167 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <getopt.h>
#include <stdio.h>
#include "alloc-util.h"
#include "id128-print.h"
#include "terminal-util.h"
#include "util.h"
#include "verbs.h"
static bool arg_pretty = false;
static sd_id128_t arg_app = {};
static int verb_new(int argc, char **argv, void *userdata) {
return id128_print_new(arg_pretty);
}
static int verb_machine_id(int argc, char **argv, void *userdata) {
sd_id128_t id;
int r;
if (sd_id128_is_null(arg_app))
r = sd_id128_get_machine(&id);
else
r = sd_id128_get_machine_app_specific(arg_app, &id);
if (r < 0)
return log_error_errno(r, "Failed to get %smachine-ID: %m",
sd_id128_is_null(arg_app) ? "" : "app-specific ");
return id128_pretty_print(id, arg_pretty);
}
static int verb_boot_id(int argc, char **argv, void *userdata) {
sd_id128_t id;
int r;
if (sd_id128_is_null(arg_app))
r = sd_id128_get_boot(&id);
else
r = sd_id128_get_boot_app_specific(arg_app, &id);
if (r < 0)
return log_error_errno(r, "Failed to get %sboot-ID: %m",
sd_id128_is_null(arg_app) ? "" : "app-specific ");
return id128_pretty_print(id, arg_pretty);
}
static int verb_invocation_id(int argc, char **argv, void *userdata) {
sd_id128_t id;
int r;
if (!sd_id128_is_null(arg_app))
return log_error_errno(EINVAL, "Verb \"invocation-id\" cannot be combined with --app-specific=.");
r = sd_id128_get_invocation(&id);
if (r < 0)
return log_error_errno(r, "Failed to get invocation-ID: %m");
return id128_pretty_print(id, arg_pretty);
}
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
r = terminal_urlify_man("systemd-id128", "1", &link);
if (r < 0)
return log_oom();
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Generate and print id128 strings.\n\n"
" -h --help Show this help\n\n"
" -p --pretty Generate samples of program code\n\n"
" -a --app-specific=ID Generate app-specific IDs\n\n"
"Commands:\n"
" new Generate a new id128 string\n"
" machine-id Print the ID of current machine\n"
" boot-id Print the ID of current boot\n"
" invocation-id Print the ID of current invocation\n"
" help Show this help\n"
"\nSee the %s for details.\n"
, program_invocation_short_name
, link
);
return 0;
}
static int verb_help(int argc, char **argv, void *userdata) {
return help();
}
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "app-specific", required_argument, NULL, 'a' },
{},
};
int c, r;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "hpa:", options, NULL)) >= 0)
switch (c) {
case 'h':
return help();
case ARG_VERSION:
return version();
case 'p':
arg_pretty = true;
break;
case 'a':
r = sd_id128_from_string(optarg, &arg_app);
if (r < 0)
return log_error_errno(r, "Failed to parse \"%s\" as application-ID: %m", optarg);
break;
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
return 1;
}
static int id128_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "new", VERB_ANY, 1, 0, verb_new },
{ "machine-id", VERB_ANY, 1, 0, verb_machine_id },
{ "boot-id", VERB_ANY, 1, 0, verb_boot_id },
{ "invocation-id", VERB_ANY, 1, 0, verb_invocation_id },
{ "help", VERB_ANY, VERB_ANY, 0, verb_help },
{}
};
return dispatch_verb(argc, argv, verbs, NULL);
}
int main(int argc, char *argv[]) {
int r;
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = id128_main(argc, argv);
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -2064,7 +2064,7 @@ int main(int argc, char *argv[]) {
switch (arg_action) {
case ACTION_NEW_ID128:
r = id128_generate_new();
r = id128_print_new(true);
goto finish;
case ACTION_SETUP_KEYS:

View File

@ -7,14 +7,14 @@
#include "id128-print.h"
#include "log.h"
int id128_generate_new(void) {
sd_id128_t id;
int r;
int id128_pretty_print(sd_id128_t id, bool pretty) {
unsigned i;
r = sd_id128_randomize(&id);
if (r < 0)
return log_error_errno(r, "Failed to generate ID: %m");
if (!pretty) {
printf(SD_ID128_FORMAT_STR "\n",
SD_ID128_FORMAT_VAL(id));
return 0;
}
printf("As string:\n"
SD_ID128_FORMAT_STR "\n\n"
@ -35,3 +35,14 @@ int id128_generate_new(void) {
return 0;
}
int id128_print_new(bool pretty) {
sd_id128_t id;
int r;
r = sd_id128_randomize(&id);
if (r < 0)
return log_error_errno(r, "Failed to generate ID: %m");
return id128_pretty_print(id, pretty);
}

View File

@ -2,4 +2,9 @@
#pragma once
int id128_generate_new(void);
#include <stdbool.h>
#include "sd-id128.h"
int id128_pretty_print(sd_id128_t id, bool pretty);
int id128_print_new(bool pretty);