Skip to content

Commit

Permalink
build: Refactor signing process
Browse files Browse the repository at this point in the history
Signed-off-by: Paulo Gomes <[email protected]>
  • Loading branch information
pjbgf committed Jan 23, 2024
1 parent 4490c7c commit a39f1c6
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 333 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ jobs:
with:
go-version: 'stable'

- run: make build
- run: make build DRY_RUN=true
17 changes: 12 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ RUN yum install -y \
selinux-policy-devel \
yum-utils \
rpm-build \
rpm-sign expect
rpm-sign expect \
unzip

# Confirm this is needed, move to final if not.
COPY hack/centos7_sign /usr/local/bin/sign
Expand All @@ -25,7 +26,8 @@ RUN yum install -y \
selinux-policy-devel \
yum-utils \
rpm-build \
rpm-sign
rpm-sign \
unzip

# Move to final stage if centos7_sign is removed.
COPY hack/sign /usr/local/bin/sign
Expand All @@ -38,7 +40,8 @@ RUN yum install -y \
selinux-policy-devel \
yum-utils \
rpm-build \
rpm-sign
rpm-sign \
unzip

# Move to final stage if centos7_sign is removed.
COPY hack/sign /usr/local/bin/sign
Expand All @@ -48,7 +51,9 @@ RUN dnf install -y \
createrepo_c \
container-selinux \
selinux-policy-devel \
rpm-build
rpm-build \
rpm-sign \
unzip

# Move to final stage if centos7_sign is removed.
COPY hack/sign /usr/local/bin/sign
Expand All @@ -57,7 +62,9 @@ FROM opensuse/tumbleweed as microos
RUN zypper install -y \
container-selinux \
selinux-policy-devel \
rpm-build
rpm-build \
rpm \
unzip

# libglib is required to install createrepo_c in Tumbleweed.
RUN zypper install -y libglib-2_0-0 createrepo_c
Expand Down
24 changes: 24 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
RUNNER ?= docker
POLICIES = $(shell find policy -mindepth 2 -maxdepth 2 -type d | sort -u | cut -f 2 -d'/')

DRY_RUN ?= false
SIGN_KEY_EMAIL ?= [email protected]
PRIVATE_KEY ?=
PRIVATE_KEY_PASS_PHRASE ?=
TESTING_PRIVATE_KEY ?=
TESTING_PRIVATE_KEY_PASS_PHRASE ?=

ifeq ($(DRY_RUN),true)
DRY_RUN_SIGN := --dry-run
endif

SHELL := /bin/bash

include hack/make/version.mk

.PHONY: build
Expand All @@ -11,6 +24,7 @@ build: ## build all policies.
$(MAKE) $(subst :,/,$*)-build-clean
$(MAKE) $(subst :,/,$*)-build-image
$(MAKE) $(subst :,/,$*)-build-artefacts
$(MAKE) $(subst :,/,$*)-build-sign
$(MAKE) $(subst :,/,$*)-build-metadata

%-build-image: ## build the container image used to generate a given policy.
Expand All @@ -27,6 +41,16 @@ build: ## build all policies.
-v $(shell pwd)/build/$(subst :,/,$*):/out \
rancher-selinux:$(subst :,/,$*) ./build $(RPM_VERSION) $(RPM_RELEASE)

%-build-sign: ## sign the generate rpms of a given policy.
@$(RUNNER) run --rm \
-e USER=$(shell id -u) -e GROUP=$(shell id -g) \
-e SIGN_KEY_EMAIL -e RPM_CHANNEL="$(RPM_CHANNEL)" \
-e TESTING_PRIVATE_KEY_PASS_PHRASE \
-e TESTING_PRIVATE_KEY \
-e PRIVATE_KEY -e PRIVATE_KEY_PASS_PHRASE \
-v $(shell pwd)/build/$(subst :,/,$*):/dist \
rancher-selinux:$(subst :,/,$*) sign $(DRY_RUN_SIGN)

%-build-metadata: ## generate repository metadata for a given policy.
$(RUNNER) run --rm \
-e USER=$(shell id -u) -e GROUP=$(shell id -g) \
Expand Down
93 changes: 93 additions & 0 deletions hack/centos7_sign
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/bash
set -eo pipefail

PASSPHRASE_VAR=""

function dryrun() {
export TESTING_PRIVATE_KEY_PASS_PHRASE=$(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c20)
export PASSPHRASE_VAR=TESTING_PRIVATE_KEY_PASS_PHRASE

cat <<\EOF >~/.rpmmacros
%_signature gpg
%_gpg_name disposable-ci-test-key
EOF

gpg --gen-key --batch <(echo "Key-Type: 1"; \
echo "Key-Length: 2048"; \
echo "Subkey-Type: 1"; \
echo "Subkey-Length: 2048"; \
echo "Expire-Date: 0"; \
echo "Name-Real: disposable-ci-test-key"; \
echo "Name-Email: disposable-ci-test-key"; \
echo "%no-protection"; )

sign_rpms
}

function check_vars()
{
echo "checking for required vars"

local required_vars
required_vars=(SIGN_KEY_EMAIL RPM_CHANNEL)

for var in "${required_vars[@]}"; do
[ -z "${!var}" ] && echo "$var is not set." && var_unset=true
done

[ -n "${var_unset}" ] && exit 1
return 0
}

function import_key() {
cat <<\EOF >~/.rpmmacros
%_signature gpg
%_gpg_name [email protected]
EOF

case "${RPM_CHANNEL}" in
"testing")
PASSPHRASE_VAR="TESTING_PRIVATE_KEY_PASS_PHRASE"
KEY_VAR="TESTING_PRIVATE_KEY"
;;
"production")
PASSPHRASE_VAR="PRIVATE_KEY_PASS_PHRASE"
KEY_VAR="PRIVATE_KEY"
;;
*)
echo "RPM_CHANNEL ${RPM_CHANNEL} does not match one of: [testing, production]"
exit 1
;;
esac

if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"${!KEY_VAR}"; then
echo "${KEY_VAR} not defined, failing rpm sign"
exit 1
fi
gpg --import - <<<"${!KEY_VAR}"
echo "Signing keys imported successfully"
}

function sign_rpms() {
expect <<EOF
set timeout 60
spawn sh -c "rpmsign --addsign /dist/**/rancher-*.rpm"
expect "Enter pass phrase:"
send -- "${!PASSPHRASE_VAR}\r"
expect eof
lassign [wait] _ _ _ code
exit \$code
EOF
}

function main (){
check_vars
import_key
sign_rpms
}

if [[ "$1" == "--dry-run" ]]; then
dryrun
else
main
fi
92 changes: 92 additions & 0 deletions hack/sign
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/bin/bash
set -eo pipefail

PASSPHRASE_VAR=""

function dryrun() {
export SIGN_KEY_EMAIL="disposable-ci-test-key"
export TESTING_PRIVATE_KEY_PASS_PHRASE=$(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c20)
export PASSPHRASE_VAR=TESTING_PRIVATE_KEY_PASS_PHRASE

gpg --quiet --no-tty --pinentry-mode loopback --passphrase "${TESTING_PRIVATE_KEY_PASS_PHRASE}" \
--quick-gen-key --yes "${SIGN_KEY_EMAIL}" rsa2048

sign_rpms
verify_signatures
}

function check_vars()
{
echo "checking for required vars"

local required_vars
required_vars=(SIGN_KEY_EMAIL RPM_CHANNEL)

for var in "${required_vars[@]}"; do
[ -z "${!var}" ] && echo "$var is not set." && var_unset=true
done

[ -n "${var_unset}" ] && exit 1
return 0
}

function check_channel(){
case "${RPM_CHANNEL}" in
"testing")
PASSPHRASE_VAR="TESTING_PRIVATE_KEY_PASS_PHRASE"
KEY_VAR="TESTING_PRIVATE_KEY"
;;
"production")
PASSPHRASE_VAR="PRIVATE_KEY_PASS_PHRASE"
KEY_VAR="PRIVATE_KEY"
;;
*)
echo "RPM_CHANNEL ${RPM_CHANNEL} does not match one of: [testing, production]"
exit 1
;;
esac

if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"${!KEY_VAR}" > /dev/null; then
echo "${KEY_VAR} not defined, failing rpm sign"
exit 1
fi
echo "Importing GPG private key ${KEY_VAR}"
gpg --yes --pinentry-mode loopback --batch --passphrase "${!PASSPHRASE_VAR}" --import - <<< "${TESTING_PRIVATE_KEY}"
echo "Signing keys imported successfully"
}

function sign_rpms(){
gpg --armor --export --output "${SIGN_KEY_EMAIL}" "${SIGN_KEY_EMAIL}"
rpm --import "${SIGN_KEY_EMAIL}"

echo "Signing RPMs with ${SIGN_KEY_EMAIL} GPG KEY"
rpmsign --addsign /dist/**/rancher-*.rpm \
--define "_gpg_name ${SIGN_KEY_EMAIL}" \
--define "_gpgbin /usr/bin/gpg" \
--define "__gpg_sign_cmd %{__gpg} gpg \
--batch \
--no-armor \
--pinentry-mode loopback \
--passphrase ${!PASSPHRASE_VAR} \
-u %{_gpg_name} \
-sbo %{__signature_filename} \
--digest-algo sha256 %{__plaintext_filename}"
}

function verify_signatures(){
echo "Verifying RPMs signatures"
rpm --checksig --verbose /dist/**/rancher-*.rpm
}

function main (){
check_vars
check_channel
sign_rpms
verify_signatures
}

if [[ "$1" == "--dry-run" ]]; then
dryrun
else
main
fi
44 changes: 0 additions & 44 deletions policy/centos7/scripts/sign

This file was deleted.

Loading

0 comments on commit a39f1c6

Please sign in to comment.