From a88e10523947ae15e1f87116b56803e13d3324b4 Mon Sep 17 00:00:00 2001 From: Alberto Carretero Date: Mon, 15 Jan 2024 12:32:42 +0100 Subject: [PATCH] feat: add support for chisel release format "v1" (#115) This commits adds support for "v1" which changes the "v1-public-keys" field into "public-keys". The "chisel-v1" format is still supported. --- README.md | 39 +++++++++++++++++++++++++++++++++- internal/setup/setup.go | 29 +++++++++++++++++++------ internal/setup/setup_test.go | 26 +++++++++++++++++++++-- internal/slicer/slicer_test.go | 24 ++++++++++++++++++++- 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 503c085e..58e4fad5 100644 --- a/README.md +++ b/README.md @@ -119,13 +119,50 @@ archives: Example: ```yaml -format: chisel-v1 +format: v1 archives: ubuntu: version: 22.04 components: [main, universe] suites: [jammy, jammy-security, jammy-updates] + public-keys: [ubuntu-archive-key-2018] + +public-keys: + # Ubuntu Archive Automatic Signing Key (2018) + # rsa4096/f6ecb3762474eda9d21b7022871920d1991bc93c 2018-09-17T15:01:46Z + ubuntu-archive-key-2018: + id: "871920D1991BC93C" + armor: | + -----BEGIN PGP PUBLIC KEY BLOCK----- + + mQINBFufwdoBEADv/Gxytx/LcSXYuM0MwKojbBye81s0G1nEx+lz6VAUpIUZnbkq + dXBHC+dwrGS/CeeLuAjPRLU8AoxE/jjvZVp8xFGEWHYdklqXGZ/gJfP5d3fIUBtZ + HZEJl8B8m9pMHf/AQQdsC+YzizSG5t5Mhnotw044LXtdEEkx2t6Jz0OGrh+5Ioxq + X7pZiq6Cv19BohaUioKMdp7ES6RYfN7ol6HSLFlrMXtVfh/ijpN9j3ZhVGVeRC8k + KHQsJ5PkIbmvxBiUh7SJmfZUx0IQhNMaDHXfdZAGNtnhzzNReb1FqNLSVkrS/Pns + AQzMhG1BDm2VOSF64jebKXffFqM5LXRQTeqTLsjUbbrqR6s/GCO8UF7jfUj6I7ta + LygmsHO/JD4jpKRC0gbpUBfaiJyLvuepx3kWoqL3sN0LhlMI80+fA7GTvoOx4tpq + VlzlE6TajYu+jfW3QpOFS5ewEMdL26hzxsZg/geZvTbArcP+OsJKRmhv4kNo6Ayd + yHQ/3ZV/f3X9mT3/SPLbJaumkgp3Yzd6t5PeBu+ZQk/mN5WNNuaihNEV7llb1Zhv + Y0Fxu9BVd/BNl0rzuxp3rIinB2TX2SCg7wE5xXkwXuQ/2eTDE0v0HlGntkuZjGow + DZkxHZQSxZVOzdZCRVaX/WEFLpKa2AQpw5RJrQ4oZ/OfifXyJzP27o03wQARAQAB + tEJVYnVudHUgQXJjaGl2ZSBBdXRvbWF0aWMgU2lnbmluZyBLZXkgKDIwMTgpIDxm + dHBtYXN0ZXJAdWJ1bnR1LmNvbT6JAjgEEwEKACIFAlufwdoCGwMGCwkIBwMCBhUI + AgkKCwQWAgMBAh4BAheAAAoJEIcZINGZG8k8LHMQAKS2cnxz/5WaoCOWArf5g6UH + beOCgc5DBm0hCuFDZWWv427aGei3CPuLw0DGLCXZdyc5dqE8mvjMlOmmAKKlj1uG + g3TYCbQWjWPeMnBPZbkFgkZoXJ7/6CB7bWRht1sHzpt1LTZ+SYDwOwJ68QRp7DRa + Zl9Y6QiUbeuhq2DUcTofVbBxbhrckN4ZteLvm+/nG9m/ciopc66LwRdkxqfJ32Cy + q+1TS5VaIJDG7DWziG+Kbu6qCDM4QNlg3LH7p14CrRxAbc4lvohRgsV4eQqsIcdF + kuVY5HPPj2K8TqpY6STe8Gh0aprG1RV8ZKay3KSMpnyV1fAKn4fM9byiLzQAovC0 + LZ9MMMsrAS/45AvC3IEKSShjLFn1X1dRCiO6/7jmZEoZtAp53hkf8SMBsi78hVNr + BumZwfIdBA1v22+LY4xQK8q4XCoRcA9G+pvzU9YVW7cRnDZZGl0uwOw7z9PkQBF5 + KFKjWDz4fCk+K6+YtGpovGKekGBb8I7EA6UpvPgqA/QdI0t1IBP0N06RQcs1fUaA + QEtz6DGy5zkRhR4pGSZn+dFET7PdAjEK84y7BdY4t+U1jcSIvBj0F2B7LwRL7xGp + SpIKi/ekAXLs117bvFHaCvmUYN7JVp1GMmVFxhIdx6CFm3fxG8QjNb5tere/YqK+ + uOgcXny1UlwtCUzlrSaP + =9AdM + -----END PGP PUBLIC KEY BLOCK----- ``` #### Slice definitions diff --git a/internal/setup/setup.go b/internal/setup/setup.go index e04f8eca..fe142d92 100644 --- a/internal/setup/setup.go +++ b/internal/setup/setup.go @@ -321,17 +321,19 @@ func readSlices(release *Release, baseDir, dirName string) error { type yamlRelease struct { Format string `yaml:"format"` Archives map[string]yamlArchive `yaml:"archives"` - PubKeys map[string]yamlPubKey `yaml:"v1-public-keys"` + PubKeys map[string]yamlPubKey `yaml:"public-keys"` + // V1PubKeys is used for compatibility with format "chisel-v1". + V1PubKeys map[string]yamlPubKey `yaml:"v1-public-keys"` } -const yamlReleaseFormat = "chisel-v1" - type yamlArchive struct { Version string `yaml:"version"` Suites []string `yaml:"suites"` Components []string `yaml:"components"` Default bool `yaml:"default"` - PubKeys []string `yaml:"v1-public-keys"` + PubKeys []string `yaml:"public-keys"` + // V1PubKeys is used for compatibility with format "chisel-v1". + V1PubKeys []string `yaml:"v1-public-keys"` } type yamlPackage struct { @@ -417,8 +419,17 @@ func parseRelease(baseDir, filePath string, data []byte) (*Release, error) { if err != nil { return nil, fmt.Errorf("%s: cannot parse release definition: %v", fileName, err) } - if yamlVar.Format != yamlReleaseFormat { - return nil, fmt.Errorf("%s: expected format %q, got %q", fileName, yamlReleaseFormat, yamlVar.Format) + if yamlVar.Format != "chisel-v1" && yamlVar.Format != "v1" { + return nil, fmt.Errorf("%s: unknown format %q", fileName, yamlVar.Format) + } + // If format is "chisel-v1" we have to translate from the yaml key "v1-public-keys" to + // "public-keys". + if yamlVar.Format == "chisel-v1" { + yamlVar.PubKeys = yamlVar.V1PubKeys + for name, details := range yamlVar.Archives { + details.PubKeys = details.V1PubKeys + yamlVar.Archives[name] = details + } } if len(yamlVar.Archives) == 0 { return nil, fmt.Errorf("%s: no archives defined", fileName) @@ -460,7 +471,11 @@ func parseRelease(baseDir, filePath string, data []byte) (*Release, error) { release.DefaultArchive = archiveName } if len(details.PubKeys) == 0 { - return nil, fmt.Errorf("%s: archive %q missing v1-public-keys field", fileName, archiveName) + if yamlVar.Format == "chisel-v1" { + return nil, fmt.Errorf("%s: archive %q missing v1-public-keys field", fileName, archiveName) + } else { + return nil, fmt.Errorf("%s: archive %q missing public-keys field", fileName, archiveName) + } } var archiveKeys []*packet.PublicKey for _, keyName := range details.PubKeys { diff --git a/internal/setup/setup_test.go b/internal/setup/setup_test.go index 9bbf444b..9a92089b 100644 --- a/internal/setup/setup_test.go +++ b/internal/setup/setup_test.go @@ -3,6 +3,7 @@ package setup_test import ( "os" "path/filepath" + "strings" "golang.org/x/crypto/openpgp/packet" . "gopkg.in/check.v1" @@ -33,7 +34,7 @@ var setupTests = []setupTest{{ format: foobar `, }, - relerror: `chisel.yaml: expected format "chisel-v1", got "foobar"`, + relerror: `chisel.yaml: unknown format "foobar"`, }, { summary: "Missing archives", input: map[string]string{ @@ -1030,7 +1031,28 @@ var defaultChiselYaml = ` ` func (s *S) TestParseRelease(c *C) { - for _, test := range setupTests { + // Run tests for format chisel-v1. + runParseReleaseTests(c, setupTests) + + // Run tests for format v1. + v1SetupTests := make([]setupTest, len(setupTests)) + for i, t := range setupTests { + t.relerror = strings.Replace(t.relerror, "chisel-v1", "v1", -1) + t.relerror = strings.Replace(t.relerror, "v1-public-keys", "public-keys", -1) + m := map[string]string{} + for k, v := range t.input { + v = strings.Replace(v, "chisel-v1", "v1", -1) + v = strings.Replace(v, "v1-public-keys", "public-keys", -1) + m[k] = v + } + t.input = m + v1SetupTests[i] = t + } + runParseReleaseTests(c, v1SetupTests) +} + +func runParseReleaseTests(c *C, tests []setupTest) { + for _, test := range tests { c.Logf("Summary: %s", test.summary) if _, ok := test.input["chisel.yaml"]; !ok { diff --git a/internal/slicer/slicer_test.go b/internal/slicer/slicer_test.go index 48e21bf1..1a19a144 100644 --- a/internal/slicer/slicer_test.go +++ b/internal/slicer/slicer_test.go @@ -7,6 +7,7 @@ import ( "io" "os" "path/filepath" + "strings" . "gopkg.in/check.v1" @@ -562,7 +563,28 @@ func (a *testArchive) Exists(pkg string) bool { } func (s *S) TestRun(c *C) { - for _, test := range slicerTests { + // Run tests for format chisel-v1. + runSlicerTests(c, slicerTests) + + // Run tests for format v1. + v1SlicerTests := make([]slicerTest, len(slicerTests)) + for i, t := range slicerTests { + t.error = strings.Replace(t.error, "chisel-v1", "v1", -1) + t.error = strings.Replace(t.error, "v1-public-keys", "public-keys", -1) + m := map[string]string{} + for k, v := range t.release { + v = strings.Replace(v, "chisel-v1", "v1", -1) + v = strings.Replace(v, "v1-public-keys", "public-keys", -1) + m[k] = v + } + t.release = m + v1SlicerTests[i] = t + } + runSlicerTests(c, v1SlicerTests) +} + +func runSlicerTests(c *C, tests []slicerTest) { + for _, test := range tests { c.Logf("Summary: %s", test.summary) if _, ok := test.release["chisel.yaml"]; !ok {