Compare commits
10 Commits
d43dcbde20
...
af231dc92e
| Author | SHA1 | Date |
|---|---|---|
|
|
af231dc92e | |
|
|
2058525bc2 | |
|
|
52531c53c9 | |
|
|
67de892b2a | |
|
|
45f49687f3 | |
|
|
d3e8dd770c | |
|
|
0916a74007 | |
|
|
112694c8e5 | |
|
|
22a7ef2d6e | |
|
|
89549c285c |
|
|
@ -87,10 +87,23 @@ coreos-bblayers-envsub COREOS_LAYERSDIR "${COREOS_ROOT}/layers"
|
||||||
# Add support for ##COREOS_EXTLAYERSDIR## inside of bblayer template
|
# Add support for ##COREOS_EXTLAYERSDIR## inside of bblayer template
|
||||||
coreos-bblayers-envsub COREOS_EXTLAYERSDIR "${COREOS_ROOT}/external-layers"
|
coreos-bblayers-envsub COREOS_EXTLAYERSDIR "${COREOS_ROOT}/external-layers"
|
||||||
|
|
||||||
# Generate the ${BUILDDIR}/key directory. The scripts doesn't generate anything it
|
# Generate the ${BUILDDIR}/key directory. The scripts doesn't generate anything
|
||||||
# the directory already exist, so it's safe to call it everytime
|
# if the directory already exist so it's safe to call it everytime
|
||||||
# stdout is redirected to reduce the amount of output but not stderr
|
# stdout is redirected to reduce the amount of output but not stderr
|
||||||
coreos-keygen > /dev/null || {
|
#
|
||||||
echo "The coreos-keygen script has failed" >&2
|
#Note: if a final build is detected all the dev keys are deleted
|
||||||
return 1
|
|
||||||
}
|
if [ "$CreateFinal" = "true" ]; then
|
||||||
|
echo "\nFinal build detected delete dev keys and dont use or generate them" >&2
|
||||||
|
rm -rf "${BUILDDIR}/keys"
|
||||||
|
else
|
||||||
|
echo "\nNo final build detected use development keys" >&2
|
||||||
|
coreos-get-dev-keys > /dev/null || {
|
||||||
|
echo "The coreos-get-dev-keys script has failed" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
coreos-keygen > /dev/null || {
|
||||||
|
echo "The coreos-keygen script has failed" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"ms-vscode.makefile-tools",
|
||||||
|
"lextudio.restructuredtext",
|
||||||
|
"trond-snekvik.simple-rst"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"files.watcherExclude": {
|
||||||
|
"**/_build/**": true,
|
||||||
|
},
|
||||||
|
"python.formatting.provider": "black",
|
||||||
|
"editor.rulers": [
|
||||||
|
80,
|
||||||
|
100,
|
||||||
|
120
|
||||||
|
],
|
||||||
|
"esbonio.sphinx.confDir": ""
|
||||||
|
}
|
||||||
|
|
@ -11,3 +11,4 @@ Belden CoreOS Boot Concepts
|
||||||
|
|
||||||
overview
|
overview
|
||||||
uboot
|
uboot
|
||||||
|
secure-boot
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,268 @@
|
||||||
|
*******************
|
||||||
|
Secure Boot Concept
|
||||||
|
*******************
|
||||||
|
|
||||||
|
Currently CoreOS provide a Proof Of Concept of some of the secure boot element that we want to
|
||||||
|
implement a full secure-boot solution based on UEFI secure boot.
|
||||||
|
|
||||||
|
The current proof of concept is structured as follows:
|
||||||
|
|
||||||
|
Hardware Requirements
|
||||||
|
=====================
|
||||||
|
|
||||||
|
- The device must have an `eMMC`.
|
||||||
|
- The architecture of the device must be either `ARM32` or `AARCH64`.
|
||||||
|
|
||||||
|
|
||||||
|
eMMC Embedded MultiMediaCard
|
||||||
|
============================
|
||||||
|
|
||||||
|
eMMC, or Embedded MultiMediaCard, represents a prevalent storage format in devices such as
|
||||||
|
smartphones, tablets, and other embedded systems. It encapsulates NAND flash memory and a dedicated
|
||||||
|
controller within one package. This structure not only eases integration for device manufacturers
|
||||||
|
but also ensures a compact, efficient storage medium.
|
||||||
|
|
||||||
|
Within eMMC's architecture, distinct hardware partitions cater to diverse operational demands:
|
||||||
|
|
||||||
|
.. graphviz::
|
||||||
|
|
||||||
|
digraph emmcStructure {
|
||||||
|
rankdir=TB;
|
||||||
|
node [shape=box, style=filled, fillcolor="#e6f2ff"];
|
||||||
|
edge [color="#0099cc", fontsize=12];
|
||||||
|
|
||||||
|
compound=true;
|
||||||
|
|
||||||
|
subgraph cluster_eMMC {
|
||||||
|
label="eMMC";
|
||||||
|
color="#0099cc";
|
||||||
|
|
||||||
|
Boot0 [label="Boot0"];
|
||||||
|
Boot1 [label="Boot1"];
|
||||||
|
RPMB [label="RPMB"];
|
||||||
|
|
||||||
|
subgraph cluster_User {
|
||||||
|
label="User";
|
||||||
|
color="#00cc99";
|
||||||
|
GPT [label="GPT Table"];
|
||||||
|
|
||||||
|
subgraph cluster_GPT {
|
||||||
|
label="Software Partitions (GPT)";
|
||||||
|
color="#99e6e6";
|
||||||
|
|
||||||
|
SoftwarePartition1 [label="Partition 1"];
|
||||||
|
SoftwarePartition2 [label="Partition 2"];
|
||||||
|
SoftwarePartitionN [label="Partition N"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#. **Boot0 and Boot1**: The boot partitions cater to device start-up requirements, typically hosting
|
||||||
|
the firmware. Boot0 predominantly initiates the boot-up, while Boot1 stands as a secondary guard
|
||||||
|
or backup, ensuring booting is resilient and failsafe.
|
||||||
|
|
||||||
|
#. **RPMB (Replay Protected Memory Block)**: As a secure partition, RPMB shelters data against
|
||||||
|
potential tampering. It's tailored for sensitive information storage, such as cryptographic keys.
|
||||||
|
Its design counters data replays or rollbacks, fortifying against particular attack types.
|
||||||
|
|
||||||
|
#. **User**: The primary storage domain, the User partition accommodates the OS, applications,
|
||||||
|
and user-centric data. It's reminiscent of the primary storage drive in larger computing devices.
|
||||||
|
Importantly, the User partition has a layered structure. Using the GPT (GUID Partition Table), it
|
||||||
|
is further divided into multiple software partitions, which can house diverse datasets or file
|
||||||
|
systems.
|
||||||
|
|
||||||
|
The boot concept of CoreOS rely on the presence of an eMMC to implement the following feature:
|
||||||
|
|
||||||
|
- Storage of two copy of the firmware with a way to switch from a copy to another using the eMMC
|
||||||
|
boot0 and boot1 hardware partition
|
||||||
|
- Storage of keys used by the UEFI Secure Key specification inside the secure RPMB hardware
|
||||||
|
partition.
|
||||||
|
- Storage of the bootloader, kernel and rootfs inside the user hardware partition using multiple
|
||||||
|
software partition in the GPT format.
|
||||||
|
|
||||||
|
Firmware
|
||||||
|
========
|
||||||
|
|
||||||
|
The firmware of the device should implement a subset of the UEFI specification as defined in the
|
||||||
|
ARM Base Boot Requirements (EBBR) and should implement the optional UEFI Secure Boot part of the
|
||||||
|
EBBR specifications.
|
||||||
|
|
||||||
|
This is done in CoreOS by levering the built-in EBBR and UEFI Secure Boot present into the u-boot
|
||||||
|
project.
|
||||||
|
|
||||||
|
The hardware should verify the validity of the firmware using a hardware specific way. Then the
|
||||||
|
generic secure boot concept explained here can be used to valide all the following component of
|
||||||
|
CoreOS.
|
||||||
|
|
||||||
|
UEFI Key used by UEFI Secure Boot
|
||||||
|
=================================
|
||||||
|
|
||||||
|
|
||||||
|
- **PK (Platform Key)**: This top-tier key shoulders the responsibility of KEK verification and its
|
||||||
|
potential revocation. PK holders have the exclusive privilege to configure the KEK and the `db`
|
||||||
|
database. It's the gatekeeper ensuring only authorized software can touch the firmware or
|
||||||
|
bootloader.
|
||||||
|
|
||||||
|
- **KEK (Key Exchange Key)**: As a medium for data exchange, the KEK is pivotal for signing the `db`
|
||||||
|
and `dbx` databases.
|
||||||
|
|
||||||
|
- **db (Allowed Database)**: This is the white list. It houses the keys or hashes of permitted
|
||||||
|
firmware and OS loaders. Execution is only granted to software with a signature that resonates
|
||||||
|
with the keys/hashes in this database.
|
||||||
|
|
||||||
|
- **dbx (Forbidden Database)**: The black sheep are here. Housing keys or hashes of known
|
||||||
|
unauthorized software, it ensures any associated software is prohibited from executing.
|
||||||
|
|
||||||
|
Currently all theses public keys are built-in into u-boot at build time and are read only. In the
|
||||||
|
future we will use the OP-TEE support into u-boot to use OP-TEE to manage the keys.
|
||||||
|
|
||||||
|
OP-TEE and RPMB as key manager
|
||||||
|
==============================
|
||||||
|
|
||||||
|
OP-TEE, or Open Portable Trusted Execution Environment, is an open-source implementation of the
|
||||||
|
Trusted Execution Environment (TEE) designed for ARM-powered platforms. In essence, a TEE is a
|
||||||
|
secure enclave that provides a separated, isolated environment where specific applications and their
|
||||||
|
data can run independently from the regular operating system, ensuring they are protected against
|
||||||
|
potential tampering or unauthorized access.
|
||||||
|
|
||||||
|
OP-TEE guarantees confidentiality, integrity, and authenticity for critical applications by
|
||||||
|
executing them in this secure space. It offers a wide range of security features, including secure
|
||||||
|
storage of cryptographic keys, secure boot, and hardware-backed crypto operations.
|
||||||
|
|
||||||
|
In the context of UEFI secure boot, OP-TEE becomes instrumental. UEFI's secure boot mechanism
|
||||||
|
ensures that only trusted, signed firmware, OS loaders, and OS kernels are executed during the boot
|
||||||
|
process. To enforce this level of trust, UEFI relies on a set of cryptographic keys, including PK
|
||||||
|
(Platform Key), KEK (Key Exchange Key), and db/dbx (allowed and forbidden signature databases).
|
||||||
|
Safeguarding these keys is paramount to maintain the security and integrity of the boot process.
|
||||||
|
|
||||||
|
By leveraging OP-TEE, these UEFI secure boot keys can be securely stored in the RPMB (Replay
|
||||||
|
Protected Memory Block) partition of the eMMC. The RPMB is a write-protected, secure area of the
|
||||||
|
eMMC designed to hold sensitive data and protect it against tampering and replay attacks.
|
||||||
|
Since OP-TEE manages secure access to the RPMB partition, it ensures that the UEFI secure boot keys
|
||||||
|
are not only safely stored but are also accessible only by authorized firmware components.
|
||||||
|
|
||||||
|
eMMC User Partition
|
||||||
|
===================
|
||||||
|
|
||||||
|
The user partition of the eMMC must be structured using the GPT (GUID Partition Table) format.
|
||||||
|
|
||||||
|
Within the GPT-formatted user partition, specific partitions should be established for efficient
|
||||||
|
booting and system operation:
|
||||||
|
|
||||||
|
1. **EFI**: This is the Essential Firmware Interface partition. It holds the `efibootguard`
|
||||||
|
os-loader binary, responsible for the boot sequence's initial steps and the kernel's selection
|
||||||
|
based on its configuration. This binary is signed with a key present in the `dbx` database
|
||||||
|
|
||||||
|
2. **EBG0 - Efibootguard Config 0**: This partition houses the `efibootguard` configuration for the
|
||||||
|
first kernel option. Alongside the configuration file, it also contains a Unified Kernel Image
|
||||||
|
(UKI), a bundled package comprising the Linux kernel, device trees, and associated boot
|
||||||
|
components. The UKI is signed with a key present in the `dbx` database
|
||||||
|
|
||||||
|
3. **EBG1 - Efibootguard Config 1**: Similar to EBG0, this partition carries the `efibootguard`
|
||||||
|
configuration for the second kernel option. It too holds a Unified Kernel Image tailored for this
|
||||||
|
alternate boot choice.
|
||||||
|
|
||||||
|
4. **rootfs0**: This partition stores the CoreOS root filesystem designed to complement and operate
|
||||||
|
with the kernel embedded in the EBG0 partition. It provides the essential system files and
|
||||||
|
structures required for the operating system's functioning when the kernel from EBG0 is booted.
|
||||||
|
Integrety of this rootfs is assured by storing an hash of the rootfs inside the UKI image.
|
||||||
|
|
||||||
|
5. **rootfs1**: Analogous to `rootfs0`, this partition houses the CoreOS root filesystem tailored
|
||||||
|
for the kernel within the EBG1 partition. It ensures that, should the system boot from the kernel
|
||||||
|
in EBG1, the appropriate file structures and system components are readily available.
|
||||||
|
|
||||||
|
EFIBootGuard Configuration
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Efibootguard, as a part of its design, employs a configuration system to determine the appropriate
|
||||||
|
kernel and associated resources to boot from. This configuration is stored in distinct partitions,
|
||||||
|
EBG0 and EBG1, each holding its configuration file.
|
||||||
|
|
||||||
|
The configuration file itself comprises several fields, but most crucially, it contains a revision
|
||||||
|
field. This field is a numerical identifier indicating the version or update level of the contained
|
||||||
|
kernel and resources. When the system initiates its boot sequence, Efibootguard assesses the
|
||||||
|
revision values in both the EBG0 and EBG1 configuration files.
|
||||||
|
|
||||||
|
The selection process is straightforward yet robust: Efibootguard chooses the partition with the
|
||||||
|
higher revision value. By doing so, it inherently opts for the most recent or updated kernel version
|
||||||
|
available. However, this system also supports failover mechanisms. In case the kernel in the
|
||||||
|
partition with the higher revision encounters issues during boot, Efibootguard can revert to the
|
||||||
|
other partition, ensuring resilience and continuity in system operations.
|
||||||
|
|
||||||
|
Moreover, the choice isn't rigidly fixed. When the system undergoes updates, the configuration files
|
||||||
|
can be rewritten, and the revision values adjusted, allowing for dynamic and flexible booting in
|
||||||
|
line with system evolutions and updates. In essence, Efibootguard, with its configuration-based
|
||||||
|
approach, ensures a blend of up-to-date system booting and built-in fail-safes for dependable
|
||||||
|
operation.
|
||||||
|
|
||||||
|
Unified Kernel Image
|
||||||
|
====================
|
||||||
|
|
||||||
|
After having choosen the right configuration file, Efibootguard takes on the responsibility of
|
||||||
|
launching the Unified Kernel Image (UKI) linked with the active configuration. This image bundle
|
||||||
|
together essential boot components like the Linux kernel, device trees, and the kernel command
|
||||||
|
line. The secure initiation of this image is paramount, and Efibootguard ensures this by leveraging
|
||||||
|
UEFI's start_image system call.
|
||||||
|
|
||||||
|
The UEFI start_image system call verifies the image's signature against the Secure Boot keys
|
||||||
|
(PK, KEK, db, and potentially dbx). If the signature matches, indicating that the image is trusted
|
||||||
|
and hasn't been tampered with, the image is permitted to execute. If not, the booting halts,
|
||||||
|
preventing any unauthorized or potentially malicious code from running.
|
||||||
|
|
||||||
|
Once the UKI has been securely initiated, it undertakes multiple tasks. It first extracts the
|
||||||
|
necessary components from the bundled package, identifying and utilizing the appropriate device
|
||||||
|
trees based on `compatible` node, by matching with the `compatible` node of the `device-tree` that
|
||||||
|
is built into the firmware. These device trees inform the system about the hardware configuration,
|
||||||
|
ensuring the kernel interacts correctly with the system's components.
|
||||||
|
|
||||||
|
The UKI os-launcher also has CoreOS specialized patches, enabling dynamic rootfs switching without
|
||||||
|
requiring an initramfs by changing the `root=` part of the kernel command line at run time to
|
||||||
|
point to the right rootfs partition.
|
||||||
|
|
||||||
|
RootFS and dm-verity
|
||||||
|
====================
|
||||||
|
|
||||||
|
dm-verity is a Linux kernel feature designed to provide transparent integrity checking of block
|
||||||
|
devices, particularly for read-only file systems. Rooted in cryptographic principles, dm-verity
|
||||||
|
employs a hash-based approach to ensure and validate the integrity of the root filesystem (rootfs).
|
||||||
|
|
||||||
|
The way dm-verity operates is by building a Merkle tree, a structure where each leaf node contains a
|
||||||
|
hash of a block of the underlying data, while each non-leaf node is a hash of its children. The
|
||||||
|
topmost node, the root of the Merkle tree, provides a cumulative hash representing the entirety of
|
||||||
|
the data. This top hash, known as the root hash, serves as a concise, cryptographic representation
|
||||||
|
of the entire filesystem's state.
|
||||||
|
|
||||||
|
When integrating dm-verity with the Unified Kernel Image (UKI), an additional layer of security is
|
||||||
|
established. By embedding the root hash into the signed UKI, any tampering or modification in the
|
||||||
|
rootfs can be swiftly detected. When the system boots, the UKI, being signed, ensures that the
|
||||||
|
embedded root hash is legitimate and untampered. As the OS accesses the rootfs, dm-verity
|
||||||
|
recalculates the hash values in real-time and compares them to the values in the original Merkle
|
||||||
|
tree, referenced by the embedded root hash.
|
||||||
|
|
||||||
|
If any discrepancies are found – that is, if the recalculated hash doesn't match the stored value –
|
||||||
|
it indicates potential tampering, and the OS can halt access or take appropriate measures.
|
||||||
|
|
||||||
|
.. graphviz::
|
||||||
|
|
||||||
|
digraph SecureBootFlow {
|
||||||
|
rankdir=TB;
|
||||||
|
|
||||||
|
node [shape=box, style=filled, fillcolor="#e6f2ff"];
|
||||||
|
edge [color="#0099cc", fontsize=12];
|
||||||
|
|
||||||
|
Hardware [label="Hardware\n(ARM32/AARCH64 with eMMC)"];
|
||||||
|
Firmware [label="u-boot Firmware\n(UEFI EBRR subset)"];
|
||||||
|
eMMCConfig [label="eMMC Configuration\n(GPT with EFI partition)"];
|
||||||
|
EFIBootGuard [label="EFIBootGuard\n(A/B Kernel Switching)"];
|
||||||
|
UnifiedKernel [label="Unified Kernel Image\n(Kernel, cmd line, DTB)"];
|
||||||
|
KernelAndRootFS [label="Kernel & RootFS\n(dm-verity validation)"];
|
||||||
|
|
||||||
|
Hardware -> Firmware [label="Flashed with u-boot\n+ Built-in keys"];
|
||||||
|
Firmware -> eMMCConfig [label="eMMC boot"];
|
||||||
|
eMMCConfig -> EFIBootGuard [label="Boots from EFI partition"];
|
||||||
|
EFIBootGuard -> UnifiedKernel [label="Selects kernel A/B"];
|
||||||
|
UnifiedKernel -> KernelAndRootFS [label="Kernel boot\n+ RootFS verification"];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -40,6 +40,7 @@ same structures.
|
||||||
|
|
||||||
Installation Manual <installation/index>
|
Installation Manual <installation/index>
|
||||||
Reference Manual <ref-manual/index>
|
Reference Manual <ref-manual/index>
|
||||||
|
Testing Manual <testing/index>
|
||||||
Boot Concepts <boot/index>
|
Boot Concepts <boot/index>
|
||||||
Best Practices <best_practices/index>
|
Best Practices <best_practices/index>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,354 @@
|
||||||
|
.. index:: BATS
|
||||||
|
|
||||||
|
************************************
|
||||||
|
BATS - Bash Automated Testing System
|
||||||
|
************************************
|
||||||
|
|
||||||
|
The CoreOS distribution supports writing tests using shell syntax by providing the `bats` command.
|
||||||
|
|
||||||
|
If you want to use `bats`, you will need the following CoreOS packages:
|
||||||
|
|
||||||
|
- bats
|
||||||
|
- bats-file
|
||||||
|
- bats-assert
|
||||||
|
|
||||||
|
Overview of BATS
|
||||||
|
================
|
||||||
|
|
||||||
|
A BATS test can be as simple as a single .bats file. For example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
bats_load_library bats-support
|
||||||
|
bats_load_library bats-assert
|
||||||
|
|
||||||
|
@test "can output to stdout" {
|
||||||
|
run echo hello
|
||||||
|
assert_output 'hello'
|
||||||
|
}
|
||||||
|
|
||||||
|
You can run it using the command `bats <filename>.bats`
|
||||||
|
|
||||||
|
This will give you the following output:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sam@SAVE:~/Projects/tests$ bats <filename>.bats
|
||||||
|
<filename>.bats
|
||||||
|
✓ can output to stdout
|
||||||
|
|
||||||
|
1 test, 0 failures
|
||||||
|
|
||||||
|
The run command
|
||||||
|
================
|
||||||
|
|
||||||
|
In shell tests, you often need to run commands and capture their output, exit
|
||||||
|
status, and error messages. The run command provided by `bats` allows you to
|
||||||
|
execute commands within your test cases and collect this information for later
|
||||||
|
assertion and validation.
|
||||||
|
|
||||||
|
The run command will make the following variables available:
|
||||||
|
|
||||||
|
- `${status}`: exit code of the command run by `run`
|
||||||
|
- `${output}`: combined content of `stdout` and `stderr`
|
||||||
|
- `${lines[@]}`: array of lines of the output
|
||||||
|
- `${BATS_RUN_COMMAND}`: command run by the `run` command
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
@test "invoking foo with a nonexistent file prints an error" {
|
||||||
|
run foo nonexistent_filename
|
||||||
|
[ "$status" -eq 1 ]
|
||||||
|
[ "$output" = "foo: no such file 'nonexistent_filename'" ]
|
||||||
|
[ "$BATS_RUN_COMMAND" = "foo nonexistent_filename" ]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
The `run` command accepts some parameters:
|
||||||
|
|
||||||
|
- `-N`: Expect N as exit status and fail otherwise
|
||||||
|
- `-!`: Expect non-zero exit status and fail if the command succeeds.
|
||||||
|
- `--keep-empty-lines`: don't remove empty lines from `${lines}`
|
||||||
|
- `--separate-stderr`: Use separate variables for stderr `${stderr}` and `${stderr_lines[@]}`
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
@test "invoking foo without arguments prints usage" {
|
||||||
|
run -1 foo
|
||||||
|
[ "${lines[0]}" = "usage: foo <filename>" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
The bats-assert helper
|
||||||
|
======================
|
||||||
|
|
||||||
|
The `bats-assert` helper provides some functions to create more readable tests.
|
||||||
|
These assertions use the variables created by the `run` command and can be used
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
@test 'assert_output()' {
|
||||||
|
run echo 'have'
|
||||||
|
assert_output 'want'
|
||||||
|
}
|
||||||
|
|
||||||
|
The following functions are provided:
|
||||||
|
|
||||||
|
- `assert` and `refute`: Assert that a given expression evaluates to true or false.
|
||||||
|
- `assert_equal`: Assert that two parameters are equal.
|
||||||
|
- `assert_not_equal`: Assert that two parameters are not equal.
|
||||||
|
- `assert_success` and `assert_failure`: Assert that the exit status is 0 or 1.
|
||||||
|
- `assert_output` and `refute_output`: Assert that the output does (or does not) contain the given content.
|
||||||
|
- `assert_line` and `refute_line`: Assert that a specific line of the output does (or does not) contain the given content.
|
||||||
|
- `assert_regex` and `refute_regex`: Assert that a parameter matches (or does not match) the given pattern.
|
||||||
|
|
||||||
|
The bats-file helper
|
||||||
|
====================
|
||||||
|
|
||||||
|
The `bats-file` helper provides functions to help work with files in tests:
|
||||||
|
|
||||||
|
**Test File Types:**
|
||||||
|
|
||||||
|
- `assert_exists` and `assert_not_exists`: Check if a file or directory exists.
|
||||||
|
- `assert_file_exists` and `assert_file_not_exists`: Check if a file exists.
|
||||||
|
- `assert_dir_exists` and `assert_dir_not_exists`: Check if a directory exists.
|
||||||
|
- `assert_link_exists` and `assert_link_not_exists`: Check if a link exists.
|
||||||
|
- `assert_block_exists` and `assert_block_not_exists`: Check if a block special file exists.
|
||||||
|
- `assert_character_exists` and `assert_character_not_exists`: Check if a character special file exists.
|
||||||
|
- `assert_socket_exists` and `assert_socket_not_exists`: Check if a socket exists.
|
||||||
|
- `assert_fifo_exists` and `assert_fifo_not_exists`: Check if a fifo special file exists.
|
||||||
|
|
||||||
|
**Test File Attributes:**
|
||||||
|
|
||||||
|
- `assert_file_executable` and `assert_file_not_executable`
|
||||||
|
- `assert_file_owner` and `assert_file_not_owner`
|
||||||
|
- `assert_file_permission` and `assert_not_file_permission`
|
||||||
|
- `assert_file_size_equals`
|
||||||
|
- `assert_size_zero` and `assert_size_not_zero`
|
||||||
|
- `assert_file_group_id_set` and `assert_file_not_group_id_set`
|
||||||
|
- `assert_file_user_id_set` and `assert_file_not_user_id_set`
|
||||||
|
- `assert_sticky_bit` and `assert_no_sticky_bit`
|
||||||
|
|
||||||
|
**Test File Content:**
|
||||||
|
|
||||||
|
- `assert_file_empty` and `assert_file_not_empty`
|
||||||
|
- `assert_file_contains` and `assert_file_not_contains`
|
||||||
|
- `assert_symlink_to` and `assert_not_symlink_to`
|
||||||
|
|
||||||
|
**Working with a temporary directory:**
|
||||||
|
|
||||||
|
- `temp_make` and `temp_del`
|
||||||
|
|
||||||
|
Pre- and Post-test case hooks
|
||||||
|
==============================
|
||||||
|
|
||||||
|
In some cases, it's useful to have a function that runs before or after each test
|
||||||
|
case in a bats file.
|
||||||
|
|
||||||
|
A function named `setup` will run before each test case, and a function
|
||||||
|
named `teardown` will run after each test case.
|
||||||
|
|
||||||
|
This example creates a directory in the setup function but lacks a teardown
|
||||||
|
that removes the directory. The second time the setup function is run, the
|
||||||
|
setup will fail as the directory already exists:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
bats_load_library bats-support
|
||||||
|
bats_load_library bats-assert
|
||||||
|
bats_load_library bats-file
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
mkdir tmp
|
||||||
|
echo 'a' >> ./tmp/test
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "test contains a single a I" {
|
||||||
|
assert_file_contains ./tmp/test '^a$'
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "test contains a single a II" {
|
||||||
|
assert_file_contains ./tmp/test '^a$'
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sam@SAVE:~/Projects/tests$ bats test.bats
|
||||||
|
test.bats
|
||||||
|
✓ test contains a single a I
|
||||||
|
✗ test contains a single a II
|
||||||
|
(from function `setup' in test file test.bats, line 8)
|
||||||
|
`mkdir tmp' failed
|
||||||
|
mkdir: cannot create directory ‘tmp’: File exists
|
||||||
|
|
||||||
|
2 tests, 1 failure
|
||||||
|
|
||||||
|
This can be easily fixed by adding a teardown function:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
bats_load_library bats-support
|
||||||
|
bats_load_library bats-assert
|
||||||
|
bats_load_library bats-file
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
mkdir tmp
|
||||||
|
echo 'a' >> ./tmp/test
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
rm -rf ./tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@test "test contains a single a I" {
|
||||||
|
assert_file_contains ./tmp/test '^a$'
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "test contains a single a II" {
|
||||||
|
assert_file_contains ./tmp/test '^a$'
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sam@SAVE:~/Projects/tests$ bats test.bats
|
||||||
|
test.bats
|
||||||
|
✓ test contains a single a I
|
||||||
|
✓ test contains a single a II
|
||||||
|
|
||||||
|
2 tests, 0 failures
|
||||||
|
|
||||||
|
Pre- and Post-test file hooks
|
||||||
|
=============================
|
||||||
|
|
||||||
|
To run some code before executing a test file or after executing it, the
|
||||||
|
functions `setup_file` and `teardown_file` can be used.
|
||||||
|
|
||||||
|
The last example could be refactored to only create the tmp directory once:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
#!/usr/bin/env bats
|
||||||
|
|
||||||
|
bats_load_library bats-support
|
||||||
|
bats_load_library bats-assert
|
||||||
|
bats_load_library bats-file
|
||||||
|
|
||||||
|
setup_file() {
|
||||||
|
export DIR="./tmp"
|
||||||
|
export FILE="${DIR}/test"
|
||||||
|
mkdir "${DIR}"
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown_file() {
|
||||||
|
rm -rf "${DIR}"
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
echo 'a' >> "${FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown() {
|
||||||
|
rm "${FILE}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "test contains a single a I" {
|
||||||
|
assert_file_contains "${FILE}" '^a$'
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "test contains a single a II" {
|
||||||
|
assert_file_contains "${FILE}" '^a$'
|
||||||
|
}
|
||||||
|
|
||||||
|
Multiple files
|
||||||
|
==============
|
||||||
|
|
||||||
|
With `bats`, a file is a test suite. If you have multiple `bats` files in a
|
||||||
|
directory and you provide the directory in the `bats` command line, `bats`
|
||||||
|
will execute all the test suites.
|
||||||
|
|
||||||
|
Example: `bats .`
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sam@SAVE:~/Projects/tests$ bats .
|
||||||
|
./first.bats
|
||||||
|
✓ can run our script
|
||||||
|
✗ second test
|
||||||
|
(in test file ./first.bats, line 27)
|
||||||
|
`false' failed
|
||||||
|
./second.bats
|
||||||
|
✓ multi file
|
||||||
|
./test.bats
|
||||||
|
✓ test contains a single a I
|
||||||
|
✓ test contains a single a II
|
||||||
|
|
||||||
|
5 tests, 1 failure
|
||||||
|
|
||||||
|
Pre- and Post-suite hooks
|
||||||
|
=========================
|
||||||
|
|
||||||
|
If you want to execute the same function before each test suite or after
|
||||||
|
each test suite, create a file named `setup_suite.bash`. In this file,
|
||||||
|
create a function named `setup_suite()` and another named `teardown_suite()`.
|
||||||
|
|
||||||
|
Exporting the test results
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Test results can be exported using the JUnit XML format. This can then be
|
||||||
|
used in other tools and merged with other JUnit XML formats to generate a final
|
||||||
|
test report.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
sam@SAVE:~/Projects/tests$ bats . -F junit
|
||||||
|
|
||||||
|
This will produce the following XML content on stdout:
|
||||||
|
|
||||||
|
.. code-block:: xml
|
||||||
|
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<testsuites time="0.048">
|
||||||
|
<testsuite name="./first.bats" tests="2" failures="1" errors="0" skipped="0" time="0.025" timestamp="2023-08-16T14:22:15" hostname="SAVE">
|
||||||
|
<testcase classname="./first.bats" name="can run our script" time="0.013" />
|
||||||
|
<testcase classname="./first.bats" name="second test" time="0.012">
|
||||||
|
<failure type="failure">(in test file ./first.bats, line 27)
|
||||||
|
`false' failed</failure>
|
||||||
|
</testcase>
|
||||||
|
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="./second.bats" tests="1" failures="0" errors="0" skipped="0" time="0.008" timestamp="2023-08-16T14:22:15" hostname="SAVE">
|
||||||
|
<testcase classname="./second.bats" name="multi file" time="0.008" />
|
||||||
|
|
||||||
|
</testsuite>
|
||||||
|
<testsuite name="./test.bats" tests="2" failures="0" errors="0" skipped="0" time="0.015" timestamp="2023-08-16T14:22:15" hostname="SAVE">
|
||||||
|
<testcase classname="./test.bats" name="test contains a single a I" time="0.008" />
|
||||||
|
<testcase classname="./test.bats" name="test contains a single a II" time="0.007" />
|
||||||
|
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
Going further
|
||||||
|
=============
|
||||||
|
|
||||||
|
`bats` scripts can be checked with shellcheck for common mistakes.
|
||||||
|
|
||||||
|
The `bats-assert` add-on provides many helper functions to perform
|
||||||
|
assertions with a more readable syntax than the shell's built-in syntax.
|
||||||
|
|
||||||
|
See https://github.com/bats-core/bats-assert
|
||||||
|
|
||||||
|
The `bats-file` add-on provides helper functions to check for files. See
|
||||||
|
https://github.com/bats-core/bats-file/
|
||||||
|
|
||||||
|
You can find a list of projects using `bats` on this page:
|
||||||
|
https://github.com/bats-core/bats-core/wiki/Projects-Using-Bats
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
==============================
|
||||||
|
Belden CoreOS Testing Manual
|
||||||
|
==============================
|
||||||
|
|
||||||
|
This manual is a work on progress on how to test and how to write test for
|
||||||
|
CoreOS or CoreOS based distribution.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: Table of Contents
|
||||||
|
:numbered:
|
||||||
|
|
||||||
|
bats
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#@TYPE: Machine
|
||||||
|
#@NAME: eagle40-03
|
||||||
|
#@DESCRIPTION: Machine support for EAGLE40-03
|
||||||
|
#
|
||||||
|
|
||||||
|
require include/coreos-generic-arch/x64.inc
|
||||||
|
|
||||||
|
MACHINE_FEATURES += "pci usbhost x86 acpi serial efi tpm2 "
|
||||||
|
|
||||||
|
# Kernel configuration
|
||||||
|
# ******************************************************************************
|
||||||
|
|
||||||
|
PREFERRED_VERSION_linux-yocto ?= "5.15%"
|
||||||
|
PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto"
|
||||||
|
|
||||||
|
KERNEL_IMAGETYPE = "bzImage"
|
||||||
|
|
||||||
|
# getty configuration
|
||||||
|
# ******************************************************************************
|
||||||
|
|
||||||
|
SERIAL_CONSOLES = "115200;ttyS0"
|
||||||
|
SERIAL_CONSOLES_CHECK = "ttyS0"
|
||||||
|
APPEND += "console=ttyS0,115200"
|
||||||
|
|
||||||
|
# Image generation
|
||||||
|
# ******************************************************************************
|
||||||
|
|
||||||
|
# Ensure that both flash-image.bin and boot.scr are generated as they are needed
|
||||||
|
# for a wic image
|
||||||
|
WKS_FILE = "generic-uefi.wks.in"
|
||||||
|
# COREOS_INSTALLER_WKS_FILE ?= "" --> TBD
|
||||||
|
IMAGE_FSTYPES += "wic.xz wic.bmap"
|
||||||
|
|
||||||
|
MACHINE_ESSENTIAL_EXTRA_RDEPENDS += " kernel-modules"
|
||||||
|
# COREOS_IMAGE_SWUPDATE_EXTRACLASSES += "" --> TBD
|
||||||
|
|
||||||
|
# No watchdog available yet
|
||||||
|
EFIBOOTGUARD_TIMEOUT ?= "0"
|
||||||
|
require conf/machine/include/coreos-generic-features/efi.inc
|
||||||
|
require conf/machine/include/coreos-generic-features/partitions.inc
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
# Variable used in WKS file
|
# Variable used in WKS file
|
||||||
|
|
||||||
WKS_PART_EFI ??= 'part --source efibootguard-efi --label efi --part-type=EF00'
|
WKS_PART_EFI ??= 'part --source efibootguard-efi --label efi --part-type=EF00'
|
||||||
WKS_PART_EFIBOOTGUARD_A ??= 'part --source efibootguard-boot --label ebg0 --part-type=0700 --sourceparams "args=coreos.root=rootfs0,watchdog=${EFIBOOTGUARD_TIMEOUT},revision=2,kernel=kernel-${MACHINE}.efi;KERNEL.EFI"'
|
WKS_PART_EFIBOOTGUARD_A ??= 'part --source efibootguard-boot --label ebg0 --part-type=0700 --sourceparams "args=coreos.root=rootfs0,watchdog=${EFIBOOTGUARD_TIMEOUT},revision=2,kernel=${COREOS_KERNEL_FILENAME};KERNEL.EFI"'
|
||||||
WKS_PART_EFIBOOTGUARD_B ??= 'part --source efibootguard-boot --label ebg1 --part-type=0700 --sourceparams "args=coreos.root=rootfs1,watchdog=${EFIBOOTGUARD_TIMEOUT},revision=1,kernel=kernel-${MACHINE}.efi;KERNEL.EFI"'
|
WKS_PART_EFIBOOTGUARD_B ??= 'part --source efibootguard-boot --label ebg1 --part-type=0700 --sourceparams "args=coreos.root=rootfs1,watchdog=${EFIBOOTGUARD_TIMEOUT},revision=1,kernel=${COREOS_KERNEL_FILENAME};KERNEL.EFI"'
|
||||||
WKS_PART_ROOT_A ??= 'part / --source rootfs --fstype=ext4 --label rootfs0'
|
WKS_PART_ROOT_A ??= 'part / --source rootfs --fstype=ext4 --label rootfs0'
|
||||||
WKS_PART_ROOT_B ??= 'part --fstype=ext4 --label rootfs1'
|
WKS_PART_ROOT_B ??= 'part --fstype=ext4 --label rootfs1'
|
||||||
WKS_PART_ROOT_SIZE ??= '2G'
|
WKS_PART_ROOT_SIZE ??= '2G'
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto"
|
||||||
|
|
||||||
MACHINE_EXTRA_RRECOMMENDS += "kernel-modules linux-firmware"
|
MACHINE_EXTRA_RRECOMMENDS += "kernel-modules linux-firmware"
|
||||||
|
|
||||||
IMAGE_FSTYPES += "ext4 wic wic.xz wic.bmap wic.vmdk"
|
IMAGE_FSTYPES += "ext4 wic wic.xz wic.bmap wic.vmdk wic.vhdx"
|
||||||
|
|
||||||
WKS_FILE ?= "generic-uefi.wks.in"
|
WKS_FILE ?= "generic-uefi.wks.in"
|
||||||
do_image_wic[depends] += "gptfdisk-native:do_populate_sysroot"
|
do_image_wic[depends] += "gptfdisk-native:do_populate_sysroot"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
CONFIG_HYPERVISOR_GUEST=y
|
||||||
|
CONFIG_PARAVIRT=y
|
||||||
|
CONFIG_PARAVIRT_SPINLOCKS=y
|
||||||
|
CONFIG_CONNECTOR=y
|
||||||
|
CONFIG_SCSI_FC_ATTRS=y
|
||||||
|
CONFIG_HYPERV=y
|
||||||
|
CONFIG_HYPERV_UTILS=y
|
||||||
|
CONFIG_HYPERV_BALLOON=y
|
||||||
|
CONFIG_HYPERV_STORAGE=y
|
||||||
|
CONFIG_HYPERV_NET=y
|
||||||
|
CONFIG_HYPERV_KEYBOARD=y
|
||||||
|
CONFIG_FB_HYPERV=y
|
||||||
|
CONFIG_HID_HYPERV_MOUSE=y
|
||||||
|
CONFIG_PCI_HYPERV=y
|
||||||
|
CONFIG_VSOCKETS=y
|
||||||
|
CONFIG_HYPERV_VSOCKETS=y
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#this file contains the necssary kernel adaption that k3s an containerd require
|
||||||
|
#Reference
|
||||||
|
#k3s config check: https://raw.githubusercontent.com/k3s-io/k3s/master/contrib/util/check-config.sh
|
||||||
|
#container config check: https://raw.githubusercontent.com/moby/moby/master/contrib/check-config.sh
|
||||||
|
#these scripts are provided by moby and rancher
|
||||||
|
CONFIG_OABI_COMPAT=n
|
||||||
|
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
|
||||||
|
CONFIG_SECCOMP_FILTER=y
|
||||||
|
|
@ -1,9 +1,18 @@
|
||||||
|
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
|
||||||
KMACHINE:vm-x64 ?= "common-pc-64"
|
KMACHINE:vm-x64 ?= "common-pc-64"
|
||||||
COMPATIBLE_MACHINE:vm-x64 = "vm-x64"
|
COMPATIBLE_MACHINE:vm-x64 = "vm-x64"
|
||||||
|
|
||||||
# Enable some kernel features related to virtualiuzation
|
# Enable some kernel features related to virtualiuzation
|
||||||
KERNEL_FEATURES:append:vm-x64=" cfg/virtio.scc cfg/paravirt_kvm.scc"
|
KERNEL_FEATURES:append:vm-x64=" cfg/virtio.scc cfg/paravirt_kvm.scc"
|
||||||
|
|
||||||
|
|
||||||
|
KMACHINE:eagle40-03 ?= "common-pc-64"
|
||||||
|
KBRANCH:eagle40-03 = "v5.15/standard/base"
|
||||||
|
SRCREV_machine:eagle40-03 ?= "3baf1c5c0e6084b3f4a1d2d805168d657f872e60"
|
||||||
|
COMPATIBLE_MACHINE:eagle40-03 = "eagle40-03"
|
||||||
|
LINUX_VERSION:eagle40-03 = "5.15.134"
|
||||||
|
|
||||||
|
|
||||||
KBRANCH:beaglebone = "v5.15/standard/beaglebone"
|
KBRANCH:beaglebone = "v5.15/standard/beaglebone"
|
||||||
KMACHINE:beaglebone ?= "beaglebone"
|
KMACHINE:beaglebone ?= "beaglebone"
|
||||||
SRCREV_machine:beaglebone ?= "9aabbaa89fcb21af7028e814c1f5b61171314d5a"
|
SRCREV_machine:beaglebone ?= "9aabbaa89fcb21af7028e814c1f5b61171314d5a"
|
||||||
|
|
@ -11,3 +20,6 @@ COMPATIBLE_MACHINE:beaglebone = "beaglebone"
|
||||||
LINUX_VERSION:beaglebone = "5.15.54"
|
LINUX_VERSION:beaglebone = "5.15.54"
|
||||||
|
|
||||||
require ${@bb.utils.contains("COMBINED_FEATURES", "efi", "linux-yocto-coreos-efi.inc", "", d)}
|
require ${@bb.utils.contains("COMBINED_FEATURES", "efi", "linux-yocto-coreos-efi.inc", "", d)}
|
||||||
|
|
||||||
|
SRC_URI += " file://k3s_kernel_adaptions.cfg"
|
||||||
|
SRC_URI:append:vm-x64 = " file://hyperv.cfg"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
DESCRIPTION = "An image that includes k3s-agent"
|
||||||
|
|
||||||
|
require recipes-core/images/coreos-image-all-features.bb
|
||||||
|
|
||||||
|
IMAGE_INSTALL += "k3s-agent"
|
||||||
|
|
||||||
|
|
@ -69,5 +69,11 @@ def coreos_swupdate_extends(d, s, key):
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
# Signature support
|
||||||
|
inherit coreos-efi-secureboot
|
||||||
|
SWUPDATE_SIGNING = "CMS"
|
||||||
|
SWUPDATE_CMS_KEY = "${COREOS_EFI_SECUREBOOT_KEYDIR}/swupdate.key"
|
||||||
|
SWUPDATE_CMS_CERT = "${COREOS_EFI_SECUREBOOT_KEYDIR}/swupdate.crt"
|
||||||
|
|
||||||
COREOS_IMAGE_SWUPDATE_EXTRACLASSES ?= ""
|
COREOS_IMAGE_SWUPDATE_EXTRACLASSES ?= ""
|
||||||
inherit ${COREOS_IMAGE_SWUPDATE_EXTRACLASSES}
|
inherit ${COREOS_IMAGE_SWUPDATE_EXTRACLASSES}
|
||||||
|
|
|
||||||
|
|
@ -37,3 +37,6 @@ case $ROOT_PARTLABEL in
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
echo "Public key used to verify software image is /usr/lib/swupdate/swupdate.crt"
|
||||||
|
SWUPDATE_ARGS="${SWUPDATE_ARGS} -k /usr/lib/swupdate/swupdate.crt"
|
||||||
|
|
|
||||||
|
|
@ -24,3 +24,7 @@ CONFIG_DISKPART=y
|
||||||
CONFIG_DISKPART_FORMAT=y
|
CONFIG_DISKPART_FORMAT=y
|
||||||
CONFIG_FAT_FILESYSTEM=y
|
CONFIG_FAT_FILESYSTEM=y
|
||||||
CONFIG_EXT_FILESYSTEM=y
|
CONFIG_EXT_FILESYSTEM=y
|
||||||
|
CONFIG_SIGNED_IMAGES=y
|
||||||
|
CONFIG_SIGALG_RAWRSA=n
|
||||||
|
CONFIG_SIGALG_CMS=y
|
||||||
|
CONFIG_CMS_IGNORE_CERTIFICATE_PURPOSE=y
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,12 @@ RRECOMMENDS:${PN} += "${PN}-coreos-config"
|
||||||
# configuration to be installed
|
# configuration to be installed
|
||||||
RCONFLICTS:${PN}-coreos-installer-config = "${PN}-coreos-config"
|
RCONFLICTS:${PN}-coreos-installer-config = "${PN}-coreos-config"
|
||||||
|
|
||||||
|
inherit coreos-efi-secureboot
|
||||||
|
|
||||||
do_install:append() {
|
do_install:append() {
|
||||||
# Probably replace revision with the value of the device tree
|
# Probably replace revision with the value of the device tree
|
||||||
install -m 755 ${WORKDIR}/50-webserver-config.sh ${D}${libdir}/swupdate/conf.d/
|
install -m 755 ${WORKDIR}/50-webserver-config.sh ${D}${libdir}/swupdate/conf.d/
|
||||||
install -m 755 ${WORKDIR}/25-sw-collections-config.sh ${D}${libdir}/swupdate/conf.d/
|
install -m 755 ${WORKDIR}/25-sw-collections-config.sh ${D}${libdir}/swupdate/conf.d/
|
||||||
|
install -m 755 ${COREOS_EFI_SECUREBOOT_KEYDIR}/swupdate.crt ${D}${libdir}/swupdate/
|
||||||
echo "${MACHINE} 1.0" > ${D}${sysconfdir}/hwrevision
|
echo "${MACHINE} 1.0" > ${D}${sysconfdir}/hwrevision
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This script will get development keys needed by the UEFI secure boot
|
||||||
|
# implementation from the k-stufen web share and put the under $BUILDDIR/keys
|
||||||
|
#
|
||||||
|
# The reason for every developer to have the same keys is that image/update
|
||||||
|
# filest are interchangable.
|
||||||
|
# Those developer keys are used for all builds except the ones that are marked
|
||||||
|
# as final. Here the official keys will be used.
|
||||||
|
#
|
||||||
|
# Following keys will be downloaded
|
||||||
|
# db.auth db.der db.key KEK.crt KEK.esl PK.auth PK.der PK.key
|
||||||
|
# db.crt db.esl KEK.auth KEK.der KEK.key PK.crt PK.esl
|
||||||
|
|
||||||
|
# This script is used every time the build environment of CoreOS is sourced
|
||||||
|
# Note: in the build environment stdout is redirected to /dev/null but not
|
||||||
|
# stderr.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Logging helper
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
RESET='\033[0m'
|
||||||
|
|
||||||
|
# Ensure that BUILDDIR is defined
|
||||||
|
# ==============================================================================
|
||||||
|
# This is usually done inside the coreos-init-build-env script
|
||||||
|
|
||||||
|
|
||||||
|
if [ -z "$BUILDDIR" ]; then
|
||||||
|
echo -e "${RED}BUILDDIR is not defined${RESET}" 2>&1
|
||||||
|
echo -e "Have you run the coreos-init-buildenv script?" 2>&1
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We need the KEYDIR directory to exist
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
KEYDIR="${BUILDDIR}/keys"
|
||||||
|
mkdir -p "${KEYDIR}"
|
||||||
|
cd "${KEYDIR}"
|
||||||
|
|
||||||
|
# we need wget and tar
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
assert_command_in_path() {
|
||||||
|
if command -v "$1" >/dev/null 2>&1; then
|
||||||
|
echo -e "✓ Command ${GREEN}${1}${RESET} was found"
|
||||||
|
else
|
||||||
|
echo -e "✗ ${RED}Command ${BOLD}${1}${RESET}${RED} was not found in your path${RESET}" >&2
|
||||||
|
echo -e "Please check the coreos-documentation for the list of required packages" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_command_in_path wget
|
||||||
|
assert_command_in_path tar
|
||||||
|
|
||||||
|
|
||||||
|
# Generate all they keys, as needed
|
||||||
|
# ==============================================================================
|
||||||
|
# Only generate the file if it's missing and don't fail if the file already
|
||||||
|
# exist
|
||||||
|
|
||||||
|
check_files_exist() {
|
||||||
|
RET=0
|
||||||
|
for file in "$@"; do
|
||||||
|
if [ ! -e "$file" ]; then
|
||||||
|
echo -e "𐄂 File ${RED}${file}${RESET} missing"
|
||||||
|
RET=1
|
||||||
|
else
|
||||||
|
echo -e "✓ File ${GREEN}${file}${RESET} already exist"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return $RET
|
||||||
|
}
|
||||||
|
|
||||||
|
check_files_exist db.auth db.crt db.der db.esl db.key KEK.auth KEK.crt KEK.der \
|
||||||
|
KEK.esl KEK.key PK.auth PK.crt PK.der PK.esl PK.key || \
|
||||||
|
{
|
||||||
|
echo -e "${RED}Incosistent or no keys.${RESET}"
|
||||||
|
echo "Downloading Keys"
|
||||||
|
wget -q https://platform-nas.gad.local/K-Stufen/CoreOS/.signing/coreos_developer_signing.keys.tar.gz && \
|
||||||
|
tar -xzf coreos_developer_signing.keys.tar.gz -C ${BUILDDIR}/keys && \
|
||||||
|
rm coreos_developer_signing.keys.tar.gz
|
||||||
|
}
|
||||||
|
|
@ -58,13 +58,16 @@ assert_command_in_path sign-efi-sig-list
|
||||||
# exist
|
# exist
|
||||||
|
|
||||||
check_files_exist() {
|
check_files_exist() {
|
||||||
|
RET=0
|
||||||
for file in "$@"; do
|
for file in "$@"; do
|
||||||
echo -e "✓ File ${GREEN}${file}${RESET} already exist"
|
|
||||||
if [ ! -e "$file" ]; then
|
if [ ! -e "$file" ]; then
|
||||||
return 1
|
echo -e "𐄂 File ${RED}${file}${RESET} missing"
|
||||||
|
RET=1
|
||||||
|
else
|
||||||
|
echo -e "✓ File ${GREEN}${file}${RESET} already exist"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
return 0
|
return $RET
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "Generating private/public keys in .key/.crt format for PK, KEK et db"
|
echo "Generating private/public keys in .key/.crt format for PK, KEK et db"
|
||||||
|
|
@ -108,3 +111,7 @@ echo "Generatic DER files with PK, KEK et db public key"
|
||||||
check_files_exist PK.der || openssl x509 -in PK.crt -outform der -out PK.der
|
check_files_exist PK.der || openssl x509 -in PK.crt -outform der -out PK.der
|
||||||
check_files_exist KEK.der || openssl x509 -in KEK.crt -outform der -out KEK.der
|
check_files_exist KEK.der || openssl x509 -in KEK.crt -outform der -out KEK.der
|
||||||
check_files_exist db.der || openssl x509 -in db.crt -outform der -out db.der
|
check_files_exist db.der || openssl x509 -in db.crt -outform der -out db.der
|
||||||
|
|
||||||
|
# keys needed to sign and verify SWUpdate
|
||||||
|
check_files_exist swupdate.key swupdate.crt || openssl req -x509 -newkey rsa:4096 -nodes -keyout swupdate.key \
|
||||||
|
-out swupdate.crt -subj "/O=SWUpdate /CN=target"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue