in-toto openSUSE demo
In this demo, we will use in-toto to secure a software supply chain for OpenSUSE. Bob is a developer for a project, Carl tests the software before packaging, and Alice oversees the project. So, using in-toto's names for the parties, Alice is the project owner — she creates and signs the software supply chain layout with her private key — and Bob and Carl are project functionaries — they carry out the steps of the software supply chain as defined in the layout.
For the sake of demonstrating in-toto, we will have you run all parts of the software supply chain. That is, you will perform the commands on behalf of Alice, Bob and Carl as well as the client who verifies the final product.
Install docker https://docs.docker.com/engine/installation/
Pull and run the docker image for this demo
docker pull intoto/opensuse-demo docker run --privileged -i -t intoto/opensuse-demo:latest
This demo requires an account on opensuse build service. If you don't have an account you could either sign up for one easily to continue. Or you could try our offline demo.
Signup for an account on opensuse build service at https://build.opensuse.org/ICSLogin/
Set your username as environment variable so that you can copy paste the demo commands
Change into the demo directory and you are ready to start
Inside the demo-opensuse directory you will find four directories:
final_product. Alice, Bob and Carl
already have RSA keys in each of their directories. This is what you see:
tree # If you don't have tree, try 'find .' instead # the tree command gives you the following output # ├── Dockerfile # ├── Offline-demo.md # ├── README.md # ├── final_product # ├── functionary_bob # │ ├── bob # │ └── bob.pub # ├── functionary_carl # │ ├── carl # │ └── carl.pub # └── owner_alice # ├── alice # ├── alice.pub # ├── create_layout.py # ├── create_layout_offline.py # └── verify-signature.sh
Define software supply chain layout (Alice)
First, we will create a new package on openSUSE's open build server. Next we will define the software supply chain layout. To simplify this process, we provide a script that generates a simple layout for the purpose of the demo.
Three people participate in this software supply chain, Alice, Bob and Carl. Alice is the project owner that creates the root layout. Bob is the developer, and he clones the project's repo and performs some pre-packaging edits. Carl then tests the sources and verifies that its fit to ship. Carl then commits the package which triggers open build server to build the RPMs.
Create and sign the software supply chain layout on behalf of Alice
cd owner_alice/ python create_layout.py
The script will create a layout, add Bob's and Carl's public keys (fetched from
their directories), sign it with Alice's private key and dump it to
root.layout, you will find that (besides the signature and other information)
there are five steps,
package, that the functionaries Bob and Carl, identified by their public keys,
are authorized to perform.
Setup project (Bob)
Execute the following commands to change to Bob's directory and perform the step.
Checkout your default project. You will be prompted for your username and password which is stored in
~/.oscrc as plain text.
cd ../functionary_bob osc checkout home:$username
Specify the build target
osc meta prj -e home:$username
This will open a template xml in your favourite editor. For this demo uncomment the first one.
<repository name="openSUSE_Factory"> <path project="openSUSE:Factory" repository="standard" /> <arch>x86_64</arch> <arch>i586</arch> </repository>
Create a new package named connman in your home project
cd home:$username osc meta pkg -e home:$username connman
osc will open a template xml, fill out name, title, description. You can see your package here https://build.opensuse.org/package/show/home:$username/connman (replace $username in url with actual username).
Update the local copy from the central server. you will get a new connman directory
Now we will create a link file as a proof that Bob created the meta files for the project and package. The link will contain the hashes of both the meta files so in the future if something goes wrong we can figure out if Bob made a mistake or someone else changed the file.
in-toto-record --step-name setup-project --key ../bob start osc meta prj home:$username >> project.meta osc meta pkg home:$username connman >> package.meta in-toto-record --step-name setup-project --key ../bob stop --products project.meta package.meta
Clone project source code (Bob)
Now, we will take the role of the functionary Bob and perform the step
clone on his behalf, that is we use in-toto to clone the project repo from GitHub and
record metadata for what we do.
in-toto-record --step-name clone --key ../bob start git clone file:///home/connman/.git/ connman-src mv connman-src/* connman/ rm -r connman-src in-toto-record --step-name clone --key ../bob stop --products connman/_service connman/connman-1.30.tar.gz connman/connman-1.30.tar.sign connman/connman-rpmlintrc connman/connman.changes connman/connman.keyring connman/connman.spec
Here is what happens behind the scenes:
- In-toto wraps the work of Bob,
- hashes the contents of the source code,
- adds the hash together with other information to a metadata file,
- signs the metadata with Bob's private key, and
- stores everything to
Before Carl tests and commits the source code, Bob will update the changelog saved in
connman.changes. He does this using the
in-toto-record command, which produces the same link metadata file as above but does not require Bob to wrap his action in a single command. So first Bob records the state of the files he will modify:
in-toto-record --step-name update-changelog --key ../bob start --materials connman/connman.changes
Then Bob uses an editor of his choice to update the changelog e.g.:
And finally he records the state of files after the modification and produces
a link metadata file called
in-toto-record --step-name update-changelog --key ../bob stop --products connman/connman.changes
Bob has done his work and can send over the sources to Carl.
cd .. mv home:$username/ ../functionary_carl/
Now, we will perform Carl’s
test step by executing the following commands to change to Carl's directory.
cd ../functionary_carl/home:$username/ in-toto-run --step-name test --key ../carl -- osc build openSUSE_Factory x86_64 connman/connman.spec
It will prompt you to trust the gpg key for
openSUSE:Factory, Choose 1
Would you like to ... 0 - quit (default) 1 - always trust packages from 'openSUSE:Factory' 2 - trust packages just this time ? 1
This will create a step link metadata file, called
Now we will execute the package step.
in-toto-record --step-name package --key ../carl start --materials connman/*
Commit changes, this would trigger an automatic build on open build server.
cd connman osc add * osc commit
Download the build RPM from server
cd ../ wget http://download.opensuse.org/repositories/home:/$username/openSUSE_Factory/src/connman-1.30-1.1.src.rpm
And finally he records the state of files after the modification and produces
a link metadata file, called
in-toto-record --step-name package --key ../carl stop --products connman-1.30-1.1.src.rpm
Verify final product (client)
Let's first copy all relevant files into the
final_product that is
our software package
<srcpackage.rpm> and the related metadata files
test.[Carl's keyid].link and
cd ../../ cp owner_alice/root.layout owner_alice/verify-signature.sh functionary_carl/home:$username/setup-project.0c6c50a1.link functionary_carl/home:$username/clone.0c6c50a1.link functionary_carl/home:$username/update-changelog.0c6c50a1.link functionary_carl/home:$username/test.c1ae1e51.link functionary_carl/home:$username/package.c1ae1e51.link functionary_carl/home:$username/connman-1.30-1.1.src.rpm final_product/
And now run verification on behalf of the client:
cd final_product # Fetch Alice's public key from a trusted source to verify the layout signature # Note: The functionary public keys are fetched from the layout cp ../owner_alice/alice.pub . in-toto-verify --layout root.layout --layout-key alice.pub
This command will verify that
- the layout has not expired,
- was signed with Alice’s private key, and that according to the definitions in the layout
- each step was performed and signed by the authorized functionary
- the recorded materials and products follow the artifact rules and
- the inspection
unpackfinds what it expects.
- the inspection
verify-signaturechecks that the signature for connman tarball is correct.
From it, you will see the meaningful output
PASSING and a return value
0, that indicates verification was successful:
echo $? # should output 0
Congratulations! You have completed the in-toto opensuse demo!
Your package can now be installed in openSUSE systems. Instructions to do so can be found here https://software.opensuse.org//download.html?project=home%3A$username&package=connman (replace $username in url with actual username). If in-toto was integrated with Open Build System and
zypper, testing and packaging step would be done on Open Build System. In-toto meta data would be hosted on http://download.opensuse.org/repositories/home:/$username/ (replace $username in url with actual username) along with the build RPMs.
zypper would download and verify in-toto metadata along with the downloaded RPMs.
This exercise shows a very simple case in how in-toto can protect the different steps within the software supply chain. More complex software supply chains that contain more steps can be created in a similar way. You can read more about what in-toto protects against and how to use it on in-toto's Github page.
We will delete the connman package from your home project now.
cd ../functionary_carl/home:$username osc delete connman osc ci -m "remove package"