diff --git a/.gitignore b/.gitignore index f25dfbb24..a4dedf903 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ system/env/ # created by make build for release artifacts build/ + +pgp/keyrings/aptly2*.gpg +pgp/keyrings/aptly2*.gpg~ diff --git a/.travis.yml b/.travis.yml index 9ce86b751..d2f673f5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,8 @@ addons: packages: - python-virtualenv - graphviz + - gnupg2 + - gpgv2 env: global: diff --git a/cmd/cmd.go b/cmd/cmd.go index e00668015..187193928 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -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") diff --git a/context/context.go b/context/context.go index eae6f1b53..eb7c88854 100644 --- a/context/context.go +++ b/context/context.go @@ -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 diff --git a/man/aptly.1 b/man/aptly.1 index de1c66510..03461f2c1 100644 --- a/man/aptly.1 +++ b/man/aptly.1 @@ -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 diff --git a/man/aptly.1.ronn.tmpl b/man/aptly.1.ronn.tmpl index b640d9d8f..29b0b44ff 100644 --- a/man/aptly.1.ronn.tmpl +++ b/man/aptly.1.ronn.tmpl @@ -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; diff --git a/pgp/gnupg.go b/pgp/gnupg.go index ba5f24b3e..82be859e5 100644 --- a/pgp/gnupg.go +++ b/pgp/gnupg.go @@ -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") - } - - 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 + if g.version == GPG21xPlus { + args = append(args, "--pinentry-mode", "loopback") } } - 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") + return args } // 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 - } -} diff --git a/pgp/gnupg_finder.go b/pgp/gnupg_finder.go new file mode 100644 index 000000000..683bba82f --- /dev/null +++ b/pgp/gnupg_finder.go @@ -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 +} diff --git a/pgp/gnupg_test.go b/pgp/gnupg_test.go index 30e93ca30..bf8305601 100644 --- a/pgp/gnupg_test.go +++ b/pgp/gnupg_test.go @@ -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,97 @@ 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.skipDefaultKey = true + + 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") +} diff --git a/pgp/internal_test.go b/pgp/internal_test.go index 79fd60d57..1780e73dc 100644 --- a/pgp/internal_test.go +++ b/pgp/internal_test.go @@ -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) diff --git a/pgp/keyrings/aptly2.pub.armor b/pgp/keyrings/aptly2.pub.armor new file mode 100644 index 000000000..689a3b359 --- /dev/null +++ b/pgp/keyrings/aptly2.pub.armor @@ -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----- diff --git a/pgp/keyrings/aptly2.sec.armor b/pgp/keyrings/aptly2.sec.armor new file mode 100644 index 000000000..b3a96f09c --- /dev/null +++ b/pgp/keyrings/aptly2.sec.armor @@ -0,0 +1,57 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 +=vqFY +-----END PGP PRIVATE KEY BLOCK----- diff --git a/pgp/keyrings/aptly2_passphrase.pub.armor b/pgp/keyrings/aptly2_passphrase.pub.armor new file mode 100644 index 000000000..04484c7a9 --- /dev/null +++ b/pgp/keyrings/aptly2_passphrase.pub.armor @@ -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----- diff --git a/pgp/keyrings/aptly2_passphrase.sec.armor b/pgp/keyrings/aptly2_passphrase.sec.armor new file mode 100644 index 000000000..09bc6df5f --- /dev/null +++ b/pgp/keyrings/aptly2_passphrase.sec.armor @@ -0,0 +1,59 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 +bt98YTvZ8TecvlNxvBHIPuD3NFXd11Tm68KeWA== +=YDL1 +-----END PGP PRIVATE KEY BLOCK----- diff --git a/pgp/keyrings/aptly2_trusted.pub b/pgp/keyrings/aptly2_trusted.pub new file mode 100644 index 000000000..9da33ce3d Binary files /dev/null and b/pgp/keyrings/aptly2_trusted.pub differ diff --git a/pgp/sign_test.go b/pgp/sign_test.go index 583329e77..54e4fd124 100644 --- a/pgp/sign_test.go +++ b/pgp/sign_test.go @@ -20,6 +20,14 @@ type SignerSuite struct { cleartext []byte passwordFile string + + skipDefaultKey bool + + keyringNoPassphrase [2]string + keyringPassphrase [2]string + + noPassphraseKey Key + passphraseKey Key } func (s *SignerSuite) SetUpTest(c *C) { @@ -70,20 +78,44 @@ 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) TestSignDetachedNoPassphraseDefaultKey(c *C) { + if s.skipDefaultKey { + c.Skip("test for default key skipped") + } + + 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) TestSignDetachedPassphraseDefaultKey(c *C) { + if s.skipDefaultKey { + c.Skip("test for default key skipped") + } + + 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 +146,45 @@ 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, s.noPassphraseKey) +} + +func (s *SignerSuite) TestClearSignNoPassphraseDefaultKey(c *C) { + if s.skipDefaultKey { + c.Skip("test for default key skipped") + } + + 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, s.passphraseKey) +} + +func (s *SignerSuite) TestClearSignPassphraseDefaultKey(c *C) { + if s.skipDefaultKey { + c.Skip("test for default key skipped") + } + + 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) } diff --git a/system/gpg-gen-key b/system/gpg-gen-key index 6af211b92..6970209ad 100644 --- a/system/gpg-gen-key +++ b/system/gpg-gen-key @@ -10,4 +10,4 @@ Expire-Date: 0 %secring aptly.sec # Do a commit here, so that we can later print "done" :-) %commit -%echo done \ No newline at end of file +%echo done diff --git a/system/lib.py b/system/lib.py index 7db35471c..cbebe1cbe 100644 --- a/system/lib.py +++ b/system/lib.py @@ -50,6 +50,34 @@ def log_message(self, format, *args): pass +class GPGFinder(object): + """ + GnuPG binary discovery. + """ + + def __init__(self): + self.gpg1 = self.find_gpg(["gpg1", "gpg"], "gpg (GnuPG) 1.") + self.gpg2 = self.find_gpg(["gpg2", "gpg"], "gpg (GnuPG) 2.") + + self.gpg = self.gpg1 + if self.gpg is None: + self.gpg = self.gpg2 + + if self.gpg is None: + raise Exception("GnuPG binary wasn't found") + + def find_gpg(self, executables, expected_version): + for executable in executables: + try: + output = subprocess.check_output([executable, "--version"]) + if expected_version in output: + return executable + except Exception: + pass + + return None + + class BaseTest(object): """ Base class for all tests. @@ -62,6 +90,8 @@ class BaseTest(object): fixtureGpg = False fixtureWebServer = False requiresFTP = False + requiresGPG1 = False + requiresGPG2 = False expectedCode = 0 configFile = { @@ -95,6 +125,8 @@ class BaseTest(object): captureResults = False + gpgFinder = GPGFinder() + def test(self): self.prepare() self.run() @@ -110,6 +142,10 @@ def prepare_remove_all(self): def prepare_default_config(self): cfg = self.configFile.copy() + if self.requiresGPG1: + cfg["gpgProvider"] = "gpg1" + elif self.requiresGPG2: + cfg["gpgProvider"] = "gpg2" cfg.update(**self.configOverride) f = open(os.path.join(os.environ["HOME"], ".aptly.conf"), "w") f.write(json.dumps(cfg)) @@ -122,6 +158,10 @@ def fixture_available(self): return False if self.requiresFTP and os.environ.get('NO_FTP_ACCESS', '') == 'yes': return False + if self.requiresGPG1 and self.gpgFinder.gpg1 is None: + return False + if self.requiresGPG2 and self.gpgFinder.gpg2 is None: + return False return True @@ -141,8 +181,13 @@ def prepare_fixture(self): self.webServerUrl = self.start_webserver(os.path.join(os.path.dirname(inspect.getsourcefile(self.__class__)), self.fixtureWebServer)) + if self.requiresGPG2: + self.run_cmd([ + self.gpgFinder.gpg2, "--import", + os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files") + "/aptly.sec"], expected_code=None) + if self.fixtureGpg: - self.run_cmd(["gpg", "--no-default-keyring", "--trust-model", "always", "--batch", "--keyring", "aptlytest.gpg", "--import"] + + self.run_cmd([self.gpgFinder.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"): @@ -176,8 +221,9 @@ def run_cmd(self, command, expected_code=0): try: proc = self._start_process(command, stdout=subprocess.PIPE) output, _ = proc.communicate() - if proc.returncode != expected_code: - raise Exception("exit code %d != %d (output: %s)" % (proc.returncode, expected_code, output)) + if expected_code is not None: + if proc.returncode != expected_code: + raise Exception("exit code %d != %d (output: %s)" % (proc.returncode, expected_code, output)) return output except Exception, e: raise Exception("Running command %s failed: %s" % (command, str(e))) diff --git a/system/t03_help/MainHelpTest_gold b/system/t03_help/MainHelpTest_gold index 6fcd5eb7f..004f140e1 100644 --- a/system/t03_help/MainHelpTest_gold +++ b/system/t03_help/MainHelpTest_gold @@ -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) diff --git a/system/t03_help/MainTest_gold b/system/t03_help/MainTest_gold index e7efbc938..5452f3f18 100644 --- a/system/t03_help/MainTest_gold +++ b/system/t03_help/MainTest_gold @@ -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 diff --git a/system/t03_help/MirrorCreateHelpTest_gold b/system/t03_help/MirrorCreateHelpTest_gold index 10e191c97..debf7621a 100644 --- a/system/t03_help/MirrorCreateHelpTest_gold +++ b/system/t03_help/MirrorCreateHelpTest_gold @@ -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 diff --git a/system/t03_help/MirrorCreateTest_gold b/system/t03_help/MirrorCreateTest_gold index 7b138a518..8aea92e83 100644 --- a/system/t03_help/MirrorCreateTest_gold +++ b/system/t03_help/MirrorCreateTest_gold @@ -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 diff --git a/system/t03_help/MirrorHelpTest_gold b/system/t03_help/MirrorHelpTest_gold index 4faee9a0b..08f6f55ad 100644 --- a/system/t03_help/MirrorHelpTest_gold +++ b/system/t03_help/MirrorHelpTest_gold @@ -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) diff --git a/system/t03_help/MirrorTest_gold b/system/t03_help/MirrorTest_gold index 6be6e8340..e48251040 100644 --- a/system/t03_help/MirrorTest_gold +++ b/system/t03_help/MirrorTest_gold @@ -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 diff --git a/system/t03_help/WrongFlagTest_gold b/system/t03_help/WrongFlagTest_gold index 811e4d646..7876cbd04 100644 --- a/system/t03_help/WrongFlagTest_gold +++ b/system/t03_help/WrongFlagTest_gold @@ -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 diff --git a/system/t04_mirror/CreateMirror32Test_gold b/system/t04_mirror/CreateMirror32Test_gold new file mode 100644 index 000000000..05b86ffc4 --- /dev/null +++ b/system/t04_mirror/CreateMirror32Test_gold @@ -0,0 +1,9 @@ +Downloading http://mirror.yandex.ru/debian/dists/wheezy/InRelease... +Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release... +Downloading http://mirror.yandex.ru/debian/dists/wheezy/Release.gpg... +gpgv: Good signature from "Debian Archive Automatic Signing Key (7.0/wheezy) " +gpgv: Good signature from "Debian Archive Automatic Signing Key (8/jessie) " +gpgv: Good signature from "Wheezy Stable Release Key " + +Mirror [mirror32]: http://mirror.yandex.ru/debian/ wheezy successfully added. +You can run 'aptly mirror update mirror32' to download repository contents. diff --git a/system/t04_mirror/CreateMirror32Test_mirror_show b/system/t04_mirror/CreateMirror32Test_mirror_show new file mode 100644 index 000000000..5cf000ceb --- /dev/null +++ b/system/t04_mirror/CreateMirror32Test_mirror_show @@ -0,0 +1,20 @@ +Name: mirror32 +Archive Root URL: http://mirror.yandex.ru/debian/ +Distribution: wheezy +Components: main, contrib, non-free +Architectures: amd64, armel, armhf, i386, ia64, kfreebsd-amd64, kfreebsd-i386, mips, mipsel, powerpc, s390, s390x, sparc +Download Sources: no +Download .udebs: no +Last update: never + +Information from release file: +Architectures: amd64 armel armhf i386 ia64 kfreebsd-amd64 kfreebsd-i386 mips mipsel powerpc s390 s390x sparc +Codename: wheezy +Components: main contrib non-free +Date: Sat, 17 Jun 2017 08:55:32 UTC +Description: Debian 7.11 Released 04 June 2016 + +Label: Debian +Origin: Debian +Suite: oldoldstable +Version: 7.11 diff --git a/system/t04_mirror/create.py b/system/t04_mirror/create.py index 5792a3390..c2bb042ea 100644 --- a/system/t04_mirror/create.py +++ b/system/t04_mirror/create.py @@ -59,6 +59,7 @@ class CreateMirror6Test(BaseTest): create mirror: missing release """ expectedCode = 1 + requiresGPG1 = True runCmd = "aptly mirror create --keyring=aptlytest.gpg mirror6 http://mirror.yandex.ru/debian/ suslik" @@ -92,6 +93,7 @@ class CreateMirror9Test(BaseTest): """ runCmd = "aptly mirror create --keyring=aptlytest.gpg mirror9 http://mirror.yandex.ru/debian/ wheezy-backports" fixtureGpg = True + requiresGPG1 = True def outputMatchPrepare(_, s): return re.sub(r'Signature made .* using|Warning: using insecure memory!\n', '', s) @@ -396,3 +398,21 @@ class CreateMirror31Test(BaseTest): def outputMatchPrepare(_, s): return re.sub(r'Signature made .* using', '', s) + + +class CreateMirror32Test(BaseTest): + """ + create mirror: repo with Release + Release.gpg verification (gpg2) + """ + runCmd = "aptly mirror create --keyring=aptlytest.gpg mirror32 http://mirror.yandex.ru/debian/ wheezy" + fixtureGpg = True + requiresGPG2 = True + + def outputMatchPrepare(_, s): + return \ + re.sub(r'([A-F0-9]{8})[A-F0-9]{8}', r'\1', + re.sub(r'^gpgv: (Signature made .+|.+using RSA key.+)\n', '', s, flags=re.MULTILINE)) + + def check(self): + self.check_output() + self.check_cmd_output("aptly mirror show mirror32", "mirror_show") diff --git a/system/t06_publish/PublishRepo32Test_gold b/system/t06_publish/PublishRepo32Test_gold new file mode 100644 index 000000000..365295fa9 --- /dev/null +++ b/system/t06_publish/PublishRepo32Test_gold @@ -0,0 +1,14 @@ +Loading packages... +Generating metadata files and linking package files... +Finalizing metadata files... +Signing file 'Release' with gpg, please enter your passphrase when prompted: +Clearsigning file 'Release' with gpg, please enter your passphrase when prompted: + +Local repo local-repo has been successfully published. +Please setup your webserver to serve directory '${HOME}/.aptly/public' with autoindexing. +Now you can add following line to apt sources: + deb http://your-server/ maverick main + deb-src http://your-server/ maverick main +Don't forget to add your GPG key to apt with apt-key. + +You can also use `aptly serve` to publish your repositories over HTTP quickly. diff --git a/system/t06_publish/repo.py b/system/t06_publish/repo.py index 4f1af5cba..bb61f9d3b 100644 --- a/system/t06_publish/repo.py +++ b/system/t06_publish/repo.py @@ -57,9 +57,9 @@ def check(self): self.check_file_contents('public/dists/maverick/Contents-i386.gz', 'contents_i386_legacy', match_prepare=ungzip_if_required) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -456,9 +456,9 @@ def check(self): self.check_file_contents('public/dists/maverick/Release', 'release', match_prepare=strip_processor) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -637,9 +637,9 @@ def check(self): super(PublishRepo26Test, self).check() # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -739,9 +739,9 @@ def check(self): super(PublishRepo30Test, self).check() # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -765,8 +765,34 @@ def check(self): super(PublishRepo31Test, self).check() # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), + "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), + os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) + + +class PublishRepo32Test(BaseTest): + """ + publish repo: default with gpg2 + """ + requiresGPG2 = True + fixtureCmds = [ + "aptly repo create local-repo", + "aptly repo add local-repo ${files}", + ] + runCmd = "aptly publish repo -gpg-key=C5ACD2179B5231DFE842EE6121DBB89C16DB3E6D -keyring=${files}/aptly.pub -distribution=maverick local-repo" + gold_processor = BaseTest.expand_environ + + def outputMatchPrepare(_, s): + return s.replace("gpg: gpg-agent is not available in this session\n", "") + + def check(self): + super(PublishRepo32Test, self).check() + + # verify signatures + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), + "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly_passphrase.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) diff --git a/system/t06_publish/snapshot.py b/system/t06_publish/snapshot.py index 4f385a6bc..788059eb1 100644 --- a/system/t06_publish/snapshot.py +++ b/system/t06_publish/snapshot.py @@ -67,9 +67,9 @@ def check(self): self.check_file_contents('public/dists/maverick/main/Contents-amd64.gz', 'contents_amd64', match_prepare=ungzip_if_required) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -455,9 +455,9 @@ def check(self): self.check_file_contents('public/dists/maverick/main/source/Sources', 'sources', match_prepare=lambda s: "\n".join(sorted(s.split("\n")))) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -502,9 +502,9 @@ def check(self): self.check_file_contents('public/dists/maverick/main/binary-i386/Packages', 'binary', match_prepare=lambda s: "\n".join(sorted(s.split("\n")))) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -716,9 +716,9 @@ def check(self): self.check_file_contents('public/dists/maverick/Release', 'release', match_prepare=strip_processor) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) diff --git a/system/t06_publish/switch.py b/system/t06_publish/switch.py index e14132071..d5178c487 100644 --- a/system/t06_publish/switch.py +++ b/system/t06_publish/switch.py @@ -49,9 +49,9 @@ def check(self): self.check_file_contents('public/dists/maverick/main/binary-i386/Packages', 'binary', match_prepare=lambda s: "\n".join(sorted(s.split("\n")))) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -313,9 +313,9 @@ def check(self): self.check_file_contents('public/dists/maverick/c/binary-i386/Packages', 'binaryC', match_prepare=lambda s: "\n".join(sorted(s.split("\n")))) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -502,9 +502,9 @@ def check(self): self.check_file_contents('public/dists/maverick/main/binary-i386/Packages', 'binary', match_prepare=lambda s: "\n".join(sorted(s.split("\n")))) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) diff --git a/system/t06_publish/update.py b/system/t06_publish/update.py index b27b852f3..752f74bcc 100644 --- a/system/t06_publish/update.py +++ b/system/t06_publish/update.py @@ -49,9 +49,9 @@ def check(self): self.check_file_contents('public/dists/maverick/main/binary-i386/Packages', 'binary', match_prepare=lambda s: "\n".join(sorted(s.split("\n")))) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')]) @@ -394,9 +394,9 @@ def check(self): self.check_file_contents('public/dists/maverick/main/binary-i386/Packages', 'binary', match_prepare=lambda s: "\n".join(sorted(s.split("\n")))) # verify signatures - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/InRelease')]) - self.run_cmd(["gpg", "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), + self.run_cmd([self.gpgFinder.gpg, "--no-auto-check-trustdb", "--keyring", os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files", "aptly.pub"), "--verify", os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release.gpg'), os.path.join(os.environ["HOME"], ".aptly", 'public/dists/maverick/Release')])