Trusted HTTPS and Code signing¶
Grendel can be setup to provision over HTTPS. This document will describe the process of setting up a custom certificate authority (CA), rebuilding iPXE to embed the CA.crt file, running Grendel provisioning server over HTTPS, and code signing boot images.
Note
These steps require building Grendel from source.
Install required software and Clone Grendel source code:¶
$ yum install lzma-sdk-devel xz-devel
# or
$ apt install liblzma-dev
$ go get -u github.com/go-bindata/go-bindata/...
$ git clone --recursive https://github.com/ubccr/grendel
$ cd grendel
Custom CA¶
Any method for obtaining SSL certificates is supported in Grendel. If you already have an organizational wide CA or use a commercial CA, all Grendel needs is the private key and signed certificates. This section will describe setting up your own custom CA used for signing SSL certificates. Here we use a tool called certstrap. These steps are also outlined in more detail here.
Initialize new certificate authority:¶
By default all output files will be created in a directory named out:
$ certstrap init --common-name "GrendelCA"
Create a new certificate request for the Grendel server¶
The common name should match the FQDN of your Grendel server:
$ certstrap request-cert --common-name grendel.local
Sign and generate the certificate¶
$ certstrap sign grendel.local --CA GrendelCA
You should now have 3 files in the out directory that we will configure Grendel to use to serve HTTPS:
out/GrendelCA.crt
out/grendel.local.crt
out/grendel.local.key
Rebuilding iPXE to include custom CA¶
We now need to rebuild the iPXE firmware to include the custom CA certificate we created in the previous step. This will allow iPXE to fetch provisioning assets over trusted HTTPS.
$ cd firmware
$ make clean
$ make build-with-ca
$ make bindata
$ cd ..
$ go build .
Note
The Makefile assumes your certificate authorities public key is in a file
named out/GrendelCA.crt
in the top level directory of the Grendel source.
If it's located elsewhere adjust the Makefile accordingly.
Now the grendel binary has the new custom built iPXE firmware embedded and is configured to trust the certificate authority we created in the previous step.
Grendel Configuration¶
Grendel uses a TOML file for configuration. To configure Grendel to use the SSL certificates created in the previous section, create a grendel.toml file with the following:
[provision]
listen = "0.0.0.0:443"
hostname = "grendel.local"
cert = "out/grendel.local.crt"
key = "out/grendel.local.key"
[dhcp]
dns_servers = ["192.168.10.254"]
Note
DNS resolution is required for HTTPS. You need to ensure the FQDN of your
grendel server (which is set via the hostname
in the above TOML) is
resovlable via dns. You must also set the dns_servers
in the dhcp
section to the IP address of your DNS server(s).
For testing with qemu, you can set the DNS server to be the IP address of the
tap0
device Grendel is listening on (as shown above). Then in the hosts.json
file just include a host for Grendel so it will resolve itself like so:
[{
"name": "tux01",
"provision": true,
"boot_image": "flatcar",
"interfaces": [
{
"fqdn": "tux01.local",
"ip": "192.168.10.12/24",
"mac": "DE:AD:BE:EF:12:8C"
}
]
},
{
"name": "grendel",
"provision": false,
"interfaces": [
{
"fqdn": "grendel.local",
"ip": "192.168.10.254/24"
}
]
}]
Start services¶
Now when you run Grendel it should be listening on port 443:
sudo ./grendel --verbose -c grendel.toml serve --hosts hosts.json --images images.json --listen 192.168.10.254
INFO CLI: Using config file: grendel.toml
INFO CLI: Using database path: :memory:
INFO CLI: Successfully loaded 2 hosts
INFO CLI: Successfully loaded 1 boot images
INFO TFTP: Server listening on: 192.168.10.254:69
INFO DHCP: Binding to interface: tap0
INFO PXE: Server listening on: 192.168.10.254:4011
INFO DHCP: Base URL for ipxe: https://grendel.local:443
INFO DNS: Server listening on: 192.168.10.254:53
INFO PROVISION: Listening on https://192.168.10.254:443
INFO PROVISION: ⇨ https server started on 192.168.10.254:443
INFO DHCP: Using DNS servers: [192.168.10.254]
INFO DHCP: Using Domain Search List: []
INFO DHCP: Default lease time: 24h0m0s
INFO DHCP: Default mtu: 1500
INFO DHCP: Using automatic router configuration
INFO DHCP: Netmask: ffffff00
INFO DHCP: Router Octet4: 1
INFO DHCP: Binding to interface: tap0
INFO DHCP: Server listening on: 192.168.10.254:67
INFO API: Listening on unix domain socket: grendel-api.socket
INFO API: ⇨ http server started on grendel-api.socket
If you followed the quickstart and are testing with qemu you can test PXE booting a vm and should now see iPXE downloading the flatcar kernel and initrd over HTTPS:
iPXE 1.0.0+ (3fe68) -- Open Source Network Boot Firmware -- http://ipxe.org
Features: DNS HTTP HTTPS iSCSI TFTP SRP VLAN AoE ELF MBOOT PXE bzImage
Configuring (net0 de:ad:be:ef:12:8c)... ok
https://grendel.local:443/boot/ipxe... ok
https://grendel.local:443/boot/file/kernel... ok
Code Signing Boot Images¶
Grendel (via iPXE) supports code signing, which allows you to verify the authenticity and integrity of boot images. For more information see the iPXE docs here. Using the custom CA we created in the previous section we create a new codesigning certificate that's used to digitally sign and verify boot images.
Create code signing certificate¶
$ certstrap request-cert --common-name codesigner.local
Sign and generate the certificate¶
$ certstrap sign --codesigning --CA GrendelCA codesigner.local
Note
certstrap doesn't currently support codesigning. There's an open PR here. In order to use the command above you can build the code from this branch here.
You should now have 2 files in the out directory that we will use to sign boot images:
out/codesigner.local.crt
out/codesigner.local.key
Sign Boot Image¶
We can now sign the boot image files using the code signing cert we created above. For example, to sign the flatcar kernel and initrd:
$ openssl cms -sign -binary -noattr -in flatcar_production_pxe.vmlinuz -signer out/codesinger.local.crt -inkey out/codesigner.local.key -certfile out/GrendelCA.crt -outform DER -out flatcar_production_pxe.vmlinuz.sig
$ openssl cms -sign -binary -noattr -in flatcar_production_pxe_image.cpio.gz -signer codesigner.local.crt -inkey out/codesigner.local.key -certfile out/GrendelCA.crt -outform DER -out flatcar_production_pxe_image.cpio.gz.sig
Create the Boot Image JSON¶
Add the "Verify" key to the Grendel boot image JSON:
[{
"name": "flatcar",
"verify": true,
"kernel": "flatcar_production_pxe.vmlinuz",
"initrd": [
"flatcar_production_pxe_image.cpio.gz"
],
"cmdline": "flatcar.autologin"
}]
If you followed the quickstart and are testing with qemu you can test PXE booting a vm and should now see iPXE verifying the flatcar kernel and initrd images:
iPXE 1.0.0+ (3fe68) -- Open Source Network Boot Firmware -- http://ipxe.org
Features: DNS HTTP HTTPS iSCSI TFTP SRP VLAN AoE ELF MBOOT PXE bzImage
Configuring (net0 de:ad:be:ef:12:8c)... ok
http://192.168.10.254:80/boot/ipxe... ok
http://192.168.10.254:80/boot/file/kernel... ok
http://192.168.10.254:80/boot/file/kernel.sig... ok
http://192.168.10.254:80/boot/file/initrd-0... ok
http://192.168.10.254:80/boot/file/initrd-0.sig... ok
Tip
You do not need to enable HTTPS with codesigning. They can be used seperately or together depending on your requirements.