Compare commits

..

10 Commits

Author SHA1 Message Date
Patrick Vogelaar af231dc92e feat: add common developer keys for signed firmware
To make images compatible with each other for development a comon set of keys
will be used. The keys are located on k-stufen.

* add script to download and extract keys
* adjustments to coreos-init-build-env script
* adjustments to check_files_exist function
2023-11-14 17:57:00 +01:00
Patrick Vogelaar 2058525bc2 refactor(eagle40-03): rename MACHINE from eagle40_03 to eagle40-03 2023-11-14 17:57:00 +01:00
Samuel Dolt 52531c53c9 feat(swupdate): add signature support
BREAKING CHANGE: Unsigned .swu file will now be rejected by swupdate
2023-11-14 17:57:00 +01:00
Patrick Vogelaar 67de892b2a feat(eagle40_03): integrate EAGLE40-03
* add basic config for EAGLE40.03
* purely based on uefi -> no uboot

NOTE: The board only boots so far. No in depth testing has been done yet.
2023-11-14 17:57:00 +01:00
Samuel Dolt 45f49687f3 feat(vm-x64): add Microsoft Hyper-V suport 2023-11-14 17:57:00 +01:00
Patrick Vogelaar d3e8dd770c refactor(partitions.inc): use variable for kernel in wks file 2023-11-14 17:57:00 +01:00
Uli Stein 0916a74007 feat(k3s): image that installs the k3s-agent
the changed image is
layers/meta-belden-coreos-demo/recipes-core/image/cores-image-demo-k3s
k3s is a orchestration tool and a slimed down version of kubernetes
k3s agent is a tool to control pods
the commands come a k3s server in a cluster
2023-11-14 17:57:00 +01:00
Uli Stein 112694c8e5 feat(linux-yocto_5.15): add kernel config for k3s
disable oabi compatibility it to solve seccomp conflict
enable seccomp filter
secccomp filter is needed for k3s to pawn pods
2023-11-14 17:57:00 +01:00
Samuel Dolt 22a7ef2d6e docs(secure-boot): add a secure boot concept to the doc 2023-11-14 17:57:00 +01:00
Samuel Dolt 89549c285c docs(bats): add info on how to use bats 2023-11-14 17:57:00 +01:00
21 changed files with 876 additions and 12 deletions

View File

@ -87,10 +87,23 @@ coreos-bblayers-envsub COREOS_LAYERSDIR "${COREOS_ROOT}/layers"
# Add support for ##COREOS_EXTLAYERSDIR## inside of bblayer template
coreos-bblayers-envsub COREOS_EXTLAYERSDIR "${COREOS_ROOT}/external-layers"
# Generate the ${BUILDDIR}/key directory. The scripts doesn't generate anything it
# the directory already exist, so it's safe to call it everytime
# Generate the ${BUILDDIR}/key directory. The scripts doesn't generate anything
# 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
coreos-keygen > /dev/null || {
echo "The coreos-keygen script has failed" >&2
return 1
}
#
#Note: if a final build is detected all the dev keys are deleted
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

7
documentation/.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"recommendations": [
"ms-vscode.makefile-tools",
"lextudio.restructuredtext",
"trond-snekvik.simple-rst"
]
}

12
documentation/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"files.watcherExclude": {
"**/_build/**": true,
},
"python.formatting.provider": "black",
"editor.rulers": [
80,
100,
120
],
"esbonio.sphinx.confDir": ""
}

View File

@ -11,3 +11,4 @@ Belden CoreOS Boot Concepts
overview
uboot
secure-boot

View File

@ -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"];
}

View File

@ -40,6 +40,7 @@ same structures.
Installation Manual <installation/index>
Reference Manual <ref-manual/index>
Testing Manual <testing/index>
Boot Concepts <boot/index>
Best Practices <best_practices/index>

View File

@ -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&#39; 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

View File

@ -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

View File

@ -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

View File

@ -2,8 +2,8 @@
# Variable used in WKS file
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_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_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=${COREOS_KERNEL_FILENAME};KERNEL.EFI"'
WKS_PART_ROOT_A ??= 'part / --source rootfs --fstype=ext4 --label rootfs0'
WKS_PART_ROOT_B ??= 'part --fstype=ext4 --label rootfs1'
WKS_PART_ROOT_SIZE ??= '2G'

View File

@ -11,7 +11,7 @@ PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto"
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"
do_image_wic[depends] += "gptfdisk-native:do_populate_sysroot"

View File

@ -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

View File

@ -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

View File

@ -1,9 +1,18 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
KMACHINE:vm-x64 ?= "common-pc-64"
COMPATIBLE_MACHINE:vm-x64 = "vm-x64"
# Enable some kernel features related to virtualiuzation
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"
KMACHINE:beaglebone ?= "beaglebone"
SRCREV_machine:beaglebone ?= "9aabbaa89fcb21af7028e814c1f5b61171314d5a"
@ -11,3 +20,6 @@ COMPATIBLE_MACHINE:beaglebone = "beaglebone"
LINUX_VERSION:beaglebone = "5.15.54"
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"

View File

@ -0,0 +1,6 @@
DESCRIPTION = "An image that includes k3s-agent"
require recipes-core/images/coreos-image-all-features.bb
IMAGE_INSTALL += "k3s-agent"

View File

@ -69,5 +69,11 @@ def coreos_swupdate_extends(d, s, key):
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 ?= ""
inherit ${COREOS_IMAGE_SWUPDATE_EXTRACLASSES}

View File

@ -37,3 +37,6 @@ case $ROOT_PARTLABEL in
exit 1
;;
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"

View File

@ -24,3 +24,7 @@ CONFIG_DISKPART=y
CONFIG_DISKPART_FORMAT=y
CONFIG_FAT_FILESYSTEM=y
CONFIG_EXT_FILESYSTEM=y
CONFIG_SIGNED_IMAGES=y
CONFIG_SIGALG_RAWRSA=n
CONFIG_SIGALG_CMS=y
CONFIG_CMS_IGNORE_CERTIFICATE_PURPOSE=y

View File

@ -37,9 +37,12 @@ RRECOMMENDS:${PN} += "${PN}-coreos-config"
# configuration to be installed
RCONFLICTS:${PN}-coreos-installer-config = "${PN}-coreos-config"
inherit coreos-efi-secureboot
do_install:append() {
# 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}/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
}

88
scripts/coreos-get-dev-keys Executable file
View File

@ -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
}

View File

@ -58,13 +58,16 @@ assert_command_in_path sign-efi-sig-list
# exist
check_files_exist() {
RET=0
for file in "$@"; do
echo -e "✓ File ${GREEN}${file}${RESET} already exist"
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
done
return 0
return $RET
}
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 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
# 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"