diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ceabb35..12a7e2e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,4 +19,4 @@ jobs: with: go-version: 'stable' - - run: make build + - run: make build DRY_RUN=true diff --git a/Dockerfile b/Dockerfile index 2338d70..d8a7f44 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/Makefile b/Makefile index 70ec46a..1533c98 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,17 @@ RUNNER ?= docker POLICIES = $(shell find policy -mindepth 2 -maxdepth 2 -type d | sort -u | cut -f 2 -d'/') +DRY_RUN ?= false +SIGN_KEY_EMAIL ?= ci@rancher.com +PRIVATE_KEY ?= +PRIVATE_KEY_PASS_PHRASE ?= +TESTING_PRIVATE_KEY ?= +TESTING_PRIVATE_KEY_PASS_PHRASE ?= + +ifeq ($(DRY_RUN),true) + DRY_RUN_SIGN := --dry-run +endif + include hack/make/version.mk .PHONY: build @@ -11,6 +22,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. @@ -27,6 +39,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) \ diff --git a/hack/centos7_sign b/hack/centos7_sign new file mode 100755 index 0000000..60e5972 --- /dev/null +++ b/hack/centos7_sign @@ -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 ci@rancher.com +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 < /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 diff --git a/policy/centos7/scripts/sign b/policy/centos7/scripts/sign deleted file mode 100755 index 8453718..0000000 --- a/policy/centos7/scripts/sign +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -set -e -x - -yum install -y rpm-sign expect - -cd $(dirname $0)/.. -. ./scripts/version - -cat <<\EOF >~/.rpmmacros -%_signature gpg -%_gpg_name ci@rancher.com -EOF - -case "$RPM_CHANNEL" in - "testing") - export PRIVATE_KEY_PASS_PHRASE=$TESTING_PRIVATE_KEY_PASS_PHRASE - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$TESTING_PRIVATE_KEY"; then - echo "TESTING_PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - gpg --import - <<<"$TESTING_PRIVATE_KEY" - ;; - "production") - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$PRIVATE_KEY"; then - echo "PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - gpg --import - <<<"$PRIVATE_KEY" - ;; - *) - echo "RPM_CHANNEL $RPM_CHANNEL does not match one of: [testing, production]" - exit 1 - ;; -esac - -expect < /dev/null; then - echo "TESTING_PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - echo "Importing GPG private key TESTING_PRIVATE_KEY" - gpg --yes --pinentry-mode loopback --batch --passphrase $PRIVATE_KEY_PASS_PHRASE --import - <<< "$TESTING_PRIVATE_KEY" - ;; - "production") - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$PRIVATE_KEY" > /dev/null; then - echo "PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - echo "Importing GPG private key PRIVATE_KEY" - gpg --yes --batch --pinentry-mode loopback --passphrase $PRIVATE_KEY_PASS_PHRASE --import - <<< "$PRIVATE_KEY" - ;; - *) - echo "RPM_CHANNEL $RPM_CHANNEL does not match one of: [testing, production]" - exit 1 - ;; -esac - -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 ${PRIVATE_KEY_PASS_PHRASE} \ - -u %{_gpg_name} \ - -sbo %{__signature_filename} \ - --digest-algo sha256 %{__plaintext_filename}" - -echo "Verifying RPMs signatures" -rpm --checksig --verbose dist/**/rancher-*.rpm - diff --git a/policy/centos9/scripts/sign b/policy/centos9/scripts/sign deleted file mode 100755 index 2cf8568..0000000 --- a/policy/centos9/scripts/sign +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -set -e - -DRY_RUN=$1 -SIGN_KEY_EMAIL="ci@rancher.com" - -export GPG_TTY=$(tty) - -yum install -y rpm-sign - -cd $(dirname $0)/.. -. ./scripts/version - -if [ "${DRY_RUN}" = "--dry-run" ] -then - echo "!! Executing in dry-run mode" - echo "!! Generating a temporary disposable GPG key to test the signing" - echo "!! process (this is only useful when testing PRs)" - - SIGN_KEY_EMAIL="disposable-ci-test-key" - TESTING_PRIVATE_KEY_PASS_PHRASE=$(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c20) - RPM_CHANNEL="testing" - - gpg --no-tty --quick-gen-key --pinentry-mode loopback --passphrase "$TESTING_PRIVATE_KEY_PASS_PHRASE" --yes "$SIGN_KEY_EMAIL" rsa2048 - - TESTING_PRIVATE_KEY=$(gpg --armor --pinentry-mode loopback --passphrase "$TESTING_PRIVATE_KEY_PASS_PHRASE" --export-secret-key "$SIGN_KEY_EMAIL") -fi - -case "$RPM_CHANNEL" in - "testing") - export PRIVATE_KEY_PASS_PHRASE=$TESTING_PRIVATE_KEY_PASS_PHRASE - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$TESTING_PRIVATE_KEY" > /dev/null; then - echo "TESTING_PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - echo "Importing GPG private key TESTING_PRIVATE_KEY" - gpg --yes --pinentry-mode loopback --batch --passphrase $PRIVATE_KEY_PASS_PHRASE --import - <<< "$TESTING_PRIVATE_KEY" - ;; - "production") - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$PRIVATE_KEY" > /dev/null; then - echo "PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - echo "Importing GPG private key PRIVATE_KEY" - gpg --yes --batch --pinentry-mode loopback --passphrase $PRIVATE_KEY_PASS_PHRASE --import - <<< "$PRIVATE_KEY" - ;; - *) - echo "RPM_CHANNEL $RPM_CHANNEL does not match one of: [testing, production]" - exit 1 - ;; -esac - -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 ${PRIVATE_KEY_PASS_PHRASE} \ - -u %{_gpg_name} \ - -sbo %{__signature_filename} \ - --digest-algo sha256 %{__plaintext_filename}" - -echo "Verifying RPMs signatures" -rpm --checksig --verbose dist/**/rancher-*.rpm - diff --git a/policy/fedora37/scripts/sign b/policy/fedora37/scripts/sign deleted file mode 100755 index 33db6cb..0000000 --- a/policy/fedora37/scripts/sign +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash -set -e - -DRY_RUN=$1 -SIGN_KEY_EMAIL="ci@rancher.com" - -export GPG_TTY=$(tty) - -dnf install -y rpm-sign - -cd $(dirname $0)/.. -. ./scripts/version - -if [ "${DRY_RUN}" = "--dry-run" ] -then - echo "!! Executing in dry-run mode" - echo "!! Generating a temporary disposable GPG key to test the signing" - echo "!! process (this is only useful when testing PRs)" - - SIGN_KEY_EMAIL="disposable-ci-test-key" - TESTING_PRIVATE_KEY_PASS_PHRASE=$(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c20) - RPM_CHANNEL="testing" - - gpg --no-tty --quick-gen-key --pinentry-mode loopback --passphrase "$TESTING_PRIVATE_KEY_PASS_PHRASE" --yes "$SIGN_KEY_EMAIL" rsa2048 - - TESTING_PRIVATE_KEY=$(gpg --armor --pinentry-mode loopback --passphrase "$TESTING_PRIVATE_KEY_PASS_PHRASE" --export-secret-key "$SIGN_KEY_EMAIL") -fi - -case "$RPM_CHANNEL" in - "testing") - export PRIVATE_KEY_PASS_PHRASE=$TESTING_PRIVATE_KEY_PASS_PHRASE - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$TESTING_PRIVATE_KEY" > /dev/null; then - echo "TESTING_PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - echo "Importing GPG private key TESTING_PRIVATE_KEY" - gpg --yes --pinentry-mode loopback --batch --passphrase $PRIVATE_KEY_PASS_PHRASE --import - <<< "$TESTING_PRIVATE_KEY" - ;; - "production") - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$PRIVATE_KEY" > /dev/null; then - echo "PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - echo "Importing GPG private key PRIVATE_KEY" - gpg --yes --batch --pinentry-mode loopback --passphrase $PRIVATE_KEY_PASS_PHRASE --import - <<< "$PRIVATE_KEY" - ;; - *) - echo "RPM_CHANNEL $RPM_CHANNEL does not match one of: [testing, production]" - exit 1 - ;; -esac - -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 ${PRIVATE_KEY_PASS_PHRASE} \ - -u %{_gpg_name} \ - -sbo %{__signature_filename} \ - --digest-algo sha256 %{__plaintext_filename}" - -echo "Verifying RPMs signatures" -rpm --checksig --verbose dist/**/rancher-*.rpm \ No newline at end of file diff --git a/policy/microos/scripts/sign b/policy/microos/scripts/sign deleted file mode 100755 index f3225da..0000000 --- a/policy/microos/scripts/sign +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -set -e - -DRY_RUN=$1 -SIGN_KEY_EMAIL="ci@rancher.com" - -export GPG_TTY=$(tty) - -zypper install -y rpm - -cd $(dirname $0)/.. -. ./scripts/version - -if [ "${DRY_RUN}" = "--dry-run" ] -then - echo "!! Executing in dry-run mode" - echo "!! Generating a temporary disposable GPG key to test the signing" - echo "!! process (this is only useful when testing PRs)" - - SIGN_KEY_EMAIL="disposable-ci-test-key" - TESTING_PRIVATE_KEY_PASS_PHRASE=$(cat /dev/urandom | tr -dc A-Za-z0-9 | head -c20) - RPM_CHANNEL="testing" - - gpg --no-tty --quick-gen-key --pinentry-mode loopback --passphrase "$TESTING_PRIVATE_KEY_PASS_PHRASE" --yes "$SIGN_KEY_EMAIL" rsa2048 - - TESTING_PRIVATE_KEY=$(gpg --armor --pinentry-mode loopback --passphrase "$TESTING_PRIVATE_KEY_PASS_PHRASE" --export-secret-key "$SIGN_KEY_EMAIL") -fi - -case "$RPM_CHANNEL" in - "testing") - export PRIVATE_KEY_PASS_PHRASE=$TESTING_PRIVATE_KEY_PASS_PHRASE - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$TESTING_PRIVATE_KEY" > /dev/null; then - echo "TESTING_PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - echo "Importing GPG private key TESTING_PRIVATE_KEY" - gpg --yes --pinentry-mode loopback --batch --passphrase $PRIVATE_KEY_PASS_PHRASE --import - <<< "$TESTING_PRIVATE_KEY" - ;; - "production") - if ! grep "BEGIN PGP PRIVATE KEY BLOCK" <<<"$PRIVATE_KEY" > /dev/null; then - echo "PRIVATE_KEY not defined, failing rpm sign" - exit 1 - fi - echo "Importing GPG private key PRIVATE_KEY" - gpg --yes --batch --pinentry-mode loopback --passphrase $PRIVATE_KEY_PASS_PHRASE --import - <<< "$PRIVATE_KEY" - ;; - *) - echo "RPM_CHANNEL $RPM_CHANNEL does not match one of: [testing, production]" - exit 1 - ;; -esac - -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 ${PRIVATE_KEY_PASS_PHRASE} \ - -u %{_gpg_name} \ - -sbo %{__signature_filename} \ - --digest-algo sha256 %{__plaintext_filename}" - -echo "Verifying RPMs signatures" -rpm --checksig --verbose dist/**/rancher-*.rpm -