Compatibility with GnuPG 1.x and 2.x, auto-detect GnuPG version

* aptly can sign and verify without issues with GnuPG 1.x and 2.x
* aptly auto-detects GnuPG version and adapts accordingly
* aptly automatically finds suitable GnuPG version

Majority of the work was to get unit-tests which can work with GnuPG 1.x & 2.x.
Locally I've verified that aptly supports GnuPG 1.4.x & 2.2.x. Travis CI
environment is based on trusty, so it runs gpg2 tests with GnuPG 2.0.x.

Configuration parameter gpgProvider now supports three values for GnuPG:

* gpg (same as before, default): use GnuPG 1.x if available (checks gpg, gpg1),
otherwise uses GnuPG 2.x; for aptly users who already have GnuPG 1.x
environment (as it was the only supported version) nothing should change; new
users might start with GnuPG 2.x if that's their installed version

* gpg1 looks for GnuPG 1.x only, fails otherwise

* gpg2 looks for GnuPG 2.x only, fails otherwise
This commit is contained in:
Andrey Smirnov
2018-07-14 00:00:43 +03:00
parent 702c1ff217
commit 1b2fccb615
25 changed files with 559 additions and 93 deletions

3
.gitignore vendored
View File

@@ -38,3 +38,6 @@ system/env/
# created by make build for release artifacts
build/
pgp/keyrings/aptly2*.gpg
pgp/keyrings/aptly2*.gpg~

View File

@@ -10,6 +10,8 @@ addons:
packages:
- python-virtualenv
- graphviz
- gnupg2
- gpgv2
env:
global:

View File

@@ -119,7 +119,7 @@ package environment to new version.`,
cmd.Flag.Bool("dep-verbose-resolve", false, "when processing dependencies, print detailed logs")
cmd.Flag.String("architectures", "", "list of architectures to consider during (comma-separated), default to all available")
cmd.Flag.String("config", "", "location of configuration file (default locations are /etc/aptly.conf, ~/.aptly.conf)")
cmd.Flag.String("gpg-provider", "", "PGP implementation (\"gpg\" for external gpg or \"internal\" for Go internal implementation)")
cmd.Flag.String("gpg-provider", "", "PGP implementation (\"gpg\", \"gpg1\", \"gpg2\" for external gpg or \"internal\" for Go internal implementation)")
if aptly.EnableDebug {
cmd.Flag.String("cpuprofile", "", "write cpu profile to file")

View File

@@ -387,23 +387,42 @@ func (context *AptlyContext) pgpProvider() string {
provider = context.config().GpgProvider
}
if !(provider == "gpg" || provider == "internal") { // nolint: goconst
switch provider {
case "gpg": // nolint: goconst
case "gpg1": // nolint: goconst
case "gpg2": // nolint: goconst
case "internal": // nolint: goconst
default:
Fatal(fmt.Errorf("unknown gpg provider: %v", provider))
}
return provider
}
func (context *AptlyContext) getGPGFinder(provider string) pgp.GPGFinder {
switch context.pgpProvider() {
case "gpg1":
return pgp.GPG1Finder()
case "gpg2":
return pgp.GPG2Finder()
case "gpg":
return pgp.GPGDefaultFinder()
}
panic("uknown GPG provider type")
}
// GetSigner returns Signer with respect to provider
func (context *AptlyContext) GetSigner() pgp.Signer {
context.Lock()
defer context.Unlock()
if context.pgpProvider() == "gpg" { // nolint: goconst
return pgp.NewGpgSigner()
provider := context.pgpProvider()
if provider == "internal" { // nolint: goconst
return &pgp.GoSigner{}
}
return &pgp.GoSigner{}
return pgp.NewGpgSigner(context.getGPGFinder(provider))
}
// GetVerifier returns Verifier with respect to provider
@@ -411,11 +430,12 @@ func (context *AptlyContext) GetVerifier() pgp.Verifier {
context.Lock()
defer context.Unlock()
if context.pgpProvider() == "gpg" { // nolint: goconst
return pgp.NewGpgVerifier()
provider := context.pgpProvider()
if provider == "internal" { // nolint: goconst
return &pgp.GoVerifier{}
}
return &pgp.GoVerifier{}
return pgp.NewGpgVerifier(context.getGPGFinder(provider))
}
// UpdateFlags sets internal copy of flags in the context

View File

@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "APTLY" "1" "November 2017" "" ""
.TH "APTLY" "1" "September 2018" "" ""
.
.SH "NAME"
\fBaptly\fR \- Debian repository management tool
@@ -150,7 +150,7 @@ don\(cqt verify remote mirrors with gpg(1), also can be disabled on per\-mirror
.
.TP
\fBgpgProvider\fR
implementation of PGP signing/validation \- \fBgpg\fR for external \fBgpg\fR utility or \fBinternal\fR to use Go internal implementation
implementation of PGP signing/validation \- \fBgpg\fR for external \fBgpg\fR utility or \fBinternal\fR to use Go internal implementation; \fBgpg1\fR might be used to force use of GnuPG 1\.x, \fBgpg2\fR enables GnuPG 2\.x only; default is to use GnuPG 1\.x if available and GnuPG 2\.x otherwise
.
.TP
\fBdownloadSourcePackages\fR
@@ -434,7 +434,7 @@ when processing dependencies, print detailed logs
.
.TP
\-\fBgpg\-provider\fR=
PGP implementation ("gpg" for external gpg or "internal" for Go internal implementation)
PGP implementation ("gpg", "gpg1", "gpg2" for external gpg or "internal" for Go internal implementation)
.
.SH "CREATE NEW MIRROR"
\fBaptly\fR \fBmirror\fR \fBcreate\fR \fIname\fR \fIarchive url\fR \fIdistribution\fR [\fIcomponent1\fR \|\.\|\.\|\.]
@@ -2038,5 +2038,17 @@ Matt Martyn (https://github\.com/MMartyn)
.IP "\[ci]" 4
Ludovico Cavedon (https://github\.com/cavedon)
.
.IP "\[ci]" 4
Petr Jediny (https://github\.com/pjediny)
.
.IP "\[ci]" 4
Maximilian Stein (https://github\.com/steinymity)
.
.IP "\[ci]" 4
Strajan Sebastian (https://github\.com/strajansebastian)
.
.IP "\[ci]" 4
Artem Smirnov (https://github\.com/urpylka)
.
.IP "" 0

View File

@@ -130,7 +130,9 @@ Options:
* `gpgProvider`:
implementation of PGP signing/validation - `gpg` for external `gpg` utility or
`internal` to use Go internal implementation
`internal` to use Go internal implementation; `gpg1` might be used to force use
of GnuPG 1.x, `gpg2` enables GnuPG 2.x only; default is to use GnuPG 1.x if
available and GnuPG 2.x otherwise
* `downloadSourcePackages`:
if enabled, all mirrors created would have flag set to download source packages;

View File

@@ -3,6 +3,7 @@ package pgp
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
@@ -18,12 +19,10 @@ var (
_ Verifier = &GpgVerifier{}
)
// Skip GPG version check for GPG 1.x
var skipGPGVersionCheck bool
// GpgSigner is implementation of Signer interface using gpg as external program
type GpgSigner struct {
gpg string
version GPGVersion
keyRef string
keyring, secretKeyring string
passphrase, passphraseFile string
@@ -55,7 +54,7 @@ func (g *GpgSigner) gpgArgs() []string {
if g.keyring != "" {
args = append(args, "--no-auto-check-trustdb", "--no-default-keyring", "--keyring", g.keyring)
}
if g.secretKeyring != "" {
if g.secretKeyring != "" && g.version == GPG1x {
args = append(args, "--secret-keyring", g.secretKeyring)
}
@@ -64,7 +63,9 @@ func (g *GpgSigner) gpgArgs() []string {
}
if g.passphrase != "" || g.passphraseFile != "" {
args = append(args, "--no-use-agent")
if g.version == GPG1x {
args = append(args, "--no-use-agent")
}
}
if g.passphrase != "" {
@@ -77,53 +78,21 @@ func (g *GpgSigner) gpgArgs() []string {
if g.batch {
args = append(args, "--no-tty", "--batch")
if g.version == GPG21xPlus {
args = append(args, "--pinentry-mode", "loopback")
}
}
return args
}
func cliVersionCheck(cmd string, marker string) bool {
output, err := exec.Command(cmd, "--version").CombinedOutput()
if err != nil {
return false
}
return skipGPGVersionCheck || strings.Contains(string(output), marker)
}
func findSuitableCLI(cmds []string, versionMarker string) string {
for _, cmd := range cmds {
if cliVersionCheck(cmd, versionMarker) {
return cmd
}
}
return ""
}
// We only support gpg1 at this time. Make sure we find a suitable binary.
func findGPG1() (string, error) {
cmd := findSuitableCLI([]string{"gpg", "gpg1"}, "gpg (GnuPG) 1.")
if cmd != "" {
return cmd, nil
}
return "", fmt.Errorf("Couldn't find a suitable gpg executable. Make sure gnupg1 is available as either gpg or gpg1 in $PATH")
}
// We only support gpgv1 at this time. Make sure we find a suitable binary.
func findGPGV1() (string, error) {
cmd := findSuitableCLI([]string{"gpgv", "gpgv1"}, "gpgv (GnuPG) 1.")
if cmd != "" {
return cmd, nil
}
return "", fmt.Errorf("Couldn't find a suitable gpgv executable. Make sure gpgv1 is available as either gpgv or gpgv1 in $PATH")
}
// NewGpgSigner creates a new gpg signer
func NewGpgSigner() *GpgSigner {
gpg, err := findGPG1()
func NewGpgSigner(finder GPGFinder) *GpgSigner {
gpg, version, err := finder.FindGPG()
if err != nil {
panic(err)
}
return &GpgSigner{gpg: gpg}
return &GpgSigner{gpg: gpg, version: version}
}
// Init verifies availability of gpg & presence of keys
@@ -171,22 +140,27 @@ func (g *GpgSigner) ClearSign(source string, destination string) error {
type GpgVerifier struct {
gpg string
gpgv string
version GPGVersion
keyRings []string
}
// NewGpgVerifier creates a new gpg verifier
func NewGpgVerifier() *GpgVerifier {
gpg, err := findGPG1()
func NewGpgVerifier(finder GPGFinder) *GpgVerifier {
gpg, versionGPG, err := finder.FindGPG()
if err != nil {
panic(err)
}
gpgv, err := findGPGV1()
gpgv, versionGPGV, err := finder.FindGPGV()
if err != nil {
panic(err)
}
return &GpgVerifier{gpg: gpg, gpgv: gpgv}
if versionGPG != versionGPGV {
panic(errors.New("gpg and gpgv versions don't match"))
}
return &GpgVerifier{gpg: gpg, gpgv: gpgv, version: versionGPG}
}
// InitKeyring verifies that gpg is installed and some keys are trusted
@@ -417,11 +391,3 @@ func (g *GpgVerifier) ExtractClearsigned(clearsigned io.Reader) (text *os.File,
return
}
func init() {
skipCheck := os.Getenv("APTLY_SKIP_GPG_VERSION_CHECK")
switch strings.ToLower(skipCheck) {
case "1", "y", "yes", "true":
skipGPGVersionCheck = true
}
}

149
pgp/gnupg_finder.go Normal file
View File

@@ -0,0 +1,149 @@
package pgp
import (
"errors"
"os/exec"
"regexp"
"strings"
)
// GPGVersion stores discovered GPG version
type GPGVersion int
// GPG version as discovered
const (
GPG1x GPGVersion = 1
GPG20x GPGVersion = 2
GPG21xPlus GPGVersion = 3
)
var gpgVersionRegex = regexp.MustCompile(`\(GnuPG\) (\d)\.(\d)`)
// GPGFinder implement search for gpg executables and returns version of discovered executables
type GPGFinder interface {
FindGPG() (gpg string, version GPGVersion, err error)
FindGPGV() (gpgv string, version GPGVersion, err error)
}
type pathGPGFinder struct {
gpgNames []string
gpgvNames []string
errorMessage string
expectedVersionSubstring string
}
type iteratingGPGFinder struct {
finders []GPGFinder
errorMessage string
}
// GPGDefaultFinder looks for GPG1 first, but falls back to GPG2 if GPG1 is not available
func GPGDefaultFinder() GPGFinder {
return &iteratingGPGFinder{
finders: []GPGFinder{GPG1Finder(), GPG2Finder()},
errorMessage: "Couldn't find a suitable gpg executable. Make sure gnupg is installed",
}
}
// GPG1Finder looks for GnuPG1.x only
func GPG1Finder() GPGFinder {
return &pathGPGFinder{
gpgNames: []string{"gpg", "gpg1"},
gpgvNames: []string{"gpgv", "gpgv1"},
expectedVersionSubstring: "(GnuPG) 1.",
errorMessage: "Couldn't find a suitable gpg executable. Make sure gnupg1 is available as either gpg(v) or gpg(v)1 in $PATH",
}
}
// GPG2Finder looks for GnuPG2.x only
func GPG2Finder() GPGFinder {
return &pathGPGFinder{
gpgNames: []string{"gpg", "gpg2"},
gpgvNames: []string{"gpgv", "gpgv2"},
expectedVersionSubstring: "(GnuPG) 2.",
errorMessage: "Couldn't find a suitable gpg executable. Make sure gnupg2 is available as either gpg(v) or gpg(v)2 in $PATH",
}
}
func (pgf *pathGPGFinder) FindGPG() (gpg string, version GPGVersion, err error) {
for _, cmd := range pgf.gpgNames {
var result bool
result, version = cliVersionCheck(cmd, pgf.expectedVersionSubstring)
if result {
gpg = cmd
break
}
}
if gpg == "" {
err = errors.New(pgf.errorMessage)
}
return
}
func (pgf *pathGPGFinder) FindGPGV() (gpgv string, version GPGVersion, err error) {
for _, cmd := range pgf.gpgvNames {
var result bool
result, version = cliVersionCheck(cmd, pgf.expectedVersionSubstring)
if result {
gpgv = cmd
break
}
}
if gpgv == "" {
err = errors.New(pgf.errorMessage)
}
return
}
func (it *iteratingGPGFinder) FindGPG() (gpg string, version GPGVersion, err error) {
for _, finder := range it.finders {
gpg, version, err = finder.FindGPG()
if err == nil {
return
}
}
err = errors.New(it.errorMessage)
return
}
func (it *iteratingGPGFinder) FindGPGV() (gpg string, version GPGVersion, err error) {
for _, finder := range it.finders {
gpg, version, err = finder.FindGPGV()
if err == nil {
return
}
}
err = errors.New(it.errorMessage)
return
}
func cliVersionCheck(cmd string, marker string) (result bool, version GPGVersion) {
output, err := exec.Command(cmd, "--version").CombinedOutput()
if err != nil {
return
}
strOutput := string(output)
result = strings.Contains(strOutput, marker)
version = GPG21xPlus
matches := gpgVersionRegex.FindStringSubmatch(strOutput)
if matches != nil {
if matches[1] == "1" {
version = GPG1x
} else if matches[1] == "2" && matches[2] == "0" {
version = GPG20x
}
}
return
}

View File

@@ -2,6 +2,7 @@ package pgp
import (
"os"
"os/exec"
"path/filepath"
"runtime"
@@ -26,7 +27,7 @@ func (s *GnupgSuite) TestGPG1(c *C) {
os.Setenv("PATH", filepath.Join(s.bins, "gpg1"))
defer func() { os.Setenv("PATH", origPath) }()
signer := NewGpgSigner()
signer := NewGpgSigner(GPG1Finder())
c.Assert(signer.gpg, Equals, "gpg")
}
@@ -36,7 +37,7 @@ func (s *GnupgSuite) TestGPG1Not2(c *C) {
os.Setenv("PATH", filepath.Join(s.bins, "gpg2-and-1"))
defer func() { os.Setenv("PATH", origPath) }()
signer := NewGpgSigner()
signer := NewGpgSigner(GPG1Finder())
c.Assert(signer.gpg, Equals, "gpg1")
}
@@ -46,7 +47,7 @@ func (s *GnupgSuite) TestGPGNothing(c *C) {
os.Setenv("PATH", filepath.Join(s.bins, "gpg2-only"))
defer func() { os.Setenv("PATH", origPath) }()
c.Assert(func() { NewGpgSigner() }, PanicMatches, `Couldn't find a suitable gpg executable.+`)
c.Assert(func() { NewGpgSigner(GPG1Finder()) }, PanicMatches, `Couldn't find a suitable gpg executable.+`)
}
// If gpgv == gpgv1 = pick gpgv
@@ -55,7 +56,7 @@ func (s *GnupgSuite) TestGPGV1(c *C) {
os.Setenv("PATH", filepath.Join(s.bins, "gpgv1")+":"+filepath.Join(s.bins, "gpg1"))
defer func() { os.Setenv("PATH", origPath) }()
verifier := NewGpgVerifier()
verifier := NewGpgVerifier(GPG1Finder())
c.Assert(verifier.gpgv, Equals, "gpgv")
}
@@ -65,7 +66,7 @@ func (s *GnupgSuite) TestGPGV1Not2(c *C) {
os.Setenv("PATH", filepath.Join(s.bins, "gpgv2-and-1")+":"+filepath.Join(s.bins, "gpg1"))
defer func() { os.Setenv("PATH", origPath) }()
verifier := NewGpgVerifier()
verifier := NewGpgVerifier(GPG1Finder())
c.Assert(verifier.gpgv, Equals, "gpgv1")
}
@@ -75,7 +76,7 @@ func (s *GnupgSuite) TestGPGVNothing(c *C) {
os.Setenv("PATH", filepath.Join(s.bins, "gpgv2-only")+":"+filepath.Join(s.bins, "gpg1"))
defer func() { os.Setenv("PATH", origPath) }()
c.Assert(func() { NewGpgVerifier() }, PanicMatches, `Couldn't find a suitable gpgv executable.+`)
c.Assert(func() { NewGpgVerifier(GPG1Finder()) }, PanicMatches, `Couldn't find a suitable gpg executable.+`)
}
type Gnupg1VerifierSuite struct {
@@ -85,7 +86,13 @@ type Gnupg1VerifierSuite struct {
var _ = Suite(&Gnupg1VerifierSuite{})
func (s *Gnupg1VerifierSuite) SetUpTest(c *C) {
s.verifier = NewGpgVerifier()
finder := GPG1Finder()
_, _, err := finder.FindGPG()
if err != nil {
c.Skip(err.Error())
}
s.verifier = NewGpgVerifier(finder)
s.verifier.AddKeyring("./trusted.gpg")
c.Assert(s.verifier.InitKeyring(), IsNil)
@@ -98,7 +105,18 @@ type Gnupg1SignerSuite struct {
var _ = Suite(&Gnupg1SignerSuite{})
func (s *Gnupg1SignerSuite) SetUpTest(c *C) {
s.signer = NewGpgSigner()
finder := GPG1Finder()
_, _, err := finder.FindGPG()
if err != nil {
c.Skip(err.Error())
}
s.keyringNoPassphrase = [2]string{"keyrings/aptly.pub", "keyrings/aptly.sec"}
s.keyringPassphrase = [2]string{"keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec"}
s.passphraseKey = "F30E8CB9CDDE2AF8"
s.noPassphraseKey = "21DBB89C16DB3E6D"
s.signer = NewGpgSigner(finder)
s.signer.SetBatch(true)
s.verifier = &GoVerifier{}
@@ -109,3 +127,95 @@ func (s *Gnupg1SignerSuite) SetUpTest(c *C) {
s.SignerSuite.SetUpTest(c)
}
type Gnupg2VerifierSuite struct {
VerifierSuite
}
var _ = Suite(&Gnupg2VerifierSuite{})
func (s *Gnupg2VerifierSuite) SetUpTest(c *C) {
finder := GPG2Finder()
_, _, err := finder.FindGPG()
if err != nil {
c.Skip(err.Error())
}
s.verifier = NewGpgVerifier(finder)
s.verifier.AddKeyring("./trusted.gpg")
c.Assert(s.verifier.InitKeyring(), IsNil)
}
type Gnupg2SignerSuite struct {
SignerSuite
}
var _ = Suite(&Gnupg2SignerSuite{})
func (s *Gnupg2SignerSuite) SetUpTest(c *C) {
finder := GPG2Finder()
gpg, ver, err := finder.FindGPG()
if err != nil {
c.Skip(err.Error())
}
// import private keys into gpg2, they're stored outside of keyring files
for _, item := range []struct {
suffix string
key string
}{
{"", "751DF85C2B220D45"},
{"_passphrase", "6656CD181E92D2D5"},
} {
if _, err := exec.Command(gpg, "--list-secret-keys", item.key).CombinedOutput(); err == nil {
// key already exists
continue
}
args := []string{"--import", "--no-default-keyring"}
if item.suffix == "_passprhase" {
args = append(args, "--passphrase", "verysecret", "--no-tty", "--batch")
if ver == GPG21xPlus {
args = append(args, "--pinentry-mode", "loopback")
}
}
args = append(args, "keyrings/aptly2"+item.suffix+".sec.armor")
output, err := exec.Command(gpg, args...).CombinedOutput()
c.Log(string(output))
c.Check(err, IsNil)
}
// import public keys into gpg2
// we can't use pre-built keyrings as gpg 2.0.x and 2.1+ have different keyring formats
for _, suffix := range []string{"", "_passphrase"} {
output, err := exec.Command(gpg, "--no-default-keyring", "--keyring", "./keyrings/aptly2"+suffix+".gpg",
"--import", "keyrings/aptly2"+suffix+".pub.armor").CombinedOutput()
c.Log(string(output))
c.Check(err, IsNil)
}
s.keyringNoPassphrase = [2]string{"./keyrings/aptly2.gpg", ""}
s.keyringPassphrase = [2]string{"./keyrings/aptly2_passphrase.gpg", ""}
s.noPassphraseKey = "751DF85C2B220D45"
s.passphraseKey = "6656CD181E92D2D5"
s.signer = NewGpgSigner(finder)
s.signer.SetBatch(true)
s.verifier = &GoVerifier{}
s.verifier.AddKeyring("./keyrings/aptly2_trusted.pub")
c.Assert(s.verifier.InitKeyring(), IsNil)
s.SignerSuite.SetUpTest(c)
}
func (s *Gnupg2SignerSuite) TearDownTest(c *C) {
s.SignerSuite.TearDownTest(c)
os.Remove("./keyrings/aptly2.gpg")
os.Remove("./keyrings/aptly2_passphrase.gpg")
}

View File

@@ -24,6 +24,11 @@ type GoSignerSuite struct {
var _ = Suite(&GoSignerSuite{})
func (s *GoSignerSuite) SetUpTest(c *C) {
s.keyringNoPassphrase = [2]string{"keyrings/aptly.pub", "keyrings/aptly.sec"}
s.keyringPassphrase = [2]string{"keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec"}
s.passphraseKey = "F30E8CB9CDDE2AF8"
s.noPassphraseKey = "21DBB89C16DB3E6D"
s.signer = &GoSigner{}
s.signer.SetBatch(true)

View File

@@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFuAfvMBCACuElVMZctaYEMSIoYLAefC2ygH/MUWA41h/MT/kMakexK7B2N/
noPUhA0Z7xWiqxnvJqaOGuT2Bp2SSOuw8hXD870VMNNAVuvg63Zvj5DGhWAjR8Sm
zHaZ09+hkD+MB7+WJnyDJb0deGpJ7cFaUgS4fz1BlTWHpJX8wMBi3iqA2tulcoNn
L/pUomusNGiD+4TuWkEeYb3/ygXvfocuE0Ji7UFrijU4Dcrh7T7L7qzHDMy8hyEr
t3oZlFDlwRkr+1LrT1QBnndaddPRt1h3Av59WpasTUC8m/It0NvLpq9mqij3TNTx
OyZNJLqHrUsz1/cg3boiT4puY8gm2jpQpNLXABEBAAG0HkFwdGx5IFRlc3RlciA8
dGVzdEBhcHRseS5pbmZvPokBTgQTAQgAOBYhBOivfuFBYsLWPPwa1XUd+FwrIg1F
BQJbgH7zAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEHUd+FwrIg1FWRwH
/RmXNwgh6DEj7wN7hILL15iXOrOIjEJ2GH0cWvPdyzc/qbL552QovcaK3yb/r3V+
+1wDJ2CuBtc/CoVFq1CN/i92wIDl+Cuozny5qcd8O6EjgdmLgeANRwqyMjiPiDz9
cuabD3JPRHIqEv26PQ+qkmad42E5mipHmbA+iOE9OEWSvhDudAlYzNXECUWlNQ9+
gWnLB6hONz5jnRDZHpcKeBcQ2aJ7r5L6qDzBIybAu3jiZfl5KlT6hArXi5vDi8DK
B5is80nWPTAEb2+CfBiY80mLScNe5jG/sgOOrTqWL681RfjRtTnRe7DFKIm8guqp
tbYrv4OzkFHJ/JbWAKsBruS5AQ0EW4B+8wEIANWaf4BWY2or9oyu001EmIdFiwu2
cxGA2y8bZiqmerk+2BXDEZN4OaLu1a9RWpwo1Mc+KuXpeJNv60SG0zRFBLVrvPyg
irhaue1p+SSuisxMdTOZrciYjWriTU4WKw+NOdiGHr5LJegE9hvW66ZYJHtYgkfB
mBuIQQ90h6qnXKGtV4FK8Fo+hr04Wh7gDGZxTRFNo3MO0a18Y87uiU5j8i/VxyfI
DSA2Uh92kPbItuEKtl23PhCSecZa4YkkWMILS7frMEbM9wDK/JFqPVPSUwQhV5jn
wwq9hwQrUimrhZjJn1EImK2QVYeJ1CVxc3K7bdlxPd8fi6zfTQ8AfpALDWkAEQEA
AYkBNgQYAQgAIBYhBOivfuFBYsLWPPwa1XUd+FwrIg1FBQJbgH7zAhsMAAoJEHUd
+FwrIg1FzpEH/2xi/DCaYRgbC4RrICebeC8FBTwI2RyBuOQJr5CIPrpWaWV4+5Ds
sIgPxU9E3QgNRjP9pzAzH2Z8WwJtRY0oYNWLFruNeg9Xl1Tf9pCK/0Csamyf/h3F
6NKfDTwNBWTsD5ttNyRx2nfDPaU4j2BZqU3kOzdwiXnmtvtxEoH059EMgQFLv91W
U7NydHYd8xcWlHIZx1uFB8HKRWB+AMXebkdLVXlUtJfZfxZr5Jb5eR77ojfsduYI
YmbV4jkDxuidSkYogYyXMO2jY2PAhx29iaZrDsNdsCsg8OmwEjCPEGWdp7tFA1QI
JrGSOnwXujoUwuqh53+n3bcVuuuKyPBW9b4=
=Tu5z
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,57 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
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
=vqFY
-----END PGP PRIVATE KEY BLOCK-----

View File

@@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFuAgf0BCADhVDnKyR5G6RzgFb7QseLqOzjvGotmbYYTuYinwLC+GGgOBD54
DTtzBk6PmU1/QW7x0yvffyeQWUXD+/zIuBLrkG2QXv9qRdADH6rCsVChtVsTRwHT
ZgJJXgfcjsZ2UUDQ43Jkb4dMaAIJTS0dASXgyLIRaN/1h4SsdKZUZY16lMH9kSxb
XI86qujCdC9WS7CWu8sLX7qKqmmAt8fTGTnTgyQCnIYtS1/je0ZfX4Z3ovzYyajJ
LA/jtCD6L+3qj9Y7desj1AvNKRCGYB8nzayYYVqozNFvlubDePinFqJThrICviNS
cNZuNmZjToPmSMF/B6zz1CkrR6Q0CIM5zkuxABEBAAG0HkFwdGx5IFRlc3RlciA8
dGVzdEBhcHRseS5pbmZvPokBTgQTAQgAOBYhBAvV0vLk0JvPtsmaFGZWzRgektLV
BQJbgIH9AhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEGZWzRgektLVAHoH
/jwdhMCDmgBR3vhS/i7ym5HFUx7o1cCv0cSoGQwgnRGLrTG4Ua4ds+FxAKjNAspC
hgxGGfTCmD1cYB4lx85I0XcpfT4ZA0ZCQ1I9m5/AJ9WWYoy2FFZNxZ7fCd2d+sm1
ydyJLCTRgJd0D2MD58vxF2+IWAkZTOridyyZP1qxfzcnSACTjbcrQFc1Bp7G1xJR
T135mcxtBSD2JeXbvq/UkeOE+LCIF5EIHUlwOdanyyHTyO86R2rU7qO0bylNyLGi
0SE3Y+j+qhg6Ns4I2SPo0JDBDrSVfPKcob1DYFF0K1yH6Cj3aGVUthsahNrP3K9S
NOVRC1JUg5an0eWcayIPpte5AQ0EW4CB/QEIAMrLVpvc2Syuhtov6mBTuIB9SUHy
9tyqK6WhyDAB7iQPC5Xrb4GXHM4z+2Vt7Pgabr630B6ySsmrKNfDB1EcUcY4aJ5Q
LBIttR25CB8PkmvllycjKp49hLXOruwx6t23/J3REyapQXLKpXDhzmMTmoGpAPcu
YTVMiiOFi0MNBI5ok9iQoG9Dbgf7F0Ie1MiLJzqfaf2dlRuh2JBayIMJ9VrtlThB
5v2CsV73Mj7EgE7oetZgH2I9Tl/2vv70VYnoXn/YL2xgfghWWlTvDTvg9s7sRnDI
4oor7SHaRZIWxqSuvVOchnlBjLADn902bFIPEanqBiAnPAHPwPOMKnBoR78AEQEA
AYkBNgQYAQgAIBYhBAvV0vLk0JvPtsmaFGZWzRgektLVBQJbgIH9AhsMAAoJEGZW
zRgektLVetQH/1QiJqu6JmEbJ4Z8mmwr25iqeC/9G1Llo6q4VAoLFygFU1EVW+wX
tPwz5RZpqoZ5K4NVFJcgLH1ExqgKW9MflPK+6ltYqH3Kgg73I5gnP9SX12hJ3oMZ
X15uGm8pN+na4fcu9rwvk87EBfXXmtP9oqdCPZ49DtkngyahTXFK/h5CbcgCx1Fw
rm1QXyH/sB8O3f6GOVly40u7CV0hzWAB98KLgEP093OI3AJjmINxErCt6cigxQzO
jgbiTMVgLKHidnpeOcKNXIlmIBFpBM4oaKFZ0qt5jiKz/QtmX7Uj+rTfCjaC1G7f
fGE72fE3nL5TcbwRyD7g9zRV3ddU5uvCnlg=
=075D
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,59 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
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
bt98YTvZ8TecvlNxvBHIPuD3NFXd11Tm68KeWA==
=YDL1
-----END PGP PRIVATE KEY BLOCK-----

Binary file not shown.

View File

@@ -20,6 +20,12 @@ type SignerSuite struct {
cleartext []byte
passwordFile string
keyringNoPassphrase [2]string
keyringPassphrase [2]string
noPassphraseKey Key
passphraseKey Key
}
func (s *SignerSuite) SetUpTest(c *C) {
@@ -70,20 +76,23 @@ func (s *SignerSuite) testSignDetached(c *C) {
}
func (s *SignerSuite) TestSignDetachedNoPassphrase(c *C) {
s.signer.SetKeyRing("keyrings/aptly.pub", "keyrings/aptly.sec")
s.signer.SetKey(string(s.noPassphraseKey))
s.signer.SetKeyRing(s.keyringNoPassphrase[0], s.keyringNoPassphrase[1])
s.testSignDetached(c)
}
func (s *SignerSuite) TestSignDetachedPassphrase(c *C) {
s.signer.SetKeyRing("keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec")
s.signer.SetKey(string(s.passphraseKey))
s.signer.SetKeyRing(s.keyringPassphrase[0], s.keyringPassphrase[1])
s.signer.SetPassphrase("verysecret", "")
s.testSignDetached(c)
}
func (s *SignerSuite) TestSignDetachedPassphraseFile(c *C) {
s.signer.SetKeyRing("keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec")
s.signer.SetKey(string(s.passphraseKey))
s.signer.SetKeyRing(s.keyringPassphrase[0], s.keyringPassphrase[1])
s.signer.SetPassphrase("", s.passwordFile)
s.testSignDetached(c)
@@ -114,21 +123,24 @@ func (s *SignerSuite) testClearSign(c *C, expectedKey Key) {
}
func (s *SignerSuite) TestClearSignNoPassphrase(c *C) {
s.signer.SetKeyRing("keyrings/aptly.pub", "keyrings/aptly.sec")
s.signer.SetKey(string(s.noPassphraseKey))
s.signer.SetKeyRing(s.keyringNoPassphrase[0], s.keyringNoPassphrase[1])
s.testClearSign(c, "21DBB89C16DB3E6D")
s.testClearSign(c, s.noPassphraseKey)
}
func (s *SignerSuite) TestClearSignPassphrase(c *C) {
s.signer.SetKeyRing("keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec")
s.signer.SetKey(string(s.passphraseKey))
s.signer.SetKeyRing(s.keyringPassphrase[0], s.keyringPassphrase[1])
s.signer.SetPassphrase("verysecret", "")
s.testClearSign(c, "F30E8CB9CDDE2AF8")
s.testClearSign(c, s.passphraseKey)
}
func (s *SignerSuite) TestClearSignPassphraseFile(c *C) {
s.signer.SetKeyRing("keyrings/aptly_passphrase.pub", "keyrings/aptly_passphrase.sec")
s.signer.SetKey(string(s.passphraseKey))
s.signer.SetKeyRing(s.keyringPassphrase[0], s.keyringPassphrase[1])
s.signer.SetPassphrase("", s.passwordFile)
s.testClearSign(c, "F30E8CB9CDDE2AF8")
s.testClearSign(c, s.passphraseKey)
}

View File

@@ -10,4 +10,4 @@ Expire-Date: 0
%secring aptly.sec
# Do a commit here, so that we can later print "done" :-)
%commit
%echo done
%echo done

View File

@@ -142,7 +142,16 @@ class BaseTest(object):
self.fixtureWebServer))
if self.fixtureGpg:
self.run_cmd(["gpg", "--no-default-keyring", "--trust-model", "always", "--batch", "--keyring", "aptlytest.gpg", "--import"] +
# try to find gpg1 as that's what aptly prefers by default to build trusted keys in DB
# in lowest supported format
gpg = "gpg1"
try:
subprocess.check_output(["gpg1", "--version"])
except Exception:
gpg = "gpg"
# TODO: fixme
self.run_cmd([gpg, "--no-default-keyring", "--trust-model", "always", "--batch", "--keyring", "aptlytest.gpg", "--import"] +
[os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", key) for key in self.fixtureGpgKeys])
if hasattr(self, "fixtureCmds"):

View File

@@ -19,5 +19,5 @@ Options:
-dep-follow-source: when processing dependencies, follow from binary to Source packages
-dep-follow-suggests: when processing dependencies, follow Suggests
-dep-verbose-resolve: when processing dependencies, print detailed logs
-gpg-provider="": PGP implementation ("gpg" for external gpg or "internal" for Go internal implementation)
-gpg-provider="": PGP implementation ("gpg", "gpg1", "gpg2" for external gpg or "internal" for Go internal implementation)

View File

@@ -27,5 +27,5 @@ Options:
-dep-follow-source: when processing dependencies, follow from binary to Source packages
-dep-follow-suggests: when processing dependencies, follow Suggests
-dep-verbose-resolve: when processing dependencies, print detailed logs
-gpg-provider="": PGP implementation ("gpg" for external gpg or "internal" for Go internal implementation)
-gpg-provider="": PGP implementation ("gpg", "gpg1", "gpg2" for external gpg or "internal" for Go internal implementation)
ERROR: unable to parse command

View File

@@ -25,7 +25,7 @@ Options:
-filter-with-deps: when filtering, include dependencies of matching packages as well
-force-architectures: (only with architecture list) skip check that requested architectures are listed in Release file
-force-components: (only with component list) skip check that requested components are listed in Release file
-gpg-provider="": PGP implementation ("gpg" for external gpg or "internal" for Go internal implementation)
-gpg-provider="": PGP implementation ("gpg", "gpg1", "gpg2" for external gpg or "internal" for Go internal implementation)
-ignore-signatures: disable verification of Release file signatures
-keyring=: gpg keyring to use when verifying Release file (could be specified multiple times)
-with-installer: download additional not packaged installer files

View File

@@ -16,7 +16,7 @@ Options:
-filter-with-deps: when filtering, include dependencies of matching packages as well
-force-architectures: (only with architecture list) skip check that requested architectures are listed in Release file
-force-components: (only with component list) skip check that requested components are listed in Release file
-gpg-provider="": PGP implementation ("gpg" for external gpg or "internal" for Go internal implementation)
-gpg-provider="": PGP implementation ("gpg", "gpg1", "gpg2" for external gpg or "internal" for Go internal implementation)
-ignore-signatures: disable verification of Release file signatures
-keyring=: gpg keyring to use when verifying Release file (could be specified multiple times)
-with-installer: download additional not packaged installer files

View File

@@ -23,4 +23,4 @@ Options:
-dep-follow-source: when processing dependencies, follow from binary to Source packages
-dep-follow-suggests: when processing dependencies, follow Suggests
-dep-verbose-resolve: when processing dependencies, print detailed logs
-gpg-provider="": PGP implementation ("gpg" for external gpg or "internal" for Go internal implementation)
-gpg-provider="": PGP implementation ("gpg", "gpg1", "gpg2" for external gpg or "internal" for Go internal implementation)

View File

@@ -23,5 +23,5 @@ Options:
-dep-follow-source: when processing dependencies, follow from binary to Source packages
-dep-follow-suggests: when processing dependencies, follow Suggests
-dep-verbose-resolve: when processing dependencies, print detailed logs
-gpg-provider="": PGP implementation ("gpg" for external gpg or "internal" for Go internal implementation)
-gpg-provider="": PGP implementation ("gpg", "gpg1", "gpg2" for external gpg or "internal" for Go internal implementation)
ERROR: unable to parse command

View File

@@ -17,7 +17,7 @@ Options:
-filter-with-deps: when filtering, include dependencies of matching packages as well
-force-architectures: (only with architecture list) skip check that requested architectures are listed in Release file
-force-components: (only with component list) skip check that requested components are listed in Release file
-gpg-provider="": PGP implementation ("gpg" for external gpg or "internal" for Go internal implementation)
-gpg-provider="": PGP implementation ("gpg", "gpg1", "gpg2" for external gpg or "internal" for Go internal implementation)
-ignore-signatures: disable verification of Release file signatures
-keyring=: gpg keyring to use when verifying Release file (could be specified multiple times)
-with-installer: download additional not packaged installer files