ci: scripts/sign-windows-bin.sh for signing Windows binaries
This introduces the `scripts/sign-windows-bin.sh` script which is used by the `Makefile` to sign application libraries and executables. It also implements the logic necessary to distinguish between different types of builds: release and non-release builds. Some other changes: * Refactore the `Makefile` target that creates the Windows ZIP to make less verbose. * Added `Microsoft.VisualStudio.Component.Windows10SDK.10240` to VisualStudio component * Added `BUILD_TYPE` parameter to `Jenkinsfile`s for different platform builds Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
parent
02b26f3c28
commit
089ee7ee80
71
Makefile
71
Makefile
|
@ -78,7 +78,6 @@ else ifeq ($(detected_OS),Windows)
|
|||
PKG_TARGET := pkg-windows
|
||||
QRCODEGEN_MAKE_PARAMS := CC=gcc
|
||||
RUN_TARGET := run-windows
|
||||
SIGNTOOL ?= C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.17763.0\\x64\\signtool.exe
|
||||
VCINSTALLDIR ?= C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\
|
||||
export VCINSTALLDIR
|
||||
else
|
||||
|
@ -350,74 +349,40 @@ $(NIM_WINDOWS_PREBUILT_DLLS):
|
|||
rm -rf tmp/windows
|
||||
mkdir -p tmp/windows/tools
|
||||
cd tmp/windows/tools && \
|
||||
wget https://nim-lang.org/download/dlls.zip && \
|
||||
wget -nv https://nim-lang.org/download/dlls.zip && \
|
||||
unzip dlls.zip
|
||||
|
||||
nim_windows_launcher: | deps
|
||||
$(ENV_SCRIPT) nim c -d:debug --outdir:./bin --passL:"-static-libgcc -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive" src/nim_windows_launcher.nim
|
||||
|
||||
ifneq ($(WINDOWS_CODESIGN_TIMESTAMP_URL),)
|
||||
WINDOWS_CODESIGN_TIMESTAMP_PARAM := -t $(WINDOWS_CODESIGN_TIMESTAMP_URL)
|
||||
endif
|
||||
|
||||
STATUS_CLIENT_ZIP ?= pkg/Status.zip
|
||||
|
||||
$(STATUS_CLIENT_ZIP): override RESOURCES_LAYOUT := -d:production
|
||||
$(STATUS_CLIENT_ZIP): OUTPUT := tmp/windows/dist/Status
|
||||
$(STATUS_CLIENT_ZIP): nim_status_client nim_windows_launcher $(NIM_WINDOWS_PREBUILT_DLLS)
|
||||
rm -rf pkg/*.zip
|
||||
rm -rf tmp/windows/dist
|
||||
mkdir -p tmp/windows/dist/Status/bin
|
||||
mkdir -p tmp/windows/dist/Status/resources
|
||||
mkdir -p tmp/windows/dist/Status/vendor
|
||||
cp windows-install.txt tmp/windows/dist/Status/INSTALL.txt
|
||||
unix2dos -k tmp/windows/dist/Status/INSTALL.txt
|
||||
# cp LICENSE tmp/windows/dist/Status/LICENSE.txt
|
||||
# unix2dos -k tmp/windows/dist/Status/LICENSE.txt
|
||||
cp status.ico tmp/windows/dist/Status/resources/
|
||||
cp status.svg tmp/windows/dist/Status/resources/
|
||||
cp resources.rcc tmp/windows/dist/Status/resources/
|
||||
cp $(FLEETS) tmp/windows/dist/Status/resources/
|
||||
cp bin/nim_status_client.exe tmp/windows/dist/Status/bin/Status.exe
|
||||
cp bin/nim_windows_launcher.exe tmp/windows/dist/Status/Status.exe
|
||||
rcedit \
|
||||
tmp/windows/dist/Status/bin/Status.exe \
|
||||
--set-icon tmp/windows/dist/Status/resources/status.ico
|
||||
rcedit \
|
||||
tmp/windows/dist/Status/Status.exe \
|
||||
--set-icon tmp/windows/dist/Status/resources/status.ico
|
||||
cp $(DOTHERSIDE) tmp/windows/dist/Status/bin/
|
||||
cp $(STATUSGO) tmp/windows/dist/Status/bin/
|
||||
cp tmp/windows/tools/*.dll tmp/windows/dist/Status/bin/
|
||||
mkdir -p tmp/windows/dist/Status/resources/i18n
|
||||
cp ui/i18n/* tmp/windows/dist/Status/resources/i18n
|
||||
cp "$(shell which libgcc_s_seh-1.dll)" tmp/windows/dist/Status/bin/
|
||||
cp "$(shell which libwinpthread-1.dll)" tmp/windows/dist/Status/bin/
|
||||
|
||||
rm -rf pkg/*.zip tmp/windows/dist
|
||||
mkdir -p $(OUTPUT)/bin $(OUTPUT)/resources $(OUTPUT)/vendor $(OUTPUT)/resources/i18n
|
||||
cat windows-install.txt | unix2dos > $(OUTPUT)/INSTALL.txt
|
||||
cp status.ico status.svg resources.rcc $(FLEETS) $(OUTPUT)/resources/
|
||||
cp ui/i18n/* $(OUTPUT)/resources/i18n
|
||||
cp bin/nim_status_client.exe $(OUTPUT)/bin/Status.exe
|
||||
cp bin/nim_windows_launcher.exe $(OUTPUT)/Status.exe
|
||||
rcedit $(OUTPUT)/bin/Status.exe --set-icon $(OUTPUT)/resources/status.ico
|
||||
rcedit $(OUTPUT)/Status.exe --set-icon $(OUTPUT)/resources/status.ico
|
||||
cp $(DOTHERSIDE) $(STATUSGO) tmp/windows/tools/*.dll $(OUTPUT)/bin/
|
||||
cp "$(shell which libgcc_s_seh-1.dll)" $(OUTPUT)/bin/
|
||||
cp "$(shell which libwinpthread-1.dll)" $(OUTPUT)/bin/
|
||||
echo -e $(BUILD_MSG) "deployable folder"
|
||||
windeployqt \
|
||||
--compiler-runtime \
|
||||
--qmldir ui \
|
||||
--release \
|
||||
windeployqt --compiler-runtime --qmldir ui --release \
|
||||
tmp/windows/dist/Status/bin/DOtherSide.dll
|
||||
mv tmp/windows/dist/Status/bin/vc_redist.x64.exe tmp/windows/dist/Status/vendor/
|
||||
|
||||
# if WINDOWS_CODESIGN_PFX_PATH is not set then DLLs, EXEs are not signed
|
||||
# if WINDOWS_CODESIGN_PFX_PATH is not set then DLLs, EXEs are not signed
|
||||
ifdef WINDOWS_CODESIGN_PFX_PATH
|
||||
find ./tmp/windows/dist/Status -type f \
|
||||
| /usr/bin/egrep -i "\.(dll|exe)$$" \
|
||||
| /usr/bin/xargs -I{} /usr/bin/bash -c \
|
||||
"if ! '$(SIGNTOOL)' verify -pa {} &>/dev/null; then echo {}; fi" \
|
||||
| /usr/bin/xargs -I{} "$(SIGNTOOL)" \
|
||||
sign \
|
||||
-v \
|
||||
-f $(WINDOWS_CODESIGN_PFX_PATH) \
|
||||
$(WINDOWS_CODESIGN_TIMESTAMP_PARAM) \
|
||||
{}
|
||||
scripts/sign-windows-bin.sh ./tmp/windows/dist/Status
|
||||
endif
|
||||
|
||||
echo -e $(BUILD_MSG) "zip"
|
||||
mkdir -p pkg
|
||||
cd tmp/windows/dist/Status && \
|
||||
cd $(OUTPUT) && \
|
||||
7z a ../../../../$(STATUS_CLIENT_ZIP) *
|
||||
|
||||
pkg: $(PKG_TARGET)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library 'status-jenkins-lib@v1.2.13'
|
||||
library 'status-jenkins-lib@v1.2.15'
|
||||
|
||||
pipeline {
|
||||
agent { label 'linux' }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
library 'status-jenkins-lib@v1.2.13'
|
||||
library 'status-jenkins-lib@v1.2.15'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
|
@ -10,6 +10,14 @@ pipeline {
|
|||
}
|
||||
}
|
||||
|
||||
parameters {
|
||||
string(
|
||||
name: 'BUILD_TYPE',
|
||||
description: 'Specify build type. Values: pr / nightly / release',
|
||||
defaultValue: 'pr',
|
||||
)
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
library 'status-jenkins-lib@v1.2.13'
|
||||
library 'status-jenkins-lib@v1.2.15'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
label 'macos'
|
||||
}
|
||||
|
||||
parameters {
|
||||
string(
|
||||
name: 'BUILD_TYPE',
|
||||
description: 'Specify build type. Values: pr / nightly / release',
|
||||
defaultValue: 'pr',
|
||||
)
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
library 'status-jenkins-lib@v1.2.13'
|
||||
library 'status-jenkins-lib@v1.2.15'
|
||||
|
||||
pipeline {
|
||||
agent { label 'windows' }
|
||||
|
||||
parameters {
|
||||
string(
|
||||
name: 'BUILD_TYPE',
|
||||
description: 'Specify build type. Values: pr / nightly / release',
|
||||
defaultValue: 'pr',
|
||||
)
|
||||
}
|
||||
|
||||
options {
|
||||
timestamps()
|
||||
/* Prevent Jenkins jobs from running forever */
|
||||
|
@ -21,23 +29,10 @@ pipeline {
|
|||
MAKEFLAGS = '-j4'
|
||||
/* Disable colors in Nim compiler logs */
|
||||
NIMFLAGS = '--colors:off'
|
||||
/* Makefile assumes the compiler folder is included */
|
||||
QTDIR = '/c/Qt/5.14.2/msvc2017_64'
|
||||
Qt5_DIR = '/c/Qt/5.14.2/msvc2017_64'
|
||||
VCINSTALLDIR = '/c/BuildTools/VC'
|
||||
/* Control output the filename */
|
||||
STATUS_CLIENT_ZIP = "pkg/${utils.pkgFilename('zip')}"
|
||||
/* Adjust path for correct access to build toos */
|
||||
PATH = [
|
||||
"${QTDIR}/bin",
|
||||
'/c/ProgramData/scoop/apps/gcc/current/bin',
|
||||
'/c/ProgramData/scoop/apps/git/current/bin',
|
||||
'/c/ProgramData/scoop/apps/git/current/usr/bin',
|
||||
'/c/BuildTools/MSBuild/Current/Bin',
|
||||
'/c/BuildTools/VC/Tools/MSVC/14.27.29110/bin',
|
||||
'/c/ProgramData/scoop/shims',
|
||||
'/c/ProgramData/scoop/apps/pypy3/current/Scripts',
|
||||
].join(':')
|
||||
/* RFC 3161 timestamping URL for DigiCert */
|
||||
WINDOWS_CODESIGN_TIMESTAMP_URL = 'http://timestamp.digicert.com'
|
||||
}
|
||||
|
||||
stages {
|
||||
|
@ -61,14 +56,9 @@ pipeline {
|
|||
}
|
||||
|
||||
stage('Package') {
|
||||
steps {
|
||||
withCredentials([string(
|
||||
credentialsId: utils.getInfuraTokenCred(),
|
||||
variable: 'INFURA_TOKEN'
|
||||
)]) {
|
||||
sh "make ${env.STATUS_CLIENT_ZIP}"
|
||||
}
|
||||
}
|
||||
steps { script {
|
||||
windows.bundle()
|
||||
} }
|
||||
}
|
||||
|
||||
stage('Parallel Upload') {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
# Description
|
||||
|
||||
This document describes how the signing of Windows application was configured.
|
||||
|
||||
# Certificates
|
||||
|
||||
The signing uses two types of Certificates:
|
||||
|
||||
* Self-Signed Code Signing certificate for development and PR builds
|
||||
* [DigiCert](https://www.digicert.com/) standard release Code Signing certificate
|
||||
|
||||
## Self-Signed Certificate
|
||||
|
||||
This certificate was created on using the following PowerShell commands:
|
||||
```Powershell
|
||||
$cert = New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname status.im -Subject "Dev Status Cert" -type CodeSigning
|
||||
$pwd = ConvertTo-SecureString -String 'SUPER-SECRET-PASSWORD -Force -AsPlainText
|
||||
Export-PfxCertificate -cert $cert -FilePath Status-Destkop-SelfSigned.pfx -Password $pwd -CryptoAlgorithmOption AES256_SHA256
|
||||
```
|
||||
Which should create a `Status-Destkop-SelfSigned.pfx` file encrypted with the provided password.
|
||||
|
||||
Keep in mind that the `-type CodeSigning` flag is important.
|
||||
|
||||
For more details see [this article](http://woshub.com/how-to-create-self-signed-certificate-with-powershell/).
|
||||
|
||||
## DigiCert Certificate
|
||||
|
||||
This certificate is was purchased on 23rd of September 2020 from [DigiCert.com](https://www.digicert.com/).
|
||||
It is a `Microsoft Authenticode` certificate and should be valid for 2 years.
|
||||
|
||||
# Continuous Integration
|
||||
|
||||
The Jenkins setup which makes use of these certificates makes them available under different job folder under different credential names. This way we can sign non-release builds while not making them appear to a user as a release build. The self-signed certificate should trigger windows warnings when starting the application.
|
||||
|
||||
The way this works is certificates are split across two Jenkins job folders:
|
||||
|
||||
* [status-desktop/platforms](https://ci.status.im/job/status-desktop/job/platforms/credentials/store/folder/domain/_/) - Release and Nightly builds.
|
||||
* [status-desktop/branches](https://ci.status.im/job/status-desktop/job/branches/credentials/store/folder/domain/_/) - Branch and PR builds.
|
||||
|
||||
These folders contain different certificates, which provides another layer of security in case someone submits a malicious PR which attempts to extract valuable secrets. In this setup the only thing they might possibly extract would be the self-signed certificate and its password.
|
||||
|
||||
The exact access to the credentials is hidden from malicious eyes that can inspect `Jenkinsfile`s in this repo, and instead are implemented in our private [`status-jenkins-lib`](https://github.com/status-im/status-jenkins-lib) repository under `vars/windows.groovy`.
|
||||
|
||||
# Known Issues
|
||||
|
||||
#### `Error: Store::ImportCertObject() failed. (-2146893808/0x80090010)`
|
||||
|
||||
This error would appears when trying to sign binaries with `signtool.exe` when Jenkins was accessing the Windows CI slave via SSH.
|
||||
|
||||
The solution was to switch the setup to deploy the [Jenkins Remoting Agent Service](https://www.jenkins.io/projects/remoting/) using the [WinSW](https://github.com/winsw/winsw) utility to run it as a Windows service.
|
||||
|
||||
#### `CertEnroll::CX509Enrollment::_CreateRequest: Access denied. 0x80090010 (-2146893808 NTE_PERM)`
|
||||
|
||||
You cannot create a self-signed certificate in a PowerShell instance without elevated privilidges. You might have to run the shell as system administrator.
|
||||
|
||||
# Links
|
||||
|
||||
* https://github.com/status-im/infra-ci/issues/28
|
||||
* https://github.com/status-im/status-desktop/issues/2170
|
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env bash
|
||||
set -eof pipefail
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "No path to search for EXE and DLL files provided!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function must_get_env() {
|
||||
declare -n VAR_VALUE="$1"
|
||||
if [[ -z "${VAR_VALUE}" ]]; then
|
||||
echo -e "Missing env variable: ${!VAR_VALUE}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# The signing certificate, password, and timestamp server is required.
|
||||
must_get_env WINDOWS_CODESIGN_PFX_PATH
|
||||
must_get_env WINDOWS_CODESIGN_PASSWORD
|
||||
must_get_env WINDOWS_CODESIGN_TIMESTAMP_URL
|
||||
|
||||
# Signing Tool usually comes with the Windows Kits.
|
||||
WINDOWS_KITS='/c/Program Files (x86)/Windows Kits'
|
||||
SIGNTOOL=$(find "${WINDOWS_KITS}" -iname 'signtool.exe' | grep x64 | sort | head -n1)
|
||||
if [[ -z "${SIGNTOOL}" ]]; then
|
||||
echo "No signtool.exe was found in '${WINDOWS_KITS}'!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Find the files to sign.
|
||||
FOUND_FILES=$(find "${1}" -type f -iname '*.dll' -or -iname '*.exe')
|
||||
declare -a FILES_TO_SIGN
|
||||
|
||||
for FILE in ${FOUND_FILES}; do
|
||||
# Some files like Qt libraries are already signed.
|
||||
if "${SIGNTOOL}" verify -pa ${FILE} &>/dev/null; then
|
||||
continue
|
||||
fi
|
||||
FILES_TO_SIGN+=("${FILE}")
|
||||
done
|
||||
|
||||
# Sign all the non-signed binaries. Add -debug if need be.
|
||||
"${SIGNTOOL}" sign -v -fd SHA256 \
|
||||
-p "${WINDOWS_CODESIGN_PASSWORD}" \
|
||||
-f "${WINDOWS_CODESIGN_PFX_PATH}" \
|
||||
-tr "${WINDOWS_CODESIGN_TIMESTAMP_URL}" \
|
||||
"${FILES_TO_SIGN[@]}" | dos2unix
|
||||
|
||||
echo "Signed successfully!"
|
|
@ -42,6 +42,7 @@ function Install-VC-BuildTools {
|
|||
"--add", "Microsoft.VisualStudio.Workload.VCTools",
|
||||
"--add", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
||||
"--add", "Microsoft.VisualStudio.Component.VC.Redist.14.Latest",
|
||||
"--add", "Microsoft.VisualStudio.Component.Windows10SDK.10240",
|
||||
"--add", "Microsoft.VisualStudio.Component.Windows10SDK.14393",
|
||||
"--add", "Microsoft.VisualStudio.Component.Windows81SDK",
|
||||
"--add", "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Win81"
|
||||
|
|
Loading…
Reference in New Issue