Initial signing support (#1345)

* Add CLI options

* Add manifest types

* Thread signature policy through to fetchers

* Thread signing section through from metadata

* Implement signing validation

* Clippy

* Attempt testing

* Yes and

* Why

* fmt

* Update crates/bin/src/args.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/gh_crate_meta.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/bin/src/args.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/signing.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/signing.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/signing.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Update crates/binstalk-fetchers/src/signing.rs

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* fixes

* Finish feature

* Document

* Include all fields in the signing.file template

* Readme document

* Review fixes

* Fail on non-utf8 sig

* Thank goodness for tests

* Run test in ci

* Add rsign2 commands

* Log utf8 error

* Update e2e-tests/signing.sh

Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `e2e-tests/signing.sh` MacOS CI failure

Move the tls cert creation into `signing.sh` and sleep for 10s to wait
for https server to start.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Refactor e2e-tests-signing files

 - Use a tempdir generated by `mktemp` for all certificates-related
   files
 - Put other checked-in files into `e2e-tests/signing`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fixed `e2e-tests-signing` connection err in MacOS CI

Wait for server to start up by trying to connect to it.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `e2e-tests-signing` passing `-subj` to `openssl` on Windows

Use single quote instead of double quote to avoid automatic expansion
from bash

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix `e2e-tests-signing` waiting for server to startup

Remove `timeout` since it is not supported on MacOS.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Try to fix windows CI by setting `MSYS_NO_PATHCONV=1` on `openssl` cmds

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fixed `e2e-tests-signing` on windows

By using double `//` for the value passed to option `-subj`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fixed infinite loop in `signing/wait-for-server` on Windows

Pass `--ssl-revoke-best-effort` to prevent schannel from checking ssl
revocation status.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Add cap on retry attempt in `signing/wait-for-server.sh`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Let `singing/server.py` print output to stderr

so that we can see the error message there.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

* Fix running `signing/server.py` on MacOS CI

use `python3` since macos-latest still has python2 installed and
`python` is a symlink to `python2` there.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>

---------

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
Co-authored-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Félix Saparelli 2023-09-23 16:02:56 +12:00 committed by GitHub
parent efbd20857b
commit 32beba507b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 723 additions and 150 deletions

View file

@ -0,0 +1,19 @@
[package]
name = "signing-test"
description = "Rust binary package installer for CI integration"
version = "0.1.0"
authors = ["ryan <ryan@kurte.nz>"]
edition = "2021"
license = "GPL-3.0"
[[bin]]
name = "signing-test"
path = "src/main.rs"
[package.metadata.binstall]
pkg-url = "https://localhost:4443/signing-test.tar"
pkg-fmt = "tar"
[package.metadata.binstall.signing]
algorithm = "minisign"
pubkey = "RWRnmBcLmQbXVcEPWo2OOKMI36kki4GiI7gcBgIaPLwvxe14Wtxm9acX"

33
e2e-tests/signing.sh Executable file
View file

@ -0,0 +1,33 @@
#!/bin/bash
set -euxo pipefail
unset CARGO_INSTALL_ROOT
CARGO_HOME=$(mktemp -d 2>/dev/null || mktemp -d -t 'cargo-home')
export CARGO_HOME
export PATH="$CARGO_HOME/bin:$PATH"
echo Generate tls cert
CERT_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'cert-dir')
export CERT_DIR
openssl req -newkey rsa:4096 -x509 -sha256 -days 1 -nodes -out "$CERT_DIR/"ca.pem -keyout "$CERT_DIR/"ca.key -subj '//C=UT/CN=ca.localhost'
openssl req -new -newkey rsa:4096 -sha256 -nodes -out "$CERT_DIR/"server.csr -keyout "$CERT_DIR/"server.key -subj '//C=UT/CN=localhost'
openssl x509 -req -in "$CERT_DIR/"server.csr -CA "$CERT_DIR/"ca.pem -CAkey "$CERT_DIR/"ca.key -CAcreateserial -out "$CERT_DIR/"server.pem -days 1 -sha256 -extfile signing/server.ext
python3 signing/server.py &
server_pid=$!
trap 'kill $server_pid' ERR INT TERM
export BINSTALL_HTTPS_ROOT_CERTS="$CERT_DIR/ca.pem"
signing/wait-for-server.sh
"./$1" binstall --force --manifest-path manifests/signing-Cargo.toml --no-confirm signing-test
"./$1" binstall --force --manifest-path manifests/signing-Cargo.toml --no-confirm --only-signed signing-test
"./$1" binstall --force --manifest-path manifests/signing-Cargo.toml --no-confirm --skip-signatures signing-test
kill $server_pid || true

View file

@ -0,0 +1,2 @@
untrusted comment: minisign encrypted secret key
RWQAAEIyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ5gXC5kG11Wu99VVpToebb+yc0MOw4cbWzxSHyOxoSTu6kBrK09z/MEPWo2OOKMI36kki4GiI7gcBgIaPLwvxe14Wtxm9acXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=

View file

@ -0,0 +1,2 @@
untrusted comment: minisign public key 55D706990B179867
RWRnmBcLmQbXVcEPWo2OOKMI36kki4GiI7gcBgIaPLwvxe14Wtxm9acX

View file

@ -0,0 +1,6 @@
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost

View file

@ -0,0 +1,15 @@
import http.server
import os
import ssl
from pathlib import Path
cert_dir = Path(os.environ["CERT_DIR"])
os.chdir(os.path.dirname(__file__))
server_address = ('', 4443)
httpd = http.server.HTTPServer(server_address, http.server.SimpleHTTPRequestHandler)
ctx = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain(certfile=cert_dir / "server.pem", keyfile=cert_dir / "server.key")
httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()

View file

@ -0,0 +1,74 @@
; tiny97.asm, copyright Alexander Sotirov
BITS 32
;
; MZ header
; The only two fields that matter are e_magic and e_lfanew
mzhdr:
dw "MZ" ; e_magic
dw 0 ; e_cblp UNUSED
; PE signature
pesig:
dd "PE" ; e_cp, e_crlc UNUSED ; PE signature
; PE header
pehdr:
dw 0x014C ; e_cparhdr UNUSED ; Machine (Intel 386)
dw 1 ; e_minalloc UNUSED ; NumberOfSections
; dd 0xC3582A6A ; e_maxalloc, e_ss UNUSED ; TimeDateStamp UNUSED
; Entry point
start:
push byte 42
pop eax
ret
codesize equ $ - start
dd 0 ; e_sp, e_csum UNUSED ; PointerToSymbolTable UNUSED
dd 0 ; e_ip, e_cs UNUSED ; NumberOfSymbols UNUSED
dw sections-opthdr ; e_lsarlc UNUSED ; SizeOfOptionalHeader
dw 0x103 ; e_ovno UNUSED ; Characteristics
; PE optional header
; The debug directory size at offset 0x94 from here must be 0
filealign equ 4
sect_align equ 4 ; must be 4 because of e_lfanew
%define round(n, r) (((n+(r-1))/r)*r)
opthdr:
dw 0x10B ; e_res UNUSED ; Magic (PE32)
db 8 ; MajorLinkerVersion UNUSED
db 0 ; MinorLinkerVersion UNUSED
; PE code section
sections:
dd round(codesize, filealign) ; SizeOfCode UNUSED ; Name UNUSED
dd 0 ; e_oemid, e_oeminfo UNUSED ; SizeOfInitializedData UNUSED
dd codesize ; e_res2 UNUSED ; SizeOfUninitializedData UNUSED ; VirtualSize
dd start ; AddressOfEntryPoint ; VirtualAddress
dd codesize ; BaseOfCode UNUSED ; SizeOfRawData
dd start ; BaseOfData UNUSED ; PointerToRawData
dd 0x400000 ; ImageBase ; PointerToRelocations UNUSED
dd sect_align ; e_lfanew ; SectionAlignment ; PointerToLinenumbers UNUSED
dd filealign ; FileAlignment ; NumberOfRelocations, NumberOfLinenumbers UNUSED
dw 4 ; MajorOperatingSystemVersion UNUSED ; Characteristics UNUSED
dw 0 ; MinorOperatingSystemVersion UNUSED
dw 0 ; MajorImageVersion UNUSED
dw 0 ; MinorImageVersion UNUSED
dw 4 ; MajorSubsystemVersion
dw 0 ; MinorSubsystemVersion UNUSED
dd 0 ; Win32VersionValue UNUSED
dd round(hdrsize, sect_align)+round(codesize,sect_align) ; SizeOfImage
dd round(hdrsize, filealign) ; SizeOfHeaders
dd 0 ; CheckSum UNUSED
db 2 ; Subsystem (Win32 GUI)
hdrsize equ $ - $$
filesize equ $ - $$

Binary file not shown.

View file

@ -0,0 +1,4 @@
untrusted comment: signature from minisign secret key
RURnmBcLmQbXVVINqskhik18fjpzn1TTn7UZWPC6TuVNSZc+0CqLiNxJhBvT3aXiFHxiEwiBeQaFipsxXux06C12+rwT9Pozgwo=
trusted comment: timestamp:1693846563 file:signing-test.tar hashed
fQqqvTO6KgHSHf6/n18FQVJgO8azb1dB90jwj2YukbRfwK3QD0rNSDFBmhN73H7Pwxsz9of42OG60dfXA+ldCQ==

View file

@ -0,0 +1,16 @@
#!/bin/bash
set -euxo pipefail
CERT="${BINSTALL_HTTPS_ROOT_CERTS?}"
counter=0
while ! curl --cacert "$CERT" --ssl-revoke-best-effort -L https://localhost:4443/signing-test.tar | file -; do
counter=$(( counter + 1 ))
if [ "$counter" = "20" ]; then
echo Failed to connect to https server
exit 1;
fi
sleep 10
done