Skip to content

Commit 8fa6b89

Browse files
committed
[DDW-1083] Finish impure Windows signing
1 parent e3e6ef9 commit 8fa6b89

File tree

2 files changed

+85
-170
lines changed

2 files changed

+85
-170
lines changed

nix/old-release-build.nix

Lines changed: 0 additions & 13 deletions
This file was deleted.

nix/x86_64-windows.nix

Lines changed: 85 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,21 @@ let
1010
inherit (pkgs) lib;
1111
inherit (oldCode) launcherConfigs;
1212

13-
signingKeys = null;
14-
HSMServer = null;
15-
1613
in rec {
1714

1815
inherit newCommon oldCode;
1916

20-
package = daedalusJs; # FIXME: this is wrong
17+
package = preSigning; # XXX: this is slightly wrong, as not all files are in their final relative paths
2118

22-
unsignedInstaller = unsigned-windows-installer;
19+
# XXX: Please, use ‘nix run -L .#packages.x86_64-windows.makeSignedInstaller.mainnet’,
20+
# as the process cannot be done purely, as it requires passing files
21+
# through `ssh` at the HSM server
22+
makeSignedInstaller = makeInstaller { signed = true; };
2323

24-
makeSignedInstaller = oldCode.pkgs.writeScriptBin "make-signed-installer" ''
25-
echo >&2 'fatal: not yet implemented'
26-
exit 1
24+
unsignedInstaller = pkgs.runCommand "win64-installer-${cluster}" {} ''
25+
${makeInstaller { signed = false; }}/bin/make-signed-installer
26+
mkdir $out
27+
cp -v installers/daedalus-*-*.exe $out/
2728
'';
2829

2930
# They’re initially the same as Linux when cross-compiling for Windows:
@@ -124,97 +125,22 @@ in rec {
124125
dontFixup = true; # TODO: just to shave some seconds, turn back on after everything works
125126
};
126127

127-
# a cross-compiled fastlist for the ps-list package
128-
fastlist = pkgs.pkgsCross.mingwW64.callPackage ./fastlist.nix {};
129-
wine = pkgs.wine.override { wineBuild = "wine32"; };
130-
wine64 = pkgs.wine.override { wineBuild = "wineWow"; };
131-
132-
dlls = pkgs.fetchurl {
133-
url = "https://s3.eu-central-1.amazonaws.com/daedalus-ci-binaries/DLLs.zip";
134-
sha256 = "0p6nrf8sg2wgcaf3b1qkbb98bz2dimb7lnshsa93xnmia9m2vsxa";
135-
};
136-
137-
needSignedBinaries = (signingKeys != null) || (HSMServer != null);
138-
139-
# TODO, nsis can't cross-compile with the nixpkgs daedalus currently uses
140-
nsisNixpkgs = pkgs.fetchFromGitHub {
141-
owner = "input-output-hk";
142-
repo = "nixpkgs";
143-
rev = "be445a9074f139d63e704fa82610d25456562c3d";
144-
hash = "sha256-ivcmGg01aeeod0rzjMJ86exUNHHRJu4526rGq9s7rJU=";
145-
};
146-
147-
nsisPkgs = import nsisNixpkgs { system = "x86_64-linux"; };
148-
149-
# the native makensis binary, with cross-compiled windows stubs
150-
nsis = nsisPkgs.callPackage ./nsis.nix {};
151-
152-
unsignedUnpackedCardano = oldCode.daedalus-bridge; # TODO
153-
154-
unpackedCardano = if needSignedBinaries then signedCardano else unsignedUnpackedCardano;
155-
156-
signFile = file: let
157-
localSigningScript = pkgs.writeScript "signing-script" ''
158-
#!${pkgs.stdenv.shell}
159-
160-
exec 3>&1
161-
exec 1>&2
162-
163-
export PATH=${pkgs.mono}/bin:$PATH
164-
PASS=hunter2
165-
166-
DIR=$(realpath $(mktemp -d))
167-
cd $DIR
168-
cp ${file} .
169-
FILE=$(basename ${file})
170-
chmod +w $FILE
171-
172-
# if stdout is a tty, then mono 5.8 will barf over the terminfo files being too new
173-
# mono 5.16 supports them, but isn't in our current nixpkgs
174-
# for more info, refer to `mcs/class/corlib/System/TermInfoReader.cs` and `ReadHeader`
175-
echo $PASS | signcode -spc ${toString signingKeys.spc} -v ${toString signingKeys.pvk} -a sha1 -$ commercial -n "TODO description" -i http://iohk.io -t http://timestamp.verisign.com/scripts/timstamp.dll -tr 10 $FILE | cat
176-
storePath=$(nix-store --add-fixed sha256 $FILE)
177-
rm -rf $DIR
178-
echo $storePath >&3
179-
'';
180-
remoteSigningScript = pkgs.writeScript "signing-script" ''
181-
#!${pkgs.stdenv.shell}
182-
183-
exec 3>&1
184-
exec 1>&2
185-
186-
echo signing "${file}"
187-
188-
set -e
189-
190-
DIR=$(realpath $(mktemp -d))
191-
cd $DIR
192-
FILE=$(basename ${file})
193-
194-
cat ${file} | ssh ${HSMServer} > $FILE
195-
196-
storePath=$(nix-store --add-fixed sha256 $FILE)
197-
cd /
198-
rm -rf $DIR
199-
echo $storePath >&3
200-
'';
201-
signingScript = if (HSMServer != null) then remoteSigningScript else localSigningScript;
202-
# requires --allow-unsafe-native-code-during-evaluation
203-
res = builtins.exec [ signingScript ];
204-
in res;
205-
206-
signedCardano = let
207-
copySignedBinaries = let
208-
signAndCopy = bin: ''
209-
cp ${signFile "${unsignedUnpackedCardano}/bin/${bin}"} bin/${bin}
210-
'';
211-
in __concatStringsSep "\n" (map signAndCopy launcherConfigs.installerConfig.installerWinBinaries);
212-
in pkgs.runCommand "signed-daedalus-bridge" {} ''
213-
cp -r ${unsignedUnpackedCardano} $out
214-
chmod -R +w $out
215-
cd $out
216-
rm bin/*.exe
217-
${copySignedBinaries}
128+
windowsIcons = let
129+
buildInputs = with pkgs; [ imagemagick ];
130+
# Allow fallback to `mainnet` if cluster’s icons don’t exist:
131+
srcCluster = if builtins.pathExists (../installers/icons + "/${cluster}") then cluster else "mainnet";
132+
in pkgs.runCommand "windows-icons-${cluster}" { inherit buildInputs; } ''
133+
mkdir -p $out/${cluster} $out
134+
cp -r ${../installers/icons + "/${srcCluster}"}/. $out/${cluster}/.
135+
cp ${../installers/icons/installBanner.bmp} $out/installBanner.bmp
136+
cd $out/${cluster}
137+
rm *.ico *.ICO || true # XXX: just in case
138+
for f in *.png ; do
139+
# XXX: these sizes are too large for the ICO format:
140+
if [ "$f" == 1024x1024.png ] || [ "$f" == 512x512.png ] ; then continue ; fi
141+
convert "$f" "''${f%.png}.ico"
142+
done
143+
convert 16x16.png 24x24.png 32x32.png 48x48.png 64x64.png 128x128.png 256x256.png ${cluster}.ico
218144
'';
219145

220146
nsisFiles = pkgs.runCommand "nsis-files" {
@@ -240,6 +166,21 @@ in rec {
240166
ls -lR $out
241167
'';
242168

169+
# the native makensis binary, with cross-compiled windows stubs
170+
nsis = let
171+
# TODO, nsis can't cross-compile with the nixpkgs daedalus currently uses
172+
nsisNixpkgs = pkgs.fetchFromGitHub {
173+
owner = "input-output-hk";
174+
repo = "nixpkgs";
175+
rev = "be445a9074f139d63e704fa82610d25456562c3d";
176+
hash = "sha256-ivcmGg01aeeod0rzjMJ86exUNHHRJu4526rGq9s7rJU=";
177+
};
178+
nsisPkgs = import nsisNixpkgs { system = "x86_64-linux"; };
179+
in nsisPkgs.callPackage ./nsis.nix {};
180+
181+
wine = pkgs.wine.override { wineBuild = "wine32"; };
182+
wine64 = pkgs.wine.override { wineBuild = "wineWow"; };
183+
243184
unsignedUninstaller = pkgs.runCommand "uninstaller" { buildInputs = [ nsis wine ]; } ''
244185
mkdir home
245186
export HOME=$(realpath home)
@@ -254,43 +195,21 @@ in rec {
254195
mv -v $HOME/.wine/drive_c/uninstall.exe $out/uninstall.exe
255196
'';
256197

257-
signedUninstaller = pkgs.runCommand "uninstaller-signed" {} ''
258-
mkdir $out
259-
cp ${signFile "${unsignedUninstaller}/uninstall.exe"} $out/uninstall.exe
260-
'';
261-
262-
uninstaller = if needSignedBinaries then signedUninstaller else unsignedUninstaller;
198+
# a cross-compiled fastlist for the ps-list package
199+
fastlist = pkgs.pkgsCross.mingwW64.callPackage ./fastlist.nix {};
263200

264-
windowsIcons = let
265-
buildInputs = with pkgs; [ imagemagick ];
266-
# Allow fallback to `mainnet` if cluster’s icons don’t exist:
267-
srcCluster = if builtins.pathExists (../installers/icons + "/${cluster}") then cluster else "mainnet";
268-
in pkgs.runCommand "windows-icons-${cluster}" { inherit buildInputs; } ''
269-
mkdir -p $out/${cluster} $out
270-
cp -r ${../installers/icons + "/${srcCluster}"}/. $out/${cluster}/.
271-
cp ${../installers/icons/installBanner.bmp} $out/installBanner.bmp
272-
cd $out/${cluster}
273-
rm *.ico *.ICO || true # XXX: just in case
274-
for f in *.png ; do
275-
# XXX: these sizes are too large for the ICO format:
276-
if [ "$f" == 1024x1024.png ] || [ "$f" == 512x512.png ] ; then continue ; fi
277-
convert "$f" "''${f%.png}.ico"
278-
done
279-
convert 16x16.png 24x24.png 32x32.png 48x48.png 64x64.png 128x128.png 256x256.png ${cluster}.ico
280-
'';
201+
dlls = pkgs.fetchurl {
202+
url = "https://s3.eu-central-1.amazonaws.com/daedalus-ci-binaries/DLLs.zip";
203+
sha256 = "0p6nrf8sg2wgcaf3b1qkbb98bz2dimb7lnshsa93xnmia9m2vsxa";
204+
};
281205

282-
unsigned-windows-installer = let
206+
preSigning = let
283207
installDir = oldCode.launcherConfigs.installerConfig.spacedName;
284-
in pkgs.runCommand "win64-installer-${cluster}" {
285-
buildInputs = [
286-
oldCode.daedalus-installer nsis pkgs.unzip pkgs.jq yaml2json
287-
];
288-
} ''
289-
echo '~~~ Preparing files for installer'
290-
mkdir home
291-
export HOME=$(realpath home)
208+
in pkgs.runCommand "pre-signing" { buildInputs = [ pkgs.unzip ]; } ''
209+
mkdir $out
210+
cd $out
292211
293-
mkdir -p $out/{nix-support,cfg-files}
212+
echo '~~~ Preparing files for installer'
294213
mkdir installers
295214
cp -vir ${windowsIcons} installers/icons
296215
cp -vir ${../package.json} package.json
@@ -306,41 +225,50 @@ in rec {
306225
pushd dlls
307226
unzip ${dlls}
308227
popd
309-
cp -vr ${unpackedCardano}/bin/* .
228+
cp -vr ${oldCode.daedalus-bridge}/bin/* .
310229
cp -v ${nsisFiles}/{*.yaml,*.json,daedalus.nsi,*.key,*.cert} .
311-
cp ${uninstaller}/uninstall.exe .
230+
cp ${unsignedUninstaller}/uninstall.exe .
312231
if [ -f ${nsisFiles}/block-0.bin ]; then
313232
cp -v ${nsisFiles}/block-0.bin .
314233
fi
315-
chmod -R +w .
234+
'';
316235

317-
echo '~~~ Generating installer'
318-
makensis daedalus.nsi -V4
236+
makeInstaller = { signed ? false }: oldCode.pkgs.writeScriptBin "make-signed-installer" ''
237+
set -euo pipefail
319238
320-
echo '~~~ Copying to $out'
321-
cp daedalus-*-*.exe $out/
322-
cp *.yaml $out/cfg-files/
323-
echo file installer $out/*.exe > $out/nix-support/hydra-build-products
324-
'';
239+
${if signed then ''
240+
# We have to do it impurely:
241+
cd $(mktemp -d)
242+
echo "~~~ We’re signing in $PWD:"
325243
326-
signed-windows-installer = let
327-
backend_version = oldCode.cardanoWalletVersion;
328-
frontend_version = (builtins.fromJSON (builtins.readFile ../package.json)).version;
329-
fullName = "daedalus-${frontend_version}.${toString sourceLib.buildCounter}-${cluster}-${sourceLib.buildRevShort}-x86_64-windows.exe"; # must match to packageFileName in make-installer
330-
in pkgs.runCommand "signed-windows-installer-${cluster}" {} ''
331-
mkdir $out
332-
cp -v ${signFile "${unsigned-windows-installer}/${fullName}"} $out/${fullName}
333-
'';
244+
sign_cmd() {
245+
echo "Signing: ‘$1’…"
246+
ssh HSM <"$1" >"$1".signed
247+
mv "$1".signed "$1"
248+
}
249+
'' else ''
250+
sign_cmd() {
251+
echo "Would sign: ‘$1’"
252+
}
253+
''}
254+
255+
cp -r ${preSigning}/. ./
256+
chmod -R +w .
334257
335-
windows-installer = if needSignedBinaries then signed-windows-installer else unsigned-windows-installer;
258+
find . '(' -iname '*.exe' -o -iname '*.dll' -o -iname '*.node' ')' | sort | while IFS= read -r binaryToSign ; do
259+
sign_cmd "$binaryToSign"
260+
done
261+
262+
echo '~~~ Generating installer'
263+
(
264+
cd installers/
265+
${nsis}/bin/makensis daedalus.nsi -V4
266+
)
336267
337-
haskell-nix = inputs.cardano-wallet-unpatched.inputs.haskellNix.legacyPackages.x86_64-linux.haskell-nix;
268+
sign_cmd installers/daedalus-*-*.exe
338269
339-
inherit ((haskell-nix.hackage-package { name = "yaml"; compiler-nix-name = "ghc8107"; cabalProject = ''
340-
packages: .
341-
package yaml
342-
flags: -no-exe
343-
''; }).components.exes) yaml2json;
270+
echo "Final installer: ‘$(realpath installers/daedalus-*-*.exe)’"
271+
'';
344272

345273
windowsSources = {
346274
electron = pkgs.fetchurl {

0 commit comments

Comments
 (0)