summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Vacek <patrickvacek@gmail.com>2019-01-29 16:39:03 +0100
committerGitHub <noreply@github.com>2019-01-29 16:39:03 +0100
commit809f438a498ba5cef59133541629dfff73346ad1 (patch)
tree1709cf3d5e92ca2789e668dfb6bdd70bffd4981a
parente3b7ea2133d0705b7e4e3ec1bb681df069fdd59e (diff)
parentc7236fe0bfeab1166addca2d3dd2096936b0fb9c (diff)
downloadmeta-updater-809f438a498ba5cef59133541629dfff73346ad1.tar.gz
Merge pull request #450 from leon-anavi/morty
Backporting latest Aktualizr to branch Morty
-rw-r--r--.gitignore1
-rw-r--r--CONTRIBUTING.adoc28
-rw-r--r--README.adoc166
-rw-r--r--classes/image_repo_manifest.bbclass23
-rw-r--r--classes/image_types_ostree.bbclass411
-rw-r--r--classes/image_types_ota.bbclass41
-rw-r--r--classes/sota.bbclass31
-rw-r--r--classes/sota_qemux86-64.bbclass2
-rw-r--r--classes/target_version_example.bbclass10
-rw-r--r--recipes-crypto/libsodium/libsodium_1.%.bbappend1
-rw-r--r--recipes-sota/aktualizr/aktualizr-auto-prov-creds.bb24
-rw-r--r--recipes-sota/aktualizr/aktualizr-auto-prov.bb43
-rw-r--r--recipes-sota/aktualizr/aktualizr-ca-implicit-prov-creds.bb51
-rw-r--r--recipes-sota/aktualizr/aktualizr-ca-implicit-prov.bb31
-rw-r--r--recipes-sota/aktualizr/aktualizr-hsm-prov.bb28
-rw-r--r--recipes-sota/aktualizr/aktualizr-uboot-env-rollback.bb19
-rwxr-xr-x[-rw-r--r--]recipes-sota/aktualizr/aktualizr_git.bb139
-rw-r--r--recipes-sota/aktualizr/credentials.inc1
-rw-r--r--recipes-sota/aktualizr/files/aktualizr-autoprovision.service13
-rw-r--r--recipes-sota/aktualizr/files/aktualizr-manual-provision.service13
-rw-r--r--recipes-sota/aktualizr/files/aktualizr-secondary.service8
-rw-r--r--recipes-sota/aktualizr/files/aktualizr-secondary.socket6
-rw-r--r--recipes-sota/aktualizr/files/aktualizr-serialcan.service15
-rw-r--r--recipes-sota/aktualizr/files/aktualizr.service11
-rw-r--r--recipes-sota/aktualizr/files/ca.cnf10
-rw-r--r--recipes-sota/aktualizr/files/sota_autoprov.toml14
-rw-r--r--recipes-sota/aktualizr/garage-sign-version.inc36
-rw-r--r--recipes-sota/asn1c/asn1c.bb17
-rw-r--r--recipes-sota/asn1c/files/skeletons_dir_fix.patch44
-rw-r--r--recipes-sota/config/aktualizr-disable-send-ip.bb22
-rw-r--r--recipes-sota/config/aktualizr-log-debug.bb22
-rw-r--r--recipes-sota/config/files/05-log-debug.toml2
-rw-r--r--recipes-sota/config/files/30-disable-send-ip.toml2
-rw-r--r--recipes-sota/ostree-initrd/files/init.sh2
-rw-r--r--recipes-sota/ostree/ostree_git.bb87
-rw-r--r--recipes-support/libp11/files/0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch42
-rw-r--r--recipes-support/libp11/libp11_0.4.9.bb39
-rw-r--r--recipes-support/slcand-start/files/slcand@.service8
-rw-r--r--recipes-support/slcand-start/slcand-start.bb21
-rw-r--r--recipes-support/softhsm-testtoken/files/createtoken.service12
-rw-r--r--recipes-support/softhsm-testtoken/files/createtoken.sh27
-rw-r--r--recipes-support/softhsm-testtoken/softhsm-testtoken.bb25
-rw-r--r--recipes-support/softhsm/files/0001-Cross-compilation-tweaks.patch86
-rw-r--r--recipes-support/softhsm/softhsm_git.bb27
-rw-r--r--recipes-test/demo-network-config/files/25-dhcp-server.network12
-rw-r--r--recipes-test/demo-network-config/files/26-dhcp-client.network6
-rw-r--r--recipes-test/demo-network-config/files/27-dhcp-client-external.network6
-rw-r--r--recipes-test/demo-network-config/primary-network-config.bb16
-rw-r--r--recipes-test/demo-network-config/secondary-network-config.bb20
-rw-r--r--recipes-test/images/primary-image.bb14
-rw-r--r--recipes-test/images/secondary-image.bb27
-rw-r--r--scripts/qemucommand.py132
-rwxr-xr-xscripts/run-qemu-ota132
53 files changed, 1570 insertions, 456 deletions
diff --git a/.gitignore b/.gitignore
index bee8a64..8d35cb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
1__pycache__ 1__pycache__
2*.pyc
diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc
new file mode 100644
index 0000000..4d9e8f6
--- /dev/null
+++ b/CONTRIBUTING.adoc
@@ -0,0 +1,28 @@
1= Contributing
2
3We welcome pull requests from anyone. The master branch is the primary branch for development, and if you wish to add new functionality, it probably belongs there. We attempt to maintain recent previous branches and welcome bug fixes and backports for those. Currently, the actively maintained branches are:
4
5* thud
6* sumo
7* rocko
8
9Previously, some older branches were also regularly supported, and while they should still be stable, they have not been updated or actively maintained for a while. These branches include:
10
11* pyro
12* morty
13
14If you are developing with meta-updater, it may be helpful to read the README and other documentation for link:README.adoc[this repo], https://github.com/advancedtelematic/aktualizr[aktualizr], and the https://github.com/advancedtelematic/updater-repo/[updater-repo], particularly the sections about development and debugging.
15
16== Contributor checklist
17
18* OTA-enabled build succeeds for at least one platform, the resulting image boots, and an update can be installed. This check is absolutely necessary for every pull request unless it only touches documentation.
19* If your change touches platform code (like `classes/sota_<platform>.bbclass`), please check building and updating on this particular platform.
20* oe-selftest succeeds. To test meta-updater, run `oe-selftest -r updater` from a build directory with `MACHINE` set to `qemux86-64`. See the link:README.adoc#qa-with-oe-selftest[relevant section of the README] for more details.
21* Updates are forwards- and backwards-compatible. You should be able to update an OTA-enabled build before the change is applied to the version with change applied and vice versa. One should pay double attention to the compatibility when bootloader code is affected.
22* The patch/branch should be based on the latest version of the target branch. This may mean that rebasing is necessary if other PRs are merged before yours is approved.
23
24We understand that completing all these tasks might be overly tedious due to build times in Yocto. Please add a comment to your PR describing the tests you've done.
25
26== Approval
27
28PR approval should be accompanied by a comment describing what tests have been done by the reviewer.
diff --git a/README.adoc b/README.adoc
index 9615f65..32630d7 100644
--- a/README.adoc
+++ b/README.adoc
@@ -1,28 +1,33 @@
1= meta-updater 1= meta-updater
2:toc: macro
3:toc-title:
2 4
3This layer enables over-the-air updates (OTA) with https://github.com/ostreedev/ostree[OSTree] and https://github.com/advancedtelematic/rvi_sota_client[RVI SOTA client]. 5This layer enables over-the-air updates (OTA) with https://github.com/ostreedev/ostree[OSTree] and https://github.com/advancedtelematic/aktualizr[Aktualizr].
4 6
5https://github.com/ostreedev/ostree[OSTree] is a tool for atomic full file system upgrades with rollback capability. OSTree has several advantages over traditional dual-bank systems, but the most important one is that it minimizes network bandwidth and data storage footprint by sharing files with the same contents across file system deployments. 7https://github.com/ostreedev/ostree[OSTree] is a tool for atomic full file system upgrades with rollback capability. OSTree has several advantages over traditional dual-bank systems, but the most important one is that it minimizes network bandwidth and data storage footprint by sharing files with the same contents across file system deployments.
6 8
7https://github.com/advancedtelematic/rvi_sota_client[RVI SOTA client] and/or https://github.com/advancedtelematic/aktualizr[aktualizr] add authentication and provisioning capabilities to OTA and are integrated with OSTree. You can connect with the open-source https://github.com/advancedtelematic/rvi_sota_server[RVI SOTA server] or sign up for a free account at https://app.atsgarage.com[ATS Garage] to get started. 9https://github.com/advancedtelematic/aktualizr[Aktualizr] (and https://github.com/advancedtelematic/rvi_sota_client[RVI SOTA client]) add authentication and provisioning capabilities to OTA and are integrated with OSTree. You can connect with these open-source applications or sign up for a free account at https://connect.ota.here.com/[HERE OTA Connect] to get started.
10
11[discrete]
12== Table of Contents
13
14toc::[]
8 15
9== Build 16== Build
10 17
11=== Quickstart 18=== Quickstart
12 19
13If you don't already have a Yocto project that you want to add OTA to, you can use the https://docs.atsgarage.com/quickstarts/raspberry-pi.html[ATS Garage Quickstart] project to rapidly get up and running on a Raspberry Pi. It takes a standard https://www.yoctoproject.org/tools-resources/projects/poky[poky] distribution, and adds OTA and OSTree capabilities. 20If you don't already have a Yocto project that you want to add OTA to, you can use the https://docs.atsgarage.com/quickstarts/raspberry-pi.html[HERE OTA Connect Quickstart] project to rapidly get up and running on a Raspberry Pi. It takes a standard https://www.yoctoproject.org/tools-resources/projects/poky[poky] distribution, and adds OTA and OSTree capabilities.
14 21
15=== Adding meta-updater capabilities to your build 22=== Adding meta-updater capabilities to your build
16 23
17If you already have a Yocto-based project and you want to add atomic filesystem updates to it, you just need to do three things: 24If you already have a Yocto-based project and you want to add atomic filesystem updates to it, you just need to do three things:
18 25
191. Clone the `meta-updater` layer and add it to your https://www.yoctoproject.org/docs/2.1/ref-manual/ref-manual.html#structure-build-conf-bblayers.conf[bblayers.conf]. 261. Clone the `meta-updater` layer and add it to your https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#structure-build-conf-bblayers.conf[bblayers.conf].
202. Clone BSP integration layer (meta-updater-$\{PLATFORM}, e.g. https://github.com/advancedtelematic/meta-updater-raspberrypi[meta-updater-raspberrypi]) and add it to your conf/bblayers.conf. If your board isn't supported yet, you could write a BSP integration for it yourself. See the <<Adding support for your board>> section for the details. 272. Clone BSP integration layer (`meta-updater-$\{PLATFORM}`, e.g. https://github.com/advancedtelematic/meta-updater-raspberrypi[meta-updater-raspberrypi]) and add it to your `conf/bblayers.conf`. If your board isn't supported yet, you could write a BSP integration for it yourself. See the <<Adding support for your board>> section for the details.
213. Set up your https://www.yoctoproject.org/docs/2.1/ref-manual/ref-manual.html#var-DISTRO[distro]. If you are using "poky", the default distro in Yocto, you can change it in your conf/local.conf to "poky-sota". Alternatively, if you are using your own or third party distro configuration, you can add 'INHERIT += " sota"' to it, thus combining capabilities of your distro with meta-updater features. 283. Set up your https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-DISTRO[distro]. If you are using "poky", the default distro in Yocto, you can change it in your `conf/local.conf` to "poky-sota". Alternatively, if you are using your own or third party distro configuration, you can add `INHERIT += " sota"` to it, thus combining capabilities of your distro with meta-updater features.
22
23You can then build your image as usual, with bitbake. After building the root file system, bitbake will then create an https://ostree.readthedocs.io/en/latest/manual/adapting-existing/[OSTree-enabled version] of it, commit it to your local OSTree repo and (optionally) push it to a remote server. Additionally, a live disk image will be created (normally named $\{IMAGE_NAME}.-sdimg-ota e.g. core-image-raspberrypi3.rpi-sdimg-ota). You can control this behaviour through <<variables in your local.conf,OSTree-related variables in your local.conf>>.
24 29
25=== Build with OpenIVI 30You can then build your image as usual, with bitbake. After building the root file system, bitbake will then create an https://ostree.readthedocs.io/en/latest/manual/adapting-existing/[OSTree-enabled version] of it, commit it to your local OSTree repo and (optionally) push it to a remote server. Additionally, a live disk image will be created (normally named `$\{IMAGE_NAME}.-sdimg-ota` e.g. `core-image-raspberrypi3.rpi-sdimg-ota`). You can control this behaviour through <<sota-related-variables-in-localconf,variables in your local.conf>>.
26 31
27=== Build in AGL 32=== Build in AGL
28 33
@@ -32,19 +37,23 @@ With AGL you can just add agl-sota feature while configuring your build environm
32source meta-agl/scripts/aglsetup.sh -m porter agl-demo agl-appfw-smack agl-devel agl-sota 37source meta-agl/scripts/aglsetup.sh -m porter agl-demo agl-appfw-smack agl-devel agl-sota
33.... 38....
34 39
35you can then run 40You can then run:
36 41
37.... 42....
38bitbake agl-demo-platform 43bitbake agl-demo-platform
39.... 44....
40 45
41and get as a result an "ostree_repo" folder in your images directory (tmp/deploy/images/$\{MACHINE}/ostree_repo). It will contain 46and get as a result an `ostree_repo` folder in your images directory (`tmp/deploy/images/$\{MACHINE}/ostree_repo`). It will contain:
42 47
43* your OSTree repository, with the rootfs committed as an OSTree deployment, 48* your OSTree repository, with the rootfs committed as an OSTree deployment,
44* an 'otaimg' bootstrap image, which is an OSTree physical sysroot as a burnable filesystem image, and optionally 49* an `otaimg` bootstrap image, which is an OSTree physical sysroot as a burnable filesystem image, and optionally
45* some machine-dependent live images (e.g. '_.rpi-sdimg-ota' for Raspberry Pi or '_.porter-sdimg-ota' Renesas Porter board). 50* some machine-dependent live images (e.g. `.wic` for Raspberry Pi or `.porter-sdimg-ota` Renesas Porter board).
51
52Although `aglsetup.sh` hooks provide reasonable defaults for SOTA-related variables, you may want to tune some of them.
53
54=== Build problems
46 55
47Although aglsetup.sh hooks provide reasonable defaults for SOTA-related variables, you may want to tune some of them. 56Ubuntu users that encounter an error due to missing `Python.h` should install `libpython2.7-dev` on their host machine.
48 57
49== Supported boards 58== Supported boards
50 59
@@ -67,35 +76,39 @@ Although we have used U-Boot so far, other boot loaders can be configured work w
67 76
68== SOTA-related variables in local.conf 77== SOTA-related variables in local.conf
69 78
70* OSTREE_REPO - path to your OSTree repository. Defaults to "$\{DEPLOY_DIR_IMAGE}/ostree_repo" 79* `OSTREE_REPO` - path to your OSTree repository. Defaults to `$\{DEPLOY_DIR_IMAGE}/ostree_repo`
71* OSTREE_BRANCHNAME - the branch your rootfs will be committed to. Defaults to "ota" 80* `OSTREE_OSNAME` - OS deployment name on your target device. For more information about deployments and osnames see the https://ostree.readthedocs.io/en/latest/manual/deployment/[OSTree documentation]. Defaults to "poky".
72* OSTREE_OSNAME - OS deployment name on your target device. For more information about deployments and osnames see the https://ostree.readthedocs.io/en/latest/manual/deployment/[OSTree documentation]. Defaults to "poky". 81* `OSTREE_INITRAMFS_IMAGE` - initramfs/initrd image that is used as a proxy while booting into OSTree deployment. Do not change this setting unless you are sure that your initramfs can serve as such a proxy.
73* OSTREE_INITRAMFS_IMAGE - initramfs/initrd image that is used as a proxy while booting into OSTree deployment. Do not change this setting unless you are sure that your initramfs can serve as such a proxy. 82* `SOTA_PACKED_CREDENTIALS` - when set, your ostree commit will be pushed to a remote repo as a bitbake step. This should be the path to a zipped credentials file in https://github.com/advancedtelematic/aktualizr/blob/master/docs/credentials.adoc[the format accepted by garage-push].
74* OSTREE_PUSH_CREDENTIALS - when set, your ostree commit will be pushed to a remote repo as a bitbake step. This should be the path to a JSON credentials file in https://github.com/advancedtelematic/sota-tools#credentials[the format accepted by garage-push]. 83* `SOTA_DEPLOY_CREDENTIALS` - when set to '1' (default value), deploys credentials to the built image. Override it in `local.conf` to built a generic image that can be provisioned manually after the build.
84* `SOTA_CLIENT_PROV` - which provisioning method to use. Valid options are https://github.com/advancedtelematic/aktualizr/blob/master/docs/automatic-provisioning.adoc[`aktualizr-auto-prov`], https://github.com/advancedtelematic/aktualizr/blob/master/docs/implicit-provisioning.adoc[`aktualizr-ca-implicit-prov`], and https://github.com/advancedtelematic/aktualizr/blob/master/docs/hsm-provisioning.adoc[`aktualizr-hsm-prov`]. The default is `aktualizr-auto-prov`. This can also be set to an empty string to avoid using a provisioning recipe.
85* `SOTA_CLIENT_FEATURES` - extensions to aktualizr. The only valid options are `hsm` (to build with HSM support) and `secondary-network` (to set up a simulated 'in-vehicle' network with support for a primary node with a DHCP server and a secondary node with a DHCP client).
86* `SOTA_SECONDARY_CONFIG_DIR` - a directory containing JSON configuration files for virtual secondaries on the host. These will be installed into `/etc/sota/ecus` on the device and automatically provided to aktualizr.
87* `SOTA_HARDWARE_ID` - a custom hardware ID that will be written to the aktualizr config. Defaults to MACHINE if not set.
75 88
76== Usage 89== Usage
77 90
78=== OSTree 91=== OSTree
79 92
80OSTree includes its own simple http server. It just exposes the whole OSTree repository to the network so that any remote device can pull data from it to device's local repository. To use the OSTree http server, you will need OSTree installed on your build machine. (Alternatively, you could run version built inside Yocto using bitbake's http://www.openembedded.org/wiki/Devshell[devshell].) 93OSTree used to include a simple HTTP server as part of the ostree binary, but this has been removed in more recent versions. However, OSTree repositories are self-contained directories, and can be trivially served over the network using any HTTP server. For example, you could use Python's SimpleHTTPServer:
81
82To expose your repo, run ostree trivial-httpd using any free port:
83 94
84.... 95....
85ostree trivial-httpd tmp/deploy/images/qemux86-64/ostree_repo -P 57556 96cd tmp/deploy/images/qemux86-64/ostree_repo
97python -m SimpleHTTPServer <port> # port defaults to 8000
86.... 98....
87 99
88You can then run ostree from inside your device by adding your repo: 100You can then run ostree from inside your device by adding your repo:
89 101
90.... 102....
91# agl-remote identifies the remote server in your local repo 103# This behaves like adding a Git remote; you can name it anything
92ostree remote add --no-gpg-verify my-remote http://192.168.7.1:57556 ota 104ostree remote add --no-gpg-verify my-remote http://<your-ip>:<port>
93 105
94# ota is a branch name in the remote repo, set in OSTREE_BRANCHNAME 106# If OSTREE_BRANCHNAME is set in local.conf, that will be the name of the
95ostree pull my-remote ota 107# branch. If not set, it defaults to the value of MACHINE (e.g. qemux86-64).
108ostree pull my-remote <branch>
96 109
97# poky is OS name as set in OSTREE_OSNAME 110# poky is the OS name as set in OSTREE_OSNAME
98ostree admin deploy --os=poky my-remote:ota 111ostree admin deploy --os=poky my-remote:<branch>
99.... 112....
100 113
101After restarting, you will boot into the newly deployed OS image. 114After restarting, you will boot into the newly deployed OS image.
@@ -113,12 +126,99 @@ ostree pull agl-snapshot agl-ota
113ostree admin deploy --os=agl agl-snapshot:agl-ota 126ostree admin deploy --os=agl agl-snapshot:agl-ota
114.... 127....
115 128
116=== SOTA tools 129=== garage-push
117 130
118SOTA tools currently contains only one tool, garage-push, which lets you push the changes in OSTree repository generated by bitbake process. It communicates with an http server capable of querying files with HEAD requests and uploading them with POST requests. In particular, this can be used with http://www.atsgarage.com/[ATS Garage]. garage-push is used as follows: 131The https://github.com/advancedtelematic/aktualizr[aktualizr repo] contains a tool, garage-push, which lets you push the changes in OSTree repository generated by bitbake process. It communicates with an http server capable of querying files with HEAD requests and uploading them with POST requests. In particular, this can be used with https://connect.ota.here.com/[HERE OTA Connect]. garage-push is used as follows:
119 132
120.... 133....
121garage-push --repo=/path/to/ostree-repo --ref=mybranch --credentials=/path/to/credentials.json 134garage-push --repo=/path/to/ostree-repo --ref=mybranch --credentials=/path/to/credentials.zip
122.... 135....
123 136
124You can set OSTREE_PUSH_CREDENTIALS in your local.conf to make your build results be automatically synchronized with a remote server. Credentials are stored in the JSON format described in the https://github.com/advancedtelematic/sota-tools#credentials[sota-tools README]. 137You can set `SOTA_PACKED_CREDENTIALS` in your `local.conf` to automatically synchronize your build results with a remote server. Credentials are stored in an archive as described in the https://github.com/advancedtelematic/aktualizr/blob/master/docs/credentials.adoc[aktualizr documentation].
138
139=== aktualizr configuration
140
141https://github.com/advancedtelematic/aktualizr[Aktualizr] supports a variety of https://github.com/advancedtelematic/aktualizr/blob/master/docs/configuration.adoc[configuration options via a configuration file and the command line]. There are two primary ways to control aktualizr's configuration from meta-updater.
142
143First, you can set `SOTA_CLIENT_PROV` to control which provisioning recipe is used. Each recipe installs an appropriate `sota.toml` file from aktualizr according to the provisioning needs. See the <<sota-related-variables-in-localconf,SOTA-related variables in local.conf>> section for more information.
144
145Second, you can write recipes to install additional config files with customized options. A few recipes already exist to address common needs and provide an example:
146
147* link:recipes-sota/config/aktualizr-disable-send-ip.bb[aktualizr-disable-send-ip.bb] disables the reporting of networking information to the server. This is enabled by default and supported by https://connect.ota.here.com/[HERE OTA Connect]. However, if you are using a different server that does not support this feature, you may want to disable it in aktualizr.
148* link:recipes-sota/config/aktualizr-log-debug.bb[aktualizr-log-debug.bb] sets the log level of aktualizr to 0 (trace). The default is 2 (info). This recipe is intended for development and debugging purposes.
149
150To use these recipes, you will need to add them to your image with a line such as `IMAGE_INSTALL_append = " aktualizr-log-debug "` in your `local.conf`.
151
152== Development configuration
153
154There are a few settings that can be controlled in `local.conf` to simplify the development process:
155
156[options="header"]
157|======================
158| Option | Effect
159| `require classes/sota_bleeding.inc` | Build the latest head (by default, using the master branch) of Aktualizr
160| `BRANCH_pn-aktualizr = "mybranch"`
161
162`BRANCH_pn-aktualizr-native = "mybranch"` | Build `mybranch` of Aktualizr. Note that both of these need to be set. This is normally used in conjunction with `require classes/sota_bleeding.inc`
163| `SRCREV_pn-aktualizr = "1004efa3f86cef90c012b34620992b5762b741e3"`
164
165`SRCREV_pn-aktualizr-native = "1004efa3f86cef90c012b34620992b5762b741e3"` | Build the specified revision of Aktualizr. Note that both of these need to be set. This can be used in conjunction with `BRANCH_pn-aktualizr` and `BRANCH_pn-aktualizr-native` but will conflict with `require classes/sota_bleeding.inc`
166| `TOOLCHAIN_HOST_TASK_append = " nativesdk-cmake "` | Use with `bitbake -c populate_sdk core-image-minimal` to build an SDK. See the https://github.com/advancedtelematic/aktualizr#developing-against-an-openembedded-system[aktualizr repo] for more information.
167|======================
168
169=== Overriding target version
170*Warning: overriding target version is a dangerous operation, make sure you understand this section completely before doing it.*
171
172Every time you build an image with `SOTA_PACKED_CREDENTIALS` set, a new entry in your Uptane metadata is created and you can see it in the OTA Garage UI if you're using one. Normally this version will be equal to OSTree hash of your root file system. If you want it to be different though you can override is using one of two methods:
173
1741. Set `GARAGE_TARGET_VERSION` variable in your `local.conf`.
1752. Write a recipe or a bbclass to write the desired version to `${STAGING_DATADIR_NATIVE}/target_version`. An example of such bbclass can be found in `classes/target_version_example.bbclass`.
176
177Please note that [target name, target version] pairs are expected to be unique in the system. If you build a new target with the same target version as a previously built one, the old package will be overwritten on the update server. It can have unpredictable effect on devices that have this version installed, and it is not guaranteed that information will be reported correctly for such devices or that you will be able to update them (we're doing our best though). The easiest way to avoid problems is to make sure that your overriding version is as unique as an OSTree commit hash.
178
179== QA with oe-selftest
180
181This layer relies on the test framework oe-selftest for quality assurance. Currently, you will need to run this in a build directory with `MACHINE` set to `qemux86-64`. Follow the steps below to run the tests:
182
1831. Append the line below to `conf/local.conf` to disable the warning about supported operating systems:
184+
185```
186SANITY_TESTED_DISTROS = ""
187```
188
1892. If your image does not already include an ssh daemon such as dropbear or openssh, add this line to `conf/local.conf` as well:
190+
191```
192IMAGE_INSTALL_append = " dropbear "
193```
194
1953. Some tests require that `SOTA_PACKED_CREDENTIALS` is set in your `conf/local.conf`. See the <<sota-related-variables-in-localconf,SOTA-related variables in local.conf>> section.
196
1974. To be able to build an image for the grub tests, you will need to install https://github.com/tianocore/tianocore.github.io/wiki/OVMF[TianoCore's ovmf] package on your host system. On Debian-like systems, you can do so with this command:
198+
199```
200sudo apt install ovmf
201```
202
2035. Run oe-selftest:
204+
205```
206oe-selftest --run-tests updater
207```
208
209For more information about oe-selftest, including details about how to run individual test modules or classes, please refer to the https://wiki.yoctoproject.org/wiki/Oe-selftest[Yocto Project wiki].
210
211== Manual provisoning
212
213As described in <<sota-related-variables-in-localconf,SOTA-related variables in local.conf>> section you can set `SOTA_DEPLOY_CREDENTIALS` to `0` to prevent deploying credentials to the built `wic` image. In this case you get a generic image that you can use e.g. on a production line to flash a series of devices. The cost of this approach is that this image is half-baked and should be provisioned before it can connect to the backend.
214
215Provisioning procedure depends on your provisioning recipe, i.e. the value of `SOTA_CLIENT_PROV` (equal to `aktualizr-auto-prov` by default):
216
217* For `aktualizr-auto-prov` put your `credentials.zip` to `/var/sota/sota_provisioning_credentials.zip` on the filesystem of a running device. If you have the filesystem of our device mounted to your build machine, prefix all paths with `/ostree/deploy/poky` as in `/ostree/deploy/poky/var/sota/sota_provisioning_credentials.zip`.
218* For `aktualizr-ca-implicit-prov`
219** put URL to the backend server (together with protocol prefix and port number) at `/var/sota/gateway.url`. If you're using HERE OTA Connect, you can find the URL in the `autoprov.url` file in your credentials archive.
220** put client certificate, private key and root CA certificate (for the *server*, not for the *device*) at `/var/sota/import/client.pem`, `/var/sota/import/pkey.pem` and `/var/sota/import/root.crt` respectively.
221* For `aktualizr-hsm-prov`
222** put URL to the server backend (together with protocol prefix and port number) at `/var/sota/gateway.url`. If you're using HERE OTA Connect, you can find the URL in the `autoprov.url` file in your credentials archive.
223** put root CA certificate (for the *server*, not for the *device*) at `/var/sota/import/root.crt`.
224** put client certificate and private key to slots 1 and 2 of the PKCS#11-compatible device.
diff --git a/classes/image_repo_manifest.bbclass b/classes/image_repo_manifest.bbclass
new file mode 100644
index 0000000..c2e7056
--- /dev/null
+++ b/classes/image_repo_manifest.bbclass
@@ -0,0 +1,23 @@
1# Writes the repo manifest to the target filesystem in /etc/manifest.xml
2#
3# Author: Phil Wise <phil@advancedtelematic.com>
4# Usage: add "inherit image_repo_manifest" to your image file
5# To reproduce a build, copy the /etc/manifest.xml to .repo/manifests/yourname.xml
6# then run:
7# repo init -m yourname.xml
8# repo sync
9# For more information, see:
10# https://web.archive.org/web/20161224194009/https://wiki.cyanogenmod.org/w/Doc:_Using_manifests
11
12HOSTTOOLS_NONFATAL += " repo "
13
14# Write build information to target filesystem
15buildinfo_manifest () {
16 if [ $(which repo) ]; then
17 repo manifest --revision-as-HEAD -o ${IMAGE_ROOTFS}${sysconfdir}/manifest.xml || bbwarn "Android repo tool failed to run; manifest not copied"
18 else
19 bbwarn "Android repo tool not found; manifest not copied."
20 fi
21}
22
23IMAGE_PREPROCESS_COMMAND += "buildinfo_manifest;"
diff --git a/classes/image_types_ostree.bbclass b/classes/image_types_ostree.bbclass
index 29f267d..0acc786 100644
--- a/classes/image_types_ostree.bbclass
+++ b/classes/image_types_ostree.bbclass
@@ -1,207 +1,274 @@
1# OSTree deployment 1# OSTree deployment
2 2
3inherit image 3do_image_ostree[depends] += "ostree-native:do_populate_sysroot \
4 4 openssl-native:do_populate_sysroot \
5IMAGE_DEPENDS_ostree = "ostree-native:do_populate_sysroot \ 5 coreutils-native:do_populate_sysroot \
6 openssl-native:do_populate_sysroot \ 6 unzip-native:do_populate_sysroot \
7 zip-native:do_populate_sysroot \ 7 virtual/kernel:do_deploy \
8 virtual/kernel:do_deploy \ 8 ${OSTREE_INITRAMFS_IMAGE}:do_image_complete"
9 ${OSTREE_INITRAMFS_IMAGE}:do_image_complete" 9do_image_ostree[lockfiles] += "${OSTREE_REPO}/ostree.lock"
10 10
11export OSTREE_REPO 11export OSTREE_REPO
12export OSTREE_BRANCHNAME 12export OSTREE_BRANCHNAME
13export GARAGE_TARGET_NAME
13 14
14RAMDISK_EXT ?= ".ext4.gz" 15RAMDISK_EXT ?= ".${OSTREE_INITRAMFS_FSTYPES}"
15RAMDISK_EXT_arm ?= ".ext4.gz.u-boot"
16 16
17OSTREE_KERNEL ??= "${KERNEL_IMAGETYPE}" 17OSTREE_KERNEL ??= "${KERNEL_IMAGETYPE}"
18 18
19export SYSTEMD_USED = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', '', d)}" 19OSTREE_COMMIT_SUBJECT ??= "Commit-id: ${IMAGE_NAME}"
20OSTREE_COMMIT_BODY ??= ""
21OSTREE_UPDATE_SUMMARY ??= "0"
22
23export SYSTEMD_USED = "${@oe.utils.ifelse(d.getVar('VIRTUAL-RUNTIME_init_manager', True) == 'systemd', 'true', '')}"
20 24
21IMAGE_CMD_ostree () { 25IMAGE_CMD_ostree () {
22 if [ -z "$OSTREE_REPO" ]; then 26 if [ -z "$OSTREE_REPO" ]; then
23 bbfatal "OSTREE_REPO should be set in your local.conf" 27 bbfatal "OSTREE_REPO should be set in your local.conf"
24 fi
25
26 if [ -z "$OSTREE_BRANCHNAME" ]; then
27 bbfatal "OSTREE_BRANCHNAME should be set in your local.conf"
28 fi
29
30 OSTREE_ROOTFS=`mktemp -du ${WORKDIR}/ostree-root-XXXXX`
31 cp -a ${IMAGE_ROOTFS} ${OSTREE_ROOTFS}
32 chmod a+rx ${OSTREE_ROOTFS}
33 sync
34
35 cd ${OSTREE_ROOTFS}
36
37 # Create sysroot directory to which physical sysroot will be mounted
38 mkdir sysroot
39 ln -sf sysroot/ostree ostree
40
41 rm -rf tmp/*
42 ln -sf sysroot/tmp tmp
43
44 mkdir -p usr/rootdirs
45
46 mv etc usr/
47 # Implement UsrMove
48 dirs="bin sbin lib"
49
50 for dir in ${dirs} ; do
51 if [ -d ${dir} ] && [ ! -L ${dir} ] ; then
52 mv ${dir} usr/rootdirs/
53 rm -rf ${dir}
54 ln -sf usr/rootdirs/${dir} ${dir}
55 fi
56 done
57
58 if [ -n "$SYSTEMD_USED" ]; then
59 mkdir -p usr/etc/tmpfiles.d
60 tmpfiles_conf=usr/etc/tmpfiles.d/00ostree-tmpfiles.conf
61 echo "d /var/rootdirs 0755 root root -" >>${tmpfiles_conf}
62 echo "L /var/rootdirs/home - - - - /sysroot/home" >>${tmpfiles_conf}
63 else
64 mkdir -p usr/etc/init.d
65 tmpfiles_conf=usr/etc/init.d/tmpfiles.sh
66 echo '#!/bin/sh' > ${tmpfiles_conf}
67 echo "mkdir -p /var/rootdirs; chmod 755 /var/rootdirs" >> ${tmpfiles_conf}
68 echo "ln -sf /sysroot/home /var/rootdirs/home" >> ${tmpfiles_conf}
69
70 ln -s ../init.d/tmpfiles.sh usr/etc/rcS.d/S20tmpfiles.sh
71 fi
72
73 # Preserve OSTREE_BRANCHNAME for future information
74 mkdir -p usr/share/sota/
75 echo -n "${OSTREE_BRANCHNAME}" > usr/share/sota/branchname
76
77 # Preserve data in /home to be later copied to /sysroot/home by
78 # sysroot generating procedure
79 mkdir -p usr/homedirs
80 if [ -d "home" ] && [ ! -L "home" ]; then
81 mv home usr/homedirs/home
82 ln -sf var/rootdirs/home home
83 fi
84
85 # Move cron jobs if exist
86 if [ -d "var/spool/cron" ] && [ "$(ls -A var/spool/cron)" ] &&
87 [ -d "usr/share/cronie-spool" ] ; then
88 mv var/spool/cron/* usr/share/cronie-spool/
89 fi 28 fi
90 29
91 # Move persistent directories to /var 30 if [ -z "$OSTREE_BRANCHNAME" ]; then
92 dirs="opt mnt media srv" 31 bbfatal "OSTREE_BRANCHNAME should be set in your local.conf"
93
94 for dir in ${dirs}; do
95 if [ -d ${dir} ] && [ ! -L ${dir} ]; then
96 if [ "$(ls -A $dir)" ]; then
97 bbwarn "Data in /$dir directory is not preserved by OSTree. Consider moving it under /usr"
98 fi
99
100 if [ -n "$SYSTEMD_USED" ]; then
101 echo "d /var/rootdirs/${dir} 0755 root root -" >>${tmpfiles_conf}
102 else
103 echo "mkdir -p /var/rootdirs/${dir}; chown 755 /var/rootdirs/${dir}" >>${tmpfiles_conf}
104 fi
105 rm -rf ${dir}
106 ln -sf var/rootdirs/${dir} ${dir}
107 fi
108 done
109
110 if [ -d root ] && [ ! -L root ]; then
111 if [ "$(ls -A root)" ]; then
112 bberror "Data in /root directory is not preserved by OSTree."
113 fi
114
115 if [ -n "$SYSTEMD_USED" ]; then
116 echo "d /var/roothome 0755 root root -" >>${tmpfiles_conf}
117 else
118 echo "mkdir -p /var/roothome; chown 755 /var/roothome" >>${tmpfiles_conf}
119 fi
120
121 rm -rf root
122 ln -sf var/roothome root
123 fi
124
125 mkdir -p var/sota
126
127 if [ -n "${SOTA_AUTOPROVISION_CREDENTIALS}" ]; then
128 bbwarn "SOTA_AUTOPROVISION_CREDENTIALS are ignored. Please use SOTA_PACKED_CREDENTIALS"
129 fi 32 fi
130 if [ -n "${SOTA_AUTOPROVISION_URL}" ]; then 33
131 bbwarn "SOTA_AUTOPROVISION_URL is ignored. Please use SOTA_PACKED_CREDENTIALS" 34 OSTREE_ROOTFS=`mktemp -du ${WORKDIR}/ostree-root-XXXXX`
35 cp -a ${IMAGE_ROOTFS} ${OSTREE_ROOTFS}
36 chmod a+rx ${OSTREE_ROOTFS}
37 sync
38
39 cd ${OSTREE_ROOTFS}
40
41 for d in var/*; do
42 if [ "${d}" != "var/local" ]; then
43 rm -rf ${d}
44 fi
45 done
46
47 # Create sysroot directory to which physical sysroot will be mounted
48 mkdir sysroot
49 ln -sf sysroot/ostree ostree
50
51 rm -rf tmp/*
52 ln -sf sysroot/tmp tmp
53
54 mkdir -p usr/rootdirs
55
56 mv etc usr/
57 # Implement UsrMove
58 dirs="bin sbin lib"
59
60 for dir in ${dirs} ; do
61 if [ -d ${dir} ] && [ ! -L ${dir} ] ; then
62 mv ${dir} usr/rootdirs/
63 rm -rf ${dir}
64 ln -sf usr/rootdirs/${dir} ${dir}
65 fi
66 done
67
68 if [ -n "$SYSTEMD_USED" ]; then
69 mkdir -p usr/etc/tmpfiles.d
70 tmpfiles_conf=usr/etc/tmpfiles.d/00ostree-tmpfiles.conf
71 echo "d /var/rootdirs 0755 root root -" >>${tmpfiles_conf}
72 echo "L /var/rootdirs/home - - - - /sysroot/home" >>${tmpfiles_conf}
73 else
74 mkdir -p usr/etc/init.d
75 tmpfiles_conf=usr/etc/init.d/tmpfiles.sh
76 echo '#!/bin/sh' > ${tmpfiles_conf}
77 echo "mkdir -p /var/rootdirs; chmod 755 /var/rootdirs" >> ${tmpfiles_conf}
78 echo "ln -sf /sysroot/home /var/rootdirs/home" >> ${tmpfiles_conf}
79
80 ln -s ../init.d/tmpfiles.sh usr/etc/rcS.d/S20tmpfiles.sh
132 fi 81 fi
133 if [ -n "${SOTA_AUTOPROVISION_URL_FILE}" ]; then 82
134 bbwarn "SOTA_AUTOPROVISION_URL_FILE is ignored. Please use SOTA_PACKED_CREDENTIALS" 83 # Preserve OSTREE_BRANCHNAME for future information
84 mkdir -p usr/share/sota/
85 echo -n "${OSTREE_BRANCHNAME}" > usr/share/sota/branchname
86
87 # Preserve data in /home to be later copied to /sysroot/home by sysroot
88 # generating procedure
89 mkdir -p usr/homedirs
90 if [ -d "home" ] && [ ! -L "home" ]; then
91 mv home usr/homedirs/home
92 ln -sf var/rootdirs/home home
135 fi 93 fi
136 if [ -n "${OSTREE_PUSH_CREDENTIALS}" ]; then 94
137 bbwarn "OSTREE_PUSH_CREDENTIALS is ignored. Please use SOTA_PACKED_CREDENTIALS" 95 # Move persistent directories to /var
96 dirs="opt mnt media srv"
97
98 for dir in ${dirs}; do
99 if [ -d ${dir} ] && [ ! -L ${dir} ]; then
100 if [ "$(ls -A $dir)" ]; then
101 bbwarn "Data in /$dir directory is not preserved by OSTree. Consider moving it under /usr"
102 fi
103
104 if [ -n "$SYSTEMD_USED" ]; then
105 echo "d /var/rootdirs/${dir} 0755 root root -" >>${tmpfiles_conf}
106 else
107 echo "mkdir -p /var/rootdirs/${dir}; chown 755 /var/rootdirs/${dir}" >>${tmpfiles_conf}
108 fi
109 rm -rf ${dir}
110 ln -sf var/rootdirs/${dir} ${dir}
111 fi
112 done
113
114 if [ -d root ] && [ ! -L root ]; then
115 if [ "$(ls -A root)" ]; then
116 bberror "Data in /root directory is not preserved by OSTree."
117 exit 1
118 fi
119
120 if [ -n "$SYSTEMD_USED" ]; then
121 echo "d /var/roothome 0755 root root -" >>${tmpfiles_conf}
122 else
123 echo "mkdir -p /var/roothome; chown 755 /var/roothome" >>${tmpfiles_conf}
124 fi
125
126 rm -rf root
127 ln -sf var/roothome root
138 fi 128 fi
139 129
140 # deploy SOTA credentials 130 # Creating boot directories is required for "ostree admin deploy"
141 if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then
142 if [ -e ${SOTA_PACKED_CREDENTIALS} ]; then
143 cp ${SOTA_PACKED_CREDENTIALS} var/sota/sota_provisioning_credentials.zip
144 # Device should not be able to push data to treehub
145 zip -d var/sota/sota_provisioning_credentials.zip treehub.json
146 fi
147 fi
148 131
149 if [ -n "${SOTA_SECONDARY_ECUS}" ]; then 132 mkdir -p boot/loader.0
150 cp ${SOTA_SECONDARY_ECUS} var/sota/ecus 133 mkdir -p boot/loader.1
151 fi 134 ln -sf boot/loader.0 boot/loader
152 135
153 # Creating boot directories is required for "ostree admin deploy" 136 checksum=`sha256sum ${DEPLOY_DIR_IMAGE}/${OSTREE_KERNEL} | cut -f 1 -d " "`
154 137
155 mkdir -p boot/loader.0 138 cp ${DEPLOY_DIR_IMAGE}/${OSTREE_KERNEL} boot/vmlinuz-${checksum}
156 mkdir -p boot/loader.1 139 cp ${DEPLOY_DIR_IMAGE}/${OSTREE_INITRAMFS_IMAGE}-${MACHINE}${RAMDISK_EXT} boot/initramfs-${checksum}
157 ln -sf boot/loader.0 boot/loader
158 140
159 checksum=`sha256sum ${DEPLOY_DIR_IMAGE}/${OSTREE_KERNEL} | cut -f 1 -d " "` 141 # Copy image manifest
142 cat ${IMAGE_MANIFEST} | cut -d " " -f1,3 > usr/package.manifest
160 143
161 cp ${DEPLOY_DIR_IMAGE}/${OSTREE_KERNEL} boot/vmlinuz-${checksum} 144 cd ${WORKDIR}
162 cp ${DEPLOY_DIR_IMAGE}/${OSTREE_INITRAMFS_IMAGE}-${MACHINE}${RAMDISK_EXT} boot/initramfs-${checksum}
163 145
164 # Copy image manifest 146 # Create a tarball that can be then commited to OSTree repo
165 cat ${IMAGE_MANIFEST} | cut -d " " -f1,3 > usr/package.manifest 147 OSTREE_TAR=${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.ostree.tar.bz2
148 tar -C ${OSTREE_ROOTFS} --xattrs --xattrs-include='*' -cjf ${OSTREE_TAR} .
149 sync
166 150
167 cd ${WORKDIR} 151 rm -f ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2
152 ln -s ${IMAGE_NAME}.rootfs.ostree.tar.bz2 ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2
168 153
169 # Create a tarball that can be then commited to OSTree repo 154 if ! ostree --repo=${OSTREE_REPO} refs 2>&1 > /dev/null; then
170 OSTREE_TAR=${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.ostree.tar.bz2 155 ostree --repo=${OSTREE_REPO} init --mode=archive-z2
171 tar -C ${OSTREE_ROOTFS} --xattrs --xattrs-include='*' -cjf ${OSTREE_TAR} . 156 fi
172 sync
173 157
174 rm -f ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2 158 # Commit the result
175 ln -s ${IMAGE_NAME}.rootfs.ostree.tar.bz2 ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2 159 ostree --repo=${OSTREE_REPO} commit \
176 160 --tree=dir=${OSTREE_ROOTFS} \
177 if [ ! -d ${OSTREE_REPO} ]; then 161 --skip-if-unchanged \
178 ostree --repo=${OSTREE_REPO} init --mode=archive-z2 162 --branch=${OSTREE_BRANCHNAME} \
179 fi 163 --subject="${OSTREE_COMMIT_SUBJECT}" \
164 --body="${OSTREE_COMMIT_BODY}"
180 165
181 # Commit the result 166 if [ "${OSTREE_UPDATE_SUMMARY}" = "1" ]; then
182 ostree --repo=${OSTREE_REPO} commit \ 167 ostree --repo=${OSTREE_REPO} summary -u
183 --tree=dir=${OSTREE_ROOTFS} \ 168 fi
184 --skip-if-unchanged \
185 --branch=${OSTREE_BRANCHNAME} \
186 --subject="Commit-id: ${IMAGE_NAME}"
187 169
188 rm -rf ${OSTREE_ROOTFS} 170 rm -rf ${OSTREE_ROOTFS}
189} 171}
190 172
191IMAGE_TYPEDEP_ostreepush = "ostree" 173IMAGE_TYPEDEP_ostreepush = "ostree"
192IMAGE_DEPENDS_ostreepush = "sota-tools-native:do_populate_sysroot" 174do_image_ostreepush[depends] += "aktualizr-native:do_populate_sysroot ca-certificates-native:do_populate_sysroot"
193IMAGE_CMD_ostreepush () { 175IMAGE_CMD_ostreepush () {
194 # Print warnings if credetials are not set or if the file has not been found. 176 # Print warnings if credetials are not set or if the file has not been found.
195 if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then 177 if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then
196 if [ -e ${SOTA_PACKED_CREDENTIALS} ]; then 178 if [ -e ${SOTA_PACKED_CREDENTIALS} ]; then
197 garage-push --repo=${OSTREE_REPO} \ 179 garage-push --repo=${OSTREE_REPO} \
198 --ref=${OSTREE_BRANCHNAME} \ 180 --ref=${OSTREE_BRANCHNAME} \
199 --credentials=${SOTA_PACKED_CREDENTIALS} \ 181 --credentials=${SOTA_PACKED_CREDENTIALS} \
200 --cacert=${STAGING_ETCDIR_NATIVE}/ssl/certs/ca-certificates.crt 182 --cacert=${STAGING_ETCDIR_NATIVE}/ssl/certs/ca-certificates.crt
201 else
202 bbwarn "SOTA_PACKED_CREDENTIALS file does not exist."
203 fi
204 else 183 else
205 bbwarn "SOTA_PACKED_CREDENTIALS not set. Please add SOTA_PACKED_CREDENTIALS." 184 bbwarn "SOTA_PACKED_CREDENTIALS file does not exist."
206 fi 185 fi
186 else
187 bbwarn "SOTA_PACKED_CREDENTIALS not set. Please add SOTA_PACKED_CREDENTIALS."
188 fi
189}
190
191IMAGE_TYPEDEP_garagesign = "ostreepush"
192do_image_garagesign[depends] += "aktualizr-native:do_populate_sysroot"
193IMAGE_CMD_garagesign () {
194 if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then
195 # if credentials are issued by a server that doesn't support offline signing, exit silently
196 unzip -p ${SOTA_PACKED_CREDENTIALS} root.json targets.pub targets.sec tufrepo.url 2>&1 >/dev/null || exit 0
197
198 java_version=$( java -version 2>&1 | awk -F '"' '/version/ {print $2}' )
199 if [ "${java_version}" = "" ]; then
200 bberror "Java is required for synchronization with update backend, but is not installed on the host machine"
201 exit 1
202 elif [ "${java_version}" \< "1.8" ]; then
203 bberror "Java version >= 8 is required for synchronization with update backend"
204 exit 1
205 fi
206
207 rm -rf ${GARAGE_SIGN_REPO}
208 garage-sign init --repo tufrepo \
209 --home-dir ${GARAGE_SIGN_REPO} \
210 --credentials ${SOTA_PACKED_CREDENTIALS}
211
212 ostree_target_hash=$(cat ${OSTREE_REPO}/refs/heads/${OSTREE_BRANCHNAME})
213
214 # Use OSTree target hash as version if none was provided by the user
215 target_version=${ostree_target_hash}
216 if [ -n "${GARAGE_TARGET_VERSION}" ]; then
217 target_version=${GARAGE_TARGET_VERSION}
218 bbwarn "Target version is overriden with GARAGE_TARGET_VERSION variable. It is a dangerous operation, make sure you've read the respective secion in meta-updater/README.adoc"
219 elif [ -e "${STAGING_DATADIR_NATIVE}/target_version" ]; then
220 target_version=$(cat "${STAGING_DATADIR_NATIVE}/target_version")
221 bbwarn "Target version is overriden with target_version file. It is a dangerous operation, make sure you've read the respective secion in meta-updater/README.adoc"
222 fi
223
224 # Push may fail due to race condition when multiple build machines try to push simultaneously
225 # in which case targets.json should be pulled again and the whole procedure repeated
226 push_success=0
227 for push_retries in $( seq 3 ); do
228 garage-sign targets pull --repo tufrepo \
229 --home-dir ${GARAGE_SIGN_REPO}
230 garage-sign targets add --repo tufrepo \
231 --home-dir ${GARAGE_SIGN_REPO} \
232 --name ${GARAGE_TARGET_NAME} \
233 --format OSTREE \
234 --version ${target_version} \
235 --length 0 \
236 --url "${GARAGE_TARGET_URL}" \
237 --sha256 ${ostree_target_hash} \
238 --hardwareids ${SOTA_HARDWARE_ID}
239 garage-sign targets sign --repo tufrepo \
240 --home-dir ${GARAGE_SIGN_REPO} \
241 --key-name=targets
242 errcode=0
243 garage-sign targets push --repo tufrepo \
244 --home-dir ${GARAGE_SIGN_REPO} || errcode=$?
245 if [ "$errcode" -eq "0" ]; then
246 push_success=1
247 break
248 else
249 bbwarn "Push to garage repository has failed, retrying"
250 fi
251 done
252 rm -rf ${GARAGE_SIGN_REPO}
253
254 if [ "$push_success" -ne "1" ]; then
255 bberror "Couldn't push to garage repository"
256 exit 1
257 fi
258 fi
259}
260
261IMAGE_TYPEDEP_garagecheck = "ostreepush garagesign"
262do_image_garagecheck[depends] += "aktualizr-native:do_populate_sysroot"
263IMAGE_CMD_garagecheck () {
264 if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then
265 # if credentials are issued by a server that doesn't support offline signing, exit silently
266 unzip -p ${SOTA_PACKED_CREDENTIALS} root.json targets.pub targets.sec tufrepo.url 2>&1 >/dev/null || exit 0
267 ostree_target_hash=$(cat ${OSTREE_REPO}/refs/heads/${OSTREE_BRANCHNAME})
268
269 garage-check --ref=${ostree_target_hash} \
270 --credentials=${SOTA_PACKED_CREDENTIALS} \
271 --cacert=${STAGING_ETCDIR_NATIVE}/ssl/certs/ca-certificates.crt
272 fi
207} 273}
274# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/classes/image_types_ota.bbclass b/classes/image_types_ota.bbclass
index 09c30ff..df3bc7c 100644
--- a/classes/image_types_ota.bbclass
+++ b/classes/image_types_ota.bbclass
@@ -7,11 +7,7 @@
7# boot scripts, kernel and initramfs images 7# boot scripts, kernel and initramfs images
8# 8#
9 9
10inherit image 10do_image_otaimg[depends] += "e2fsprogs-native:do_populate_sysroot \
11
12OSTREE_BOOTLOADER ??= 'u-boot'
13
14IMAGE_DEPENDS_otaimg = "e2fsprogs-native:do_populate_sysroot \
15 ${@'grub:do_populate_sysroot' if d.getVar('OSTREE_BOOTLOADER', True) == 'grub' else ''} \ 11 ${@'grub:do_populate_sysroot' if d.getVar('OSTREE_BOOTLOADER', True) == 'grub' else ''} \
16 ${@'virtual/bootloader:do_deploy' if d.getVar('OSTREE_BOOTLOADER', True) == 'u-boot' else ''}" 12 ${@'virtual/bootloader:do_deploy' if d.getVar('OSTREE_BOOTLOADER', True) == 'u-boot' else ''}"
17 13
@@ -32,7 +28,7 @@ calculate_size () {
32 fi 28 fi
33 29
34 if [ "$SIZE" -lt "$MIN" ]; then 30 if [ "$SIZE" -lt "$MIN" ]; then
35 $SIZE=$MIN 31 SIZE=$MIN
36 fi 32 fi
37 33
38 SIZE=`expr $SIZE \+ $EXTRA` 34 SIZE=`expr $SIZE \+ $EXTRA`
@@ -53,6 +49,8 @@ export OSTREE_BRANCHNAME
53export OSTREE_REPO 49export OSTREE_REPO
54export OSTREE_BOOTLOADER 50export OSTREE_BOOTLOADER
55 51
52export GARAGE_TARGET_NAME
53
56IMAGE_CMD_otaimg () { 54IMAGE_CMD_otaimg () {
57 if ${@bb.utils.contains('IMAGE_FSTYPES', 'otaimg', 'true', 'false', d)}; then 55 if ${@bb.utils.contains('IMAGE_FSTYPES', 'otaimg', 'true', 'false', d)}; then
58 if [ -z "$OSTREE_REPO" ]; then 56 if [ -z "$OSTREE_REPO" ]; then
@@ -67,7 +65,6 @@ IMAGE_CMD_otaimg () {
67 bbfatal "OSTREE_BRANCHNAME should be set in your local.conf" 65 bbfatal "OSTREE_BRANCHNAME should be set in your local.conf"
68 fi 66 fi
69 67
70
71 PHYS_SYSROOT=`mktemp -d ${WORKDIR}/ota-sysroot-XXXXX` 68 PHYS_SYSROOT=`mktemp -d ${WORKDIR}/ota-sysroot-XXXXX`
72 69
73 ostree admin --sysroot=${PHYS_SYSROOT} init-fs ${PHYS_SYSROOT} 70 ostree admin --sysroot=${PHYS_SYSROOT} init-fs ${PHYS_SYSROOT}
@@ -78,32 +75,48 @@ IMAGE_CMD_otaimg () {
78 75
79 if [ "${OSTREE_BOOTLOADER}" = "grub" ]; then 76 if [ "${OSTREE_BOOTLOADER}" = "grub" ]; then
80 mkdir -p ${PHYS_SYSROOT}/boot/grub2 77 mkdir -p ${PHYS_SYSROOT}/boot/grub2
81 touch ${PHYS_SYSROOT}/boot/grub2/grub.cfg 78 ln -s ../loader/grub.cfg ${PHYS_SYSROOT}/boot/grub2/grub.cfg
82 elif [ "${OSTREE_BOOTLOADER}" = "u-boot" ]; then 79 elif [ "${OSTREE_BOOTLOADER}" = "u-boot" ]; then
83 touch ${PHYS_SYSROOT}/boot/loader/uEnv.txt 80 touch ${PHYS_SYSROOT}/boot/loader/uEnv.txt
84 else 81 else
85 bberror "Invalid bootloader: ${OSTREE_BOOTLOADER}" 82 bberror "Invalid bootloader: ${OSTREE_BOOTLOADER}"
86 fi; 83 fi;
87 84
88 ostree --repo=${PHYS_SYSROOT}/ostree/repo pull-local --remote=${OSTREE_OSNAME} ${OSTREE_REPO} ${OSTREE_BRANCHNAME} 85 ostree_target_hash=$(cat ${OSTREE_REPO}/refs/heads/${OSTREE_BRANCHNAME})
86
87 ostree --repo=${PHYS_SYSROOT}/ostree/repo pull-local --remote=${OSTREE_OSNAME} ${OSTREE_REPO} ${ostree_target_hash}
89 export OSTREE_BOOT_PARTITION="/boot" 88 export OSTREE_BOOT_PARTITION="/boot"
90 kargs_list="" 89 kargs_list=""
91 for arg in ${OSTREE_KERNEL_ARGS}; do 90 for arg in ${OSTREE_KERNEL_ARGS}; do
92 kargs_list="${kargs_list} --karg-append=$arg" 91 kargs_list="${kargs_list} --karg-append=$arg"
93 done 92 done
94 93
95 ostree admin --sysroot=${PHYS_SYSROOT} deploy ${kargs_list} --os=${OSTREE_OSNAME} ${OSTREE_BRANCHNAME} 94 ostree admin --sysroot=${PHYS_SYSROOT} deploy ${kargs_list} --os=${OSTREE_OSNAME} ${ostree_target_hash}
96 95
97 # Copy deployment /home and /var/sota to sysroot 96 # Copy deployment /home and /var/sota to sysroot
98 HOME_TMP=`mktemp -d ${WORKDIR}/home-tmp-XXXXX` 97 HOME_TMP=`mktemp -d ${WORKDIR}/home-tmp-XXXXX`
99 tar --xattrs --xattrs-include='*' -C ${HOME_TMP} -xf ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2 ./usr/homedirs ./var/sota ./var/local || true 98 tar --xattrs --xattrs-include='*' -C ${HOME_TMP} -xf ${DEPLOY_DIR_IMAGE}/${IMAGE_LINK_NAME}.rootfs.ostree.tar.bz2 ./usr/homedirs ./var/local || true
100 mv ${HOME_TMP}/var/sota ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/ || true 99
101 mv ${HOME_TMP}/var/local ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/ || true 100 cp -a ${IMAGE_ROOTFS}/var/sota ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/ || true
102 # Create /var/sota if it doesn't exist yet 101 # Create /var/sota if it doesn't exist yet
103 mkdir -p ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/sota || true 102 mkdir -p ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/sota
103 # Ensure the permissions are correctly set
104 chmod 700 ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/sota
105
106 mv ${HOME_TMP}/var/local ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/ || true
104 mv ${HOME_TMP}/usr/homedirs/home ${PHYS_SYSROOT}/ || true 107 mv ${HOME_TMP}/usr/homedirs/home ${PHYS_SYSROOT}/ || true
105 # Ensure that /var/local exists (AGL symlinks /usr/local to /var/local) 108 # Ensure that /var/local exists (AGL symlinks /usr/local to /var/local)
106 install -d ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/local 109 install -d ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/local
110 # Set package version for the first deployment
111 target_version=${ostree_target_hash}
112 if [ -n "${GARAGE_TARGET_VERSION}" ]; then
113 target_version=${GARAGE_TARGET_VERSION}
114 elif [ -e "${STAGING_DATADIR_NATIVE}/target_version" ]; then
115 target_version=$(cat "${STAGING_DATADIR_NATIVE}/target_version")
116 fi
117 mkdir -p ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/sota/import
118 echo "{\"${ostree_target_hash}\":\"${GARAGE_TARGET_NAME}-${target_version}\"}" > ${PHYS_SYSROOT}/ostree/deploy/${OSTREE_OSNAME}/var/sota/import/installed_versions
119
107 rm -rf ${HOME_TMP} 120 rm -rf ${HOME_TMP}
108 121
109 # Calculate image type 122 # Calculate image type
diff --git a/classes/sota.bbclass b/classes/sota.bbclass
index 5073e29..6b53bb6 100644
--- a/classes/sota.bbclass
+++ b/classes/sota.bbclass
@@ -5,29 +5,48 @@ python __anonymous() {
5 5
6OVERRIDES .= "${@bb.utils.contains('DISTRO_FEATURES', 'sota', ':sota', '', d)}" 6OVERRIDES .= "${@bb.utils.contains('DISTRO_FEATURES', 'sota', ':sota', '', d)}"
7 7
8HOSTTOOLS_NONFATAL += "java"
9
8SOTA_CLIENT ??= "aktualizr" 10SOTA_CLIENT ??= "aktualizr"
9IMAGE_INSTALL_append_sota = " ostree os-release ${SOTA_CLIENT}" 11SOTA_CLIENT_PROV ??= "aktualizr-auto-prov"
12SOTA_DEPLOY_CREDENTIALS ?= "1"
13SOTA_HARDWARE_ID ??= "${MACHINE}"
14
15IMAGE_INSTALL_append_sota = " ostree os-release ${SOTA_CLIENT} ${SOTA_CLIENT_PROV}"
10IMAGE_CLASSES += " image_types_ostree image_types_ota" 16IMAGE_CLASSES += " image_types_ostree image_types_ota"
11IMAGE_FSTYPES += "${@bb.utils.contains('DISTRO_FEATURES', 'sota', 'ostreepush otaimg wic', ' ', d)}" 17IMAGE_FSTYPES += "${@bb.utils.contains('DISTRO_FEATURES', 'sota', 'ostreepush garagesign garagecheck otaimg wic', ' ', d)}"
18
19PACKAGECONFIG_append_pn-curl = " ssl"
20PACKAGECONFIG_remove_pn-curl = "gnutls"
12 21
13WKS_FILE_sota ?= "sdimage-sota.wks" 22WKS_FILE_sota ?= "sdimage-sota.wks"
14 23
15EXTRA_IMAGEDEPENDS_append_sota = " parted-native mtools-native dosfstools-native" 24EXTRA_IMAGEDEPENDS_append_sota = " parted-native mtools-native dosfstools-native"
16 25
26OSTREE_INITRAMFS_FSTYPES ??= "${@oe.utils.ifelse(d.getVar('OSTREE_BOOTLOADER', True) == 'u-boot' and d.getVar('MACHINE', True) != 'qemux86-64', 'ext4.gz.u-boot', 'ext4.gz')}"
27
17# Please redefine OSTREE_REPO in order to have a persistent OSTree repo 28# Please redefine OSTREE_REPO in order to have a persistent OSTree repo
18OSTREE_REPO ?= "${DEPLOY_DIR_IMAGE}/ostree_repo" 29OSTREE_REPO ?= "${DEPLOY_DIR_IMAGE}/ostree_repo"
19# For UPTANE operation, OSTREE_BRANCHNAME must start with "${MACHINE}-" 30OSTREE_BRANCHNAME ?= "${SOTA_HARDWARE_ID}"
20OSTREE_BRANCHNAME ?= "${MACHINE}-ota"
21OSTREE_OSNAME ?= "poky" 31OSTREE_OSNAME ?= "poky"
22OSTREE_INITRAMFS_IMAGE ?= "initramfs-ostree-image" 32OSTREE_INITRAMFS_IMAGE ?= "initramfs-ostree-image"
33OSTREE_BOOTLOADER ??= 'u-boot'
34
35GARAGE_SIGN_REPO ?= "${DEPLOY_DIR_IMAGE}/garage_sign_repo"
36GARAGE_SIGN_KEYNAME ?= "garage-key"
37GARAGE_TARGET_NAME ?= "${OSTREE_BRANCHNAME}"
38GARAGE_TARGET_VERSION ?= ""
39GARAGE_TARGET_URL ?= "https://example.com/"
23 40
24SOTA_MACHINE ??="none" 41SOTA_MACHINE ??="none"
25SOTA_MACHINE_raspberrypi2 ?= "raspberrypi" 42SOTA_MACHINE_rpi ?= "raspberrypi"
26SOTA_MACHINE_raspberrypi3 ?= "raspberrypi"
27SOTA_MACHINE_porter ?= "porter" 43SOTA_MACHINE_porter ?= "porter"
28SOTA_MACHINE_m3ulcb = "m3ulcb" 44SOTA_MACHINE_m3ulcb = "m3ulcb"
45SOTA_MACHINE_h3ulcb = "h3ulcb"
29SOTA_MACHINE_intel-corei7-64 ?= "minnowboard" 46SOTA_MACHINE_intel-corei7-64 ?= "minnowboard"
30SOTA_MACHINE_qemux86-64 ?= "qemux86-64" 47SOTA_MACHINE_qemux86-64 ?= "qemux86-64"
31SOTA_MACHINE_am335x-evm ?= "am335x-evm-wifi" 48SOTA_MACHINE_am335x-evm ?= "am335x-evm-wifi"
32 49
33inherit sota_${SOTA_MACHINE} 50inherit sota_${SOTA_MACHINE}
51
52inherit image_repo_manifest
diff --git a/classes/sota_qemux86-64.bbclass b/classes/sota_qemux86-64.bbclass
index 5ec4f69..53e0026 100644
--- a/classes/sota_qemux86-64.bbclass
+++ b/classes/sota_qemux86-64.bbclass
@@ -9,3 +9,5 @@ UBOOT_MACHINE_sota = "qemu-x86_defconfig"
9OSTREE_BOOTLOADER ?= "u-boot" 9OSTREE_BOOTLOADER ?= "u-boot"
10 10
11OSTREE_KERNEL_ARGS ?= "ramdisk_size=16384 rw rootfstype=ext4 rootwait rootdelay=2 ostree_root=/dev/hda" 11OSTREE_KERNEL_ARGS ?= "ramdisk_size=16384 rw rootfstype=ext4 rootwait rootdelay=2 ostree_root=/dev/hda"
12
13IMAGE_ROOTFS_EXTRA_SPACE = "${@bb.utils.contains('DISTRO_FEATURES', 'sota', '65536', '', d)}"
diff --git a/classes/target_version_example.bbclass b/classes/target_version_example.bbclass
new file mode 100644
index 0000000..ef119fb
--- /dev/null
+++ b/classes/target_version_example.bbclass
@@ -0,0 +1,10 @@
1# Writes target version to be used by garage-sign
2
3HOSTTOOLS += " git "
4
5deploy_target_version () {
6 version=$(git --git-dir=${METADIR}/.repo/manifests/.git/ rev-parse HEAD)
7 echo -n ${version} > ${STAGING_DATADIR_NATIVE}/target_version
8}
9
10IMAGE_PREPROCESS_COMMAND += "deploy_target_version;"
diff --git a/recipes-crypto/libsodium/libsodium_1.%.bbappend b/recipes-crypto/libsodium/libsodium_1.%.bbappend
new file mode 100644
index 0000000..608377e
--- /dev/null
+++ b/recipes-crypto/libsodium/libsodium_1.%.bbappend
@@ -0,0 +1 @@
BBCLASSEXTEND = "native nativesdk"
diff --git a/recipes-sota/aktualizr/aktualizr-auto-prov-creds.bb b/recipes-sota/aktualizr/aktualizr-auto-prov-creds.bb
new file mode 100644
index 0000000..34460af
--- /dev/null
+++ b/recipes-sota/aktualizr/aktualizr-auto-prov-creds.bb
@@ -0,0 +1,24 @@
1SUMMARY = "Credentials for autoprovisioning scenario"
2SECTION = "base"
3LICENSE = "MPL-2.0"
4LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
5
6DEPENDS = "aktualizr-native zip-native"
7ALLOW_EMPTY_${PN} = "1"
8
9require credentials.inc
10
11do_install() {
12 if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then
13 install -m 0700 -d ${D}${localstatedir}/sota
14 cp ${SOTA_PACKED_CREDENTIALS} ${D}${localstatedir}/sota/sota_provisioning_credentials.zip
15 # Device should not be able to push data to treehub
16 zip -d ${D}${localstatedir}/sota/sota_provisioning_credentials.zip treehub.json
17 fi
18}
19
20FILES_${PN} = " \
21 ${localstatedir}/sota/sota_provisioning_credentials.zip \
22 "
23
24# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-sota/aktualizr/aktualizr-auto-prov.bb b/recipes-sota/aktualizr/aktualizr-auto-prov.bb
new file mode 100644
index 0000000..f506cab
--- /dev/null
+++ b/recipes-sota/aktualizr/aktualizr-auto-prov.bb
@@ -0,0 +1,43 @@
1SUMMARY = "Aktualizr configuration for autoprovisioning"
2DESCRIPTION = "Configuration for automatically provisioning Aktualizr, the SOTA Client application written in C++"
3HOMEPAGE = "https://github.com/advancedtelematic/aktualizr"
4SECTION = "base"
5LICENSE = "MPL-2.0"
6LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
7
8DEPENDS = "aktualizr-native zip-native"
9RDEPENDS_${PN}_append = "${@' aktualizr-auto-prov-creds' if d.getVar('SOTA_DEPLOY_CREDENTIALS', True) == '1' else ''}"
10PV = "1.0"
11PR = "6"
12
13SRC_URI = ""
14
15require credentials.inc
16
17do_install() {
18 if [ -n "${SOTA_AUTOPROVISION_CREDENTIALS}" ]; then
19 bbwarn "SOTA_AUTOPROVISION_CREDENTIALS are ignored. Please use SOTA_PACKED_CREDENTIALS"
20 fi
21 if [ -n "${SOTA_AUTOPROVISION_URL}" ]; then
22 bbwarn "SOTA_AUTOPROVISION_URL is ignored. Please use SOTA_PACKED_CREDENTIALS"
23 fi
24 if [ -n "${SOTA_AUTOPROVISION_URL_FILE}" ]; then
25 bbwarn "SOTA_AUTOPROVISION_URL_FILE is ignored. Please use SOTA_PACKED_CREDENTIALS"
26 fi
27 if [ -n "${OSTREE_PUSH_CREDENTIALS}" ]; then
28 bbwarn "OSTREE_PUSH_CREDENTIALS is ignored. Please use SOTA_PACKED_CREDENTIALS"
29 fi
30
31 install -m 0700 -d ${D}${libdir}/sota/conf.d
32 aktualizr_toml=${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'secondary-network', 'sota_autoprov_primary.toml', 'sota_autoprov.toml', d)}
33
34 install -m 0644 ${STAGING_DIR_NATIVE}${libdir}/sota/${aktualizr_toml} \
35 ${D}${libdir}/sota/conf.d/20-${aktualizr_toml}
36}
37
38FILES_${PN} = " \
39 ${libdir}/sota/conf.d \
40 ${libdir}/sota/conf.d/20-${aktualizr_toml} \
41 "
42
43# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-sota/aktualizr/aktualizr-ca-implicit-prov-creds.bb b/recipes-sota/aktualizr/aktualizr-ca-implicit-prov-creds.bb
new file mode 100644
index 0000000..41af7c0
--- /dev/null
+++ b/recipes-sota/aktualizr/aktualizr-ca-implicit-prov-creds.bb
@@ -0,0 +1,51 @@
1SUMMARY = "Credentials for implicit provisioning with CA certificate"
2SECTION = "base"
3LICENSE = "MPL-2.0"
4LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
5
6DEPENDS = "aktualizr aktualizr-native"
7ALLOW_EMPTY_${PN} = "1"
8
9SRC_URI = " \
10 file://ca.cnf \
11 "
12
13require credentials.inc
14
15export SOTA_CACERT_PATH
16export SOTA_CAKEY_PATH
17
18do_install() {
19 if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then
20 if [ -z ${SOTA_CACERT_PATH} ]; then
21 SOTA_CACERT_PATH=${DEPLOY_DIR_IMAGE}/CA/cacert.pem
22 SOTA_CAKEY_PATH=${DEPLOY_DIR_IMAGE}/CA/ca.private.pem
23 mkdir -p ${DEPLOY_DIR_IMAGE}/CA
24 bbwarn "SOTA_CACERT_PATH is not specified, use default one at $SOTA_CACERT_PATH"
25
26 if [ ! -f ${SOTA_CACERT_PATH} ]; then
27 bbwarn "${SOTA_CACERT_PATH} does not exist, generate a new CA"
28 SOTA_CACERT_DIR_PATH="$(dirname "$SOTA_CACERT_PATH")"
29 openssl genrsa -out ${SOTA_CACERT_DIR_PATH}/ca.private.pem 4096
30 openssl req -key ${SOTA_CACERT_DIR_PATH}/ca.private.pem -new -x509 -days 7300 -out ${SOTA_CACERT_PATH} -subj "/C=DE/ST=Berlin/O=Reis und Kichererbsen e.V/commonName=meta-updater" -batch -config ${WORKDIR}/ca.cnf -extensions cacert
31 bbwarn "${SOTA_CACERT_PATH} has been created, you'll need to upload it to the server"
32 fi
33 fi
34
35 if [ -z ${SOTA_CAKEY_PATH} ]; then
36 bberror "SOTA_CAKEY_PATH should be set when using implicit provisioning"
37 fi
38
39 install -m 0700 -d ${D}${localstatedir}/sota
40 aktualizr-cert-provider --credentials ${SOTA_PACKED_CREDENTIALS} \
41 --fleet-ca ${SOTA_CACERT_PATH} \
42 --fleet-ca-key ${SOTA_CAKEY_PATH} \
43 --root-ca \
44 --server-url \
45 --local ${D} \
46 --config ${STAGING_DIR_HOST}${libdir}/sota/sota_implicit_prov_ca.toml
47 fi
48}
49
50FILES_${PN} = " \
51 ${localstatedir}/sota/*"
diff --git a/recipes-sota/aktualizr/aktualizr-ca-implicit-prov.bb b/recipes-sota/aktualizr/aktualizr-ca-implicit-prov.bb
new file mode 100644
index 0000000..5893ed2
--- /dev/null
+++ b/recipes-sota/aktualizr/aktualizr-ca-implicit-prov.bb
@@ -0,0 +1,31 @@
1SUMMARY = "Aktualizr configuration for implicit provisioning with CA"
2DESCRIPTION = "Configuration for implicitly provisioning Aktualizr using externally provided or generated CA"
3
4# WARNING: it is NOT a production solution. The secure way to provision devices is to create certificate request directly on the device
5# (either with HSM/TPM or with software) and then sign it with a CA stored on a disconnected machine
6
7HOMEPAGE = "https://github.com/advancedtelematic/aktualizr"
8SECTION = "base"
9LICENSE = "MPL-2.0"
10LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
11
12DEPENDS = "aktualizr aktualizr-native openssl-native"
13RDEPENDS_${PN}_append = "${@' aktualizr-ca-implicit-prov-creds' if d.getVar('SOTA_DEPLOY_CREDENTIALS', True) == '1' else ''}"
14
15PV = "1.0"
16PR = "1"
17
18require credentials.inc
19
20do_install() {
21 install -m 0700 -d ${D}${libdir}/sota/conf.d
22
23 install -m 0644 ${STAGING_DIR_HOST}${libdir}/sota/sota_implicit_prov_ca.toml \
24 ${D}${libdir}/sota/conf.d/20-sota_implicit_prov_ca.toml
25}
26
27FILES_${PN} = " \
28 ${libdir}/sota/conf.d/20-sota_implicit_prov_ca.toml \
29 "
30
31# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-sota/aktualizr/aktualizr-hsm-prov.bb b/recipes-sota/aktualizr/aktualizr-hsm-prov.bb
new file mode 100644
index 0000000..08fffe9
--- /dev/null
+++ b/recipes-sota/aktualizr/aktualizr-hsm-prov.bb
@@ -0,0 +1,28 @@
1SUMMARY = "Aktualizr configuration with HSM support"
2DESCRIPTION = "Configuration for HSM provisioning with Aktualizr, the SOTA Client application written in C++"
3HOMEPAGE = "https://github.com/advancedtelematic/aktualizr"
4SECTION = "base"
5LICENSE = "MPL-2.0"
6LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
7
8DEPENDS = "aktualizr aktualizr-native"
9RDEPENDS_${PN}_append = "${@' aktualizr-ca-implicit-prov-creds softhsm-testtoken' if d.getVar('SOTA_DEPLOY_CREDENTIALS', True) == '1' else ''}"
10
11SRC_URI = ""
12PV = "1.0"
13PR = "6"
14
15require credentials.inc
16
17do_install() {
18 install -m 0700 -d ${D}${libdir}/sota/conf.d
19 install -m 0644 ${STAGING_DIR_NATIVE}${libdir}/sota/sota_hsm_prov.toml \
20 ${D}${libdir}/sota/conf.d/20-sota_hsm_prov.toml
21}
22
23FILES_${PN} = " \
24 ${libdir}/sota/conf.d \
25 ${libdir}/sota/conf.d/20-sota_hsm_prov.toml \
26 "
27
28# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-sota/aktualizr/aktualizr-uboot-env-rollback.bb b/recipes-sota/aktualizr/aktualizr-uboot-env-rollback.bb
new file mode 100644
index 0000000..cf75e79
--- /dev/null
+++ b/recipes-sota/aktualizr/aktualizr-uboot-env-rollback.bb
@@ -0,0 +1,19 @@
1SUMMARY = "Aktualizr configuration snippet to enable uboot bootcount function"
2HOMEPAGE = "https://github.com/advancedtelematic/aktualizr"
3SECTION = "base"
4LICENSE = "MPL-2.0"
5LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
6DEPENDS = "aktualizr-native"
7RDEPENDS_${PN} = "aktualizr"
8
9do_install() {
10 install -m 0700 -d ${D}${libdir}/sota/conf.d
11 install -m 0644 ${STAGING_DIR_NATIVE}${libdir}/sota/sota_uboot_env.toml ${D}${libdir}/sota/conf.d/30-rollback.toml
12}
13
14FILES_${PN} = " \
15 ${libdir}/sota/conf.d \
16 ${libdir}/sota/conf.d/30-rollback.toml \
17 "
18
19# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-sota/aktualizr/aktualizr_git.bb b/recipes-sota/aktualizr/aktualizr_git.bb
index 8bc580d..ced8388 100644..100755
--- a/recipes-sota/aktualizr/aktualizr_git.bb
+++ b/recipes-sota/aktualizr/aktualizr_git.bb
@@ -4,42 +4,137 @@ HOMEPAGE = "https://github.com/advancedtelematic/aktualizr"
4SECTION = "base" 4SECTION = "base"
5LICENSE = "MPL-2.0" 5LICENSE = "MPL-2.0"
6LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=9741c346eef56131163e13b9db1241b3" 6LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=9741c346eef56131163e13b9db1241b3"
7DEPENDS = "boost curl openssl jansson libsodium ostree" 7
8RDEPENDS_${PN} = "lshw" 8DEPENDS = "boost curl openssl libarchive libsodium asn1c-native sqlite3 "
9DEPENDS_append_class-target = "ostree ${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'hsm', ' libp11', '', d)} "
10DEPENDS_append_class-native = "glib-2.0-native "
11
12RDEPENDS_${PN}_class-target = "lshw "
13RDEPENDS_${PN}_append_class-target = "${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'serialcan', ' slcand-start', '', d)} "
14RDEPENDS_${PN}_append_class-target = " ${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'ubootenv', ' u-boot-fw-utils aktualizr-uboot-env-rollback', '', d)} "
15
16RDEPENDS_${PN}_append_class-target = " ${PN}-tools "
17RDEPENDS_${PN}-secondary_append_class-target = " ${PN}-tools "
18
19PV = "1.0+git${SRCPV}"
20PR = "7"
9 21
10SRC_URI = " \ 22SRC_URI = " \
11 git://github.com/advancedtelematic/aktualizr \ 23 gitsm://github.com/advancedtelematic/aktualizr;branch=${BRANCH} \
12 file://aktualizr-manual-provision.service \ 24 file://aktualizr.service \
13 file://aktualizr-autoprovision.service \ 25 file://aktualizr-secondary.service \
14 file://sota_autoprov.toml \ 26 file://aktualizr-secondary.socket \
27 file://aktualizr-serialcan.service \
15 " 28 "
16SRCREV = "1004efa3f86cef90c012b34620992b5762b741e3" 29
17PV = "1.0+git${SRCPV}" 30SRCREV = "d00d1a04cc2366d1a5f143b84b9f507f8bd32c44"
18PR = "6" 31BRANCH ?= "master"
19 32
20S = "${WORKDIR}/git" 33S = "${WORKDIR}/git"
34
35inherit cmake
36
37inherit systemd
38
39SYSTEMD_PACKAGES = "${PN} ${PN}-secondary"
21SYSTEMD_SERVICE_${PN} = "aktualizr.service" 40SYSTEMD_SERVICE_${PN} = "aktualizr.service"
41SYSTEMD_SERVICE_${PN}-secondary = "aktualizr-secondary.socket"
42
43BBCLASSEXTEND =+ "native"
22 44
23inherit cmake systemd 45require garage-sign-version.inc
24 46
25EXTRA_OECMAKE = "-DWARNING_AS_ERROR=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=OFF -DBUILD_OSTREE=ON -DAKTUALIZR_VERSION=${PV}" 47EXTRA_OECMAKE = "-DWARNING_AS_ERROR=OFF \
48 -DCMAKE_BUILD_TYPE=Release \
49 -DAKTUALIZR_VERSION=${PV} \
50 -DBUILD_LOAD_TESTS=OFF \
51 -Dgtest_disable_pthreads=ON"
52EXTRA_OECMAKE_append_class-target = " -DBUILD_OSTREE=ON \
53 ${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'hsm', '-DBUILD_P11=ON', '', d)} "
54EXTRA_OECMAKE_append_class-native = " -DBUILD_SOTA_TOOLS=ON \
55 -DBUILD_OSTREE=OFF \
56 -DBUILD_SYSTEMD=OFF \
57 -DGARAGE_SIGN_VERSION=${GARAGE_SIGN_VERSION} \
58 -DGARAGE_SIGN_SHA256=${GARAGE_SIGN_SHA256}"
26 59
27export SOTA_PACKED_CREDENTIALS 60do_install_append () {
61 install -d ${D}${libdir}/sota
62 install -m 0644 ${S}/config/sota_autoprov.toml ${D}/${libdir}/sota/sota_autoprov.toml
63 install -m 0644 ${S}/config/sota_autoprov_primary.toml ${D}/${libdir}/sota/sota_autoprov_primary.toml
64 install -m 0644 ${S}/config/sota_hsm_prov.toml ${D}/${libdir}/sota/sota_hsm_prov.toml
65 install -m 0644 ${S}/config/sota_implicit_prov_ca.toml ${D}/${libdir}/sota/sota_implicit_prov_ca.toml
66 install -m 0644 ${S}/config/sota_secondary.toml ${D}/${libdir}/sota/sota_secondary.toml
67 install -m 0644 ${S}/config/sota_uboot_env.toml ${D}/${libdir}/sota/sota_uboot_env.toml
68 install -d ${D}${systemd_unitdir}/system
69 install -m 0644 ${WORKDIR}/aktualizr-secondary.socket ${D}${systemd_unitdir}/system/aktualizr-secondary.socket
70 install -m 0644 ${WORKDIR}/aktualizr-secondary.service ${D}${systemd_unitdir}/system/aktualizr-secondary.service
71 install -m 0700 -d ${D}${libdir}/sota/conf.d
72 install -m 0700 -d ${D}${sysconfdir}/sota/conf.d
28 73
29do_install_append() { 74 if [ -n "${SOTA_HARDWARE_ID}" ]; then
30 if [ -n "${SOTA_PACKED_CREDENTIALS}" ]; then 75 echo "[provision]\nprimary_ecu_hardware_id = ${SOTA_HARDWARE_ID}\n" > ${D}${libdir}/sota/conf.d/40-hardware-id.toml
31 install -d ${D}/${systemd_unitdir}/system
32 install -m 0644 ${WORKDIR}/aktualizr-autoprovision.service ${D}/${systemd_unitdir}/system/aktualizr.service
33 install -d ${D}/usr/lib/sota
34 install -m "0644" ${WORKDIR}/sota_autoprov.toml ${D}/usr/lib/sota/sota.toml
35 else
36 install -d ${D}/${systemd_unitdir}/system
37 install -m 0644 ${WORKDIR}/aktualizr-manual-provision.service ${D}/${systemd_unitdir}/system/aktualizr.service
38 fi 76 fi
77
78 if [ -n "${SOTA_SECONDARY_CONFIG_DIR}" ]; then
79 if [ -d "${SOTA_SECONDARY_CONFIG_DIR}" ]; then
80 install -m 0700 -d ${D}${sysconfdir}/sota/ecus
81 install -m 0644 "${SOTA_SECONDARY_CONFIG_DIR}"/* ${D}${sysconfdir}/sota/ecus/
82 echo "[uptane]\nsecondary_configs_dir = /etc/sota/ecus/\n" > ${D}${libdir}/sota/conf.d/30-secondary-configs-dir.toml
83 else
84 bbwarn "SOTA_SECONDARY_CONFIG_DIR is set to an invalid directory (${SOTA_SECONDARY_CONFIG_DIR})"
85 fi
86 fi
87
39} 88}
40 89
90do_install_append_class-target () {
91 install -m 0755 -d ${D}${systemd_unitdir}/system
92 aktualizr_service=${@bb.utils.contains('SOTA_CLIENT_FEATURES', 'serialcan', '${WORKDIR}/aktualizr-serialcan.service', '${WORKDIR}/aktualizr.service', d)}
93 install -m 0644 ${aktualizr_service} ${D}${systemd_unitdir}/system/aktualizr.service
94}
95
96do_install_append_class-native () {
97 install -m 0755 ${B}/src/sota_tools/garage-sign/bin/* ${D}${bindir}
98 install -m 0644 ${B}/src/sota_tools/garage-sign/lib/* ${D}${libdir}
99}
100
101PACKAGES =+ " ${PN}-examples ${PN}-host-tools ${PN}-tools ${PN}-secondary "
102
41FILES_${PN} = " \ 103FILES_${PN} = " \
42 ${bindir}/aktualizr \ 104 ${bindir}/aktualizr \
105 ${bindir}/aktualizr-info \
106 ${bindir}/aktualizr-check-discovery \
43 ${systemd_unitdir}/system/aktualizr.service \ 107 ${systemd_unitdir}/system/aktualizr.service \
44 /usr/lib/sota/sota.toml \ 108 ${libdir}/sota/conf.d \
109 ${sysconfdir}/sota/conf.d \
110 ${sysconfdir}/sota/ecus/* \
111 "
112
113FILES_${PN}-examples = " \
114 ${bindir}/hmi-stub \
45 " 115 "
116
117FILES_${PN}-host-tools = " \
118 ${bindir}/aktualizr-repo \
119 ${bindir}/aktualizr-cert-provider \
120 ${bindir}/garage-deploy \
121 ${bindir}/garage-push \
122 ${libdir}/sota/sota_autoprov.toml \
123 ${libdir}/sota/sota_autoprov_primary.toml \
124 ${libdir}/sota/sota_hsm_prov.toml \
125 ${libdir}/sota/sota_implicit_prov_ca.toml \
126 ${libdir}/sota/sota_uboot_env.toml \
127 "
128
129FILES_${PN}-tools = " \
130 ${bindir}/aktualizr-check-discovery \
131 "
132
133FILES_${PN}-secondary = " \
134 ${bindir}/aktualizr-secondary \
135 ${libdir}/sota/sota_secondary.toml \
136 ${systemd_unitdir}/system/aktualizr-secondary.socket \
137 ${systemd_unitdir}/system/aktualizr-secondary.service \
138 "
139
140# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-sota/aktualizr/credentials.inc b/recipes-sota/aktualizr/credentials.inc
new file mode 100644
index 0000000..256c8ff
--- /dev/null
+++ b/recipes-sota/aktualizr/credentials.inc
@@ -0,0 +1 @@
SRC_URI_append = "${@('file://' + d.getVar('SOTA_PACKED_CREDENTIALS', True)) if d.getVar('SOTA_PACKED_CREDENTIALS', True) else ''}"
diff --git a/recipes-sota/aktualizr/files/aktualizr-autoprovision.service b/recipes-sota/aktualizr/files/aktualizr-autoprovision.service
deleted file mode 100644
index 4a595f0..0000000
--- a/recipes-sota/aktualizr/files/aktualizr-autoprovision.service
+++ /dev/null
@@ -1,13 +0,0 @@
1[Unit]
2Description=Aktualizr SOTA Client
3Wants=network-online.target
4After=network.target network-online.target
5Requires=network-online.target
6
7[Service]
8RestartSec=10
9Restart=always
10ExecStart=/usr/bin/aktualizr --disable-keyid-validation --config /usr/lib/sota/sota.toml
11
12[Install]
13WantedBy=multi-user.target
diff --git a/recipes-sota/aktualizr/files/aktualizr-manual-provision.service b/recipes-sota/aktualizr/files/aktualizr-manual-provision.service
deleted file mode 100644
index a70f2f9..0000000
--- a/recipes-sota/aktualizr/files/aktualizr-manual-provision.service
+++ /dev/null
@@ -1,13 +0,0 @@
1[Unit]
2Description=Aktualizr SOTA Client
3Wants=network-online.target
4After=network.target network-online.target
5Requires=network-online.target
6
7[Service]
8RestartSec=10
9Restart=always
10ExecStart=/usr/bin/aktualizr --config /sysroot/boot/sota.toml --loglevel 2
11
12[Install]
13WantedBy=multi-user.target
diff --git a/recipes-sota/aktualizr/files/aktualizr-secondary.service b/recipes-sota/aktualizr/files/aktualizr-secondary.service
new file mode 100644
index 0000000..9628ee3
--- /dev/null
+++ b/recipes-sota/aktualizr/files/aktualizr-secondary.service
@@ -0,0 +1,8 @@
1[Unit]
2Description=Aktualizr SOTA Client (UPTANE Secondary)
3
4[Service]
5RestartSec=10
6Restart=always
7ExecStart=/usr/bin/aktualizr-secondary --config /usr/lib/sota/sota_secondary.toml
8
diff --git a/recipes-sota/aktualizr/files/aktualizr-secondary.socket b/recipes-sota/aktualizr/files/aktualizr-secondary.socket
new file mode 100644
index 0000000..da0ee44
--- /dev/null
+++ b/recipes-sota/aktualizr/files/aktualizr-secondary.socket
@@ -0,0 +1,6 @@
1[Socket]
2ListenStream=9030
3ListenDatagram=9031
4
5[Install]
6WantedBy=sockets.target \ No newline at end of file
diff --git a/recipes-sota/aktualizr/files/aktualizr-serialcan.service b/recipes-sota/aktualizr/files/aktualizr-serialcan.service
new file mode 100644
index 0000000..b42f348
--- /dev/null
+++ b/recipes-sota/aktualizr/files/aktualizr-serialcan.service
@@ -0,0 +1,15 @@
1[Unit]
2Description=Aktualizr SOTA Client
3Wants=network-online.target slcand@ttyACM0.service
4After=network.target network-online.target slcand@ttyACM0.service
5
6Requires=network-online.target
7
8[Service]
9RestartSec=10
10Restart=always
11EnvironmentFile=/usr/lib/sota/sota.env
12ExecStart=/bin/sh -c "(ip addr | grep can0) && /usr/bin/aktualizr $AKTUALIZR_CMDLINE_PARAMETERS"
13
14[Install]
15WantedBy=multi-user.target
diff --git a/recipes-sota/aktualizr/files/aktualizr.service b/recipes-sota/aktualizr/files/aktualizr.service
new file mode 100644
index 0000000..726809e
--- /dev/null
+++ b/recipes-sota/aktualizr/files/aktualizr.service
@@ -0,0 +1,11 @@
1[Unit]
2Description=Aktualizr SOTA Client
3After=network.target
4
5[Service]
6RestartSec=10
7Restart=always
8ExecStart=/usr/bin/aktualizr $AKTUALIZR_CMDLINE_PARAMETERS
9
10[Install]
11WantedBy=multi-user.target
diff --git a/recipes-sota/aktualizr/files/ca.cnf b/recipes-sota/aktualizr/files/ca.cnf
new file mode 100644
index 0000000..352ec38
--- /dev/null
+++ b/recipes-sota/aktualizr/files/ca.cnf
@@ -0,0 +1,10 @@
1[req]
2req_extensions = cacert
3distinguished_name = req_distinguished_name
4
5[req_distinguished_name]
6
7[cacert]
8basicConstraints = critical,CA:true
9keyUsage = keyCertSign
10
diff --git a/recipes-sota/aktualizr/files/sota_autoprov.toml b/recipes-sota/aktualizr/files/sota_autoprov.toml
deleted file mode 100644
index 9fbb093..0000000
--- a/recipes-sota/aktualizr/files/sota_autoprov.toml
+++ /dev/null
@@ -1,14 +0,0 @@
1[tls]
2certificates_directory = "/var/sota/"
3ca_file = "root.crt"
4client_certificate = "client.pem"
5pkey_file = "pkey.pem"
6
7[uptane]
8metadata_path = "/var/sota/metadata"
9private_key_path = "ecukey.der"
10public_key_path = "ecukey.pub"
11
12[provision]
13provision_path = "/var/sota/sota_provisioning_credentials.zip"
14
diff --git a/recipes-sota/aktualizr/garage-sign-version.inc b/recipes-sota/aktualizr/garage-sign-version.inc
new file mode 100644
index 0000000..1b89a3d
--- /dev/null
+++ b/recipes-sota/aktualizr/garage-sign-version.inc
@@ -0,0 +1,36 @@
1
2python () {
3 if d.getVar("GARAGE_SIGN_VERSION", True) or not d.getVar("SOTA_PACKED_CREDENTIALS", True):
4 return
5 import json
6 import urllib.request
7 import zipfile
8 with zipfile.ZipFile(d.getVar("SOTA_PACKED_CREDENTIALS", True), 'r') as zip_ref:
9 try:
10 with zip_ref.open('tufrepo.url', mode='r') as url_file:
11 url = url_file.read().decode().strip(' \t\n') + '/health/version'
12 except (KeyError, ValueError, RuntimeError):
13 return
14 connected = False
15 tries = 3
16 for i in range(tries):
17 try:
18 r = urllib.request.urlopen(url)
19 if r.code == 200:
20 connected = True
21 break
22 else:
23 print('Bad return code from server ' + url + ': ' + str(r.code) +
24 ' (attempt ' + str(i + 1) + ' of ' + str(tries) + ')')
25 except urllib.error.URLError as e:
26 print('Error connecting to server ' + url + ': ' + str(e) +
27 ' (attempt ' + str(i + 1) + ' of ' + str(tries) + ')')
28 if not connected:
29 return
30 resp = r.read().decode('utf-8')
31 j = json.loads(resp)
32 version = 'cli-' + j['version'] + '.tgz'
33 d.setVar("GARAGE_SIGN_VERSION", version)
34}
35
36# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-sota/asn1c/asn1c.bb b/recipes-sota/asn1c/asn1c.bb
new file mode 100644
index 0000000..9d1517d
--- /dev/null
+++ b/recipes-sota/asn1c/asn1c.bb
@@ -0,0 +1,17 @@
1SUMMARY = "ASN.1 to C compiler"
2DESCRIPTION = "Generates serialization routines from ASN.1 schemas"
3HOMEPAGE = "http://lionet.info/asn1c"
4SECTION = "base"
5LICENSE = "BSD"
6LIC_FILES_CHKSUM = "file://LICENSE;md5=ee8bfaaa7d71cf3edb079475e6716d4b"
7
8inherit autotools native
9
10PV = "0.9.28"
11SRC_URI = "https://github.com/vlm/asn1c/releases/download/v${PV}/asn1c-${PV}.tar.gz \
12 file://skeletons_dir_fix.patch"
13SRC_URI[sha256sum] = "8007440b647ef2dd9fb73d931c33ac11764e6afb2437dbe638bb4e5fc82386b9"
14
15BBCLASSEXTEND = "native nativesdk"
16
17# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-sota/asn1c/files/skeletons_dir_fix.patch b/recipes-sota/asn1c/files/skeletons_dir_fix.patch
new file mode 100644
index 0000000..f1caa2f
--- /dev/null
+++ b/recipes-sota/asn1c/files/skeletons_dir_fix.patch
@@ -0,0 +1,44 @@
1From 1a1c2c94f700cf0f4dc5dba863950b16477fdc6d Mon Sep 17 00:00:00 2001
2From: Laurent Bonnans <laurent.bonnans@here.com>
3Date: Thu, 25 Jan 2018 09:49:41 +0100
4Subject: [PATCH] Patch the skeletons directory detection
5
6Detect `share/asn1c` from `bin/` if it exists
7---
8 asn1c/asn1c.c | 9 ++++-----
9 1 file changed, 4 insertions(+), 5 deletions(-)
10
11diff --git a/asn1c/asn1c.c b/asn1c/asn1c.c
12index eb1eff7c..dd9fc832 100644
13--- a/asn1c/asn1c.c
14+++ b/asn1c/asn1c.c
15@@ -226,22 +226,21 @@ main(int ac, char **av) {
16 if(skeletons_dir == NULL) {
17 struct stat sb;
18 skeletons_dir = DATADIR;
19- if((av[-optind][0] == '.' || av[-optind][1] == '/')
20- && stat(skeletons_dir, &sb)) {
21+ if(stat(skeletons_dir, &sb)) {
22 /*
23 * The default skeletons directory does not exist,
24 * compute it from my file name:
25- * ./asn1c/asn1c -> ./skeletons
26+ * ./asn1c/asn1c -> ./share/asn1c
27 */
28 char *p;
29 size_t len;
30
31 p = a1c_dirname(av[-optind]);
32
33- len = strlen(p) + sizeof("/../skeletons");
34+ len = strlen(p) + sizeof("/../share/asn1c");
35 skeletons_dir = malloc(len);
36 assert(skeletons_dir);
37- snprintf(skeletons_dir, len, "%s/../skeletons", p);
38+ snprintf(skeletons_dir, len, "%s/../share/asn1c", p);
39 if(stat(skeletons_dir, &sb)) {
40 fprintf(stderr,
41 "WARNING: skeletons are neither in "
42--
432.15.1
44
diff --git a/recipes-sota/config/aktualizr-disable-send-ip.bb b/recipes-sota/config/aktualizr-disable-send-ip.bb
new file mode 100644
index 0000000..8dd2647
--- /dev/null
+++ b/recipes-sota/config/aktualizr-disable-send-ip.bb
@@ -0,0 +1,22 @@
1SUMMARY = "Disable IP reporting in Aktualizr"
2DESCRIPTION = "Configures aktualizr to disable IP reporting to the server"
3HOMEPAGE = "https://github.com/advancedtelematic/aktualizr"
4SECTION = "base"
5LICENSE = "MPL-2.0"
6LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
7
8SRC_URI = " \
9 file://30-disable-send-ip.toml \
10 "
11
12do_install_append () {
13 install -m 0700 -d ${D}${libdir}/sota/conf.d
14 install -m 0644 ${WORKDIR}/30-disable-send-ip.toml ${D}${libdir}/sota/conf.d/30-disable-send-ip.toml
15}
16
17FILES_${PN} = " \
18 ${libdir}/sota/conf.d/30-disable-send-ip.toml \
19 "
20
21# vim:set ts=4 sw=4 sts=4 expandtab:
22
diff --git a/recipes-sota/config/aktualizr-log-debug.bb b/recipes-sota/config/aktualizr-log-debug.bb
new file mode 100644
index 0000000..098faf4
--- /dev/null
+++ b/recipes-sota/config/aktualizr-log-debug.bb
@@ -0,0 +1,22 @@
1SUMMARY = "Set debug logging in Aktualizr"
2DESCRIPTION = "Configures aktualizr to log at a debugging level"
3HOMEPAGE = "https://github.com/advancedtelematic/aktualizr"
4SECTION = "base"
5LICENSE = "MPL-2.0"
6LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad"
7
8SRC_URI = " \
9 file://05-log-debug.toml \
10 "
11
12do_install_append () {
13 install -m 0700 -d ${D}${libdir}/sota/conf.d
14 install -m 0644 ${WORKDIR}/05-log-debug.toml ${D}${libdir}/sota/conf.d/05-log-debug.toml
15}
16
17FILES_${PN} = " \
18 ${libdir}/sota/conf.d/05-log-debug.toml \
19 "
20
21# vim:set ts=4 sw=4 sts=4 expandtab:
22
diff --git a/recipes-sota/config/files/05-log-debug.toml b/recipes-sota/config/files/05-log-debug.toml
new file mode 100644
index 0000000..100a146
--- /dev/null
+++ b/recipes-sota/config/files/05-log-debug.toml
@@ -0,0 +1,2 @@
1[logger]
2loglevel = 0
diff --git a/recipes-sota/config/files/30-disable-send-ip.toml b/recipes-sota/config/files/30-disable-send-ip.toml
new file mode 100644
index 0000000..5cd5108
--- /dev/null
+++ b/recipes-sota/config/files/30-disable-send-ip.toml
@@ -0,0 +1,2 @@
1[telemetry]
2report_network = false
diff --git a/recipes-sota/ostree-initrd/files/init.sh b/recipes-sota/ostree-initrd/files/init.sh
index 0b0693d..d7e0429 100644
--- a/recipes-sota/ostree-initrd/files/init.sh
+++ b/recipes-sota/ostree-initrd/files/init.sh
@@ -67,7 +67,7 @@ ostree-prepare-root /sysroot
67 67
68# move mounted devices to new root 68# move mounted devices to new root
69cd /sysroot 69cd /sysroot
70for x in dev proc; do 70for x in dev proc run; do
71 log_info "Moving /$x to new rootfs" 71 log_info "Moving /$x to new rootfs"
72 mount -o move "/$x" "$x" 72 mount -o move "/$x" "$x"
73done 73done
diff --git a/recipes-sota/ostree/ostree_git.bb b/recipes-sota/ostree/ostree_git.bb
index 8937e5e..6386910 100644
--- a/recipes-sota/ostree/ostree_git.bb
+++ b/recipes-sota/ostree/ostree_git.bb
@@ -1,89 +1,72 @@
1SUMMARY = "Tool for managing bootable, immutable, versioned filesystem trees" 1SUMMARY = "Tool for managing bootable, immutable, versioned filesystem trees"
2LICENSE = "GPLv2+" 2HOMEPAGE = "https://ostree.readthedocs.io/en/latest/"
3LICENSE = "LGPLv2+"
3LIC_FILES_CHKSUM = "file://COPYING;md5=5f30f0716dfdd0d91eb439ebec522ec2" 4LIC_FILES_CHKSUM = "file://COPYING;md5=5f30f0716dfdd0d91eb439ebec522ec2"
4 5
5inherit autotools-brokensep pkgconfig systemd gobject-introspection 6inherit autotools pkgconfig systemd bash-completion gobject-introspection
6 7
7INHERIT_remove_class-native = "systemd" 8INHERIT_remove_class-native = "systemd"
8 9
9SRC_URI = "gitsm://github.com/ostreedev/ostree.git;branch=master" 10SRC_URI = "gitsm://github.com/ostreedev/ostree.git;branch=master"
10 11
11SRCREV="3b09620c2738bce4ed45e099cf2e4c5df7671d39" 12SRCREV="3e96ec9811b5cfc5481f8b6b06c8d34d9a35408e"
12 13
13PV = "2017.3-31-g3b09620c" 14PV = "v2018.7"
14 15
15S = "${WORKDIR}/git" 16S = "${WORKDIR}/git"
16 17
17BBCLASSEXTEND = "native" 18BBCLASSEXTEND = "native"
18 19
19DEPENDS += "attr libarchive glib-2.0 pkgconfig gpgme libgsystem fuse libsoup-2.4 e2fsprogs gtk-doc-native curl xz" 20DEPENDS += "attr bison-native libarchive libcap glib-2.0 gpgme fuse e2fsprogs curl xz"
20DEPENDS_append = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', ' systemd', '', d)}" 21DEPENDS_append = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', ' systemd', '', d)}"
21DEPENDS_remove_class-native = "systemd-native" 22DEPENDS_remove_class-native = "systemd-native"
23RDEPENDS_${PN}-dracut = "bash"
22 24
23RDEPENDS_${PN} = "python util-linux-libuuid util-linux-libblkid util-linux-libmount libcap bash" 25CFLAGS_append = " -Wno-error=missing-prototypes"
24RDEPENDS_${PN}_remove_class-native = "python-native" 26EXTRA_OECONF = "--disable-gtk-doc --disable-man --with-smack --with-builtin-grub2-mkconfig --with-curl --without-soup"
25
26EXTRA_OECONF = "--with-libarchive --disable-gtk-doc --disable-gtk-doc-html --disable-gtk-doc-pdf --disable-man --with-smack --with-builtin-grub2-mkconfig --with-curl"
27EXTRA_OECONF_append_class-native = " --enable-wrpseudo-compat" 27EXTRA_OECONF_append_class-native = " --enable-wrpseudo-compat"
28 28
29PACKAGECONFIG ??= "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)}"
30PACKAGECONFIG_class-native = ""
31PACKAGECONFIG[systemd] = "--with-systemdsystemunitdir=${systemd_unitdir}/system/ --with-dracut"
32
29# Path to ${prefix}/lib/ostree/ostree-grub-generator is hardcoded on the 33# Path to ${prefix}/lib/ostree/ostree-grub-generator is hardcoded on the
30# do_configure stage so we do depend on it 34# do_configure stage so we do depend on it
31SYSROOT_DIR = "${STAGING_DIR_TARGET}" 35SYSROOT_DIR = "${STAGING_DIR_TARGET}"
32SYSROOT_DIR_class-native = "${STAGING_DIR_NATIVE}" 36SYSROOT_DIR_class-native = "${STAGING_DIR_NATIVE}"
33do_configure[vardeps] += "SYSROOT_DIR" 37do_configure[vardeps] += "SYSROOT_DIR"
34 38
35SYSTEMD_REQUIRED = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}" 39SYSTEMD_SERVICE_${PN} = "ostree-prepare-root.service ostree-remount.service ostree-finalize-staged.service"
36SYSTEMD_REQUIRED_class-native = ""
37
38SYSTEMD_SERVICE_${PN} = "ostree-prepare-root.service ostree-remount.service"
39SYSTEMD_SERVICE_${PN}_class-native = ""
40
41PACKAGECONFIG ??= "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)}"
42PACKAGECONFIG_class-native = ""
43PACKAGECONFIG[systemd] = "--with-systemdsystemunitdir=${systemd_unitdir}/system/ --with-dracut"
44
45FILES_${PN} += "${libdir}/ostree/ ${libdir}/ostbuild"
46 40
41export BUILD_SYS
42export HOST_SYS
47export STAGING_INCDIR 43export STAGING_INCDIR
48export STAGING_LIBDIR 44export STAGING_LIBDIR
49 45
50do_configure() { 46do_configure_prepend() {
51 unset docdir 47 unset docdir
52 NOCONFIGURE=1 ./autogen.sh 48 NOCONFIGURE=1 "${S}/autogen.sh"
53 oe_runconf
54}
55
56do_compile_prepend() {
57 export BUILD_SYS="${BUILD_SYS}"
58 export HOST_SYS="${HOST_SYS}"
59}
60
61export SYSTEMD_REQUIRED
62
63do_install_append() {
64 if [ -n ${SYSTEMD_REQUIRED} ]; then
65 install -p -D ${S}/src/boot/ostree-prepare-root.service ${D}${systemd_unitdir}/system/ostree-prepare-root.service
66 install -p -D ${S}/src/boot/ostree-remount.service ${D}${systemd_unitdir}/system/ostree-remount.service
67 fi
68} 49}
69 50
70do_install_append_class-native() { 51do_install_append_class-native() {
71 create_wrapper ${D}${bindir}/ostree OSTREE_GRUB2_EXEC="${STAGING_LIBDIR_NATIVE}/ostree/ostree-grub-generator" 52 create_wrapper ${D}${bindir}/ostree OSTREE_GRUB2_EXEC="${STAGING_LIBDIR_NATIVE}/ostree/ostree-grub-generator"
72} 53}
73 54
74 55PACKAGES += " \
75FILES_${PN} += " \ 56 ${PN}-switchroot \
76 ${@'${systemd_unitdir}/system/' if d.getVar('SYSTEMD_REQUIRED', True) else ''} \ 57 ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'ostree-dracut', '', d)} \
77 ${@'${libdir}/dracut/modules.d/98ostree/module-setup.sh' if d.getVar('SYSTEMD_REQUIRED', True) else ''} \
78 ${datadir}/gir-1.0 \
79 ${datadir}/gir-1.0/OSTree-1.0.gir \
80 ${libdir}/girepository-1.0 \
81 ${libdir}/girepository-1.0/OSTree-1.0.typelib \
82" 58"
83 59
84PACKAGES =+ "${PN}-switchroot" 60FILES_${PN} = "${bindir} \
85 61 ${sysconfdir}/ostree \
62 ${datadir}/ostree \
63 ${libdir}/*.so.* \
64 ${libdir}/ostree/ostree-grub-generator \
65 ${libdir}/ostree/ostree-remount \
66 ${libdir}/girepository-1.0/* \
67 ${@bb.utils.contains('DISTRO_FEATURES','systemd','${libdir}/tmpfiles.d', '', d)} \
68 ${@bb.utils.contains('DISTRO_FEATURES','systemd','${systemd_unitdir}/system-generators', '', d)} \
69"
70FILES_${PN}-dev += " ${datadir}/gir-1.0"
71FILES_${PN}-dracut = "${sysconfdir}/dracut.conf.d ${libdir}/dracut"
86FILES_${PN}-switchroot = "${libdir}/ostree/ostree-prepare-root" 72FILES_${PN}-switchroot = "${libdir}/ostree/ostree-prepare-root"
87RDEPENDS_${PN}-switchroot = ""
88DEPENDS_remove_class-native = "systemd-native"
89
diff --git a/recipes-support/libp11/files/0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch b/recipes-support/libp11/files/0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch
new file mode 100644
index 0000000..902352c
--- /dev/null
+++ b/recipes-support/libp11/files/0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch
@@ -0,0 +1,42 @@
1From ccab5ce63dd5d3dbb4bd02998d21d34407e550f2 Mon Sep 17 00:00:00 2001
2From: Anton Gerasimov <anton.gerasimov@here.com>
3Date: Fri, 19 Jan 2018 12:44:27 +0100
4Subject: [PATCH] Workaround for a buggy version of openssl (1.0.2m)
5
6---
7 src/p11_pkey.c | 12 +++++++++---
8 1 file changed, 9 insertions(+), 3 deletions(-)
9
10diff --git a/src/p11_pkey.c b/src/p11_pkey.c
11index 45d5ad3..75625e6 100644
12--- a/src/p11_pkey.c
13+++ b/src/p11_pkey.c
14@@ -139,8 +139,14 @@ static void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src)
15
16 #endif
17
18-#if OPENSSL_VERSION_NUMBER < 0x100020d0L || defined(LIBRESSL_VERSION_NUMBER)
19-static void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth,
20+#if OPENSSL_VERSION_NUMBER < 0x10002100L || defined(LIBRESSL_VERSION_NUMBER)
21+
22+# if (OPENSSL_VERSION_NUMBER & 0xFFFFFFF0) == 0x100020d0L
23+# undef EVP_PKEY_meth_get_sign
24+# undef EVP_PKEY_meth_get_decrypt
25+# endif
26+
27+void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth,
28 int (**psign_init) (EVP_PKEY_CTX *ctx),
29 int (**psign) (EVP_PKEY_CTX *ctx,
30 unsigned char *sig, size_t *siglen,
31@@ -152,7 +158,7 @@ static void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth,
32 *psign = pmeth->sign;
33 }
34
35-static void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth,
36+void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth,
37 int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
38 int (**pdecrypt) (EVP_PKEY_CTX *ctx,
39 unsigned char *out,
40--
412.15.1
42
diff --git a/recipes-support/libp11/libp11_0.4.9.bb b/recipes-support/libp11/libp11_0.4.9.bb
new file mode 100644
index 0000000..6d0165f
--- /dev/null
+++ b/recipes-support/libp11/libp11_0.4.9.bb
@@ -0,0 +1,39 @@
1SUMMARY = "Library for using PKCS"
2DESCRIPTION = "\
3Libp11 is a library implementing a small layer on top of PKCS \
4make using PKCS"
5HOMEPAGE = "http://www.opensc-project.org/libp11"
6SECTION = "Development/Libraries"
7LICENSE = "LGPLv2+"
8LIC_FILES_CHKSUM = "file://COPYING;md5=fad9b3332be894bab9bc501572864b29"
9DEPENDS = "libtool openssl"
10RDEPENDS_${PN} += " opensc"
11
12SRC_URI = "git://github.com/OpenSC/libp11.git \
13 file://0001-Workaround-for-a-buggy-version-of-openssl-1.0.2m.patch"
14SRCREV = "e1210903291b1de9eabcad26e740a4b2fbcca692"
15
16S = "${WORKDIR}/git"
17
18inherit autotools pkgconfig
19
20# Currently, Makefile dependencies are incorrectly defined which causes build errors
21# if the number of jobs is high
22# See https://github.com/OpenSC/libp11/issues/94
23PARALLEL_MAKE = ""
24EXTRA_OECONF = "--disable-static"
25
26do_install_append () {
27 rm -rf ${D}${libdir}/*.la
28 rm -rf ${D}${docdir}/${BPN}
29}
30
31FILES_${PN} = "${libdir}/engines*/pkcs11.so \
32 ${libdir}/engines*/libpkcs11${SOLIBS} \
33 ${libdir}/libp11${SOLIBS}"
34
35FILES_${PN}-dev = " \
36 ${libdir}/engines*/libpkcs11${SOLIBSDEV} \
37 ${libdir}/libp11${SOLIBSDEV} \
38 ${libdir}/pkgconfig/libp11.pc \
39 /usr/include"
diff --git a/recipes-support/slcand-start/files/slcand@.service b/recipes-support/slcand-start/files/slcand@.service
new file mode 100644
index 0000000..c539568
--- /dev/null
+++ b/recipes-support/slcand-start/files/slcand@.service
@@ -0,0 +1,8 @@
1[Unit]
2Description=Serial CAN daemon (can-utils)
3
4[Service]
5Type=forking
6ExecStart=/usr/bin/slcand -o -c -s4 %I can0
7ExecStartPost=/bin/sh -c '/bin/sleep 3; /sbin/ip link set can0 up'
8
diff --git a/recipes-support/slcand-start/slcand-start.bb b/recipes-support/slcand-start/slcand-start.bb
new file mode 100644
index 0000000..dfefaea
--- /dev/null
+++ b/recipes-support/slcand-start/slcand-start.bb
@@ -0,0 +1,21 @@
1SUMMARY = "Mock smartcard for aktualizr"
2LICENSE = "MIT"
3LIC_FILES_CHKSUM = "file://${COREBASE}/LICENSE;md5=4d92cd373abda3937c2bc47fbc49d690 \
4 file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
5
6
7inherit systemd
8
9RDEPENDS_${PN} = "can-utils"
10
11SRC_URI = "file://slcand@.service"
12
13SYSTEMD_SERVICE_${PN} = "slcand@.service"
14
15do_install() {
16 install -d ${D}${systemd_unitdir}/system
17 install -m 0644 ${WORKDIR}/slcand@.service ${D}${systemd_unitdir}/system/slcand@.service
18}
19
20FILES_${PN} = "${systemd_unitdir}/system/createtoken.service"
21
diff --git a/recipes-support/softhsm-testtoken/files/createtoken.service b/recipes-support/softhsm-testtoken/files/createtoken.service
new file mode 100644
index 0000000..23317b9
--- /dev/null
+++ b/recipes-support/softhsm-testtoken/files/createtoken.service
@@ -0,0 +1,12 @@
1[Unit]
2Description=Create a mock smartcard for testing
3Before=aktualizr.service
4RequiredBy=aktualizr.service
5
6[Service]
7RestartSec=10
8Restart=on-failure
9ExecStart=/usr/bin/createtoken.sh
10
11[Install]
12WantedBy=aktualizr.service
diff --git a/recipes-support/softhsm-testtoken/files/createtoken.sh b/recipes-support/softhsm-testtoken/files/createtoken.sh
new file mode 100644
index 0000000..fa4569d
--- /dev/null
+++ b/recipes-support/softhsm-testtoken/files/createtoken.sh
@@ -0,0 +1,27 @@
1#!/bin/sh
2
3if pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so -O; then
4 # The token has already been initialized, exit
5 exit 0
6fi
7
8if ! ls /var/sota/import/pkey.pem /var/sota/import/client.pem; then
9 # Key/certificate pair is not present, repeat
10 exit 1
11fi
12
13mkdir -p /var/lib/softhsm/tokens
14softhsm2-util --init-token --slot 0 --label "Virtual token" --pin 1234 --so-pin 1234
15
16openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in /var/sota/import/pkey.pem -out /var/sota/import/pkey.p8
17softhsm2-util --import /var/sota/import/pkey.p8 --label "pkey" --id 02 --token 'Virtual token' --pin 1234
18openssl x509 -outform der -in /var/sota/import/client.pem -out /var/sota/import/client.der
19pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so --id 1 --write-object /var/sota/import/client.der --type cert --login --pin 1234
20
21# Import UPTANE keypair if it exists
22if [ -f /var/sota/import/ecukey.pem ]; then
23 openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in /var/sota/import/ecukey.pem -out /var/sota/import/ecukey.p8
24 softhsm2-util --import /var/sota/import/ecukey.p8 --label "uptanekey" --id 03 --token 'Virtual token' --pin 1234
25fi
26
27exit 0
diff --git a/recipes-support/softhsm-testtoken/softhsm-testtoken.bb b/recipes-support/softhsm-testtoken/softhsm-testtoken.bb
new file mode 100644
index 0000000..029fe1c
--- /dev/null
+++ b/recipes-support/softhsm-testtoken/softhsm-testtoken.bb
@@ -0,0 +1,25 @@
1SUMMARY = "Mock smartcard for aktualizr"
2LICENSE = "MIT"
3LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
4
5inherit systemd
6
7RDEPENDS_${PN} = "softhsm libp11"
8DEPENDS_append = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', ' systemd', '', d)}"
9
10
11SRC_URI = "file://createtoken.service \
12 file://createtoken.sh"
13
14SYSTEMD_SERVICE_${PN} = "createtoken.service"
15
16do_install() {
17 install -d ${D}${systemd_unitdir}/system
18 install -m 0644 ${WORKDIR}/createtoken.service ${D}${systemd_unitdir}/system/createtoken.service
19 install -d ${D}${bindir}
20 install -m 0744 ${WORKDIR}/createtoken.sh ${D}${bindir}/createtoken.sh
21}
22
23FILES_${PN} = "${bindir}/createtoken.sh \
24 ${systemd_unitdir}/system/createtoken.service"
25
diff --git a/recipes-support/softhsm/files/0001-Cross-compilation-tweaks.patch b/recipes-support/softhsm/files/0001-Cross-compilation-tweaks.patch
new file mode 100644
index 0000000..b3a7622
--- /dev/null
+++ b/recipes-support/softhsm/files/0001-Cross-compilation-tweaks.patch
@@ -0,0 +1,86 @@
1From b6add28acb884b6006216e8422cc18504483c72e Mon Sep 17 00:00:00 2001
2From: Anton Gerasimov <anton@advancedtelematic.com>
3Date: Fri, 8 Sep 2017 15:08:40 +0200
4Subject: [PATCH] Cross-compilation tweaks
5
6---
7 m4/acx_openssl.m4 | 2 ++
8 m4/acx_openssl_ecc.m4 | 3 +++
9 m4/acx_openssl_fips.m4 | 2 ++
10 m4/acx_openssl_gost.m4 | 2 ++
11 4 files changed, 9 insertions(+)
12
13diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4
14index e90c78f..9de6055 100644
15--- a/m4/acx_openssl.m4
16+++ b/m4/acx_openssl.m4
17@@ -25,6 +25,7 @@ AC_DEFUN([ACX_OPENSSL],[
18 AC_CHECK_HEADERS([openssl/ssl.h],,[AC_MSG_ERROR([Can't find OpenSSL headers])])
19 AC_CHECK_LIB(crypto, BN_new,,[AC_MSG_ERROR([Can't find OpenSSL library])])
20
21+ if test "$cross_compiling" != yes; then
22 AC_MSG_CHECKING([for OpenSSL version])
23 CHECK_OPENSSL_VERSION=m4_format(0x%02x%02x%02x000L, $1, $2, $3)
24 AC_LANG_PUSH([C])
25@@ -51,6 +52,7 @@ AC_DEFUN([ACX_OPENSSL],[
26 AC_MSG_ERROR([OpenSSL library too old ($1.$2.$3 or later required)])
27 ],[])
28 AC_LANG_POP([C])
29+ fi
30
31 CPPFLAGS=$tmp_CPPFLAGS
32 LIBS=$tmp_LIBS
33diff --git a/m4/acx_openssl_ecc.m4 b/m4/acx_openssl_ecc.m4
34index 612c505..ba2389d 100644
35--- a/m4/acx_openssl_ecc.m4
36+++ b/m4/acx_openssl_ecc.m4
37@@ -1,4 +1,5 @@
38 AC_DEFUN([ACX_OPENSSL_ECC],[
39+ if test "$cross_compiling" != yes; then
40 AC_MSG_CHECKING(for OpenSSL ECC support)
41
42 tmp_CPPFLAGS=$CPPFLAGS
43@@ -32,6 +33,8 @@ AC_DEFUN([ACX_OPENSSL_ECC],[
44 ],[])
45 AC_LANG_POP([C])
46
47+ fi
48+
49 CPPFLAGS=$tmp_CPPFLAGS
50 LIBS=$tmp_LIBS
51 ])
52diff --git a/m4/acx_openssl_fips.m4 b/m4/acx_openssl_fips.m4
53index 0491397..896cdbf 100644
54--- a/m4/acx_openssl_fips.m4
55+++ b/m4/acx_openssl_fips.m4
56@@ -1,4 +1,5 @@
57 AC_DEFUN([ACX_OPENSSL_FIPS],[
58+ if test "$cross_compiling" != yes; then
59 AC_MSG_CHECKING(for OpenSSL FIPS capable library)
60
61 tmp_CPPFLAGS=$CPPFLAGS
62@@ -47,4 +48,5 @@ AC_DEFUN([ACX_OPENSSL_FIPS],[
63
64 CPPFLAGS=$tmp_CPPFLAGS
65 LIBS=$tmp_LIBS
66+ fi
67 ])
68diff --git a/m4/acx_openssl_gost.m4 b/m4/acx_openssl_gost.m4
69index dca489b..34c39d8 100644
70--- a/m4/acx_openssl_gost.m4
71+++ b/m4/acx_openssl_gost.m4
72@@ -1,4 +1,5 @@
73 AC_DEFUN([ACX_OPENSSL_GOST],[
74+ if test "$cross_compiling" != yes; then
75 AC_MSG_CHECKING(for OpenSSL GOST support)
76
77 tmp_CPPFLAGS=$CPPFLAGS
78@@ -62,4 +63,5 @@ AC_DEFUN([ACX_OPENSSL_GOST],[
79
80 CPPFLAGS=$tmp_CPPFLAGS
81 LIBS=$tmp_LIBS
82+ fi
83 ])
84--
852.7.4
86
diff --git a/recipes-support/softhsm/softhsm_git.bb b/recipes-support/softhsm/softhsm_git.bb
new file mode 100644
index 0000000..c26903d
--- /dev/null
+++ b/recipes-support/softhsm/softhsm_git.bb
@@ -0,0 +1,27 @@
1SUMMARY = "HSM emulator"
2LICENSE = "BSD"
3LIC_FILES_CHKSUM = "file://LICENSE;md5=ef3f77a3507c3d91e75b9f2bdaee4210"
4
5inherit autotools-brokensep
6
7
8SRC_URI = "git://github.com/opendnssec/SoftHSMv2.git;branch=master \
9 file://0001-Cross-compilation-tweaks.patch"
10SRCREV="1f7498c0c65b1b1ad5e1bdbd87e9d4b100705745"
11
12S = "${WORKDIR}/git"
13
14DEPENDS += " openssl"
15
16EXTRA_OECONF = "--disable-gost --with-openssl=${STAGING_LIBDIR}/.."
17
18do_configure() {
19 unset docdir
20 sh ./autogen.sh
21 oe_runconf
22}
23
24FILES_${PN} = "${bindir} \
25 ${libdir}/softhsm \
26 ${sysconfdir} \
27 ${localstatedir}/lib/softhsm "
diff --git a/recipes-test/demo-network-config/files/25-dhcp-server.network b/recipes-test/demo-network-config/files/25-dhcp-server.network
new file mode 100644
index 0000000..4766f9a
--- /dev/null
+++ b/recipes-test/demo-network-config/files/25-dhcp-server.network
@@ -0,0 +1,12 @@
1[Match]
2Name=enp0s4
3
4[Network]
5Description=Private internal network between aktualizr Primary and Secondary nodes
6DHCPServer=yes
7Address=10.0.3.1/24
8IPForward=yes
9IPMasquerade=yes
10
11[DHCPServer]
12PoolOffset=10 \ No newline at end of file
diff --git a/recipes-test/demo-network-config/files/26-dhcp-client.network b/recipes-test/demo-network-config/files/26-dhcp-client.network
new file mode 100644
index 0000000..319664f
--- /dev/null
+++ b/recipes-test/demo-network-config/files/26-dhcp-client.network
@@ -0,0 +1,6 @@
1[Match]
2Name=enp0s4
3
4[Network]
5Description=Private internal network between aktualizr Primary and Secondary nodes
6DHCP=yes
diff --git a/recipes-test/demo-network-config/files/27-dhcp-client-external.network b/recipes-test/demo-network-config/files/27-dhcp-client-external.network
new file mode 100644
index 0000000..ba49593
--- /dev/null
+++ b/recipes-test/demo-network-config/files/27-dhcp-client-external.network
@@ -0,0 +1,6 @@
1[Match]
2Name=enp0s3
3
4[Network]
5Description=External network for secondary
6DHCP=yes
diff --git a/recipes-test/demo-network-config/primary-network-config.bb b/recipes-test/demo-network-config/primary-network-config.bb
new file mode 100644
index 0000000..78678a2
--- /dev/null
+++ b/recipes-test/demo-network-config/primary-network-config.bb
@@ -0,0 +1,16 @@
1DESCRIPTION = "Sample network configuration for an Uptane Primary"
2LICENSE = "CLOSED"
3
4inherit allarch
5
6SRC_URI = "file://25-dhcp-server.network"
7
8
9FILES_${PN} = "/usr/lib/systemd/network"
10
11PR = "1"
12
13do_install() {
14 install -d ${D}/usr/lib/systemd/network
15 install -m 0644 ${WORKDIR}/25-dhcp-server.network ${D}/usr/lib/systemd/network/
16}
diff --git a/recipes-test/demo-network-config/secondary-network-config.bb b/recipes-test/demo-network-config/secondary-network-config.bb
new file mode 100644
index 0000000..9091c65
--- /dev/null
+++ b/recipes-test/demo-network-config/secondary-network-config.bb
@@ -0,0 +1,20 @@
1DESCRIPTION = "Sample network configuration for an Uptane Secondary"
2LICENSE = "CLOSED"
3
4inherit allarch
5
6SRC_URI = "\
7 file://26-dhcp-client.network \
8 file://27-dhcp-client-external.network \
9 "
10
11
12FILES_${PN} = "/usr/lib/systemd/network"
13
14PR = "1"
15
16do_install() {
17 install -d ${D}/usr/lib/systemd/network
18 install -m 0644 ${WORKDIR}/26-dhcp-client.network ${D}/usr/lib/systemd/network/
19 install -m 0644 ${WORKDIR}/27-dhcp-client-external.network ${D}/usr/lib/systemd/network/
20}
diff --git a/recipes-test/images/primary-image.bb b/recipes-test/images/primary-image.bb
new file mode 100644
index 0000000..6d2df94
--- /dev/null
+++ b/recipes-test/images/primary-image.bb
@@ -0,0 +1,14 @@
1include recipes-core/images/core-image-minimal.bb
2
3SUMMARY = "A minimal Uptane Primary image running aktualizr, for testing with a Linux secondary"
4
5LICENSE = "MIT"
6
7IMAGE_INSTALL_remove = " \
8 "
9
10IMAGE_INSTALL_append = " \
11 primary-network-config \
12 "
13
14# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/recipes-test/images/secondary-image.bb b/recipes-test/images/secondary-image.bb
new file mode 100644
index 0000000..1a41169
--- /dev/null
+++ b/recipes-test/images/secondary-image.bb
@@ -0,0 +1,27 @@
1include recipes-core/images/core-image-minimal.bb
2
3SUMMARY = "A minimal Uptane Secondary image running aktualizr-secondary"
4
5LICENSE = "MIT"
6
7
8# Remove default aktualizr primary, and the provisioning configuration (which
9# RDEPENDS on aktualizr)
10IMAGE_INSTALL_remove = " \
11 aktualizr \
12 aktualizr-auto-prov \
13 aktualizr-auto-prov-creds \
14 aktualizr-ca-implicit-prov \
15 aktualizr-ca-implicit-prov-creds \
16 aktualizr-hsm-prov \
17 aktualizr-uboot-env-rollback \
18 connman \
19 connman-client \
20 "
21
22IMAGE_INSTALL_append = " \
23 aktualizr-secondary \
24 secondary-network-config \
25 "
26
27# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/scripts/qemucommand.py b/scripts/qemucommand.py
new file mode 100644
index 0000000..86362f7
--- /dev/null
+++ b/scripts/qemucommand.py
@@ -0,0 +1,132 @@
1from os.path import exists, join, realpath, abspath
2from os import listdir
3import random
4import socket
5from subprocess import check_output, CalledProcessError
6
7EXTENSIONS = {
8 'intel-corei7-64': 'wic',
9 'qemux86-64': 'otaimg'
10}
11
12
13def find_local_port(start_port):
14 """"
15 Find the next free TCP port after 'start_port'.
16 """
17
18 for port in range(start_port, start_port + 10):
19 try:
20 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
21 s.bind(('', port))
22 return port
23 except socket.error:
24 print("Skipping port %d" % port)
25 finally:
26 s.close()
27 raise Exception("Could not find a free TCP port")
28
29
30def random_mac():
31 """Return a random Ethernet MAC address
32 @link https://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml#ethernet-numbers-2
33 """
34 head = "ca:fe:"
35 hex_digits = '0123456789abcdef'
36 tail = ':'.join([random.choice(hex_digits) + random.choice(hex_digits) for _ in range(4)])
37 return head + tail
38
39
40class QemuCommand(object):
41 def __init__(self, args):
42 if args.machine:
43 self.machine = args.machine
44 else:
45 machines = listdir(args.dir)
46 if len(machines) == 1:
47 self.machine = machines[0]
48 else:
49 raise ValueError("Could not autodetect machine type. More than one entry in %s. Maybe --machine qemux86-64?" % args.dir)
50 if args.efi:
51 self.bios = 'OVMF.fd'
52 else:
53 uboot = abspath(join(args.dir, self.machine, 'u-boot-qemux86-64.rom'))
54 if not exists(uboot):
55 raise ValueError("U-Boot image %s does not exist" % uboot)
56 self.bios = uboot
57 if exists(args.imagename):
58 image = args.imagename
59 else:
60 ext = EXTENSIONS.get(self.machine, 'wic')
61 image = join(args.dir, self.machine, '%s-%s.%s' % (args.imagename, self.machine, ext))
62 self.image = realpath(image)
63 if not exists(self.image):
64 raise ValueError("OS image %s does not exist" % self.image)
65 if args.mac:
66 self.mac_address = args.mac
67 else:
68 self.mac_address = random_mac()
69 self.serial_port = find_local_port(8990)
70 self.ssh_port = find_local_port(2222)
71 if args.kvm is None:
72 # Autodetect KVM using 'kvm-ok'
73 try:
74 check_output(['kvm-ok'])
75 self.kvm = True
76 except Exception:
77 self.kvm = False
78 else:
79 self.kvm = args.kvm
80 self.gui = not args.no_gui
81 self.gdb = args.gdb
82 self.pcap = args.pcap
83 self.overlay = args.overlay
84 self.secondary_network = args.secondary_network
85
86 def command_line(self):
87 netuser = 'user,hostfwd=tcp:0.0.0.0:%d-:22,restrict=off' % self.ssh_port
88 if self.gdb:
89 netuser += ',hostfwd=tcp:0.0.0.0:2159-:2159'
90 cmdline = [
91 "qemu-system-x86_64",
92 "-bios", self.bios
93 ]
94 if not self.overlay:
95 cmdline += ["-drive", "file=%s,if=ide,format=raw,snapshot=on" % self.image]
96 cmdline += [
97 "-serial", "tcp:127.0.0.1:%d,server,nowait" % self.serial_port,
98 "-m", "1G",
99 "-usb",
100 "-device", "usb-tablet",
101 "-show-cursor",
102 "-vga", "std",
103 "-net", netuser,
104 "-net", "nic,macaddr=%s" % self.mac_address
105 ]
106 if self.pcap:
107 cmdline += ['-net', 'dump,file=' + self.pcap]
108 if self.secondary_network:
109 cmdline += [
110 '-net', 'nic,vlan=1,macaddr='+random_mac(),
111 '-net', 'socket,vlan=1,mcast=230.0.0.1:1234,localaddr=127.0.0.1',
112 ]
113 if self.gui:
114 cmdline += ["-serial", "stdio"]
115 else:
116 cmdline.append('-nographic')
117 if self.kvm:
118 cmdline += ['-enable-kvm', '-cpu', 'host']
119 else:
120 cmdline += ['-cpu', 'Haswell']
121 if self.overlay:
122 cmdline.append(self.overlay)
123 return cmdline
124
125 def img_command_line(self):
126 cmdline = [
127 "qemu-img", "create",
128 "-o", "backing_file=%s" % self.image,
129 "-f", "qcow2",
130 self.overlay]
131 return cmdline
132
diff --git a/scripts/run-qemu-ota b/scripts/run-qemu-ota
index 6a3586c..b2f55e9 100755
--- a/scripts/run-qemu-ota
+++ b/scripts/run-qemu-ota
@@ -2,127 +2,17 @@
2 2
3from argparse import ArgumentParser 3from argparse import ArgumentParser
4from subprocess import Popen 4from subprocess import Popen
5from os.path import exists, join, realpath 5from os.path import exists
6from os import listdir
7import random
8import sys 6import sys
9import socket 7from qemucommand import QemuCommand
10 8
11DEFAULT_DIR = 'tmp/deploy/images' 9DEFAULT_DIR = 'tmp/deploy/images'
12 10
13EXTENSIONS = {
14 'intel-corei7-64': 'wic',
15 'qemux86-64': 'otaimg'
16}
17
18
19def find_local_port(start_port):
20 """"
21 Find the next free TCP port after 'start_port'.
22 """
23
24 for port in range(start_port, start_port + 10):
25 try:
26 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
27 s.bind(('', port))
28 return port
29 except socket.error:
30 print("Skipping port %d" % port)
31 finally:
32 s.close()
33 raise Exception("Could not find a free TCP port")
34
35
36def random_mac():
37 """Return a random Ethernet MAC address
38 @link https://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml#ethernet-numbers-2
39 """
40 head = "ca:fe:"
41 hex_digits = '0123456789abcdef'
42 tail = ':'.join([random.choice(hex_digits) + random.choice(hex_digits) for _ in range(4)])
43 return head + tail
44
45
46class QemuCommand(object):
47 def __init__(self, args):
48 if args.machine:
49 self.machine = args.machine
50 else:
51 machines = listdir(args.dir)
52 if len(machines) == 1:
53 self.machine = machines[0]
54 else:
55 raise ValueError("Could not autodetect machine type from %s" % args.dir)
56 if args.efi:
57 self.bios = 'OVMF.fd'
58 else:
59 uboot = join(args.dir, self.machine, 'u-boot-qemux86-64.rom')
60 if not exists(uboot):
61 raise ValueError("U-Boot image %s does not exist" % uboot)
62 self.bios = uboot
63 ext = EXTENSIONS.get(self.machine, 'wic')
64 image = join(args.dir, self.machine, '%s-%s.%s' % (args.imagename, self.machine, ext))
65 self.image = realpath(image)
66 if not exists(self.image):
67 raise ValueError("OS image %s does not exist" % self.image)
68 if args.mac:
69 self.mac_address = args.mac
70 else:
71 self.mac_address = random_mac()
72 self.serial_port = find_local_port(8990)
73 self.ssh_port = find_local_port(2222)
74 self.kvm = not args.no_kvm
75 self.gui = not args.no_gui
76 self.gdb = args.gdb
77 self.pcap = args.pcap
78 self.overlay = args.overlay
79
80 def command_line(self):
81 netuser = 'user,hostfwd=tcp:0.0.0.0:%d-:22,restrict=off' % self.ssh_port
82 if self.gdb:
83 netuser += ',hostfwd=tcp:0.0.0.0:2159-:2159'
84 cmdline = [
85 "qemu-system-x86_64",
86 "-bios", self.bios
87 ]
88 if not self.overlay:
89 cmdline += ["-drive", "file=%s,if=ide,format=raw,snapshot=on" % self.image]
90 cmdline += [
91 "-serial", "tcp:127.0.0.1:%d,server,nowait" % self.serial_port,
92 "-m", "1G",
93 "-usb",
94 "-usbdevice", "tablet",
95 "-show-cursor",
96 "-vga", "std",
97 "-net", netuser,
98 "-net", "nic,macaddr=%s" % self.mac_address
99 ]
100 if self.pcap:
101 cmdline += ['-net', 'dump,file=' + self.pcap]
102 if self.gui:
103 cmdline += ["-serial", "stdio"]
104 else:
105 cmdline.append('-nographic')
106 if self.kvm:
107 cmdline.append('-enable-kvm')
108 else:
109 cmdline += ['-cpu', 'Haswell']
110 if self.overlay:
111 cmdline.append(self.overlay)
112 return cmdline
113
114 def img_command_line(self):
115 cmdline = [
116 "qemu-img", "create",
117 "-o", "backing_file=%s" % self.image,
118 "-f", "qcow2",
119 self.overlay]
120 return cmdline
121
122 11
123def main(): 12def main():
124 parser = ArgumentParser(description='Run meta-updater image in qemu') 13 parser = ArgumentParser(description='Run meta-updater image in qemu')
125 parser.add_argument('imagename', default='core-image-minimal', nargs='?') 14 parser.add_argument('imagename', default='core-image-minimal', nargs='?',
15 help="Either the name of the bitbake image target, or a path to the image to run")
126 parser.add_argument('mac', default=None, nargs='?') 16 parser.add_argument('mac', default=None, nargs='?')
127 parser.add_argument('--dir', default=DEFAULT_DIR, 17 parser.add_argument('--dir', default=DEFAULT_DIR,
128 help='Path to build directory containing the image and u-boot-qemux86-64.rom') 18 help='Path to build directory containing the image and u-boot-qemux86-64.rom')
@@ -131,11 +21,21 @@ def main():
131 'OSTREE_BOOTLOADER = "grub" and OVMF.fd firmware to be installed (try "apt install ovmf")', 21 'OSTREE_BOOTLOADER = "grub" and OVMF.fd firmware to be installed (try "apt install ovmf")',
132 action='store_true') 22 action='store_true')
133 parser.add_argument('--machine', default=None, help="Target MACHINE") 23 parser.add_argument('--machine', default=None, help="Target MACHINE")
134 parser.add_argument('--no-kvm', help='Disable KVM in QEMU', action='store_true') 24 kvm_group = parser.add_argument_group()
25 kvm_group.add_argument('--force-kvm', help='Force use of KVM (default is to autodetect)',
26 dest='kvm', action='store_true', default=None)
27 kvm_group.add_argument('--no-kvm', help='Disable KVM in QEMU',
28 dest='kvm', action='store_false')
135 parser.add_argument('--no-gui', help='Disable GUI', action='store_true') 29 parser.add_argument('--no-gui', help='Disable GUI', action='store_true')
136 parser.add_argument('--gdb', help='Export gdbserver port 2159 from the image', action='store_true') 30 parser.add_argument('--gdb', help='Export gdbserver port 2159 from the image', action='store_true')
137 parser.add_argument('--pcap', default=None, help='Dump all network traffic') 31 parser.add_argument('--pcap', default=None, help='Dump all network traffic')
138 parser.add_argument('-o', '--overlay', type=str, metavar='file.cow', help='Use an overlay storage image file. Will be created if it does not exist. This option lets you have a persistent image without modifying the underlying image file, permitting multiple different persistent machines.') 32 parser.add_argument('-o', '--overlay', type=str, metavar='file.cow',
33 help='Use an overlay storage image file. Will be created if it does not exist. ' +
34 'This option lets you have a persistent image without modifying the underlying image ' +
35 'file, permitting multiple different persistent machines.')
36 parser.add_argument('--secondary-network', action='store_true', dest='secondary_network',
37 help='Give the image a second network card connected to a virtual network. ' +
38 'This can be used to test Uptane Primary/Secondary communication.')
139 parser.add_argument('-n', '--dry-run', help='Print qemu command line rather then run it', action='store_true') 39 parser.add_argument('-n', '--dry-run', help='Print qemu command line rather then run it', action='store_true')
140 args = parser.parse_args() 40 args = parser.parse_args()
141 try: 41 try: