…
|
||
---|---|---|
.. | ||
README.md |
README.md
Building a Secure Software Supply Chain with GNU Guix
Artifact Evaluation
Getting Started
The artifact is a virtual machine (VM) image, in QCOW2 format, which can be used by most emulators:
- image: https://ftp.gnu.org/gnu/guix/guix-system-vm-image-1.3.0.x86_64-linux.qcow2
- OpenPGP signature: https://ftp.gnu.org/gnu/guix/guix-system-vm-image-1.3.0.x86_64-linux.qcow2.sig
- SHA256: 980312e9c94204537a9e0f7fca7d765fc316686a8bbaff111989688ce353b16c
- usage instructions: https://guix.gnu.org/manual/en/html_node/Running-Guix-in-a-VM.html
In a nutshell, you can run the following commands on an x86_64 GNU/Linux system to retrieve and authenticate the image:
wget -O /tmp/qemu-image \
https://ftp.gnu.org/gnu/guix/guix-system-vm-image-1.3.0.x86_64-linux.qcow2
wget -O /tmp/qemu-image.sig \
https://ftp.gnu.org/gnu/guix/guix-system-vm-image-1.3.0.x86_64-linux.qcow2.sig
wget https://sv.gnu.org/people/viewgpg.php?user_id=127547 \
-qO - | gpg --import -
gpg --verify /tmp/qemu-image.sig
You can then spawn the VM, using QEMU (with network
access, as specified with -nic
, and at least 2 GiB of RAM, as
specified with -m
):
qemu-system-x86_64 \
-nic user,model=virtio-net-pci \
-enable-kvm -m 2048 \
-device virtio-blk,drive=myhd \
-drive if=none,file=/tmp/qemu-image,id=myhd
Note: We highly recommend running this on an x86_64 machine (64-bit AMD/Intel processor); running it from another architecture would incur significant run-time overhead.
Furthermore, when using QEMU on GNU/Linux, the
-enable-kvm
switch instructs QEMU to use the KVM virtualization mechanism, which allows it to run code with very little overhead compared to native code. You can omit the-enable-kvm
option (for example if KVM is not supported on your machine or if you are not running GNU/Linux), but be aware that emulation without KVM will be much slower.
Please see the installation instructions mentioned above for more information.
Contents of the Virtual Machine Image
The image is not specific to this artifact evaluation: it is a “live” image of Guix System distributed as part of the latest Guix release (version 1.3.0 in this case).
The live image boots in a graphical environment, Xfce. You can start a terminal by clicking on the terminal icon at the bottom of the screen.
The shell lets you run various commands, in particular the ‘guix’ command and the usual GNU/Linux utilities. You can also use it to install more packages. For instance, you might install Emacs by running:
guix install emacs
Note that most
guix
operations rely on good network connectivity to download packages. Failures due to transient networking issues are harmless; operations such asguix install
andguix pull
are transactional and can be restarted without any risks.
Supported Claims
Performance
Claim: our code authenticates between 600 and 700 commits per second.
The image runs version 1.3.0 of Guix, released in May 2020. You can update it by running:
guix pull --commit=20303c0b1c75bc4770cdfa8b8c6b33fd6e77c168
This will first make a local clone of the Git repository of Guix, which can take several minutes; a progress bar is displayed during that process.
This is followed by a message along these lines:
Authenticating channel 'guix', commits 9edb3f6 to 20303c0 (17,390 new commits)...
This message and the subsequent progress bar correspond to the authentication of commits between the revision that is shipped and the target revision, a year and more than 17,000 commits later. This process (starting from the “Authenticating …” message until the progress bar reaches 100%) should take less than a minute on recent hardware, consistent with Section 8.3 of the paper.
The performance claim can also be verified by running guix git authenticate
as will be shown below.
Note: To verify the performance claim, you must be running QEMU on an x86_64 machine and with
-enable-kvm
flag. Failing to do that, the emulation overhead will be prohibitively high.
Commit Authentication
Claim: guix pull
authenticates commits.
The Git authentication code, like the rest of Guix, is free software. It underwent a public review process among Guix developers. It is written in Scheme, a functional programming language of the Lisp family, and the current revision can be seen at:
- core Git authentication module
- authentication support for the “channel” mechanism, used by
guix pull
- unit tests of the authentication module
This code is used by the guix
command provided in this virtual machine
image.
More informally, to experiment with the authentication mechanism, we invite reviewers to follow the steps below:
- Install Git and GnuPG with
guix install git gnupg
. - Clone the Guix repository:
git clone https://git.savannah.gnu.org/git/guix.git; cd guix
- Notice that commits are signed:
git log --oneline --show-signature
. - With the command above,
gpg
will report display information about each commit signature and report that public keys are unavailable in its keyring (“No public key”). Those keys are available in thekeyring
branch and can be imported from there:git checkout keyring && cat *.key | gpg --import
. - Going back to our target revision, we can see that
gpg
can indeed verify signatures now:git checkout 20303c0b1c75bc4770cdfa8b8c6b33fd6e77c168 && git log --oneline --show-signature
.gpg
warns about expired keys but, as the paper notes, OpenPGP key expiration dates are ignored for our purposes (and the authentication code in Guix does not usegpg
).
We can now exercise the authentication code of Guix, this time using the
guix git authenticate
command, which is low-level compared to guix pull
(it operates on raw Git repositories rather than on channels). To
authenticate the repository, run:
guix git authenticate \
9edb3f66fd807b096b48283debdcddccfea34bad \
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA"
This authenticates the whole repository, starting from commit 9edb3f6
,
which is expected to be signed by the OpenPGP key with fingerprint BBB0 2DDF …
. This corresponds to what our guix pull
command above did
though guix pull
was able to skip parent commits of its own commit (as
returned by guix describe
). On success, guix git authenticate
prints nothing and has exit code zero. A cache of
previously-authenticated commits is kept under
~/.cache/guix/authentication
.
To see the effect of an unsigned commit on authentication, run:
git config --global user.email reviewer@example.org
git config --global user.name Programming
git rm README
git commit -m "This is unsigned." -a
guix git authenticate \
9edb3f66fd807b096b48283debdcddccfea34bad \
"BBB0 2DDF 2CEA F6A8 0D1D E643 A2A0 6DF2 A33A 54FA"
This time, the command should fail with an error such as:
guix git: error: commit XYZ lacks a signature
One can similarly test the effect of a commit signed with an
unauthorized key—a key whose fingerprint does not appear in the
.guix-authorizations
file.
This behavior shown here is consistent with the claims in Section 4 of the paper.
Downgrade Prevention
Claim: guix pull
cannot unwillingly downgrade guix
.
If you ran guix pull --commit=20303c0b1c75bc4770cdfa8b8c6b33fd6e77c168
as instructed above, the revision of Guix you are now using is commit
20303c0…; guix describe
should confirm that.
Now let’s instruct guix pull
to target a commit that is the parent of
this one and is thus “older”:
guix pull --commit=b1e7e64f351fa03a66ce1f9776f9ba84cf2c6294
This command fails with:
guix pull: error: aborting update of channel 'guix' to commit
b1e7e64f351fa03a66ce1f9776f9ba84cf2c6294, which is not a descendant of
20303c0b1c75bc4770cdfa8b8c6b33fd6e77c168
An attempt to pull the version-1.2.0
branch, which is older than the
currently used commit, fails in a similar way:
guix pull --branch=version-1.2.0
This is consistent with claims in Section 6 of the paper.
System Downgrade Prevention
Claim: guix system reconfigure
cannot unwillingly downgrade the system.
The paper further claims that guix system reconfigure
similarly
prevents downgrade of the system. To verify this claim, we need to
reconfigure (upgrade) the system running in the VM twice: first update
it to commit 20303c0, then attempt to reconfigure it from an older
commit, and notice that it fails.
Note: The first
reconfigure
operation is demanding in terms of disk space and network bandwidth and takes several minutes, mostly downloading the latest software packages. It is necessary because the system running in the VM lacks provenance information:guix system describe
does not show the commit that was used to build it.
First, reconfigure the system:
sudo guix system reconfigure /run/current-system/configuration.scm
Upon completion, notice that the system provenance is indeed commit 20303c0 as shown in the “channels” section of:
guix system describe
From there, attempt to reconfigure to an older commit (we use
time-machine
which fetches the given commit, similar to what guix pull
does, and immediately launches, from that commit, the command that
follows):
sudo guix time-machine \
--commit=b1e7e64f351fa03a66ce1f9776f9ba84cf2c6294 -- \
system reconfigure /run/current-system/configuration.scm
This command first builds the requested Guix revision, which can take a
few minutes. The subsequent system reconfigure
fails:
guix system: error: aborting reconfiguration because commit
b1e7e64f351fa03a66ce1f9776f9ba84cf2c6294 of channel 'guix' is not a
descendant of 20303c0b1c75bc4770cdfa8b8c6b33fd6e77c168
This is consistent with claims in Section 6 of the paper.
Claim: Likewise, guix deploy
cannot unwillingly downgrade the system
on a set of machines.
We do not provide instructions to verify this claim because it requires
a set of one or more machines running Guix System that we would remotely
upgrade over SSH (secure shell), which is impractical to set up.
Downgrade prevention for guix deploy
builds upon downgrade prevention for guix system reconfigure
.