[OBJECT-16744] Add helpers for signing Nuget packages
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
This commit is contained in:
parent
45e73a6f8e
commit
9248874a9e
5 changed files with 252 additions and 1 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -32,5 +32,8 @@ antlr-*.jar
|
||||||
|
|
||||||
# binary
|
# binary
|
||||||
bin/
|
bin/
|
||||||
release/
|
|
||||||
obj/
|
obj/
|
||||||
|
|
||||||
|
# Repository signing keys
|
||||||
|
release/maintainer.*
|
||||||
|
release/ca.*
|
||||||
|
|
58
Makefile
Normal file
58
Makefile
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
DOTNET?=dotnet
|
||||||
|
DOCKER?=docker
|
||||||
|
|
||||||
|
NUGET_REGISTRY?=TrueCloudLab
|
||||||
|
NUGET_REGISTRY_URL?=https://git.frostfs.info/api/packages/TrueCloudLab/nuget/index.json
|
||||||
|
NUGET_REGISTRY_USER?=
|
||||||
|
NUGET_REGISTRY_PASSWORD?=
|
||||||
|
|
||||||
|
NUPKG=find -iname '*.nupkg' | grep . | xargs -d'\n' -t -r -n1
|
||||||
|
RFC3161_TSA?=http://timestamp.digicert.com
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
$(DOTNET) build
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: sign
|
||||||
|
sign: export NUGET_CERT_REVOCATION_MODE=offline
|
||||||
|
sign: release/maintainer.pfx
|
||||||
|
$(NUPKG) $(DOTNET) nuget sign --overwrite --certificate-path $< --timestamper "$(RFC3161_TSA)"
|
||||||
|
@rm -v "$<" # maintainer.pfx is not password protected and must be ephemeral
|
||||||
|
$(NUPKG) $(DOTNET) nuget verify
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: publish
|
||||||
|
publish:
|
||||||
|
$(NUPKG) $(DOTNET) nuget verify
|
||||||
|
$(NUPKG) $(DOTNET) nuget push --source "$(NUGET_REGISTRY)"
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: nuget-registry
|
||||||
|
nuget-registry:
|
||||||
|
ifeq (,$(NUGET_REGISTRY_USER))
|
||||||
|
$(error NUGET_REGISTRY_USER not set)
|
||||||
|
endif
|
||||||
|
ifeq (,$(NUGET_REGISTRY_PASSWORD))
|
||||||
|
$(error NUGET_REGISTRY_PASSWORD not set)
|
||||||
|
endif
|
||||||
|
$(DOTNET) nuget add source \
|
||||||
|
--name "$(NUGET_REGISTRY)" \
|
||||||
|
--username "$(NUGET_REGISTRY_USER)" \
|
||||||
|
--password "$(NUGET_REGISTRY_PASSWORD)" \
|
||||||
|
--store-password-in-clear-text \
|
||||||
|
"$(NUGET_REGISTRY_URL)"
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
-$(NUPKG) rm -v
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: container
|
||||||
|
container:
|
||||||
|
$(DOCKER) run --pull=always --rm -it -v "$$PWD:/src" -w /src git.frostfs.info/truecloudlab/env:dotnet-8.0
|
||||||
|
|
||||||
|
|
||||||
|
include release/codesign.mk
|
82
release/README.md
Normal file
82
release/README.md
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
# Release process
|
||||||
|
|
||||||
|
## Preparing release
|
||||||
|
|
||||||
|
_TBD_
|
||||||
|
|
||||||
|
## Trusting TrueCloudLab code signing CA certificate
|
||||||
|
|
||||||
|
Verifying signatures (and signing) TrueCloudLab packages requires adding
|
||||||
|
[TrueCloudLab Code Signing CA](ca.cert) to the list of trusted roots.
|
||||||
|
|
||||||
|
On Linux this can be done by appending [release/ca.cert](ca.cert) to one of:
|
||||||
|
|
||||||
|
- `/etc/pki/ca-trust/extracted/pem/objsign-ca-bundle.pem`: compatible with
|
||||||
|
[update-ca-trust] and originally proposed in [.NET design docs]
|
||||||
|
- `…/dotnet/sdk/X.Y.ZZZ/trustedroots/codesignctl.pem`: [fallback] codesigning certificate trust list for .NET
|
||||||
|
|
||||||
|
[update-ca-trust]: https://www.linux.org/docs/man8/update-ca-trust.html
|
||||||
|
[.NET design docs]: https://github.com/dotnet/designs/blob/main/accepted/2021/signed-package-verification/re-enable-signed-package-verification-technical.md#linux
|
||||||
|
[fallback]: https://github.com/dotnet/sdk/blob/11150c0ec9020625308edeec555a8b78dbfb2aa5/src/Layout/redist/trustedroots/README.md
|
||||||
|
|
||||||
|
## Signing Nuget packages
|
||||||
|
|
||||||
|
Repository maintainer places `maintainer.cert` and `maintainer.key` (see below
|
||||||
|
regarding obtaining these files) into `release/` directory and then
|
||||||
|
executes:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ make build sign
|
||||||
|
```
|
||||||
|
|
||||||
|
## Uploading packages to Nuget registry
|
||||||
|
|
||||||
|
**IMPORTANT: the following steps upload all `*.nupkg` files located under
|
||||||
|
`src/`. Maintainer MUST make sure that no unnecessary package versions will be
|
||||||
|
uploaded to the registry.**
|
||||||
|
|
||||||
|
Configure registry credentials (once per machine):
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ make nuget-registry NUGET_REGISTRY_USER=username NUGET_REGISTRY_PASSWORD=token
|
||||||
|
```
|
||||||
|
|
||||||
|
Publish all locally built packages (implicitly clear existing `*.nupkg` and
|
||||||
|
rebuild current version only):
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ make clean build sign publish
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Obtaining release signing certificate
|
||||||
|
|
||||||
|
Repository maintainer owns and keeps safe the release signing key
|
||||||
|
(`maintainer.key`). Private key should never leave maintainer's machine and
|
||||||
|
should be considered a highly sensitive secret.
|
||||||
|
|
||||||
|
- Generating new maintainer key and the corresponding CSR:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ make maintainer.csr
|
||||||
|
...lines skipped...
|
||||||
|
Enter PEM pass phrase:
|
||||||
|
Verifying - Enter PEM pass phrase:
|
||||||
|
-----
|
||||||
|
IMPORTANT: Keep maintainer.key private!
|
||||||
|
|
||||||
|
Certificate signing request is ready.
|
||||||
|
Send maintainer.csr to CA administrator to obtain the certificate.
|
||||||
|
```
|
||||||
|
|
||||||
|
Resulting CSR (`maintainer.csr`) does not contain any sensitive
|
||||||
|
cryptographic material and may be passed to CA administrator through regular
|
||||||
|
communication channels.
|
||||||
|
|
||||||
|
- CA administrator then issues the certificate (`make maintainer.cert`) and
|
||||||
|
sends it back to the maintainer to be used in combination with
|
||||||
|
`maintainer.key`
|
||||||
|
|
||||||
|
This procedure should be repeated once per machine per `maintainer.cert`
|
||||||
|
lifetime (1 year) - typically just once per year since we expect the
|
||||||
|
maintainer to use only a single computer to sign releases.
|
34
release/ca.cert
Normal file
34
release/ca.cert
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIF2zCCA8OgAwIBAgIUa9xC/RgvFtUG/xeR016nn0B4K0YwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwdTELMAkGA1UEBhMCUlUxFTATBgNVBAoMDFRydWVDbG91ZExhYjEVMBMGA1UE
|
||||||
|
CwwMVHJ1ZUNsb3VkTGFiMTgwNgYDVQQDDC9UcnVlQ2xvdWRMYWIgQ29kZSBTaWdu
|
||||||
|
aW5nIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0yNTA0MTAxNTI2MTFaFw0zNTA0
|
||||||
|
MDgxNTI2MTFaMHUxCzAJBgNVBAYTAlJVMRUwEwYDVQQKDAxUcnVlQ2xvdWRMYWIx
|
||||||
|
FTATBgNVBAsMDFRydWVDbG91ZExhYjE4MDYGA1UEAwwvVHJ1ZUNsb3VkTGFiIENv
|
||||||
|
ZGUgU2lnbmluZyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEB
|
||||||
|
AQUAA4ICDwAwggIKAoICAQCyANB4cjf+ZEAFx9RiUYXCAOPMV+jyqgcVbhzh2YKc
|
||||||
|
9SlvGKRlc00Ar1RlFcrycdkIrTKmhhobiWsFp7UgphwLqRTCb5NB6qfUoWhnfiD9
|
||||||
|
m0OBgeVX5wivVaibRI9PSTbFDcIhYUiNvwFJ6GduH/9zOxf1BvuL7LMaoyhIDcg/
|
||||||
|
XVLuekE2lnX83zsedv0v/2jyyMY9Ct6N2BXzyHSAzSdYYg0F9Qu9fIMAPjoKhWPc
|
||||||
|
PnotqaACjb1DScLUr3E/o2W1FfprTT2Pip/0AXxO4wixl4QWh9HeOKV22KRcCHo6
|
||||||
|
3wNdg5q1ZVGTNBW0+yoB4jsSG8/JM+2Ujhc1ZnYH10armvGq/0Oc2YQE00960Wy8
|
||||||
|
t0drCFWJUO1XHNeBxkkupmj7N1TAPbixtfiGZJhECOWOJwyMpcKixlt5P0cNH4N/
|
||||||
|
p3vjyrGQxGLBIkgV/QgjfGkpTHKT1/H40YK6DliWJc01KfNTqn0K+/TIyF0n26kD
|
||||||
|
BWYVlvDh5P1+V9DGuD2zeXB3PstoifD/Pd7D8wuqpm17noFE19MLp94xv03q9nEa
|
||||||
|
jRMEd2J2buTLvMh5BBVH0Sm38QAHpSIZ9O3dSLvvjlALbVtwmcsNE9fgxiue3vTB
|
||||||
|
iXNW8wWs+/DMYwbWyBoCwORxVOdOyc1JLn7qAAEUBweilPVXpWuzMLdUsifPiqrV
|
||||||
|
dQIDAQABo2MwYTAdBgNVHQ4EFgQUEz4y/RvQMmbUFvf5JbGe/0PZR90wHwYDVR0j
|
||||||
|
BBgwFoAUEz4y/RvQMmbUFvf5JbGe/0PZR90wDwYDVR0TAQH/BAUwAwEB/zAOBgNV
|
||||||
|
HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADggIBAF79W9hMGnrKUWLDOcoeXDEn
|
||||||
|
+gZxd5rjeF0tNEQGbWKGTJAGQdprOkzWQ47PewpFeS+ePpjOglBAt7cV2ZnOugAT
|
||||||
|
Brx31vYpNAvYnUCYn+/IUqD8S/U4uErVS9zG9QjirZWo56eJP62vnScKuApCQCbA
|
||||||
|
pp0zrIyJ+2lQKzlMOENRqzYYA/UTOqYTtnW6x2D8goVqCmDXpgpxEp5XliFjJSr6
|
||||||
|
dOjiopNWMvaV3R/Bnd4i41taM7M6HpIV+gbXmEKEFS0ejVfzT8z1pTigN7GBqbxf
|
||||||
|
nXD03eLUIsbMDv4ZQPrheN7nKnjRUn8kxz0SSK1m2YDrXW51m8fOs6aTvwC/cNe+
|
||||||
|
FJMqQMF32i4IXVfUbyUJi+JMvawqm2wEY46vrh7siprY6rXsAzCKJo07i6jvUwnT
|
||||||
|
TXMldSCPgTEqzT2JBzzr0tRfuPKsv0/NqflHvwfuMRCpcZ7jJZ700iN92xXkiQHP
|
||||||
|
DmCZOILXcNclAth3nAnyY4XE5a8myv8bwYaPdJdIFlV+BoU/8mClDeA8ck4rDy12
|
||||||
|
T5YChKew2oiL4j4B6v9/yrDjD1IT0gv4BWyPhb/n390BCEXt8g9auNcT0s6O8kEc
|
||||||
|
VUDVc1519ocMCuWVuqUK9o2w0zu50/pBn4hVLfT3QyW8sqtlRKghOWtqZzigvCWF
|
||||||
|
VjATeO5F/Z7OSDebHUGv
|
||||||
|
-----END CERTIFICATE-----
|
74
release/codesign.mk
Normal file
74
release/codesign.mk
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
PKI_ROLE?=maintainer
|
||||||
|
PKI_DIR?=release
|
||||||
|
|
||||||
|
# Note: Only RSA signatures are supported (NU3013)
|
||||||
|
# https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu3013)
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(PKI_ROLE),maintainer)
|
||||||
|
.PHONY: maintainer.csr
|
||||||
|
maintainer.csr: $(PKI_DIR)/maintainer.csr
|
||||||
|
$(PKI_DIR)/maintainer.csr: KEY=$(patsubst %.csr,%.key,$@)
|
||||||
|
$(PKI_DIR)/maintainer.csr:
|
||||||
|
openssl req \
|
||||||
|
-new \
|
||||||
|
-newkey rsa:4096 \
|
||||||
|
-keyout $(KEY) \
|
||||||
|
-out $@ \
|
||||||
|
-sha256 \
|
||||||
|
-addext keyUsage=critical,digitalSignature \
|
||||||
|
-addext extendedKeyUsage=critical,codeSigning,msCodeCom \
|
||||||
|
-subj "/C=RU/O=TrueCloudLab/OU=TrueCloudLab/CN=frostfs-sdk-csharp Release Team"
|
||||||
|
@echo "IMPORTANT: Keep $(KEY) private!\n"
|
||||||
|
@echo "Certificate signing request is ready.\nSend $@ to CA administrator to obtain the certificate."
|
||||||
|
|
||||||
|
$(PKI_DIR)/maintainer.pfx: $(PKI_DIR)/maintainer.cert $(PKI_DIR)/maintainer.key $(PKI_DIR)/ca.cert
|
||||||
|
openssl verify \
|
||||||
|
-CAfile $(PKI_DIR)/ca.cert \
|
||||||
|
$(PKI_DIR)/maintainer.cert
|
||||||
|
openssl pkcs12 \
|
||||||
|
-export \
|
||||||
|
-out $@ \
|
||||||
|
-inkey $(PKI_DIR)/maintainer.key \
|
||||||
|
-in $(PKI_DIR)/maintainer.cert \
|
||||||
|
-CAfile $(PKI_DIR)/ca.cert \
|
||||||
|
-chain \
|
||||||
|
-passout pass:
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(PKI_ROLE),ca)
|
||||||
|
.PHONY: maintainer.cert
|
||||||
|
maintainer.cert: $(PKI_DIR)/maintainer.cert
|
||||||
|
$(PKI_DIR)/maintainer.cert: CSR=$(patsubst %.cert,%.csr,$@)
|
||||||
|
$(PKI_DIR)/maintainer.cert: $(PKI_DIR)/ca.key $(PKI_DIR)/ca.cert
|
||||||
|
openssl req -noout -text -in $(CSR)
|
||||||
|
@read -p "Review the CSR above. Press Enter to continue, Ctrl+C to cancel
" -r null
|
||||||
|
openssl x509 \
|
||||||
|
-req \
|
||||||
|
-days 365 \
|
||||||
|
-in $(CSR) \
|
||||||
|
-copy_extensions copy \
|
||||||
|
-ext keyUsage,extendedKeyUsage \
|
||||||
|
-CA $(PKI_DIR)/ca.cert \
|
||||||
|
-CAkey $(PKI_DIR)/ca.key \
|
||||||
|
-CAcreateserial \
|
||||||
|
-out $@
|
||||||
|
echo >> $@
|
||||||
|
cat $(PKI_DIR)/ca.cert >> $@
|
||||||
|
openssl x509 -noout -text -in $@ -fingerprint -sha256
|
||||||
|
@echo "Certificate is ready.\nSend $@ back to maintainer."
|
||||||
|
|
||||||
|
$(PKI_DIR)/ca.key: CERT=$(patsubst %.key,%.cert,$@)
|
||||||
|
$(PKI_DIR)/ca.key:
|
||||||
|
openssl req \
|
||||||
|
-x509 \
|
||||||
|
-newkey rsa:4096 \
|
||||||
|
-keyout $@ \
|
||||||
|
-out $(CERT) \
|
||||||
|
-sha256 \
|
||||||
|
-days 3650 \
|
||||||
|
-addext keyUsage=critical,keyCertSign \
|
||||||
|
-subj "/C=RU/O=TrueCloudLab/OU=TrueCloudLab/CN=TrueCloudLab Code Signing Certificate Authority"
|
||||||
|
@echo "IMPORTANT: Keep $@ private!\n"
|
||||||
|
endif
|
Loading…
Add table
Reference in a new issue