imds: add new systemd-imdsd.service that makes IMDS data accessible locally

This service's job is to talk to a VM associated IMDS service provided
by the local Cloud. It tries to abstract the protocol differences
various IMDS implementations implement, but does *not* really try to
abstract more than a few basic fields of the actual IMDS metadata.

IMDS access is wrapped in a Varlink API that local clients can talk to.

If possible this makes use of the IMDS endpoint information that has
been added to hwdb in the preceeding commit. However, endpoint info can
also be provided via kernel command line and credentials. For debugging
purposes we also accept them via environment variables and command line
arguments.

This adds a concept of early-boot networking, just enough to be able to
talk to the IMDS service. It is minimally configurable via a kernel
cmdline option (and a build-time option): the user may choose between
"locked" and "unlocked" mode. In the former mode direct access to IMDS via
HTTPS is blocked via a prohibit route (and thus all IMDS communication
has to be done via systemd-imdsd@.service). In the latter case no such
lockdown takes place, and IMDS may be acquired both via this new service
and directly. The latter is typically a good idea for compatibility with
current systems, the former is preferable for secure installations.

Access to IMDS fields is controlled via PK.
This commit is contained in:
Lennart Poettering
2026-03-26 10:54:15 +01:00
parent f3eac272e6
commit eb6e5b07f1
22 changed files with 3828 additions and 3 deletions
+13
View File
@@ -793,6 +793,19 @@
<xi:include href="version-info.xml" xpointer="v258"/></listitem> <xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>systemd.imds=</varname></term>
<term><varname>systemd.imds.*=</varname></term>
<listitem><para>Controls various Instance Metadata Service (IMDS) cloud aspects, see
<citerefentry><refentrytitle>systemd-imdsd@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
and
<citerefentry><refentrytitle>systemd-imds-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for details.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>
+6
View File
@@ -1045,6 +1045,12 @@ manpages = [
['systemd-hostnamed.service', '8', ['systemd-hostnamed'], 'ENABLE_HOSTNAMED'], ['systemd-hostnamed.service', '8', ['systemd-hostnamed'], 'ENABLE_HOSTNAMED'],
['systemd-hwdb', '8', [], 'ENABLE_HWDB'], ['systemd-hwdb', '8', [], 'ENABLE_HWDB'],
['systemd-id128', '1', [], ''], ['systemd-id128', '1', [], ''],
['systemd-imdsd@.service',
'8',
['systemd-imdsd',
'systemd-imdsd-early-network.service',
'systemd-imdsd.socket'],
'ENABLE_IMDS'],
['systemd-import-generator', '8', [], ''], ['systemd-import-generator', '8', [], ''],
['systemd-importd.service', '8', ['systemd-importd'], 'ENABLE_IMPORTD'], ['systemd-importd.service', '8', ['systemd-importd'], 'ENABLE_IMPORTD'],
['systemd-inhibit', '1', [], ''], ['systemd-inhibit', '1', [], ''],
+269
View File
@@ -0,0 +1,269 @@
<?xml version="1.0"?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="systemd-imdsd_.service" conditional='ENABLE_IMDS' xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-imdsd@.service</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-imdsd@.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-imdsd@.service</refname>
<refname>systemd-imdsd</refname>
<refname>systemd-imdsd.socket</refname>
<refname>systemd-imdsd-early-network.service</refname>
<refpurpose>Cloud IMDS (Instance Metadata Service) client</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-imdsd@.service</filename></para>
<para><filename>systemd-imdsd.socket</filename></para>
<para><filename>systemd-imdsd-early-network.service</filename></para>
<para><filename>/usr/lib/systemd/systemd-imdsd</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><command>systemd-imdsd@.service</command> is a system service that provides local access to IMDS
(Instance Metadata Service; or equivalent) functionality, as provided by many public clouds.</para>
<para>The service provides a Varlink IPC interface via
<filename>/run/systemd/io.systemd.InstanceMetadata</filename> to query IMDS fields.</para>
<para><filename>systemd-imdsd-early-network.service</filename> is a system service that generates a
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
compatible
<citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry> file
for configuring the early-boot network in order to be able to contact the IMDS endpoint.</para>
<para>The
<citerefentry><refentrytitle>systemd-imds</refentrytitle><manvolnum>1</manvolnum></citerefentry> tool may
be used to query information from this service.</para>
</refsect1>
<!-- Note: we do not document the command line switches here for now. The systemd-imdsd binary itself
should not be called by users, but only as a service, hence the command line options shouldn't be user
visible, but exist mostly as debugging tools. People should always use the client side tool
(i.e. systemd-imds; or an equivalent Varlink client) to do actual IMDS operations. -->
<refsect1>
<title>Kernel Command Line Options</title>
<para>The IMDS endpoint is typically determined automatically via
<citerefentry><refentrytitle>hwdb</refentrytitle><manvolnum>7</manvolnum></citerefentry> records, but can
also be configured explicitly via the kernel command line, via the following options:</para>
<variablelist class='kernel-commandline-options'>
<varlistentry id='kernel-cmdline-imds-network'>
<term><varname>systemd.imds.network=</varname></term>
<listitem>
<para>Takes one of <literal>off</literal>, <literal>locked</literal>,
<literal>unlocked</literal>. Controls whether and how to set up networking for IMDS endpoint
access. Unless set to <literal>off</literal> early boot networking is enabled, ensuring that the
IMDS endpoint can be reached. If set to <literal>locked</literal> (the default) direct access to
the IMDS endpoint by regular unprivileged processes is disabled via a "prohibit" route, so that any
access must be done through <filename>systemd-imdsd@.service</filename> or its associated tools. If
set to <literal>unlocked</literal> this "prohibit" route is not created, and regular unprivileged
processes can directly contact IMDS.</para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.vendor=</varname></term>
<listitem>
<para>A short string identifying the cloud vendor.</para>
<para>Example: <programlisting>systemd.imds.vendor=foobarcloud</programlisting></para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.token_url=</varname></term>
<listitem>
<para>If a bearer token must be acquired to talk to the IMDS service, this is the URL to acquire it
from.</para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.refresh_header_name=</varname></term>
<listitem>
<para>Takes a HTTP header field name (excluding the <literal>:</literal>) that declares the header
field for passing the TTL value (in seconds) to the HTTP server when acquiring a token. Only
applies if <varname>systemd.imds.token_url=</varname> is set too.</para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.data_url=</varname></term>
<listitem>
<para>Takes the base URL to acquire the IMDS data from (the IMDS "endpoint"). All data fields are
acquired from below this URL. This URL should typically not end in <literal>/</literal>.</para>
<para>The data URLs are concatenated from this base URL, the IMDS "key" and the suffix configured
via <varname>systemd.imds.data_url_suffix=</varname> below. Well-known IMDS "keys" can be
configured via the <varname>systemd.imds.key=*</varname> options below.</para>
<para>Example: <programlisting>systemd.imds.data_url=http://169.254.169.254/metadata</programlisting></para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.data_url_suffix=</varname></term>
<listitem>
<para>If specified, this field is appended to the end of the data URL (after appending the IMDS
"key" to the data base URL), see above.</para>
<para>Example: <programlisting>systemd.imds.data_url_suffix=?api-version=2025-04-07&amp;format=text</programlisting></para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.token_header_name=</varname></term>
<listitem>
<para>Takes a HTTP header field name (excluding the <literal>:</literal>) that declares the header
field to pass the bearer token acquired from the token URL (see above) in. Only applies if
<varname>systemd.imds.token_url=</varname> is set too.</para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.extra_header=</varname></term>
<listitem>
<para>Takes a full HTTP header expression (both field name and value, separated by a colon
<literal>:</literal>) to pass to the HTTP server when requesting data. May be used multiple times
to set multiple headers.</para>
<para>Example: <programlisting>systemd.imds.extra_header=Metadata:true</programlisting></para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.address_ipv4=</varname></term>
<listitem>
<para>Configures the IPv4 address the IMDS endpoint is contacted on. This should typically be the
IP address also configured via <varname>systemd.imds.data_url=</varname> (if IPv4 is used) and is
used to set up IP routing.</para>
<para>Example: <programlisting>systemd.imds.address_ipv4=169.254.169.254</programlisting></para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.address_ipv6=</varname></term>
<listitem>
<para>Configures the IPv6 address the IMDS endpoint is contacted on. This should typically be the
IP address also configured via <varname>systemd.imds.data_url=</varname> (if IPv6 is used) and is
used to set up IP routing.</para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>systemd.imds.key.hostname=</varname></term>
<term><varname>systemd.imds.key.region=</varname></term>
<term><varname>systemd.imds.key.zone=</varname></term>
<term><varname>systemd.imds.key.ipv4_public=</varname></term>
<term><varname>systemd.imds.key.ipv6_public=</varname></term>
<term><varname>systemd.imds.key.ssh_key=</varname></term>
<term><varname>systemd.imds.key.userdata=</varname></term>
<term><varname>systemd.imds.key.userdata_base=</varname></term>
<term><varname>systemd.imds.key.userdata_base64=</varname></term>
<listitem>
<para>Configures strings to concatenate to the data base URL (see above) to acquire data for
various "well-known" fields. These strings must begin with a <literal>/</literal>. They should
return the relevant data in plain text.</para>
<para>A special case are the three "userdata" keys: the option
<varname>systemd.imds.key.userdata_base=</varname> should be used if the IMDS service knows a
concept of multiple userdata fields, and a field identifier thus still needs to be appended to the
userdata base URL. The option <varname>systemd.imds.key.userdata=</varname> should be used if only
a single userdata field is supported. The option <varname>systemd.imds.key.userdata_base64=</varname>
should be used in the same case, but only if the userdata field is encoded in Base64.</para>
<para>Example: <programlisting>systemd.imds.key.hostname=/instance/compute/osProfile/computerName</programlisting></para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Credentials</title>
<para><filename>systemd-imdsd@.service</filename> supports the service credentials logic as implemented by
<varname>ImportCredential=</varname>/<varname>LoadCredential=</varname>/<varname>SetCredential=</varname>
(see <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details). The following credentials are used when passed in:</para>
<variablelist class='system-credentials'>
<varlistentry>
<term><varname>imds.vendor</varname></term>
<term><varname>imds.vendor_token</varname></term>
<term><varname>imds.refresh_header_name</varname></term>
<term><varname>imds.data_url</varname></term>
<term><varname>imds.data_url_suffix</varname></term>
<term><varname>imds.token_header_name</varname></term>
<term><varname>imds.extra_header</varname></term>
<term><varname>imds.extra_header2</varname></term>
<term><varname>imds.extra_header3</varname></term>
<term><varname>imds.extra_header…</varname></term>
<term><varname>imds.address_ipv4</varname></term>
<term><varname>imds.address_ipv6</varname></term>
<term><varname>imds.key_hostname</varname></term>
<term><varname>imds.key_region</varname></term>
<term><varname>imds.key_zone</varname></term>
<term><varname>imds.key_ipv4_public</varname></term>
<term><varname>imds.key_ipv6_public</varname></term>
<term><varname>imds.key_ssh_key</varname></term>
<term><varname>imds.key_userdata</varname></term>
<term><varname>imds.key_userdata_base</varname></term>
<term><varname>imds.key_userdata_base64</varname></term>
<listitem><para>The various IMDS endpoint parameters. The semantics are very close to those configurable
via kernel command line, see above for the matching list.</para>
<xi:include href="version-info.xml" xpointer="v261"/></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para><simplelist type="inline">
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemd-imds</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemd-imds-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
<member><citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
</simplelist></para>
</refsect1>
</refentry>
+10
View File
@@ -580,6 +580,16 @@
<xi:include href="version-info.xml" xpointer="v258"/> <xi:include href="version-info.xml" xpointer="v258"/>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>imds.*</varname></term>
<listitem>
<para>Read by <citerefentry><refentrytitle>systemd-imdsd@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<xi:include href="version-info.xml" xpointer="v261"/>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>
+8
View File
@@ -906,6 +906,7 @@ foreach option : ['adm-gid',
'video-gid', 'video-gid',
'wheel-gid', 'wheel-gid',
'systemd-journal-gid', 'systemd-journal-gid',
'systemd-imds-uid',
'systemd-network-uid', 'systemd-network-uid',
'systemd-resolve-uid', 'systemd-resolve-uid',
'systemd-timesync-uid'] 'systemd-timesync-uid']
@@ -1539,6 +1540,11 @@ conf.set('DEFAULT_DNSSEC_MODE',
'DNSSEC_' + default_dnssec.underscorify().to_upper()) 'DNSSEC_' + default_dnssec.underscorify().to_upper())
conf.set_quoted('DEFAULT_DNSSEC_MODE_STR', default_dnssec) conf.set_quoted('DEFAULT_DNSSEC_MODE_STR', default_dnssec)
have = get_option('imds').require(
conf.get('HAVE_LIBCURL') == 1,
error_message : 'curl required').allowed()
conf.set10('ENABLE_IMDS', have)
have = get_option('importd').require( have = get_option('importd').require(
conf.get('HAVE_LIBCURL') == 1 and conf.get('HAVE_LIBCURL') == 1 and
conf.get('HAVE_OPENSSL') == 1 and conf.get('HAVE_OPENSSL') == 1 and
@@ -2375,6 +2381,7 @@ subdir('src/hostname')
subdir('src/hwdb') subdir('src/hwdb')
subdir('src/id128') subdir('src/id128')
subdir('src/import') subdir('src/import')
subdir('src/imds') # Note, we are not alphabetically here, since we want to use a variable from src/import/ here
subdir('src/integritysetup') subdir('src/integritysetup')
subdir('src/journal') subdir('src/journal')
subdir('src/journal-remote') subdir('src/journal-remote')
@@ -3145,6 +3152,7 @@ foreach tuple : [
['homed'], ['homed'],
['hostnamed'], ['hostnamed'],
['hwdb'], ['hwdb'],
['imds'],
['importd'], ['importd'],
['initrd'], ['initrd'],
['kernel-install'], ['kernel-install'],
+4
View File
@@ -142,6 +142,8 @@ option('timedated', type : 'boolean',
description : 'install the systemd-timedated daemon') description : 'install the systemd-timedated daemon')
option('timesyncd', type : 'boolean', option('timesyncd', type : 'boolean',
description : 'install the systemd-timesyncd daemon') description : 'install the systemd-timesyncd daemon')
option('imds', type : 'feature',
description : 'install the systemd-imds stack')
option('journal-storage-default', type : 'combo', choices : ['persistent', 'auto', 'volatile', 'none'], option('journal-storage-default', type : 'combo', choices : ['persistent', 'auto', 'volatile', 'none'],
description : 'default storage mode for journald (main namespace)') description : 'default storage mode for journald (main namespace)')
option('remote', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' }, option('remote', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
@@ -334,6 +336,8 @@ option('systemd-resolve-uid', type : 'integer', value : 0,
description : 'soft-static allocation for the systemd-resolve user') description : 'soft-static allocation for the systemd-resolve user')
option('systemd-timesync-uid', type : 'integer', value : 0, option('systemd-timesync-uid', type : 'integer', value : 0,
description : 'soft-static allocation for the systemd-timesync user') description : 'soft-static allocation for the systemd-timesync user')
option('systemd-imds-uid', type : 'integer', value : 0,
description : 'soft-static allocation for the systemd-imds user')
option('dev-kvm-mode', type : 'string', value : '0666', option('dev-kvm-mode', type : 'string', value : '0666',
description : '/dev/kvm access mode') description : '/dev/kvm access mode')
+50
View File
@@ -0,0 +1,50 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <assert.h>
#include "imds-util.h"
#include "string-table.h"
#include "string-util.h"
#include "utf8.h"
bool imds_key_is_valid(const char *key) {
/* Just some pretty superficial validation. */
if (!key)
return false;
if (!startswith(key, "/"))
return false;
if (!ascii_is_valid(key))
return false;
if (string_has_cc(key, /* ok= */ NULL))
return false;
return true;
}
static const char* const imds_well_known_table[_IMDS_WELL_KNOWN_MAX] = {
[IMDS_BASE] = "base",
[IMDS_HOSTNAME] = "hostname",
[IMDS_REGION] = "region",
[IMDS_ZONE] = "zone",
[IMDS_IPV4_PUBLIC] = "ipv4-public",
[IMDS_IPV6_PUBLIC] = "ipv6-public",
[IMDS_SSH_KEY] = "ssh-key",
[IMDS_USERDATA] = "userdata",
[IMDS_USERDATA_BASE] = "userdata-base",
[IMDS_USERDATA_BASE64] = "userdata-base64",
};
DEFINE_STRING_TABLE_LOOKUP(imds_well_known, ImdsWellKnown);
static const char* const imds_network_mode_table[_IMDS_NETWORK_MODE_MAX] = {
[IMDS_NETWORK_OFF] = "off",
[IMDS_NETWORK_LOCKED] = "locked",
[IMDS_NETWORK_UNLOCKED] = "unlocked",
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(imds_network_mode, ImdsNetworkMode, IMDS_NETWORK_LOCKED);
+38
View File
@@ -0,0 +1,38 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "macro.h"
#include "string-table.h" /* IWYU pragma: keep */
typedef enum ImdsNetworkMode {
IMDS_NETWORK_OFF, /* No automatic pre-IMDS network configuration, something else has to do this. (Also: no "prohibit" route) */
IMDS_NETWORK_LOCKED, /* "Prohibit" route for the IMDS server, unless you have SO_MARK set to 0x7FFF0815 */
IMDS_NETWORK_UNLOCKED, /* No "prohibit" route for the IMDS server */
_IMDS_NETWORK_MODE_MAX,
_IMDS_NETWORK_MODE_INVALID = -EINVAL,
} ImdsNetworkMode;
/* Various well-known keys */
typedef enum ImdsWellKnown {
IMDS_BASE, /* The same as "/", typically suffixed */
IMDS_HOSTNAME,
IMDS_REGION,
IMDS_ZONE,
IMDS_IPV4_PUBLIC,
IMDS_IPV6_PUBLIC,
IMDS_SSH_KEY,
IMDS_USERDATA,
IMDS_USERDATA_BASE, /* typically suffixed */
IMDS_USERDATA_BASE64,
_IMDS_WELL_KNOWN_MAX,
_IMDS_WELL_KNOWN_INVALID = -EINVAL,
} ImdsWellKnown;
static inline bool imds_well_known_can_suffix(ImdsWellKnown wk) {
return IN_SET(wk, IMDS_BASE, IMDS_USERDATA_BASE);
}
bool imds_key_is_valid(const char *key);
DECLARE_STRING_TABLE_LOOKUP(imds_well_known, ImdsWellKnown);
DECLARE_STRING_TABLE_LOOKUP(imds_network_mode, ImdsNetworkMode);
+3163
View File
File diff suppressed because it is too large Load Diff
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"https://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<!--
SPDX-License-Identifier: LGPL-2.1-or-later
This file is part of systemd.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
-->
<policyconfig>
<vendor>The systemd Project</vendor>
<vendor_url>https://systemd.io</vendor_url>
<action id="io.systemd.imds.get">
<description gettext-domain="systemd">Acquire IMDS instance metadata.</description>
<message gettext-domain="systemd">Authentication is required for an application to acquire IMDS instance metadata.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>
+21
View File
@@ -0,0 +1,21 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
if conf.get('ENABLE_IMDS') != 1
subdir_done()
endif
executables += [
libexec_template + {
'name' : 'systemd-imdsd',
'public' : true,
'sources' : files(
'imdsd.c',
'imds-util.c'
) + import_curl_util_c,
'dependencies' : [ libcurl ],
},
]
install_data(
'io.systemd.imds.policy',
install_dir : polkitpolicydir)
+3 -2
View File
@@ -1,5 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
import_curl_util_c = files('curl-util.c')
if conf.get('ENABLE_IMPORTD') != 1 if conf.get('ENABLE_IMPORTD') != 1
subdir_done() subdir_done()
endif endif
@@ -32,14 +34,13 @@ executables += [
'name' : 'systemd-pull', 'name' : 'systemd-pull',
'public' : true, 'public' : true,
'sources' : files( 'sources' : files(
'curl-util.c',
'pull.c', 'pull.c',
'pull-common.c', 'pull-common.c',
'pull-job.c', 'pull-job.c',
'pull-oci.c', 'pull-oci.c',
'pull-raw.c', 'pull-raw.c',
'pull-tar.c', 'pull-tar.c',
), ) + import_curl_util_c,
'objects' : ['systemd-importd'], 'objects' : ['systemd-importd'],
'dependencies' : common_deps + [ 'dependencies' : common_deps + [
libopenssl, libopenssl,
+1
View File
@@ -207,6 +207,7 @@ shared_sources = files(
'varlink-io.systemd.FactoryReset.c', 'varlink-io.systemd.FactoryReset.c',
'varlink-io.systemd.Hostname.c', 'varlink-io.systemd.Hostname.c',
'varlink-io.systemd.Import.c', 'varlink-io.systemd.Import.c',
'varlink-io.systemd.InstanceMetadata.c',
'varlink-io.systemd.Journal.c', 'varlink-io.systemd.Journal.c',
'varlink-io.systemd.JournalAccess.c', 'varlink-io.systemd.JournalAccess.c',
'varlink-io.systemd.Login.c', 'varlink-io.systemd.Login.c',
@@ -0,0 +1,103 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "bus-polkit.h"
#include "varlink-io.systemd.InstanceMetadata.h"
static SD_VARLINK_DEFINE_ENUM_TYPE(
WellKnown,
SD_VARLINK_DEFINE_ENUM_VALUE(base),
SD_VARLINK_DEFINE_ENUM_VALUE(hostname),
SD_VARLINK_DEFINE_ENUM_VALUE(region),
SD_VARLINK_DEFINE_ENUM_VALUE(zone),
SD_VARLINK_DEFINE_ENUM_VALUE(ipv4_public),
SD_VARLINK_DEFINE_ENUM_VALUE(ipv6_public),
SD_VARLINK_DEFINE_ENUM_VALUE(ssh_key),
SD_VARLINK_DEFINE_ENUM_VALUE(userdata),
SD_VARLINK_DEFINE_ENUM_VALUE(userdata_base),
SD_VARLINK_DEFINE_ENUM_VALUE(userdata_base64));
static SD_VARLINK_DEFINE_METHOD(
Get,
SD_VARLINK_FIELD_COMMENT("The key to retrieve"),
SD_VARLINK_DEFINE_INPUT(key, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Start with a well-known key"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(wellKnown, WellKnown, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The network interface to use"),
SD_VARLINK_DEFINE_INPUT(interface, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Refresh cached data if older (CLOCK_BOOTTIME, µs)"),
SD_VARLINK_DEFINE_INPUT(refreshUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Whether to accept cached data"),
SD_VARLINK_DEFINE_INPUT(cache, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The firewall mark value to use"),
SD_VARLINK_DEFINE_INPUT(firewallMark, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Controls whether to wait for connectivity"),
SD_VARLINK_DEFINE_INPUT(wait, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
VARLINK_DEFINE_POLKIT_INPUT,
SD_VARLINK_FIELD_COMMENT("The data in Base64 encoding."),
SD_VARLINK_DEFINE_OUTPUT(data, SD_VARLINK_STRING, 0),
SD_VARLINK_FIELD_COMMENT("The interface the data was found on."),
SD_VARLINK_DEFINE_OUTPUT(interface, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_METHOD(
GetVendorInfo,
SD_VARLINK_FIELD_COMMENT("The detected cloud vendor"),
SD_VARLINK_DEFINE_OUTPUT(vendor, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The URL to acquire the token from"),
SD_VARLINK_DEFINE_OUTPUT(tokenUrl, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The HTTP header to configure the refresh timeout for the token in"),
SD_VARLINK_DEFINE_OUTPUT(refreshHeaderName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The base URL to acquire the data from"),
SD_VARLINK_DEFINE_OUTPUT(dataUrl, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("A suffix to append to the data URL"),
SD_VARLINK_DEFINE_OUTPUT(dataUrlSuffix, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The HTTP header to pass the token in when requesting data"),
SD_VARLINK_DEFINE_OUTPUT(tokenHeaderName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Additional HTTP headers to pass when acquiring data"),
SD_VARLINK_DEFINE_OUTPUT(extraHeader, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
SD_VARLINK_FIELD_COMMENT("IPv4 address of IMDS server"),
SD_VARLINK_DEFINE_OUTPUT(addressIPv4, SD_VARLINK_INT, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
SD_VARLINK_FIELD_COMMENT("IPv6 address of IMDS server"),
SD_VARLINK_DEFINE_OUTPUT(addressIPv6, SD_VARLINK_INT, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
SD_VARLINK_FIELD_COMMENT("Well-known fields"),
SD_VARLINK_DEFINE_OUTPUT(wellKnown, SD_VARLINK_OBJECT, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_ERROR(
KeyNotFound);
static SD_VARLINK_DEFINE_ERROR(
WellKnownKeyUnset);
static SD_VARLINK_DEFINE_ERROR(
NotAvailable);
static SD_VARLINK_DEFINE_ERROR(
NotSupported);
static SD_VARLINK_DEFINE_ERROR(
CommunicationFailure);
static SD_VARLINK_DEFINE_ERROR(
Timeout);
SD_VARLINK_DEFINE_INTERFACE(
io_systemd_InstanceMetadata,
"io.systemd.InstanceMetadata",
SD_VARLINK_INTERFACE_COMMENT("APIs for acquiring cloud IMDS information."),
SD_VARLINK_SYMBOL_COMMENT("Well known data fields"),
&vl_type_WellKnown,
SD_VARLINK_SYMBOL_COMMENT("Acquire data."),
&vl_method_Get,
SD_VARLINK_SYMBOL_COMMENT("Get information about cloud vendor and IMDS connectivity."),
&vl_method_GetVendorInfo,
SD_VARLINK_SYMBOL_COMMENT("The requested key is not found on the IMDS server."),
&vl_error_KeyNotFound,
SD_VARLINK_SYMBOL_COMMENT("IMDS is disabled or otherwise not available."),
&vl_error_NotAvailable,
SD_VARLINK_SYMBOL_COMMENT("IMDS is not supported."),
&vl_error_NotSupported,
SD_VARLINK_SYMBOL_COMMENT("Well-known key is not set."),
&vl_error_WellKnownKeyUnset,
SD_VARLINK_SYMBOL_COMMENT("Communication with IMDS failed."),
&vl_error_CommunicationFailure,
SD_VARLINK_SYMBOL_COMMENT("Timeout reached"),
&vl_error_Timeout);
@@ -0,0 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "sd-varlink-idl.h"
extern const sd_varlink_interface vl_interface_io_systemd_InstanceMetadata;
+2
View File
@@ -24,6 +24,7 @@
#include "varlink-io.systemd.FactoryReset.h" #include "varlink-io.systemd.FactoryReset.h"
#include "varlink-io.systemd.Hostname.h" #include "varlink-io.systemd.Hostname.h"
#include "varlink-io.systemd.Import.h" #include "varlink-io.systemd.Import.h"
#include "varlink-io.systemd.InstanceMetadata.h"
#include "varlink-io.systemd.Journal.h" #include "varlink-io.systemd.Journal.h"
#include "varlink-io.systemd.JournalAccess.h" #include "varlink-io.systemd.JournalAccess.h"
#include "varlink-io.systemd.Login.h" #include "varlink-io.systemd.Login.h"
@@ -190,6 +191,7 @@ TEST(parse_format) {
&vl_interface_io_systemd_FactoryReset, &vl_interface_io_systemd_FactoryReset,
&vl_interface_io_systemd_Hostname, &vl_interface_io_systemd_Hostname,
&vl_interface_io_systemd_Import, &vl_interface_io_systemd_Import,
&vl_interface_io_systemd_InstanceMetadata,
&vl_interface_io_systemd_Journal, &vl_interface_io_systemd_Journal,
&vl_interface_io_systemd_JournalAccess, &vl_interface_io_systemd_JournalAccess,
&vl_interface_io_systemd_Login, &vl_interface_io_systemd_Login,
+2 -1
View File
@@ -15,7 +15,8 @@ in_files = [['basic.conf', true],
['systemd-journal.conf', true], ['systemd-journal.conf', true],
['systemd-network.conf', conf.get('ENABLE_NETWORKD') == 1], ['systemd-network.conf', conf.get('ENABLE_NETWORKD') == 1],
['systemd-resolve.conf', conf.get('ENABLE_RESOLVE') == 1], ['systemd-resolve.conf', conf.get('ENABLE_RESOLVE') == 1],
['systemd-timesync.conf', conf.get('ENABLE_TIMESYNCD') == 1]] ['systemd-timesync.conf', conf.get('ENABLE_TIMESYNCD') == 1],
['systemd-imds.conf', conf.get('ENABLE_IMDS') == 1]]
foreach tuple : in_files foreach tuple : in_files
file = tuple[0] file = tuple[0]
+8
View File
@@ -0,0 +1,8 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
u! systemd-imds {{SYSTEMD_IMDS_UID}} "systemd Instance Metadata"
+12
View File
@@ -392,6 +392,18 @@ units = [
'file' : 'systemd-hybrid-sleep.service.in', 'file' : 'systemd-hybrid-sleep.service.in',
'conditions' : ['ENABLE_HIBERNATE'], 'conditions' : ['ENABLE_HIBERNATE'],
}, },
{
'file' : 'systemd-imdsd@.service.in',
'conditions' : ['ENABLE_IMDS'],
},
{
'file' : 'systemd-imdsd.socket',
'conditions' : ['ENABLE_IMDS'],
},
{
'file' : 'systemd-imds-early-network.service.in',
'conditions' : ['ENABLE_IMDS'],
},
{ {
'file' : 'systemd-importd.service.in', 'file' : 'systemd-importd.service.in',
'conditions' : ['ENABLE_IMPORTD'], 'conditions' : ['ENABLE_IMPORTD'],
@@ -0,0 +1,23 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Enable Pre-IMDS Networking
Documentation=man:systemd-imdsd@.service(8)
DefaultDependencies=no
Before=network-pre.target
Wants=network-pre.target
Conflicts=shutdown.target initrd-switch-root.target
Before=shutdown.target initrd-switch-root.target
After=sys-devices-virtual-dmi-id.device
[Service]
ExecStart={{LIBEXECDIR}}/systemd-imdsd --setup-network
Type=oneshot
RemainAfterExit=yes
+28
View File
@@ -0,0 +1,28 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Cloud Instance Metadata Access (IMDS)
Documentation=man:systemd-imdsd@.service(8)
DefaultDependencies=no
Before=sockets.target
[Socket]
ListenStream=/run/systemd/io.systemd.InstanceMetadata
Symlinks=/run/varlink/registry/io.systemd.InstanceMetadata
FileDescriptorName=varlink
SocketMode=0666
Accept=yes
MaxConnectionsPerSource=16
RemoveOnStop=yes
# Note that this is typically pulled in automatically by
# systemd-imds-generator, but you can also enable it manually if you like.
[Install]
WantedBy=sockets.target
+28
View File
@@ -0,0 +1,28 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Cloud Instance Metadata Access (IMDS)
Documentation=man:systemd-imdsd@.service(8)
DefaultDependencies=no
Conflicts=shutdown.target initrd-switch-root.target
Before=shutdown.target initrd-switch-root.target
After=sys-devices-virtual-dmi-id.device
[Service]
ExecStart=-{{LIBEXECDIR}}/systemd-imdsd
User=systemd-imds
RuntimeDirectory=systemd/imds
RuntimeDirectoryPreserve=yes
# CAP_NET_ADMIN is required to set SO_FWMARK and bypass the routing restrictions, and CAP_NET_BIND_SERVICE to bind to a low port
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
ImportCredential=imds.*