{cmd/dist,release/dist}: add support for intermediary QNAP signing certificates

Updates #23528

Signed-off-by: Percy Wegmann <percy@tailscale.com>
This commit is contained in:
Percy Wegmann 2025-08-15 15:45:17 -05:00 committed by Percy Wegmann
parent 6006bc92b5
commit 192fa6f05d
4 changed files with 31 additions and 23 deletions

8
cmd/dist/dist.go vendored
View File

@ -27,6 +27,7 @@ var (
gcloudKeyring string gcloudKeyring string
qnapKeyName string qnapKeyName string
qnapCertificateBase64 string qnapCertificateBase64 string
qnapCertificateIntermediariesBase64 string
) )
func getTargets() ([]dist.Target, error) { func getTargets() ([]dist.Target, error) {
@ -47,11 +48,11 @@ func getTargets() ([]dist.Target, error) {
// To build for package center, run // To build for package center, run
// ./tool/go run ./cmd/dist build --synology-package-center synology // ./tool/go run ./cmd/dist build --synology-package-center synology
ret = append(ret, synology.Targets(synologyPackageCenter, nil)...) ret = append(ret, synology.Targets(synologyPackageCenter, nil)...)
qnapSigningArgs := []string{gcloudCredentialsBase64, gcloudProject, gcloudKeyring, qnapKeyName, qnapCertificateBase64} qnapSigningArgs := []string{gcloudCredentialsBase64, gcloudProject, gcloudKeyring, qnapKeyName, qnapCertificateBase64, qnapCertificateIntermediariesBase64}
if cmp.Or(qnapSigningArgs...) != "" && slices.Contains(qnapSigningArgs, "") { if cmp.Or(qnapSigningArgs...) != "" && slices.Contains(qnapSigningArgs, "") {
return nil, errors.New("all of --gcloud-credentials, --gcloud-project, --gcloud-keyring, --qnap-key-name and --qnap-certificate must be set") return nil, errors.New("all of --gcloud-credentials, --gcloud-project, --gcloud-keyring, --qnap-key-name, --qnap-certificate and --qnap-certificate-intermediaries must be set")
} }
ret = append(ret, qnap.Targets(gcloudCredentialsBase64, gcloudProject, gcloudKeyring, qnapKeyName, qnapCertificateBase64)...) ret = append(ret, qnap.Targets(gcloudCredentialsBase64, gcloudProject, gcloudKeyring, qnapKeyName, qnapCertificateBase64, qnapCertificateIntermediariesBase64)...)
return ret, nil return ret, nil
} }
@ -65,6 +66,7 @@ func main() {
subcmd.FlagSet.StringVar(&gcloudKeyring, "gcloud-keyring", "", "path to keyring in GCP KMS (used when signing QNAP builds)") subcmd.FlagSet.StringVar(&gcloudKeyring, "gcloud-keyring", "", "path to keyring in GCP KMS (used when signing QNAP builds)")
subcmd.FlagSet.StringVar(&qnapKeyName, "qnap-key-name", "", "name of GCP key to use when signing QNAP builds") subcmd.FlagSet.StringVar(&qnapKeyName, "qnap-key-name", "", "name of GCP key to use when signing QNAP builds")
subcmd.FlagSet.StringVar(&qnapCertificateBase64, "qnap-certificate", "", "base64 encoded certificate to use when signing QNAP builds") subcmd.FlagSet.StringVar(&qnapCertificateBase64, "qnap-certificate", "", "base64 encoded certificate to use when signing QNAP builds")
subcmd.FlagSet.StringVar(&qnapCertificateIntermediariesBase64, "qnap-certificate-intermediaries", "", "base64 encoded intermediary certificate to use when signing QNAP builds")
} }
} }

View File

@ -24,7 +24,9 @@ MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEtfLbXkHUVc9oUPTNyaEK3hIwmuGRoTtd
-----END PUBLIC KEY-----" > pkcs11-release-signing-key.pem -----END PUBLIC KEY-----" > pkcs11-release-signing-key.pem
openssl dgst -sha384 -verify pkcs11-release-signing-key.pem -signature "$PKCS11_MODULE_PATH.sig" "$PKCS11_MODULE_PATH" openssl dgst -sha384 -verify pkcs11-release-signing-key.pem -signature "$PKCS11_MODULE_PATH.sig" "$PKCS11_MODULE_PATH"
echo "$QNAP_SIGNING_CERT_BASE64" | base64 --decode > cert.crt echo "$QNAP_SIGNING_CERT_BASE64" | base64 --decode > signer.pem
echo "$QNAP_SIGNING_CERT_INTERMEDIARIES_BASE64" | base64 --decode > certs.pem
openssl cms \ openssl cms \
-sign \ -sign \
@ -35,6 +37,7 @@ openssl cms \
-inkey "pkcs11:object=$QNAP_SIGNING_KEY_NAME" \ -inkey "pkcs11:object=$QNAP_SIGNING_KEY_NAME" \
-keyopt rsa_padding_mode:pss \ -keyopt rsa_padding_mode:pss \
-keyopt rsa_pss_saltlen:digest \ -keyopt rsa_pss_saltlen:digest \
-signer cert.crt \ -signer signer.pem \
-certfile certs.pem \
-in "$1" \ -in "$1" \
-out - -out -

View File

@ -32,6 +32,7 @@ type signer struct {
gcloudKeyring string gcloudKeyring string
keyName string keyName string
certificateBase64 string certificateBase64 string
certificateIntermediariesBase64 string
} }
func (t *target) String() string { func (t *target) String() string {
@ -90,6 +91,7 @@ func (t *target) buildQPKG(b *dist.Build, qnapBuilds *qnapBuilds, inner *innerPk
"-e", fmt.Sprintf("GCLOUD_KEYRING=%s", t.signer.gcloudKeyring), "-e", fmt.Sprintf("GCLOUD_KEYRING=%s", t.signer.gcloudKeyring),
"-e", fmt.Sprintf("QNAP_SIGNING_KEY_NAME=%s", t.signer.keyName), "-e", fmt.Sprintf("QNAP_SIGNING_KEY_NAME=%s", t.signer.keyName),
"-e", fmt.Sprintf("QNAP_SIGNING_CERT_BASE64=%s", t.signer.certificateBase64), "-e", fmt.Sprintf("QNAP_SIGNING_CERT_BASE64=%s", t.signer.certificateBase64),
"-e", fmt.Sprintf("QNAP_SIGNING_CERT_INTERMEDIARIES_BASE64=%s", t.signer.certificateIntermediariesBase64),
"-e", fmt.Sprintf("QNAP_SIGNING_SCRIPT=%s", "/sign-qpkg.sh"), "-e", fmt.Sprintf("QNAP_SIGNING_SCRIPT=%s", "/sign-qpkg.sh"),
"-v", fmt.Sprintf("%s:/sign-qpkg.sh", filepath.Join(qnapBuilds.tmpDir, "files/scripts/sign-qpkg.sh")), "-v", fmt.Sprintf("%s:/sign-qpkg.sh", filepath.Join(qnapBuilds.tmpDir, "files/scripts/sign-qpkg.sh")),
) )

View File

@ -18,15 +18,16 @@ import (
// gcloudKeyring is the full path to the Google Cloud keyring containing the signing key. // gcloudKeyring is the full path to the Google Cloud keyring containing the signing key.
// keyName is the name of the key. // keyName is the name of the key.
// certificateBase64 is the PEM certificate to use in the signature, base64 encoded. // certificateBase64 is the PEM certificate to use in the signature, base64 encoded.
func Targets(gcloudCredentialsBase64, gcloudProject, gcloudKeyring, keyName, certificateBase64 string) []dist.Target { func Targets(gcloudCredentialsBase64, gcloudProject, gcloudKeyring, keyName, certificateBase64, certificateIntermediariesBase64 string) []dist.Target {
var signerInfo *signer var signerInfo *signer
if !slices.Contains([]string{gcloudCredentialsBase64, gcloudProject, gcloudKeyring, keyName, certificateBase64}, "") { if !slices.Contains([]string{gcloudCredentialsBase64, gcloudProject, gcloudKeyring, keyName, certificateBase64, certificateIntermediariesBase64}, "") {
signerInfo = &signer{ signerInfo = &signer{
gcloudCredentialsBase64: gcloudCredentialsBase64, gcloudCredentialsBase64: gcloudCredentialsBase64,
gcloudProject: gcloudProject, gcloudProject: gcloudProject,
gcloudKeyring: gcloudKeyring, gcloudKeyring: gcloudKeyring,
keyName: keyName, keyName: keyName,
certificateBase64: certificateBase64, certificateBase64: certificateBase64,
certificateIntermediariesBase64: certificateIntermediariesBase64,
} }
} }
return []dist.Target{ return []dist.Target{