mirror of
https://github.com/systemd/systemd.git
synced 2025-03-19 22:50:17 +03:00
Merge 2da37ae9f930836c1a51b0d739bc0fc67ca67f8b into 104587314ff25a5c35390eeb42308f083e1e0488
This commit is contained in:
commit
eea06798d9
@ -129,6 +129,31 @@
|
||||
<listitem><para>Takes a boolean value, enforces using compression without content encoding negotiation.
|
||||
Defaults to <literal>false</literal>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Header=</varname></term>
|
||||
|
||||
<listitem><para>HTTP header which should be added to each request to URL.</para>
|
||||
|
||||
<para>Header consists of name and value, which are separated by colon.</para>
|
||||
|
||||
<para>Header name can contains alphanumeric values, "_" and "-" symbols additionally.</para>
|
||||
|
||||
<para>This option may be specified more than once, in which case all listed headers will be set. If
|
||||
the same header name is listed more than once, all its unique values will be concatenated with comma.
|
||||
Setting <literal>Header</literal> to empty string clears all previous assignments.
|
||||
</para>
|
||||
|
||||
<para>Example:
|
||||
<programlisting>Header=HeaderName: HeaderValue
|
||||
Header=HeaderName: NewValue
|
||||
Header=HeaderName: HeaderValue
|
||||
</programlisting>
|
||||
|
||||
adds <literal>HeaderName</literal> header with <literal>HeaderValue, NewValue</literal> to each HTTP request.
|
||||
</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
98
src/journal-remote/journal-header-util.c
Normal file
98
src/journal-remote/journal-header-util.c
Normal file
@ -0,0 +1,98 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "escape.h"
|
||||
#include "journal-header-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
/* HTTP header name can contains:
|
||||
- Alphanumeric characters: a-z, A-Z, and 0-9
|
||||
- The following special characters: - and _ */
|
||||
#define VALID_HEADER_NAME_CHARS \
|
||||
ALPHANUMERICAL "_-"
|
||||
|
||||
#define VALID_HEADER_NAME_LENGTH 40
|
||||
|
||||
#define VALID_HEADER_VALUE_CHARS \
|
||||
ALPHANUMERICAL "_ :;.,\\/'\"?!(){}[]@<>=-+*#$&`|~^%"
|
||||
|
||||
static bool header_name_is_valid(const char *e) {
|
||||
if (!e)
|
||||
return false;
|
||||
|
||||
if (strlen(e) == 0 || strlen(e) > VALID_HEADER_NAME_LENGTH)
|
||||
return false;
|
||||
|
||||
return in_charset(e, VALID_HEADER_NAME_CHARS);
|
||||
}
|
||||
|
||||
static bool header_value_is_valid(const char *e) {
|
||||
if (!e)
|
||||
return false;
|
||||
|
||||
return in_charset(e, VALID_HEADER_VALUE_CHARS);
|
||||
}
|
||||
|
||||
int header_put(OrderedHashmap **headers, const char *name, const char *value) {
|
||||
assert(headers);
|
||||
|
||||
if (!header_value_is_valid(value))
|
||||
return -EINVAL;
|
||||
|
||||
if (!header_name_is_valid(name))
|
||||
return -EINVAL;
|
||||
|
||||
return string_strv_ordered_hashmap_put(headers, name, value);
|
||||
}
|
||||
|
||||
int config_parse_header(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
OrderedHashmap **headers = ASSERT_PTR(data);
|
||||
char *unescaped, *t;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
/* an empty string clears the previous assignments. */
|
||||
*headers = ordered_hashmap_free(*headers);
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = cunescape(rvalue, 0, &unescaped);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to unescape headers: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
t = strchr(unescaped, ':');
|
||||
if (!t) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Failed to parse header, name: value separator was not found, ignoring: %s", unescaped);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*t++ = '\0';
|
||||
|
||||
r = header_put(headers, strstrip(unescaped), skip_leading_chars(t, WHITESPACE));
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to update headers: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
9
src/journal-remote/journal-header-util.h
Normal file
9
src/journal-remote/journal-header-util.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "hashmap.h"
|
||||
|
||||
int header_put(OrderedHashmap **headers, const char *name, const char *value);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_header);
|
@ -15,11 +15,13 @@
|
||||
#include "constants.h"
|
||||
#include "daemon-util.h"
|
||||
#include "env-file.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "glob-util.h"
|
||||
#include "journal-header-util.h"
|
||||
#include "journal-upload.h"
|
||||
#include "journal-util.h"
|
||||
#include "log.h"
|
||||
@ -59,6 +61,7 @@ static int arg_follow = -1;
|
||||
static char *arg_save_state = NULL;
|
||||
static usec_t arg_network_timeout_usec = USEC_INFINITY;
|
||||
static OrderedHashmap *arg_compression = NULL;
|
||||
static OrderedHashmap *arg_headers = NULL;
|
||||
static bool arg_force_compression = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_url, freep);
|
||||
@ -72,6 +75,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_machine, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_namespace, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_save_state, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_compression, ordered_hashmap_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_headers, ordered_hashmap_freep);
|
||||
|
||||
static void close_fd_input(Uploader *u);
|
||||
|
||||
@ -226,6 +230,23 @@ int start_upload(Uploader *u,
|
||||
h = l;
|
||||
}
|
||||
|
||||
char **values;
|
||||
const char *name;
|
||||
ORDERED_HASHMAP_FOREACH_KEY(values, name, arg_headers) {
|
||||
_cleanup_free_ char *joined = strv_join(values, ", ");
|
||||
if (!joined)
|
||||
return log_oom();
|
||||
|
||||
_cleanup_free_ char *header = strjoin(name, ": ", joined);
|
||||
if (!header)
|
||||
return log_oom();
|
||||
|
||||
l = curl_slist_append(h, header);
|
||||
if (!l)
|
||||
return log_oom();
|
||||
h = l;
|
||||
}
|
||||
|
||||
u->header = TAKE_PTR(h);
|
||||
}
|
||||
|
||||
@ -657,6 +678,7 @@ static int parse_config(void) {
|
||||
{ "Upload", "ServerCertificateFile", config_parse_path_or_ignore, 0, &arg_cert },
|
||||
{ "Upload", "TrustedCertificateFile", config_parse_path_or_ignore, 0, &arg_trust },
|
||||
{ "Upload", "NetworkTimeoutSec", config_parse_sec, 0, &arg_network_timeout_usec },
|
||||
{ "Upload", "Header", config_parse_header, 0, &arg_headers },
|
||||
{ "Upload", "Compression", config_parse_compression, /* with_level */ true, &arg_compression },
|
||||
{ "Upload", "ForceCompression", config_parse_bool, 0, &arg_force_compression },
|
||||
{}
|
||||
|
@ -4,6 +4,7 @@ systemd_journal_upload_sources = files(
|
||||
'journal-compression-util.c',
|
||||
'journal-upload-journal.c',
|
||||
'journal-upload.c',
|
||||
'journal-header-util.c',
|
||||
)
|
||||
|
||||
libsystemd_journal_remote_sources = files(
|
||||
@ -90,6 +91,12 @@ executables += [
|
||||
},
|
||||
]
|
||||
|
||||
executables += [
|
||||
test_template + {
|
||||
'sources' : files('test-journal-header-util.c', 'journal-header-util.c'),
|
||||
},
|
||||
]
|
||||
|
||||
in_files = [
|
||||
['journal-upload.conf',
|
||||
conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_LIBCURL') == 1 and install_sysconfdir_samples],
|
||||
|
21
src/journal-remote/test-journal-header-util.c
Normal file
21
src/journal-remote/test-journal-header-util.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "journal-header-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
TEST(header_put) {
|
||||
_cleanup_ordered_hashmap_free_ OrderedHashmap *headers = NULL;
|
||||
|
||||
ASSERT_OK_POSITIVE(header_put(&headers, "NewName", "Val"));
|
||||
ASSERT_OK_POSITIVE(header_put(&headers, "Name", "FirstName"));
|
||||
ASSERT_OK_POSITIVE(header_put(&headers, "Name", "Override"));
|
||||
ASSERT_OK_ZERO(header_put(&headers, "Name", "FirstName"));
|
||||
ASSERT_ERROR(header_put(&headers, "InvalidN@me", "test"), EINVAL);
|
||||
ASSERT_ERROR(header_put(&headers, "Name", NULL), EINVAL);
|
||||
ASSERT_ERROR(header_put(&headers, NULL, "Value"), EINVAL);
|
||||
ASSERT_OK_POSITIVE(header_put(&headers, "Name", ""));
|
||||
ASSERT_ERROR(header_put(&headers, "", "Value"), EINVAL);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
@ -272,3 +272,41 @@ EOF
|
||||
rm /run/systemd/journal-upload.conf.d/99-test.conf
|
||||
rm /run/systemd/journal-remote.conf.d/99-test.conf
|
||||
done
|
||||
|
||||
# Let's test sending data with custom headers
|
||||
echo "$TEST_MESSAGE" | systemd-cat -t "$TEST_TAG"
|
||||
journalctl --sync
|
||||
|
||||
cat >/run/systemd/journal-remote.conf.d/99-test.conf <<EOF
|
||||
[Remote]
|
||||
SplitMode=host
|
||||
ServerKeyFile=/run/systemd/remote-pki/server.key
|
||||
ServerCertificateFile=/run/systemd/remote-pki/server.crt
|
||||
TrustedCertificateFile=/run/systemd/remote-pki/ca.crt
|
||||
EOF
|
||||
|
||||
cat >/run/systemd/journal-upload.conf.d/99-test.conf <<EOF
|
||||
[Upload]
|
||||
URL=https://localhost:19532
|
||||
Header=TestHeader: TestValue
|
||||
ServerKeyFile=/run/systemd/remote-pki/client.key
|
||||
ServerCertificateFile=/run/systemd/remote-pki/client.crt
|
||||
TrustedCertificateFile=/run/systemd/remote-pki/ca.crt
|
||||
EOF
|
||||
|
||||
systemd-analyze cat-config systemd/journal-remote.conf
|
||||
systemd-analyze cat-config systemd/journal-upload.conf
|
||||
|
||||
systemctl restart systemd-journal-remote.socket
|
||||
systemctl restart systemd-journal-upload
|
||||
timeout 15 bash -xec 'until systemctl -q is-active systemd-journal-remote.service; do sleep 1; done'
|
||||
systemctl status systemd-journal-{remote,upload}
|
||||
|
||||
# It may take a bit until the whole journal is transferred
|
||||
timeout 30 bash -xec "until journalctl --directory=/var/log/journal/remote --identifier='$TEST_TAG' --grep='$TEST_MESSAGE'; do sleep 1; done"
|
||||
|
||||
systemctl stop systemd-journal-upload
|
||||
systemctl stop systemd-journal-remote.{socket,service}
|
||||
rm -rf /var/log/journal/remote/*
|
||||
rm /run/systemd/journal-upload.conf.d/99-test.conf
|
||||
rm /run/systemd/journal-remote.conf.d/99-test.conf
|
||||
|
Loading…
x
Reference in New Issue
Block a user