cmd/dist,release/dist: expose RPM signing hook (#8789)

Plumb a signing callback function to `unixpkgs.rpmTarget` to allow
signing RPMs. This callback is optional and RPMs will build unsigned if
not set, just as before.

Updates https://github.com/tailscale/tailscale/issues/1882

Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
pull/8813/head
Andrew Lytvynov 1 year ago committed by GitHub
parent eb6883bb5a
commit 371e1ebf07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

5
cmd/dist/dist.go vendored

@ -6,7 +6,6 @@ package main
import ( import (
"context" "context"
"crypto"
"errors" "errors"
"flag" "flag"
"log" "log"
@ -20,10 +19,10 @@ import (
var synologyPackageCenter bool var synologyPackageCenter bool
func getTargets(tgzSigner crypto.Signer) ([]dist.Target, error) { func getTargets(signers unixpkgs.Signers) ([]dist.Target, error) {
var ret []dist.Target var ret []dist.Target
ret = append(ret, unixpkgs.Targets(tgzSigner)...) ret = append(ret, unixpkgs.Targets(signers)...)
// Synology packages can be built either for sideloading, or for // Synology packages can be built either for sideloading, or for
// distribution by Synology in their package center. When // distribution by Synology in their package center. When
// distributed through the package center, apps can request // distributed through the package center, apps can request

@ -19,6 +19,7 @@ import (
"github.com/peterbourgon/ff/v3/ffcli" "github.com/peterbourgon/ff/v3/ffcli"
"tailscale.com/release/dist" "tailscale.com/release/dist"
"tailscale.com/release/dist/unixpkgs"
) )
// CLI returns a CLI root command to build release packages. // CLI returns a CLI root command to build release packages.
@ -26,7 +27,7 @@ import (
// getTargets is a function that gets run in the Exec function of commands that // getTargets is a function that gets run in the Exec function of commands that
// need to know the target list. Its execution is deferred in this way to allow // need to know the target list. Its execution is deferred in this way to allow
// customization of command FlagSets with flags that influence the target list. // customization of command FlagSets with flags that influence the target list.
func CLI(getTargets func(tgzSigner crypto.Signer) ([]dist.Target, error)) *ffcli.Command { func CLI(getTargets func(unixpkgs.Signers) ([]dist.Target, error)) *ffcli.Command {
return &ffcli.Command{ return &ffcli.Command{
Name: "dist", Name: "dist",
ShortUsage: "dist [flags] <command> [command flags]", ShortUsage: "dist [flags] <command> [command flags]",
@ -36,7 +37,7 @@ func CLI(getTargets func(tgzSigner crypto.Signer) ([]dist.Target, error)) *ffcli
{ {
Name: "list", Name: "list",
Exec: func(ctx context.Context, args []string) error { Exec: func(ctx context.Context, args []string) error {
targets, err := getTargets(nil) targets, err := getTargets(unixpkgs.Signers{})
if err != nil { if err != nil {
return err return err
} }
@ -56,7 +57,7 @@ func CLI(getTargets func(tgzSigner crypto.Signer) ([]dist.Target, error)) *ffcli
if err != nil { if err != nil {
return err return err
} }
targets, err := getTargets(tgzSigner) targets, err := getTargets(unixpkgs.Signers{Tarball: tgzSigner})
if err != nil { if err != nil {
return err return err
} }

@ -24,8 +24,8 @@ import (
) )
type tgzTarget struct { type tgzTarget struct {
filenameArch string // arch to use in filename instead of deriving from goenv["GOARCH"] filenameArch string // arch to use in filename instead of deriving from goEnv["GOARCH"]
goenv map[string]string goEnv map[string]string
signer crypto.Signer signer crypto.Signer
} }
@ -33,11 +33,11 @@ func (t *tgzTarget) arch() string {
if t.filenameArch != "" { if t.filenameArch != "" {
return t.filenameArch return t.filenameArch
} }
return t.goenv["GOARCH"] return t.goEnv["GOARCH"]
} }
func (t *tgzTarget) os() string { func (t *tgzTarget) os() string {
return t.goenv["GOOS"] return t.goEnv["GOOS"]
} }
func (t *tgzTarget) String() string { func (t *tgzTarget) String() string {
@ -46,18 +46,18 @@ func (t *tgzTarget) String() string {
func (t *tgzTarget) Build(b *dist.Build) ([]string, error) { func (t *tgzTarget) Build(b *dist.Build) ([]string, error) {
var filename string var filename string
if t.goenv["GOOS"] == "linux" { if t.goEnv["GOOS"] == "linux" {
// Linux used to be the only tgz architecture, so we didn't put the OS // Linux used to be the only tgz architecture, so we didn't put the OS
// name in the filename. // name in the filename.
filename = fmt.Sprintf("tailscale_%s_%s.tgz", b.Version.Short, t.arch()) filename = fmt.Sprintf("tailscale_%s_%s.tgz", b.Version.Short, t.arch())
} else { } else {
filename = fmt.Sprintf("tailscale_%s_%s_%s.tgz", b.Version.Short, t.os(), t.arch()) filename = fmt.Sprintf("tailscale_%s_%s_%s.tgz", b.Version.Short, t.os(), t.arch())
} }
ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goenv) ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tsd, err := b.BuildGoBinary("tailscale.com/cmd/tailscaled", t.goenv) tsd, err := b.BuildGoBinary("tailscale.com/cmd/tailscaled", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -173,19 +173,19 @@ func (t *tgzTarget) Build(b *dist.Build) ([]string, error) {
} }
type debTarget struct { type debTarget struct {
goenv map[string]string goEnv map[string]string
} }
func (t *debTarget) os() string { func (t *debTarget) os() string {
return t.goenv["GOOS"] return t.goEnv["GOOS"]
} }
func (t *debTarget) arch() string { func (t *debTarget) arch() string {
return t.goenv["GOARCH"] return t.goEnv["GOARCH"]
} }
func (t *debTarget) String() string { func (t *debTarget) String() string {
return fmt.Sprintf("linux/%s/deb", t.goenv["GOARCH"]) return fmt.Sprintf("linux/%s/deb", t.goEnv["GOARCH"])
} }
func (t *debTarget) Build(b *dist.Build) ([]string, error) { func (t *debTarget) Build(b *dist.Build) ([]string, error) {
@ -193,11 +193,11 @@ func (t *debTarget) Build(b *dist.Build) ([]string, error) {
return nil, errors.New("deb only supported on linux") return nil, errors.New("deb only supported on linux")
} }
ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goenv) ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tsd, err := b.BuildGoBinary("tailscale.com/cmd/tailscaled", t.goenv) tsd, err := b.BuildGoBinary("tailscale.com/cmd/tailscaled", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -284,15 +284,16 @@ func (t *debTarget) Build(b *dist.Build) ([]string, error) {
} }
type rpmTarget struct { type rpmTarget struct {
goenv map[string]string goEnv map[string]string
signFn func(io.Reader) ([]byte, error)
} }
func (t *rpmTarget) os() string { func (t *rpmTarget) os() string {
return t.goenv["GOOS"] return t.goEnv["GOOS"]
} }
func (t *rpmTarget) arch() string { func (t *rpmTarget) arch() string {
return t.goenv["GOARCH"] return t.goEnv["GOARCH"]
} }
func (t *rpmTarget) String() string { func (t *rpmTarget) String() string {
@ -304,11 +305,11 @@ func (t *rpmTarget) Build(b *dist.Build) ([]string, error) {
return nil, errors.New("rpm only supported on linux") return nil, errors.New("rpm only supported on linux")
} }
ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goenv) ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tsd, err := b.BuildGoBinary("tailscale.com/cmd/tailscaled", t.goenv) tsd, err := b.BuildGoBinary("tailscale.com/cmd/tailscaled", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -375,6 +376,11 @@ func (t *rpmTarget) Build(b *dist.Build) ([]string, error) {
Conflicts: []string{"tailscale-relay"}, Conflicts: []string{"tailscale-relay"},
RPM: nfpm.RPM{ RPM: nfpm.RPM{
Group: "Network", Group: "Network",
Signature: nfpm.RPMSignature{
PackageSignature: nfpm.PackageSignature{
SignFn: t.signFn,
},
},
}, },
}, },
}) })

@ -6,6 +6,7 @@ package unixpkgs
import ( import (
"crypto" "crypto"
"fmt" "fmt"
"io"
"sort" "sort"
"strings" "strings"
@ -15,22 +16,27 @@ import (
_ "github.com/goreleaser/nfpm/v2/rpm" _ "github.com/goreleaser/nfpm/v2/rpm"
) )
func Targets(signer crypto.Signer) []dist.Target { type Signers struct {
Tarball crypto.Signer
RPM func(io.Reader) ([]byte, error)
}
func Targets(signers Signers) []dist.Target {
var ret []dist.Target var ret []dist.Target
for goosgoarch := range tarballs { for goosgoarch := range tarballs {
goos, goarch := splitGoosGoarch(goosgoarch) goos, goarch := splitGoosGoarch(goosgoarch)
ret = append(ret, &tgzTarget{ ret = append(ret, &tgzTarget{
goenv: map[string]string{ goEnv: map[string]string{
"GOOS": goos, "GOOS": goos,
"GOARCH": goarch, "GOARCH": goarch,
}, },
signer: signer, signer: signers.Tarball,
}) })
} }
for goosgoarch := range debs { for goosgoarch := range debs {
goos, goarch := splitGoosGoarch(goosgoarch) goos, goarch := splitGoosGoarch(goosgoarch)
ret = append(ret, &debTarget{ ret = append(ret, &debTarget{
goenv: map[string]string{ goEnv: map[string]string{
"GOOS": goos, "GOOS": goos,
"GOARCH": goarch, "GOARCH": goarch,
}, },
@ -39,10 +45,11 @@ func Targets(signer crypto.Signer) []dist.Target {
for goosgoarch := range rpms { for goosgoarch := range rpms {
goos, goarch := splitGoosGoarch(goosgoarch) goos, goarch := splitGoosGoarch(goosgoarch)
ret = append(ret, &rpmTarget{ ret = append(ret, &rpmTarget{
goenv: map[string]string{ goEnv: map[string]string{
"GOOS": goos, "GOOS": goos,
"GOARCH": goarch, "GOARCH": goarch,
}, },
signFn: signers.RPM,
}) })
} }
@ -50,12 +57,12 @@ func Targets(signer crypto.Signer) []dist.Target {
// an ancient architecture. // an ancient architecture.
ret = append(ret, &tgzTarget{ ret = append(ret, &tgzTarget{
filenameArch: "geode", filenameArch: "geode",
goenv: map[string]string{ goEnv: map[string]string{
"GOOS": "linux", "GOOS": "linux",
"GOARCH": "386", "GOARCH": "386",
"GO386": "softfloat", "GO386": "softfloat",
}, },
signer: signer, signer: signers.Tarball,
}) })
sort.Slice(ret, func(i, j int) bool { sort.Slice(ret, func(i, j int) bool {

Loading…
Cancel
Save