How to: Publish a signed delivery
The IT installed the starter once with its project file; from then on the publisher delivers new versions to the share every day, and every user's starter must install only files the publisher signed.
Solution overview
Wkl.Bootstrapper.exe /new-key <name>creates the publisher's delivery key once, in the Windows key store of the publisher's user account, and prints its public part.- The public part goes into
deliveryKeyof the project file the IT rolls out. tools\Export-ComRegistration.ps1writesregistration.jsonbeside every COM server of the delivery.Wkl.Bootstrapper.exe /publish /key <name>writesdelivery.json(every file with size and SHA-256) and its signaturedelivery.json.siginto the source, after the last change of the delivery.
The delivery key signs one small file per delivery; it is not the company's code-signing certificate, whose number of signatures may be limited. Programs and libraries the delivery brings are signed with the company certificate as before, where Windows' application control requires it.
Implementation
Once, on the publisher's computer, in the folder of a starter that has the project file:
.\Wkl.Bootstrapper.exe /new-key Contoso # prints the public key, for example MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
Put the printed text into the project file and give that file to the IT for the initial installation:
{ "format": 2, "product": "Checkout", "deliveryKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...", "...": "..." }
For every delivery, when all files are in the source:
# for each COM server of the delivery (once per bitness folder); DllInstall for servers registering per user pwsh -File tools\Export-ComRegistration.ps1 -Dll \\server\share\checkout\com\x86\Checkout.Interop.dll pwsh -File tools\Export-ComRegistration.ps1 -Dll \\server\share\checkout\net\Checkout.Bridge.dll -Kind NetCom # last step: sign what is in the source now .\Wkl.Bootstrapper.exe /publish /key Contoso # Checkout 3.2.1: 14 files in \\server\share\checkout\delivery.json, signed.
/publish reads the project file beside the starter (or the one /RUNCFG <file> names) for the product, the source and the
version. It refuses a key that does not match deliveryKey.
Going back to an earlier version
A starter with deliveryKey never installs a version lower than the highest one its user ever installed (code 52), so an
older signed delivery put back on the share is refused. To go back on purpose - version 3.3.0 is faulty, the users should
run 3.2.1 again - put 3.2.1 into the source and name the version it replaces:
.\Wkl.Bootstrapper.exe /publish /key Contoso /withdraw 3.3.0 # Checkout 3.2.1: 14 files in \\server\share\checkout\delivery.json, signed, withdraws 3.3.0.
Several versions are separated by commas (/withdraw 3.3.0,3.3.1); name every version a user may have installed above the
delivered one. Each must be higher than the delivered version. The list lies under the signature: nobody can add a version
to it without the delivery key. A user who installed 3.4.0 meanwhile is not taken back by this delivery.
Remarks
- Publish last: a file changed after
/publishis not installed (code 51), and the users keep the installed version until the delivery is published again. /publishremoves the old signature before it writes the new manifest, so a starter reading in between finds an unsigned manifest and keeps the installed version - never an old signature beside a new manifest.- The private key never lies in a file, but it is created exportable: every program running as the publisher's Windows user can sign with it and export it. Keep that account for publishing only. The starter has no export or backup command; losing the key means a new key and a new project file rolled out by the IT.
- The signature covers the files of
files. Programs ofactionsrun directly from the source and are not checked againstdelivery.json: whoever can write to the source can change them, and they run with the rights of every user who starts the application. - A delivery signed earlier stays valid, but from 2.2.4 the starters do not go back with it: whoever puts an older signed delivery back into the source gets code 52 on every computer that had a higher version, and those users keep it. A user who never installed a higher version (a new computer, a new user) does install the older delivery. Protect write access to the source.
- The trust anchor is the starter's folder with its project file: the delivery key protects a delivery only as long as users cannot change
bootstrapper.json, as when the IT installs the starter under Program Files with the MSI. A starter and project file on the share or in the profile can be changed together with the key. Export-ComRegistration.ps1runs the server's registration once on the publisher's computer with every registry write redirected into a temporary key, and deletes that key; the computer's own registration does not change. It restarts itself in the PowerShell of the server's bitness. It captures servers that register withDllRegisterServerorDllInstall(such as WKL Forms Object Library) and .NET Framework assemblies. Some Windows components (for examplescrrun.dll,msxml6.dll) register in other ways and cannot be captured. A server that writes throughHKEY_CLASSES_ROOT, the usual way of ATL and Visual Basic 6: check that the written table holds itsCLSIDkeys before you publish it.- Without
deliveryKey,/publishwithout/keystill writesdelivery.json: the starters then check sizes and hashes (integrity), not the publisher.