From 2ef3be31eb2b7bd47284d91e5afd12406175d674 Mon Sep 17 00:00:00 2001 From: James Le Cuirot Date: Thu, 3 Sep 2026 11:26:29 +0100 Subject: [PATCH 1/2] internal/resource/url: Add a file:// schema for local files The recent addition of `ignition.config.path` already supports local files, but only for fetching Ignition config, and it includes mounting logic that may be unwanted when all you want to do is read an already-mounted file. This file:// schema does exactly what you would expect it to do, just read a local file without trying to mount anything first, and it works as a generic resource that can be used in the files section. Only absolute paths are supported. Signed-off-by: James Le Cuirot --- butane/docs/config-fcos-v1_8-exp.md | 16 ++--- butane/docs/config-fiot-v1_1-exp.md | 10 +-- butane/docs/config-flatcar-v1_2-exp.md | 16 ++--- butane/docs/config-openshift-v4_23-exp.md | 12 ++-- butane/docs/config-r4e-v1_2-exp.md | 10 +-- config/doc/ignition.yaml | 7 ++- config/shared/errors/errors.go | 1 + config/v3_7_experimental/types/url.go | 9 +++ config/v3_7_experimental/types/url_test.go | 12 ++++ docs/configuration-v3_7_experimental.md | 12 ++-- docs/release-notes.md | 2 + internal/resource/url.go | 18 +++++- internal/util/url.go | 2 +- tests/fixtures/config.ign | 9 +++ tests/fixtures/embed.go | 24 ++++++++ tests/positive/cmdline/cmdline.go | 72 ++++++++++++++++------ tests/positive/files/file.go | 56 +++++++++++++++++ tests/types/fixtures.go | 55 +++++++++++++++++ 18 files changed, 284 insertions(+), 59 deletions(-) create mode 100644 tests/fixtures/config.ign create mode 100644 tests/fixtures/embed.go create mode 100644 tests/types/fixtures.go diff --git a/butane/docs/config-fcos-v1_8-exp.md b/butane/docs/config-fcos-v1_8-exp.md index f00a1ff709..fff095fccc 100644 --- a/butane/docs/config-fcos-v1_8-exp.md +++ b/butane/docs/config-fcos-v1_8-exp.md @@ -19,7 +19,7 @@ The Fedora CoreOS configuration is a YAML document conforming to the following s * **_ignition_** (object): metadata about the configuration itself. * **_config_** (object): options related to the configuration. * **_merge_** (list of objects): a list of the configs to be merged to the current config. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -29,7 +29,7 @@ The Fedora CoreOS configuration is a YAML document conforming to the following s * **_verification_** (object): options related to the verification of the config. * **_hash_** (string): the hash of the config, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed config. * **_replace_** (object): the config that will replace the current. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -44,7 +44,7 @@ The Fedora CoreOS configuration is a YAML document conforming to the following s * **_security_** (object): options relating to network security. * **_tls_** (object): options relating to TLS when fetching resources over `https`. * **_certificate_authorities_** (list of objects): the list of additional certificate authorities (in addition to the system authorities) to be used for TLS verification when fetching over `https`. All certificate authorities must have a unique `source`, `inline`, or `local`. - * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the certificate bundle (in PEM format), relative to the directory specified by the `--files-dir` command-line argument. The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the certificate bundle (null or gzip). Compression cannot be used with S3. @@ -78,8 +78,8 @@ The Fedora CoreOS configuration is a YAML document conforming to the following s * **_spares_** (integer): the number of spares (if applicable) in the array. * **_options_** (list of strings): any additional options to be passed to mdadm. * **_filesystems_** (list of objects): the list of filesystems to be configured. `device` and `format` need to be specified. Every filesystem must have a unique `device`. - * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. - * **format** (string): the filesystem format (ext4, btrfs, xfs, vfat, swap, or none). + * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. For virtiofs, this is the tag name. + * **format** (string): the filesystem format (ext4, btrfs, xfs, vfat, virtiofs, swap, or none). * **_path_** (string): the mount-point of the filesystem while Ignition is running relative to where the root filesystem will be mounted. This is not necessarily the same as where it should be mounted in the real root, but it is encouraged to make it the same. * **_wipe_filesystem_** (boolean): whether or not to wipe the device before filesystem creation, see [Ignition's documentation on filesystems](https://coreos.github.io/ignition/operator-notes/#filesystem-reuse-semantics) for more information. Defaults to false. * **_label_** (string): the label of the filesystem. @@ -91,7 +91,7 @@ The Fedora CoreOS configuration is a YAML document conforming to the following s * **path** (string): the absolute path to the file. * **_overwrite_** (boolean): whether to delete preexisting nodes at the path. `contents` must be specified if `overwrite` is true. Defaults to false. * **_contents_** (object): options related to the contents of the file. - * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the file (null or gzip). Compression cannot be used with S3. @@ -101,7 +101,7 @@ The Fedora CoreOS configuration is a YAML document conforming to the following s * **_verification_** (object): options related to the verification of the file. * **_hash_** (string): the hash of the file, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed file. * **_append_** (list of objects): list of fragments to be appended to the file. Follows the same structure as `contents`. - * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the fragment. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the fragment, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the fragment (null or gzip). Compression cannot be used with S3. @@ -142,7 +142,7 @@ The Fedora CoreOS configuration is a YAML document conforming to the following s * **name** (string): the name of the luks device. * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. * **_key_file_** (object): options related to the contents of the key file. - * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the key file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the key file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the key file (null or gzip). Compression cannot be used with S3. diff --git a/butane/docs/config-fiot-v1_1-exp.md b/butane/docs/config-fiot-v1_1-exp.md index d91d04341e..4f90868d33 100644 --- a/butane/docs/config-fiot-v1_1-exp.md +++ b/butane/docs/config-fiot-v1_1-exp.md @@ -19,7 +19,7 @@ The Fedora IoT configuration is a YAML document conforming to the following spec * **_ignition_** (object): metadata about the configuration itself. * **_config_** (object): options related to the configuration. * **_merge_** (list of objects): a list of the configs to be merged to the current config. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -29,7 +29,7 @@ The Fedora IoT configuration is a YAML document conforming to the following spec * **_verification_** (object): options related to the verification of the config. * **_hash_** (string): the hash of the config, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed config. * **_replace_** (object): the config that will replace the current. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -44,7 +44,7 @@ The Fedora IoT configuration is a YAML document conforming to the following spec * **_security_** (object): options relating to network security. * **_tls_** (object): options relating to TLS when fetching resources over `https`. * **_certificate_authorities_** (list of objects): the list of additional certificate authorities (in addition to the system authorities) to be used for TLS verification when fetching over `https`. All certificate authorities must have a unique `source`, `inline`, or `local`. - * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the certificate bundle (in PEM format), relative to the directory specified by the `--files-dir` command-line argument. The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the certificate bundle (null or gzip). Compression cannot be used with S3. @@ -62,7 +62,7 @@ The Fedora IoT configuration is a YAML document conforming to the following spec * **path** (string): the absolute path to the file. * **_overwrite_** (boolean): whether to delete preexisting nodes at the path. `contents` must be specified if `overwrite` is true. Defaults to false. * **_contents_** (object): options related to the contents of the file. - * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the file (null or gzip). Compression cannot be used with S3. @@ -72,7 +72,7 @@ The Fedora IoT configuration is a YAML document conforming to the following spec * **_verification_** (object): options related to the verification of the file. * **_hash_** (string): the hash of the file, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed file. * **_append_** (list of objects): list of fragments to be appended to the file. Follows the same structure as `contents`. - * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the fragment. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the fragment, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the fragment (null or gzip). Compression cannot be used with S3. diff --git a/butane/docs/config-flatcar-v1_2-exp.md b/butane/docs/config-flatcar-v1_2-exp.md index c2dfab33bb..b8d55e9be8 100644 --- a/butane/docs/config-flatcar-v1_2-exp.md +++ b/butane/docs/config-flatcar-v1_2-exp.md @@ -19,7 +19,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_ignition_** (object): metadata about the configuration itself. * **_config_** (object): options related to the configuration. * **_merge_** (list of objects): a list of the configs to be merged to the current config. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -29,7 +29,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_verification_** (object): options related to the verification of the config. * **_hash_** (string): the hash of the config, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed config. * **_replace_** (object): the config that will replace the current. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -44,7 +44,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_security_** (object): options relating to network security. * **_tls_** (object): options relating to TLS when fetching resources over `https`. * **_certificate_authorities_** (list of objects): the list of additional certificate authorities (in addition to the system authorities) to be used for TLS verification when fetching over `https`. All certificate authorities must have a unique `source`, `inline`, or `local`. - * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the certificate bundle (in PEM format), relative to the directory specified by the `--files-dir` command-line argument. The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the certificate bundle (null or gzip). Compression cannot be used with S3. @@ -78,8 +78,8 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_spares_** (integer): the number of spares (if applicable) in the array. * **_options_** (list of strings): any additional options to be passed to mdadm. * **_filesystems_** (list of objects): the list of filesystems to be configured. `device` and `format` need to be specified. Every filesystem must have a unique `device`. - * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. - * **format** (string): the filesystem format (ext4, btrfs, xfs, vfat, swap, or none). + * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. For virtiofs, this is the tag name. + * **format** (string): the filesystem format (ext4, btrfs, xfs, vfat, virtiofs, swap, or none). * **_path_** (string): the mount-point of the filesystem while Ignition is running relative to where the root filesystem will be mounted. This is not necessarily the same as where it should be mounted in the real root, but it is encouraged to make it the same. * **_wipe_filesystem_** (boolean): whether or not to wipe the device before filesystem creation, see [Ignition's documentation on filesystems](https://coreos.github.io/ignition/operator-notes/#filesystem-reuse-semantics) for more information. Defaults to false. * **_label_** (string): the label of the filesystem. @@ -91,7 +91,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **path** (string): the absolute path to the file. * **_overwrite_** (boolean): whether to delete preexisting nodes at the path. `contents` must be specified if `overwrite` is true. Defaults to false. * **_contents_** (object): options related to the contents of the file. - * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the file (null or gzip). Compression cannot be used with S3. @@ -101,7 +101,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_verification_** (object): options related to the verification of the file. * **_hash_** (string): the hash of the file, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed file. * **_append_** (list of objects): list of fragments to be appended to the file. Follows the same structure as `contents`. - * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the fragment. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the fragment, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the fragment (null or gzip). Compression cannot be used with S3. @@ -142,7 +142,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **name** (string): the name of the luks device. * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. * **_key_file_** (object): options related to the contents of the key file. - * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the key file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the key file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the key file (null or gzip). Compression cannot be used with S3. diff --git a/butane/docs/config-openshift-v4_23-exp.md b/butane/docs/config-openshift-v4_23-exp.md index 9f84e5f76d..f782bc0217 100644 --- a/butane/docs/config-openshift-v4_23-exp.md +++ b/butane/docs/config-openshift-v4_23-exp.md @@ -22,7 +22,7 @@ The OpenShift configuration is a YAML document conforming to the following speci * **_ignition_** (object): metadata about the configuration itself. * **_config_** (object): options related to the configuration. * **_merge_** (list of objects): a list of the configs to be merged to the current config. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -32,7 +32,7 @@ The OpenShift configuration is a YAML document conforming to the following speci * **_verification_** (object): options related to the verification of the config. * **_hash_** (string): the hash of the config, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed config. * **_replace_** (object): the config that will replace the current. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -47,7 +47,7 @@ The OpenShift configuration is a YAML document conforming to the following speci * **_security_** (object): options relating to network security. * **_tls_** (object): options relating to TLS when fetching resources over `https`. * **_certificate_authorities_** (list of objects): the list of additional certificate authorities (in addition to the system authorities) to be used for TLS verification when fetching over `https`. All certificate authorities must have a unique `source`, `inline`, or `local`. - * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the certificate bundle (in PEM format), relative to the directory specified by the `--files-dir` command-line argument. The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the certificate bundle (null or gzip). Compression cannot be used with S3. @@ -81,8 +81,8 @@ The OpenShift configuration is a YAML document conforming to the following speci * **_spares_** (integer): the number of spares (if applicable) in the array. * **_options_** (list of strings): any additional options to be passed to mdadm. * **_filesystems_** (list of objects): the list of filesystems to be configured. `device` and `format` need to be specified. Every filesystem must have a unique `device`. - * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. - * **format** (string): the filesystem format (ext4, xfs, vfat, or swap). + * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. For virtiofs, this is the tag name. + * **format** (string): the filesystem format (ext4, xfs, vfat, virtiofs, or swap). * **_path_** (string): the mount-point of the filesystem while Ignition is running relative to where the root filesystem will be mounted. This is not necessarily the same as where it should be mounted in the real root, but it is encouraged to make it the same. * **_wipe_filesystem_** (boolean): whether or not to wipe the device before filesystem creation, see [Ignition's documentation on filesystems](https://coreos.github.io/ignition/operator-notes/#filesystem-reuse-semantics) for more information. Defaults to false. * **_label_** (string): the label of the filesystem. @@ -111,7 +111,7 @@ The OpenShift configuration is a YAML document conforming to the following speci * **name** (string): the name of the luks device. * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. * **_key_file_** (object): options related to the contents of the key file. - * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the key file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the key file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the key file (null or gzip). Compression cannot be used with S3. diff --git a/butane/docs/config-r4e-v1_2-exp.md b/butane/docs/config-r4e-v1_2-exp.md index 9aeceab405..c26abdc450 100644 --- a/butane/docs/config-r4e-v1_2-exp.md +++ b/butane/docs/config-r4e-v1_2-exp.md @@ -19,7 +19,7 @@ The RHEL for Edge configuration is a YAML document conforming to the following s * **_ignition_** (object): metadata about the configuration itself. * **_config_** (object): options related to the configuration. * **_merge_** (list of objects): a list of the configs to be merged to the current config. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -29,7 +29,7 @@ The RHEL for Edge configuration is a YAML document conforming to the following s * **_verification_** (object): options related to the verification of the config. * **_hash_** (string): the hash of the config, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed config. * **_replace_** (object): the config that will replace the current. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -44,7 +44,7 @@ The RHEL for Edge configuration is a YAML document conforming to the following s * **_security_** (object): options relating to network security. * **_tls_** (object): options relating to TLS when fetching resources over `https`. * **_certificate_authorities_** (list of objects): the list of additional certificate authorities (in addition to the system authorities) to be used for TLS verification when fetching over `https`. All certificate authorities must have a unique `source`, `inline`, or `local`. - * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the certificate bundle (in PEM format), relative to the directory specified by the `--files-dir` command-line argument. The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the certificate bundle (null or gzip). Compression cannot be used with S3. @@ -62,7 +62,7 @@ The RHEL for Edge configuration is a YAML document conforming to the following s * **path** (string): the absolute path to the file. * **_overwrite_** (boolean): whether to delete preexisting nodes at the path. `contents` must be specified if `overwrite` is true. Defaults to false. * **_contents_** (object): options related to the contents of the file. - * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the file (null or gzip). Compression cannot be used with S3. @@ -72,7 +72,7 @@ The RHEL for Edge configuration is a YAML document conforming to the following s * **_verification_** (object): options related to the verification of the file. * **_hash_** (string): the hash of the file, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed file. * **_append_** (list of objects): list of fragments to be appended to the file. Follows the same structure as `contents`. - * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the fragment. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the fragment, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the fragment (null or gzip). Compression cannot be used with S3. diff --git a/config/doc/ignition.yaml b/config/doc/ignition.yaml index 508c44062f..29c7c7a6ef 100644 --- a/config/doc/ignition.yaml +++ b/config/doc/ignition.yaml @@ -1,7 +1,7 @@ resource: children: - name: source - desc: "the URL of the %TYPE%. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified." + desc: "the URL of the %TYPE%. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified." # source is typically required by validation, but some inclusion sites # will override this required: true @@ -16,6 +16,11 @@ resource: if: - variant: ignition max: 3.3.0 + - regex: "`file`, " + replacement: "" + if: + - variant: ignition + max: 3.6.0 - name: compression desc: "the type of compression used on the %TYPE% (null or gzip). Compression cannot be used with S3." - name: httpHeaders diff --git a/config/shared/errors/errors.go b/config/shared/errors/errors.go index 98296d02c8..e24a4ff603 100644 --- a/config/shared/errors/errors.go +++ b/config/shared/errors/errors.go @@ -110,6 +110,7 @@ var ( ErrHashWrongSize = errors.New("incorrect size for hash sum") ErrHashUnrecognized = errors.New("unrecognized hash function") ErrEngineConfiguration = errors.New("engine incorrectly configured") + ErrPathNotAbsolute = errors.New("path is not absolute") // AWS S3 specific errors ErrInvalidS3ARN = errors.New("invalid S3 ARN format") diff --git a/config/v3_7_experimental/types/url.go b/config/v3_7_experimental/types/url.go index 97a4c9ae22..185796907f 100644 --- a/config/v3_7_experimental/types/url.go +++ b/config/v3_7_experimental/types/url.go @@ -16,6 +16,7 @@ package types import ( "net/url" + "path" "strings" "github.com/aws/aws-sdk-go-v2/aws/arn" @@ -70,6 +71,14 @@ func validateURL(s string) error { return err } return nil + case "file": + if u.Host != "" || u.Path == "" { + return errors.ErrPathNotAbsolute + } + if path.Clean(u.Path) != u.Path { + return errors.ErrDirtyPath + } + return nil default: return errors.ErrInvalidScheme } diff --git a/config/v3_7_experimental/types/url_test.go b/config/v3_7_experimental/types/url_test.go index 1901b7aff9..b6b9137d67 100644 --- a/config/v3_7_experimental/types/url_test.go +++ b/config/v3_7_experimental/types/url_test.go @@ -126,6 +126,18 @@ func TestURLValidate(t *testing.T) { util.StrToPtr("gs://bucket/object"), nil, }, + { + util.StrToPtr("file:///config.ign"), + nil, + }, + { + util.StrToPtr("file:///../etc/passwd"), + errors.ErrDirtyPath, + }, + { + util.StrToPtr("file:///foo/./bar"), + errors.ErrDirtyPath, + }, } for i, test := range tests { diff --git a/docs/configuration-v3_7_experimental.md b/docs/configuration-v3_7_experimental.md index ebf18e009b..5f8295c948 100644 --- a/docs/configuration-v3_7_experimental.md +++ b/docs/configuration-v3_7_experimental.md @@ -18,7 +18,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **version** (string): the semantic version number of the spec. The spec version must be compatible with the latest version (`3.7.0-experimental`). Compatibility requires the major versions to match and the spec version be less than or equal to the latest version. `-experimental` versions compare less than the final version with the same number, and previous experimental versions are not accepted. * **_config_** (object): options related to the configuration. * **_merge_** (list of objects): a list of the configs to be merged to the current config. - * **source** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **source** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -26,7 +26,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **_verification_** (object): options related to the verification of the config. * **_hash_** (string): the hash of the config, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed config. * **_replace_** (object): the config that will replace the current. - * **source** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **source** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -39,7 +39,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **_security_** (object): options relating to network security. * **_tls_** (object): options relating to TLS when fetching resources over `https`. * **_certificateAuthorities_** (list of objects): the list of additional certificate authorities (in addition to the system authorities) to be used for TLS verification when fetching over `https`. All certificate authorities must have a unique `source`. - * **source** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **source** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the certificate bundle (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -83,7 +83,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **path** (string): the absolute path to the file. * **_overwrite_** (boolean): whether to delete preexisting nodes at the path. `contents` must be specified if `overwrite` is true. Defaults to false. * **_contents_** (object): options related to the contents of the file. - * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. + * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. * **_compression_** (string): the type of compression used on the file (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -91,7 +91,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **_verification_** (object): options related to the verification of the file. * **_hash_** (string): the hash of the file, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed file. * **_append_** (list of objects): list of fragments to be appended to the file. Follows the same structure as `contents`. - * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the fragment (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -130,7 +130,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **name** (string): the name of the luks device. * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. * **_keyFile_** (object): options related to the contents of the key file. - * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the key file (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. diff --git a/docs/release-notes.md b/docs/release-notes.md index 95d3ad5a66..f0a97d4470 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -10,6 +10,8 @@ nav_order: 9 ### Features +- Add support for the `file` URL scheme, which reads files from local files at the given path. + ### Changes ### Bug fixes diff --git a/internal/resource/url.go b/internal/resource/url.go index 6fe693a698..c40e6736cd 100644 --- a/internal/resource/url.go +++ b/internal/resource/url.go @@ -28,6 +28,7 @@ import ( "net/netip" "net/url" "os" + "path/filepath" "strings" "sync" "syscall" @@ -60,7 +61,6 @@ const ( var ( ErrSchemeUnsupported = errors.New("unsupported source scheme") - ErrPathNotAbsolute = errors.New("path is not absolute") ErrNotFound = errors.New("resource not found") ErrFailed = errors.New("failed to fetch resource") ErrCompressionUnsupported = errors.New("compression is not supported with that scheme") @@ -183,6 +183,8 @@ func (f *Fetcher) FetchToBuffer(u url.URL, opts FetchOptions) ([]byte, error) { return buf.Bytes(), err case "gs": err = f.fetchFromGCS(u, dest, opts) + case "file": + err = f.fetchFromFile(u.Path, dest, opts) case "": return nil, nil default: @@ -251,6 +253,8 @@ func (f *Fetcher) Fetch(u url.URL, dest *os.File, opts FetchOptions) error { return f.fetchFromS3(u, dest, opts) case "gs": return f.fetchFromGCS(u, dest, opts) + case "file": + return f.fetchFromFile(u.Path, dest, opts) case "": return nil default: @@ -459,6 +463,18 @@ func (f *Fetcher) fetchFromGCS(u url.URL, dest io.Writer, opts FetchOptions) err return f.fetchFromHTTP(gcsURL, dest, opts) } +func (f *Fetcher) fetchFromFile(path string, dest io.Writer, opts FetchOptions) error { + path = filepath.Clean(path) + + fi, err := os.Open(path) + if err != nil { + f.Logger.Err("failed to read file: %v", err) + return err + } + defer func() { _ = fi.Close() }() + return f.decompressCopyHashAndVerify(dest, fi, opts) +} + type s3target interface { io.WriterAt io.ReadSeeker diff --git a/internal/util/url.go b/internal/util/url.go index 3087187edb..de465ba4b9 100644 --- a/internal/util/url.go +++ b/internal/util/url.go @@ -19,5 +19,5 @@ import ( ) func UrlNeedsNet(u url.URL) bool { - return u.Scheme != "data" && u.Scheme != "" + return u.Scheme != "data" && u.Scheme != "file" && u.Scheme != "" } diff --git a/tests/fixtures/config.ign b/tests/fixtures/config.ign new file mode 100644 index 0000000000..a5313978f7 --- /dev/null +++ b/tests/fixtures/config.ign @@ -0,0 +1,9 @@ +{ + "ignition": { "version": "@VERSION@" }, + "storage": { + "files": [{ + "path": "/foo/bar", + "contents": { "source": "data:,example%20file%0A" } + }] + } +} diff --git a/tests/fixtures/embed.go b/tests/fixtures/embed.go new file mode 100644 index 0000000000..1107489733 --- /dev/null +++ b/tests/fixtures/embed.go @@ -0,0 +1,24 @@ +// Copyright 2026 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fixtures + +import "embed" + +// FS holds fixture files baked into the test binary at build time, so they +// are available even when the binary runs without the source repository +// present (e.g. under kola/tmt). +// +//go:embed *.ign +var FS embed.FS diff --git a/tests/positive/cmdline/cmdline.go b/tests/positive/cmdline/cmdline.go index f11d693e7d..717938aae4 100644 --- a/tests/positive/cmdline/cmdline.go +++ b/tests/positive/cmdline/cmdline.go @@ -15,12 +15,15 @@ package cmdline import ( + "net/url" + "github.com/coreos/ignition/v2/tests/register" "github.com/coreos/ignition/v2/tests/types" ) func init() { register.Register(register.PositiveTest, FetchConfigFromDevice()) + register.Register(register.PositiveTest, FetchConfigFromFileURL()) } func FetchConfigFromDevice() types.Test { @@ -30,28 +33,13 @@ func FetchConfigFromDevice() types.Test { // Config that will be placed on the labeled device partition. // This is what Ignition will actually read via the cmdline provider. - deviceConfig := `{ - "ignition": { "version": "3.4.0" }, - "storage": { - "files": [{ - "path": "/foo/bar", - "contents": { "source": "data:,example%20file%0A" } - }] - } - }` + // It is placed on disk verbatim, so it needs a concrete spec version. + deviceConfig := types.ReadFixture("config.ign", "3.4.0") // Config for the test framework's validation. Uses $version so the // test is registered across spec versions. The file platform won't // be consulted because the cmdline provider takes priority. - config := `{ - "ignition": { "version": "$version" }, - "storage": { - "files": [{ - "path": "/foo/bar", - "contents": { "source": "data:,example%20file%0A" } - }] - } - }` + config := types.ReadFixture("config.ign", "$version") configMinVersion := "3.0.0" // Add a second disk with a labeled partition containing the config file. @@ -129,3 +117,51 @@ func FetchConfigFromDevice() types.Test { }, } } + +func FetchConfigFromFileURL() types.Test { + name := "cmdline.file.fetch" + in := types.GetBaseDisk() + out := types.GetBaseDisk() + + // Config that Ignition will fetch from a file:// URL. It is read + // verbatim from the host filesystem, so it needs a concrete spec + // version and a stable absolute path. + configPath := types.WriteVersionedFixture("config.ign", "3.4.0") + configURL := url.URL{Scheme: "file", Path: configPath} + + // Config for the test framework's validation. Uses $version so the + // test is registered across spec versions. The file platform won't + // be consulted because the cmdline provider takes priority. + config := types.ReadFixture("config.ign", "$version") + configMinVersion := "3.0.0" + + out[0].Partitions.AddFiles("ROOT", []types.File{ + { + Node: types.Node{ + Name: "bar", + Directory: "foo", + }, + Contents: "example file\n", + }, + }) + + return types.Test{ + Name: name, + In: in, + Out: out, + Config: config, + ConfigMinVersion: configMinVersion, + Env: []string{ + "IGNITION_KERNEL_CMDLINE_PATH=$SYSTEM_CONFIG_DIR/cmdline", + }, + SystemDirFiles: []types.File{ + { + Node: types.Node{ + Name: "cmdline", + Directory: "/", + }, + Contents: "ignition.config.url=" + configURL.String(), + }, + }, + } +} diff --git a/tests/positive/files/file.go b/tests/positive/files/file.go index bd2d952aca..dd024ac020 100644 --- a/tests/positive/files/file.go +++ b/tests/positive/files/file.go @@ -15,6 +15,9 @@ package files import ( + "net/url" + "os" + "github.com/coreos/ignition/v2/tests/register" "github.com/coreos/ignition/v2/tests/types" ) @@ -31,6 +34,7 @@ func init() { register.Register(register.PositiveTest, ApplyCustomFilePermissions()) register.Register(register.PositiveTest, ApplyCustomFilePermissionsBeforeBugfix()) register.Register(register.PositiveTest, CreateFileFromCompressedDataURL()) + register.Register(register.PositiveTest, CreateFileFromFileURL()) // TODO: Investigate why ignition's C code hates our environment // register.Register(register.PositiveTest, UserGroupByName()) } @@ -775,3 +779,55 @@ func CreateFileFromCompressedDataURL() types.Test { ConfigMinVersion: configMinVersion, } } + +func CreateFileFromFileURL() types.Test { + name := "files.create.file" + in := types.GetBaseDisk() + out := types.GetBaseDisk() + // Write a file to the host filesystem so we can verify that Ignition + // fetches its real contents via a file:// URL. Using a temporary file + // keeps the test self-contained and independent of the source repository, + // which may not be present when the test binary runs. + fileContents := "example file\n" + f, err := os.CreateTemp("", "ignition-file-url") + if err != nil { + panic(err) + } + if _, err := f.WriteString(fileContents); err != nil { + _ = f.Close() + panic(err) + } + if err := f.Close(); err != nil { + panic(err) + } + fileURL := url.URL{Scheme: "file", Path: f.Name()} + config := `{ + "ignition": { "version": "$version" }, + "storage": { + "files": [{ + "path": "/foo/bar", + "contents": { + "source": "` + fileURL.String() + `" + } + }] + } + }` + out[0].Partitions.AddFiles("ROOT", []types.File{ + { + Node: types.Node{ + Name: "bar", + Directory: "foo", + }, + Contents: fileContents, + }, + }) + configMinVersion := "3.7.0-experimental" + + return types.Test{ + Name: name, + In: in, + Out: out, + Config: config, + ConfigMinVersion: configMinVersion, + } +} diff --git a/tests/types/fixtures.go b/tests/types/fixtures.go new file mode 100644 index 0000000000..981ebd1dad --- /dev/null +++ b/tests/types/fixtures.go @@ -0,0 +1,55 @@ +// Copyright 2026 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "os" + "strings" + + "github.com/coreos/ignition/v2/tests/fixtures" +) + +// ReadFixture returns the embedded fixture named name (from tests/fixtures) +// with the @VERSION@ placeholder replaced by version. The fixture is baked +// into the test binary at build time, so it works even when the binary runs +// without the source repository present. Pass "$version" to defer substitution +// to the test framework's per-version registration. +func ReadFixture(name, version string) string { + data, err := fixtures.FS.ReadFile(name) + if err != nil { + panic(err) + } + return strings.ReplaceAll(string(data), "@VERSION@", version) +} + +// WriteVersionedFixture writes ReadFixture(name, version) to a temporary host +// file and returns its absolute path. This is useful for configs that Ignition +// fetches directly (e.g. via a file:// URL), which must contain a concrete spec +// version and a real path. The file persists for the lifetime of the test +// process. +func WriteVersionedFixture(name, version string) string { + f, err := os.CreateTemp("", "ignition-"+name) + if err != nil { + panic(err) + } + if _, err := f.WriteString(ReadFixture(name, version)); err != nil { + _ = f.Close() + panic(err) + } + if err := f.Close(); err != nil { + panic(err) + } + return f.Name() +} From ba0d1fbb46ec48bfeb68205a4cd7895b9f43a704 Mon Sep 17 00:00:00 2001 From: James Le Cuirot Date: Fri, 4 Sep 2026 18:46:20 +0100 Subject: [PATCH 2/2] internal/resource/url: Add an optional oem:// schema to read from /oem The `github.com/flatcar/ignition/v2/internal/distro.oemFetch` build flag enables this feature. Ignition previously supported this, but it now requires less additional code thanks to the existing file:// support. Note that Flatcar no longer needs Ignition to handle the mounting. This would have been added to Butane's Flatcar variant, but that only covers use of oem:// as a resource, not as a `ignition.config.url` location. Signed-off-by: James Le Cuirot --- butane/docs/config-flatcar-v1_2-exp.md | 12 ++++++------ config/doc/ignition.yaml | 19 ++++++++++++++++--- config/v3_7_experimental/types/url.go | 2 +- config/v3_7_experimental/types/url_test.go | 16 ++++++++++++++++ docs/configuration-v3_7_experimental.md | 12 ++++++------ docs/distributor-notes.md | 4 ++++ docs/release-notes.md | 1 + internal/distro/distro.go | 5 +++++ internal/resource/url.go | 11 +++++++++++ internal/util/url.go | 2 +- 10 files changed, 67 insertions(+), 17 deletions(-) diff --git a/butane/docs/config-flatcar-v1_2-exp.md b/butane/docs/config-flatcar-v1_2-exp.md index b8d55e9be8..a025dcbe0a 100644 --- a/butane/docs/config-flatcar-v1_2-exp.md +++ b/butane/docs/config-flatcar-v1_2-exp.md @@ -19,7 +19,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_ignition_** (object): metadata about the configuration itself. * **_config_** (object): options related to the configuration. * **_merge_** (list of objects): a list of the configs to be merged to the current config. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -29,7 +29,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_verification_** (object): options related to the verification of the config. * **_hash_** (string): the hash of the config, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed config. * **_replace_** (object): the config that will replace the current. - * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the config. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the config, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. @@ -44,7 +44,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_security_** (object): options relating to network security. * **_tls_** (object): options relating to TLS when fetching resources over `https`. * **_certificate_authorities_** (list of objects): the list of additional certificate authorities (in addition to the system authorities) to be used for TLS verification when fetching over `https`. All certificate authorities must have a unique `source`, `inline`, or `local`. - * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the certificate bundle (in PEM format), relative to the directory specified by the `--files-dir` command-line argument. The bundle can contain multiple concatenated certificates. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the certificate bundle (null or gzip). Compression cannot be used with S3. @@ -91,7 +91,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **path** (string): the absolute path to the file. * **_overwrite_** (boolean): whether to delete preexisting nodes at the path. `contents` must be specified if `overwrite` is true. Defaults to false. * **_contents_** (object): options related to the contents of the file. - * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the file (null or gzip). Compression cannot be used with S3. @@ -101,7 +101,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **_verification_** (object): options related to the verification of the file. * **_hash_** (string): the hash of the file, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed file. * **_append_** (list of objects): list of fragments to be appended to the file. Follows the same structure as `contents`. - * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the fragment. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the fragment, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the fragment (null or gzip). Compression cannot be used with S3. @@ -142,7 +142,7 @@ The Flatcar configuration is a YAML document conforming to the following specifi * **name** (string): the name of the luks device. * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. * **_key_file_** (object): options related to the contents of the key file. - * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. + * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. Mutually exclusive with `inline` and `local`. * **_inline_** (string): the contents of the key file. Mutually exclusive with `source` and `local`. * **_local_** (string): a local path to the contents of the key file, relative to the directory specified by the `--files-dir` command-line argument. Mutually exclusive with `source` and `inline`. * **_compression_** (string): the type of compression used on the key file (null or gzip). Compression cannot be used with S3. diff --git a/config/doc/ignition.yaml b/config/doc/ignition.yaml index 29c7c7a6ef..3d6e23fbba 100644 --- a/config/doc/ignition.yaml +++ b/config/doc/ignition.yaml @@ -1,7 +1,7 @@ resource: children: - name: source - desc: "the URL of the %TYPE%. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified." + desc: "the URL of the %TYPE%. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified." # source is typically required by validation, but some inclusion sites # will override this required: true @@ -21,6 +21,19 @@ resource: if: - variant: ignition max: 3.6.0 + - regex: "`oem`[^,]*, " + replacement: "" + if: + - variant: ignition + max: 3.6.0 + - variant: fcos + min: 1.8.0-experimental + - variant: fiot + min: 1.1.0-experimental + - variant: openshift + min: 4.23.0-experimental + - variant: r4e + min: 1.2.0-experimental - name: compression desc: "the type of compression used on the %TYPE% (null or gzip). Compression cannot be used with S3." - name: httpHeaders @@ -399,8 +412,8 @@ root: - name: cex desc: describes the IBM Crypto Express (CEX) card configuration for the luks device. children: - - name: enabled - desc: whether or not to enable cex compatibility for luks. If omitted, defaults to false. + - name: enabled + desc: whether or not to enable cex compatibility for luks. If omitted, defaults to false. - name: systemd desc: describes the desired state of the systemd units. children: diff --git a/config/v3_7_experimental/types/url.go b/config/v3_7_experimental/types/url.go index 185796907f..b5478b53c5 100644 --- a/config/v3_7_experimental/types/url.go +++ b/config/v3_7_experimental/types/url.go @@ -71,7 +71,7 @@ func validateURL(s string) error { return err } return nil - case "file": + case "file", "oem": if u.Host != "" || u.Path == "" { return errors.ErrPathNotAbsolute } diff --git a/config/v3_7_experimental/types/url_test.go b/config/v3_7_experimental/types/url_test.go index b6b9137d67..5290caa4bc 100644 --- a/config/v3_7_experimental/types/url_test.go +++ b/config/v3_7_experimental/types/url_test.go @@ -138,6 +138,22 @@ func TestURLValidate(t *testing.T) { util.StrToPtr("file:///foo/./bar"), errors.ErrDirtyPath, }, + { + util.StrToPtr("oem:///config.ign"), + nil, + }, + { + util.StrToPtr("oem://config.ign"), + errors.ErrPathNotAbsolute, + }, + { + util.StrToPtr("oem:///../etc/passwd"), + errors.ErrDirtyPath, + }, + { + util.StrToPtr("oem:///foo/../../etc/passwd"), + errors.ErrDirtyPath, + }, } for i, test := range tests { diff --git a/docs/configuration-v3_7_experimental.md b/docs/configuration-v3_7_experimental.md index 5f8295c948..64de2bc1f3 100644 --- a/docs/configuration-v3_7_experimental.md +++ b/docs/configuration-v3_7_experimental.md @@ -18,7 +18,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **version** (string): the semantic version number of the spec. The spec version must be compatible with the latest version (`3.7.0-experimental`). Compatibility requires the major versions to match and the spec version be less than or equal to the latest version. `-experimental` versions compare less than the final version with the same number, and previous experimental versions are not accepted. * **_config_** (object): options related to the configuration. * **_merge_** (list of objects): a list of the configs to be merged to the current config. - * **source** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **source** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -26,7 +26,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **_verification_** (object): options related to the verification of the config. * **_hash_** (string): the hash of the config, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed config. * **_replace_** (object): the config that will replace the current. - * **source** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **source** (string): the URL of the config. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the config (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -39,7 +39,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **_security_** (object): options relating to network security. * **_tls_** (object): options relating to TLS when fetching resources over `https`. * **_certificateAuthorities_** (list of objects): the list of additional certificate authorities (in addition to the system authorities) to be used for TLS verification when fetching over `https`. All certificate authorities must have a unique `source`. - * **source** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **source** (string): the URL of the certificate bundle (in PEM format). The bundle can contain multiple concatenated certificates. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the certificate bundle (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -83,7 +83,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **path** (string): the absolute path to the file. * **_overwrite_** (boolean): whether to delete preexisting nodes at the path. `contents` must be specified if `overwrite` is true. Defaults to false. * **_contents_** (object): options related to the contents of the file. - * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. + * **_source_** (string): the URL of the file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. If source is omitted and a regular file already exists at the path, Ignition will do nothing. If source is omitted and no file exists, an empty file will be created. * **_compression_** (string): the type of compression used on the file (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -91,7 +91,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **_verification_** (object): options related to the verification of the file. * **_hash_** (string): the hash of the file, in the form `-` where type is either `sha512` or `sha256`. If `compression` is specified, the hash describes the decompressed file. * **_append_** (list of objects): list of fragments to be appended to the file. Follows the same structure as `contents`. - * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **_source_** (string): the URL of the fragment. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the fragment (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. @@ -130,7 +130,7 @@ The Ignition configuration is a JSON document conforming to the following specif * **name** (string): the name of the luks device. * **device** (string): the absolute path to the device. Devices are typically referenced by the `/dev/disk/by-*` symlinks. * **_keyFile_** (object): options related to the contents of the key file. - * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. + * **_source_** (string): the URL of the key file. Supported schemes are `http`, `https`, `tftp`, `s3`, `arn`, `gs`, `file`, `oem` (in some builds), and [`data`](https://tools.ietf.org/html/rfc2397). When using `http`, it is advisable to use the verification option to ensure the contents haven't been modified. * **_compression_** (string): the type of compression used on the key file (null or gzip). Compression cannot be used with S3. * **_httpHeaders_** (list of objects): a list of HTTP headers to be added to the request. Available for `http` and `https` source schemes only. * **name** (string): the header name. diff --git a/docs/distributor-notes.md b/docs/distributor-notes.md index d7f34e51d0..57fed2ac77 100644 --- a/docs/distributor-notes.md +++ b/docs/distributor-notes.md @@ -35,3 +35,7 @@ When Ignition is updating kernel arguments it will call out to a binary (defined As an example of the binary implementation look at [`examples/ignition-kargs-helper`](https://github.com/coreos/ignition/blob/main/examples/ignition-kargs-helper). If your implementation of Ignition doesn't intend to ship kargs functionality the [`ignition-kargs.service` unit](https://github.com/coreos/ignition/blob/main/dracut/30ignition/ignition-kargs.service) should be disabled. + +## OEM Partition URL Scheme + +The `oem` URL scheme reads files from the OEM partition mounted at `/oem` (e.g. `oem:///config.ign`). It is only meaningful on distros that provide such a partition, so it is disabled by default and fetching an `oem` URL fails with an unsupported-scheme error. Distributors that ship an OEM partition can enable it at build time with the linker flag `-X github.com/coreos/ignition/v2/internal/distro.oemFetch=true`. diff --git a/docs/release-notes.md b/docs/release-notes.md index f0a97d4470..384200a865 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -11,6 +11,7 @@ nav_order: 9 ### Features - Add support for the `file` URL scheme, which reads files from local files at the given path. +- Add support for the `oem` URL scheme, which reads files from the local `/oem` directory (disabled by default; enabled by distributors via a build flag). ### Changes diff --git a/internal/distro/distro.go b/internal/distro/distro.go index 5e03425b14..e375ed36c6 100644 --- a/internal/distro/distro.go +++ b/internal/distro/distro.go @@ -81,6 +81,10 @@ var ( // ".ssh/authorized_keys.d/ignition" ("true"), or to // ".ssh/authorized_keys" ("false"). writeAuthorizedKeysFragment = "true" + // oemFetch indicates whether the "oem" URL scheme is supported, + // reading files from the local "/oem" directory. It is only + // meaningful on distros that provide this directory (e.g. Flatcar). + oemFetch = "false" // Special file paths in the real root luksRealRootKeyFilePath = "/etc/luks/" @@ -150,6 +154,7 @@ func BlackboxTesting() bool { return bakedStringToBool(blackboxTesting) } func WriteAuthorizedKeysFragment() bool { return bakedStringToBool(fromEnv("WRITE_AUTHORIZED_KEYS_FRAGMENT", writeAuthorizedKeysFragment)) } +func OEMFetch() bool { return bakedStringToBool(oemFetch) } func fromEnv(nameSuffix, defaultValue string) string { value := os.Getenv("IGNITION_" + nameSuffix) diff --git a/internal/resource/url.go b/internal/resource/url.go index c40e6736cd..436b7be631 100644 --- a/internal/resource/url.go +++ b/internal/resource/url.go @@ -35,6 +35,7 @@ import ( "cloud.google.com/go/compute/metadata" configErrors "github.com/coreos/ignition/v2/config/shared/errors" + "github.com/coreos/ignition/v2/internal/distro" "github.com/coreos/ignition/v2/internal/log" "github.com/coreos/ignition/v2/internal/util" "github.com/coreos/vcontext/report" @@ -185,6 +186,11 @@ func (f *Fetcher) FetchToBuffer(u url.URL, opts FetchOptions) ([]byte, error) { err = f.fetchFromGCS(u, dest, opts) case "file": err = f.fetchFromFile(u.Path, dest, opts) + case "oem": + if !distro.OEMFetch() { + return nil, ErrSchemeUnsupported + } + err = f.fetchFromFile(filepath.Join("/oem", u.Path), dest, opts) case "": return nil, nil default: @@ -255,6 +261,11 @@ func (f *Fetcher) Fetch(u url.URL, dest *os.File, opts FetchOptions) error { return f.fetchFromGCS(u, dest, opts) case "file": return f.fetchFromFile(u.Path, dest, opts) + case "oem": + if !distro.OEMFetch() { + return ErrSchemeUnsupported + } + return f.fetchFromFile(filepath.Join("/oem", u.Path), dest, opts) case "": return nil default: diff --git a/internal/util/url.go b/internal/util/url.go index de465ba4b9..63828c9554 100644 --- a/internal/util/url.go +++ b/internal/util/url.go @@ -19,5 +19,5 @@ import ( ) func UrlNeedsNet(u url.URL) bool { - return u.Scheme != "data" && u.Scheme != "file" && u.Scheme != "" + return u.Scheme != "data" && u.Scheme != "file" && u.Scheme != "oem" && u.Scheme != "" }