]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hwdb: add database for basic IMDS properties
authorLennart Poettering <lennart@amutable.com>
Wed, 4 Mar 2026 14:07:09 +0000 (15:07 +0100)
committerLennart Poettering <lennart@amutable.com>
Thu, 26 Mar 2026 09:54:15 +0000 (10:54 +0100)
This adds a hardware database that contains information about IDMS
functionality of various clouds, keyed off the SMBIOS identification of
each. Currently this contains information about 6 major clouds, but the
idea is that this grows to include more and more major clouds.

Nothing uses this data yet, that's added in a later commit.

hwdb.d/40-imds.hwdb [new file with mode: 0644]
hwdb.d/meson.build
hwdb.d/parse_hwdb.py

diff --git a/hwdb.d/40-imds.hwdb b/hwdb.d/40-imds.hwdb
new file mode 100644 (file)
index 0000000..397a32b
--- /dev/null
@@ -0,0 +1,105 @@
+# This file is part of systemd
+
+# This provides various properties that declare if and how IMDS is available on
+# the local system, i.e. we are running in a major cloud service that provides
+# something resembling AWS' or Azure's Instance Metadata Service.
+#
+# General IMDS endpoint data:
+#   IMDS_VENDOR=                → Indicates IMDS is available, and which vendor it is
+#   IMDS_TOKEN_URL=             → The URL to request an API token from. If not set, no API token is requested.
+#   IMDS_REFRESH_HEADER_NAME=   → The HTTP request header field (everything before the ":") that contains the refresh TTL (in seconds) when requesting a token.
+#   IMDS_DATA_URL=              → The base URL to request actual IMDS data fields from
+#   IMDS_DATA_URL_SUFFIX=       → Parameters to suffix the URLs with
+#   IMDS_TOKEN_HEADER_NAME=     → The HTTP request header field (everything before the ":") used to pass the token
+#   IMDS_EXTRA_HEADER=, IMDS_EXTRA_HEADER2=, IMDS_EXTRA_HEADER3=, …
+#                               → Additional HTTP headers to pass when requesting a data field (full header, including ":")
+#   IMDS_ADDRESS_IPV4=          → IPv4 address of the IMDS server
+#   IMDS_ADDRESS_IPV6=          → IPv6 address of the IMDS server
+#
+# Well-known IMDS keys:
+#   IMDS_KEY_HOSTNAME=          → IMDS key for the hostname
+#   IMDS_KEY_REGION=            → IMDS key for the region, if that concept applies
+#   IMDS_KEY_ZONE=              → IMDS key for the zone, if that concept applies
+#   IMDS_KEY_IPV4_PUBLIC=       → IMDS key for the primary public IPv4 address if there is any
+#   IMDS_KEY_IPV6_PUBLIC=       → IMDS key for the primary public IPv6 address if there is any
+#   IMDS_KEY_SSH_KEY=           → IMDS key for an SSH public key to install in the root account
+#   IMDS_KEY_USERDATA=          → IMDS key for arbitrary userdata (if there's only one)
+#   IMDS_KEY_USERDATA_BASE=     → IMDS key for arbitrary userdata (if there are multiple, this is the common prefix)
+#   IMDS_KEY_USERDATA_BASE64=   → IMDS key for arbitrary userdata (if there's only one, but it is base64 encoded)
+
+# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html
+dmi:bvnAmazonEC2:*
+ IMDS_VENDOR=amazon-ec2
+ IMDS_TOKEN_URL=http://169.254.169.254/latest/api/token
+ IMDS_REFRESH_HEADER_NAME=X-aws-ec2-metadata-token-ttl-seconds
+ IMDS_DATA_URL=http://169.254.169.254/latest
+ IMDS_TOKEN_HEADER_NAME=X-aws-ec2-metadata-token
+ IMDS_ADDRESS_IPV4=169.254.169.254
+ IMDS_ADDRESS_IPV6=fd00:ec2::254
+ IMDS_KEY_HOSTNAME=/meta-data/hostname
+ IMDS_KEY_REGION=/meta-data/placement/region
+ IMDS_KEY_ZONE=/meta-data/placement/availability-zone
+ IMDS_KEY_IPV4_PUBLIC=/meta-data/public-ipv4
+ IMDS_KEY_IPV6_PUBLIC=/meta-data/ipv6
+ IMDS_KEY_SSH_KEY=/meta-data/public-keys/0/openssh-key
+ IMDS_KEY_USERDATA=/user-data
+
+# https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service#instance-metadata
+dmi:*:cat7783-7084-3265-9085-8269-3286-77:*
+ IMDS_VENDOR=microsoft-azure
+ IMDS_DATA_URL=http://169.254.169.254/metadata
+ IMDS_DATA_URL_SUFFIX=?api-version=2025-04-07&format=text
+ IMDS_EXTRA_HEADER=Metadata: true
+ IMDS_ADDRESS_IPV4=169.254.169.254
+ IMDS_KEY_HOSTNAME=/instance/compute/osProfile/computerName
+ IMDS_KEY_REGION=/instance/compute/location
+ IMDS_KEY_ZONE=/instance/compute/physicalZone
+ IMDS_KEY_IPV4_PUBLIC=/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress
+ IMDS_KEY_IPV6_PUBLIC=/instance/network/interface/0/ipv6/ipAddress/0/publicIpAddress
+ IMDS_KEY_SSH_KEY=/instance/compute/publicKeys/0/keyData
+ IMDS_KEY_USERDATA_BASE64=/instance/compute/userData
+
+# https://docs.cloud.google.com/compute/docs/metadata/predefined-metadata-keys
+dmi:*:pnGoogleComputeEngine:*
+ IMDS_VENDOR=google-gcp
+ IMDS_DATA_URL=http://169.254.169.254/computeMetadata/v1
+ IMDS_EXTRA_HEADER=Metadata-Flavor: Google
+ IMDS_ADDRESS_IPV4=169.254.169.254
+ IMDS_KEY_HOSTNAME=/instance/hostname
+ IMDS_KEY_REGION=/instance/region
+ IMDS_KEY_ZONE=/instance/zone
+ IMDS_KEY_IPV4_PUBLIC=/instance/network-interfaces/0/access-configs/0/external-ip
+ IMDS_KEY_USERDATA_BASE=/instance/attributes
+
+# https://docs.hetzner.cloud/reference/cloud#description/server-metadata
+dmi:bvnHetzner:*
+ IMDS_VENDOR=hetzner-cloud
+ IMDS_DATA_URL=http://169.254.169.254/hetzner/v1/metadata
+ IMDS_ADDRESS_IPV4=169.254.169.254
+ IMDS_KEY_HOSTNAME=/hostname
+ IMDS_KEY_REGION=/region
+ IMDS_KEY_ZONE=/availability-zone
+ IMDS_KEY_IPV4_PUBLIC=/public-ipv4
+ IMDS_KEY_SSH_KEY=/public-keys/0
+ IMDS_KEY_USERDATA=/userdata
+
+# https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm#metadata-keys
+dmi:*:catOracleCloud.com:*
+ IMDS_VENDOR=oracle-cloud-oci
+ IMDS_DATA_URL=http://169.254.169.254/opc/v2
+ IMDS_ADDRESS_IPV4=169.254.169.254
+ IMDS_ADDRESS_IPV6=fd00:c1::a9fe:a9fe
+ IMDS_EXTRA_HEADER=Authorization: Bearer Oracle
+ IMDS_KEY_HOSTNAME=/instance/hostname
+ IMDS_KEY_REGION=/instance/region
+ IMDS_KEY_ZONE=/instance/availabilityDomain
+ IMDS_KEY_SSH_KEY=/instance/metadata/ssh_authorized_keys
+ IMDS_KEY_USERDATA_BASE64=/metadata/user_data
+
+# https://www.scaleway.com/en/docs/instances/how-to/use-cloud-init/
+dmi:*:svnScaleway:*
+ IMDS_VENDOR=scaleway
+ IMDS_DATA_URL=http://169.254.42.42
+ IMDS_ADDRESS_IPV4=169.254.42.42
+ IMDS_ADDRESS_IPV6=fd00:42::42
+ IMDS_KEY_USERDATA=/user_data
index 9ba73b21d63933caffe07b1a1c7fff069e28ac82..3299eaf8a75bfc36b0bb300d7b027e677b46b2a9 100644 (file)
@@ -19,6 +19,7 @@ hwdb_files_notest = files(
 hwdb_files_test = files(
         '20-dmi-id.hwdb',
         '20-net-ifname.hwdb',
+        '40-imds.hwdb',
         '60-autosuspend.hwdb',
         '60-autosuspend-fingerprint-reader.hwdb',
         '60-evdev.hwdb',
index e98510839b73fc65c6b2f772161059ee994f5403..e70b0ff04e94ecd5971a891bd5a1488898b34619 100755 (executable)
@@ -125,7 +125,7 @@ def hwdb_grammar():
     matchline = (matchline_typed | matchline_general) + EOL
 
     propertyline = (White(' ', exact=1).suppress() +
-                    Combine(UDEV_TAG - '=' - Optional(Word(alphanums + '_=:@*.!-;, "/'))
+                    Combine(UDEV_TAG - '=' - Optional(Word(alphanums + '_=:@*.!-;, "/?&'))
                             - Optional(pythonStyleComment)) +
                     EOL)
     propertycomment = White(' ', exact=1) + pythonStyleComment + EOL
@@ -215,6 +215,24 @@ def property_grammar():
              ('ID_NET_NAME_FROM_DATABASE', name_literal),
              ('ID_NET_NAME_INCLUDE_DOMAIN', zero_one),
              ('TPM2_BROKEN_NVPCR', zero_one),
+             ('IMDS_VENDOR', name_literal),
+             ('IMDS_TOKEN_URL', name_literal),
+             ('IMDS_REFRESH_HEADER_NAME', name_literal),
+             ('IMDS_DATA_URL', name_literal),
+             ('IMDS_DATA_URL_SUFFIX', name_literal),
+             ('IMDS_TOKEN_HEADER_NAME', name_literal),
+             ('IMDS_EXTRA_HEADER', name_literal),
+             ('IMDS_ADDRESS_IPV4', name_literal),
+             ('IMDS_ADDRESS_IPV6', name_literal),
+             ('IMDS_KEY_HOSTNAME', name_literal),
+             ('IMDS_KEY_REGION', name_literal),
+             ('IMDS_KEY_ZONE', name_literal),
+             ('IMDS_KEY_IPV4_PUBLIC', name_literal),
+             ('IMDS_KEY_IPV6_PUBLIC', name_literal),
+             ('IMDS_KEY_SSH_KEY', name_literal),
+             ('IMDS_KEY_USERDATA', name_literal),
+             ('IMDS_KEY_USERDATA_BASE', name_literal),
+             ('IMDS_KEY_USERDATA_BASE64', name_literal),
             )
     fixed_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE')
                    for name, val in props]