Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds initial support for building Hedgehog RPI images #294

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions RaspberryPi/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Copyright Β© 2017, Michael Stapelberg and contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

* Neither the name of Michael Stapelberg nor the
names of contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY Michael Stapelberg ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Michael Stapelberg BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
75 changes: 75 additions & 0 deletions RaspberryPi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
all: shasums

# List all the supported and built Pi platforms here. They get expanded
# to names like 'raspi_2_buster.yaml' and 'raspi_3_bullseye.img.xz'.
BUILD_FAMILIES := 1 2 3 4
BUILD_RELEASES := bullseye bookworm trixie

platforms := $(foreach plat, $(BUILD_FAMILIES),$(foreach rel, $(BUILD_RELEASES), raspi_$(plat)_$(rel)))

shasums: $(addsuffix .img.sha256,$(platforms)) $(addsuffix .img.xz.sha256,$(platforms))
xzimages: $(addsuffix .img.xz,$(platforms))
images: $(addsuffix .img,$(platforms))
yaml: $(addsuffix .yaml,$(platforms))

ifeq ($(shell id -u),0)
as_root =
else ifneq (,$(wildcard /usr/bin/fakemachine))
$(warning "This should normally be run as root, but found 'fakemachine', so using that.")
as_root = fakemachine -v $(CURDIR) -- env --chdir $(CURDIR)
else
$(error "This must be run as root")
endif

target_platforms:
@echo $(platforms)

# Generate targets based on all family * release combinations:
define dynamic_yaml_target =
raspi_$(1)_$(2).yaml: raspi_master.yaml generate-recipe.py
raspi_$(1)_$(2).yaml:
./generate-recipe.py $(1) $(2)
endef
$(foreach release,$(BUILD_RELEASES), \
$(foreach family,$(BUILD_FAMILIES), \
$(eval $(call dynamic_yaml_target,$(family),$(release)))))

%.img.sha256: %.img
echo $@
sha256sum $< > $@

%.img.xz.sha256: %.img.xz
echo $@
sha256sum $< > $@

%.img.xz: %.img
xz -f -k -z -9 $<

%.img.bmap: %.img
bmaptool create -o $@ $<

%.img: %.yaml
touch $(@:.img=.log)
time nice $(as_root) vmdb2 --verbose --rootfs-tarball=$(subst .img,.tar.gz,$@) --output=$@ $(subst .img,.yaml,$@) --log $(subst .img,.log,$@)
chmod 0644 $@ $(@,.img=.log)

_ck_root:
[ `whoami` = 'root' ] # Only root can summon vmdb2 ☹

_clean_yaml:
rm -f $(addsuffix .yaml,$(platforms)) raspi_base_bullseye.yaml raspi_base_bookworm.yaml raspi_base_trixie.yaml
_clean_images:
rm -f $(addsuffix .img,$(platforms))
_clean_xzimages:
rm -f $(addsuffix .img.xz,$(platforms))
_clean_bmaps:
rm -f $(addsuffix .img.bmap,$(platforms))
_clean_shasums:
rm -f $(addsuffix .img.sha256,$(platforms)) $(addsuffix .img.xz.sha256,$(platforms))
_clean_logs:
rm -f $(addsuffix .log,$(platforms))
_clean_tarballs:
rm -f $(addsuffix .tar.gz,$(platforms))
clean: _clean_xzimages _clean_images _clean_shasums _clean_yaml _clean_tarballs _clean_logs _clean_bmaps

.PHONY: _ck_root _build_img clean _clean_images _clean_yaml _clean_tarballs _clean_logs
118 changes: 118 additions & 0 deletions RaspberryPi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Raspberry Pi Hedgehog Sensor Build

This build process builds upon the Debian RPi build process located here:
http://salsa.debian.org/raspi-team/image-specs

## Building an image

Steps to build a Hedgehog Raspberry Pi image.
If you are reading this document online, you should first
clone this repository:

```shell
git clone https://github.com/cisagov/Malcolm.git
cd Malcolm/RaspberryPi
```

For this you will first need to install the following packages on a
Debian Bullseye (11), Devuan Daedalus (5), or higher system:

* binfmt-support
* bmap-tools
* debootstrap
* dosfstools
* fakemachine (optional, only available on amd64)
* kpartx
* qemu-utils
* qemu-user-static
* time
* vmdb2 (>= 0.17)
* python3

To install these (as root):
```shell
apt install -y vmdb2 dosfstools qemu-utils qemu-user-static debootstrap binfmt-support time kpartx bmap-tools python3
apt install -y fakemachine
```

If debootstrap still fails with exec format error, try
running `dpkg-reconfigure qemu-user-static`. This calls
`/var/lib/dpkg/info/qemu-user-static.postinst` which uses binfmt-support
to register the executable format with /usr/bin/qemu-$fmt-static

This repository includes a master YAML recipe (which is basically a
configuration file) for all of the generated images, diverting as
little as possible in a parametrized way. The master recipe is
[raspi_master.yaml](raspi_master.yaml).

A Makefile is supplied to drive the build of the recipes into images.
If `fakemachine` is installed, it can be run as an unprivileged user.
Otherwise, because some steps of building the image require root privileges,
you'll need to execute `make` as root.

The argument to `make` is constructed as follows:
`raspi_<model>_<release>.<result-type>`

Whereby <model\> is one of `1`, `2`, `3` or `4`, <release\> is either
`bullseye`, `bookworm`, or `trixie`; and <result-type\> is `img` or `yaml`.

Model `1` should be used for the Raspberry Pi 0, 0w and 1, models A and
B. Model `2` for the Raspberry Pi 2 models A and B. Model `3` for all
models of the Raspberry Pi 3 and model `4` for all models of the
Raspberry Pi 4.
So if you want to build the default image for a Raspberry Pi 3B+ with
Bullseye, you can just issue:

```shell
make raspi_4_bookworm.img
```

**NOTE:** While this setup will build hedgehog for all raspberry pi variants, it is highly unlikely
that any variant other than RPI 4 (8GB version) will have adequate resources to function effectively as a sensor.

At this point; it might be wise to go do something else. The build **WILL** take a while.
Initial testing on a 8-core 16GB build machine took approximately 5.5 hours to complete the image.

## Installing the image onto the Raspberry Pi

If the build completes properly, it can be tested locally before writing to an SD card if desired.
To do so, simply run (as root):

```shell
mount -o loop,offset=$((1048576*512)) raspi_4_bookworm.img /mnt && chroot /mnt
```

If an error is returned by the mount command, there is a chance the image was corrupted during the build.
It is, unfortunately, advised to run `make clean` and rebuild the image.

Plug an SD card which you would like to **entirely OVERWRITE** into the Build machine's SD card reader.

Assuming your SD card reader provides the device `/dev/mmcblk0`
(**Beware** If you choose the wrong device, you might overwrite
important parts of your system. Double check it's the correct
device!), copy the image onto the SD card:

```shell
bmaptool copy raspi_3_bullseye.img.xz /dev/mmcblk0
```

Alternatively, if you don't have `bmap-tools` installed, you can use
`dd` with the compressed image:

```shell
xzcat raspi_3_bullseye.img | dd of=/dev/mmcblk0 bs=64k oflag=dsync status=progress
```

Or with the uncompressed image:

```shell
dd if=raspi_3_bullseye.img of=/dev/mmcblk0 bs=64k oflag=dsync status=progress
```

Then, plug the SD card into the Raspberry Pi, and power it up.

The image uses the hostname `Hedgehog-rpi-0w`, `Hedgehog-rpi-2`, `Hedgehog-rpi-3`, or `Hedgehog-rpi-4` depending on the
target build. The provided image will allow you to log in with the
`sensor` account with a default password of `Hedgehog_Linux` or
`root` account with a default password of `Hedgehog_Linux_Root`, but only logging in at the
physical console (be it serial or by USB keyboard and HDMI monitor).
43 changes: 43 additions & 0 deletions RaspberryPi/debian/salsa-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
stages:
# Garbage in is garbage out, so verify our input
- check input
- build

variables:
DEBIAN_FRONTEND: "noninteractive"
# At https://salsa.debian.org/salsa-ci-team/pipeline/container_registry one can see which images are available
SALSA_CI_IMAGES: registry.salsa.debian.org/salsa-ci-team/pipeline
BASE_CI_IMAGES: ${SALSA_CI_IMAGES}/base

yamllint:
stage: check input
image: $BASE_CI_IMAGES:unstable
dependencies: []
script:
- apt-get update && apt-get upgrade -y
- apt-get install -y yamllint
- yamllint -c debian/yamllint.yml .

shellcheck:
stage: check input
image: $BASE_CI_IMAGES:unstable
dependencies: []
script:
- apt-get update && apt-get upgrade -y
- apt-get install -y shellcheck
- shellcheck -e SC1090,SC1091 -s dash $(find rootfs/etc/initramfs-tools -type f -executable | xargs grep -l '^#!/bin/sh')

build yamls:
stage: build
image: $BASE_CI_IMAGES:unstable
dependencies: []
script:
- apt-get update && apt-get upgrade -y
- apt-get install -y python3 make git
- make yaml
- mkdir build
- cp raspi*.yaml build/
artifacts:
paths:
- build/
6 changes: 6 additions & 0 deletions RaspberryPi/debian/yamllint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---

extends: default

rules:
line-length: disable
Loading