func (mbss *memBackstoreSuite) TestPutOldRevision(c *C) { bs := asserts.NewMemoryBackstore() // Create two revisions of assertion. a0, err := asserts.Decode([]byte("type: test-only\n" + "authority-id: auth-id1\n" + "primary-key: foo\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==")) c.Assert(err, IsNil) a1, err := asserts.Decode([]byte("type: test-only\n" + "authority-id: auth-id1\n" + "primary-key: foo\n" + "revision: 1\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==")) c.Assert(err, IsNil) // Put newer revision, follwed by old revision. err = bs.Put(asserts.TestOnlyType, a1) c.Assert(err, IsNil) err = bs.Put(asserts.TestOnlyType, a0) c.Check(err, ErrorMatches, `revision 0 is older than current revision 1`) c.Check(err, DeepEquals, &asserts.RevisionError{Current: 1, Used: 0}) }
func (as *assertsSuite) TestEncoderSingleDecodeOK(c *C) { encoded := []byte("type: test-only\n" + "authority-id: auth-id2\n" + "primary-key: abc\n" + "revision: 5\n" + "header1: value1\n" + "header2: value2\n" + "body-length: 8\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij\n\n" + "THE-BODY" + "\n\n" + "AXNpZw==") a0, err := asserts.Decode(encoded) c.Assert(err, IsNil) cont0, _ := a0.Signature() stream := new(bytes.Buffer) enc := asserts.NewEncoder(stream) enc.Encode(a0) a1, err := asserts.Decode(stream.Bytes()) c.Assert(err, IsNil) cont1, _ := a1.Signature() c.Check(cont1, DeepEquals, cont0) }
func (mbss *memBackstoreSuite) TestSearch(c *C) { encoded := "type: test-only\n" + "authority-id: auth-id1\n" + "primary-key: one\n" + "other: other1\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==" a1, err := asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) encoded = "type: test-only\n" + "authority-id: auth-id1\n" + "primary-key: two\n" + "other: other2\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==" a2, err := asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) err = mbss.bs.Put(asserts.TestOnlyType, a1) c.Assert(err, IsNil) err = mbss.bs.Put(asserts.TestOnlyType, a2) c.Assert(err, IsNil) found := map[string]asserts.Assertion{} cb := func(a asserts.Assertion) { found[a.HeaderString("primary-key")] = a } err = mbss.bs.Search(asserts.TestOnlyType, nil, cb, 0) c.Assert(err, IsNil) c.Check(found, HasLen, 2) found = map[string]asserts.Assertion{} err = mbss.bs.Search(asserts.TestOnlyType, map[string]string{ "primary-key": "one", }, cb, 0) c.Assert(err, IsNil) c.Check(found, DeepEquals, map[string]asserts.Assertion{ "one": a1, }) found = map[string]asserts.Assertion{} err = mbss.bs.Search(asserts.TestOnlyType, map[string]string{ "other": "other2", }, cb, 0) c.Assert(err, IsNil) c.Check(found, DeepEquals, map[string]asserts.Assertion{ "two": a2, }) found = map[string]asserts.Assertion{} err = mbss.bs.Search(asserts.TestOnlyType, map[string]string{ "primary-key": "two", "other": "other1", }, cb, 0) c.Assert(err, IsNil) c.Check(found, HasLen, 0) }
func (fsbss *fsBackstoreSuite) TestGetFormat(c *C) { topDir := filepath.Join(c.MkDir(), "asserts-db") bs, err := asserts.OpenFSBackstore(topDir) c.Assert(err, IsNil) af0, err := asserts.Decode([]byte("type: test-only\n" + "authority-id: auth-id1\n" + "primary-key: foo\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==")) c.Assert(err, IsNil) af1, err := asserts.Decode([]byte("type: test-only\n" + "authority-id: auth-id1\n" + "primary-key: foo\n" + "format: 1\n" + "revision: 1\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==")) c.Assert(err, IsNil) af2, err := asserts.Decode([]byte("type: test-only\n" + "authority-id: auth-id1\n" + "primary-key: zoo\n" + "format: 2\n" + "revision: 22\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==")) c.Assert(err, IsNil) err = bs.Put(asserts.TestOnlyType, af0) c.Assert(err, IsNil) err = bs.Put(asserts.TestOnlyType, af1) c.Assert(err, IsNil) a, err := bs.Get(asserts.TestOnlyType, []string{"foo"}, 1) c.Assert(err, IsNil) c.Check(a.Revision(), Equals, 1) a, err = bs.Get(asserts.TestOnlyType, []string{"foo"}, 0) c.Assert(err, IsNil) c.Check(a.Revision(), Equals, 0) a, err = bs.Get(asserts.TestOnlyType, []string{"zoo"}, 0) c.Assert(err, Equals, asserts.ErrNotFound) err = bs.Put(asserts.TestOnlyType, af2) c.Assert(err, IsNil) a, err = bs.Get(asserts.TestOnlyType, []string{"zoo"}, 1) c.Assert(err, Equals, asserts.ErrNotFound) a, err = bs.Get(asserts.TestOnlyType, []string{"zoo"}, 2) c.Assert(err, IsNil) c.Check(a.Revision(), Equals, 22) }
func init() { stagingTrustedAccount, err := asserts.Decode([]byte(encodedStagingTrustedAccount)) if err != nil { panic(fmt.Sprintf("cannot decode trusted assertion: %v", err)) } stagingRootAccountKey, err := asserts.Decode([]byte(encodedStagingRootAccountKey)) if err != nil { panic(fmt.Sprintf("cannot decode trusted assertion: %v", err)) } trustedStagingAssertions = []asserts.Assertion{stagingTrustedAccount, stagingRootAccountKey} }
func init() { canonicalAccount, err := asserts.Decode([]byte(encodedCanonicalAccount)) if err != nil { panic(fmt.Sprintf("cannot decode trusted assertion: %v", err)) } canonicalRootAccountKey, err := asserts.Decode([]byte(encodedCanonicalRootAccountKey)) if err != nil { panic(fmt.Sprintf("cannot decode trusted assertion: %v", err)) } trustedAssertions = []asserts.Assertion{canonicalAccount, canonicalRootAccountKey} }
func (s *systemUserSuite) TestUntilNoModels(c *C) { // no models is good for <1y su := strings.Replace(s.systemUserStr, s.modelsLine, "", -1) _, err := asserts.Decode([]byte(su)) c.Check(err, IsNil) // but invalid for more than one year oneYearPlusOne := time.Now().AddDate(1, 0, 1).Truncate(time.Second) su = strings.Replace(su, s.untilLine, fmt.Sprintf("until: %s\n", oneYearPlusOne.Format(time.RFC3339)), -1) _, err = asserts.Decode([]byte(su)) c.Check(err, ErrorMatches, systemUserErrPrefix+"'until' time cannot be more than 365 days in the future when no models are specified") }
func (mods *modelSuite) TestDecodeStoreIsOptional(c *C) { withTimestamp := strings.Replace(modelExample, "TSLINE", mods.tsLine, 1) encoded := strings.Replace(withTimestamp, "store: brand-store\n", "store: \n", 1) a, err := asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) model := a.(*asserts.Model) c.Check(model.Store(), Equals, "") encoded = strings.Replace(withTimestamp, "store: brand-store\n", "", 1) a, err = asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) model = a.(*asserts.Model) c.Check(model.Store(), Equals, "") }
func (mods *modelSuite) TestDecodeSystemUserAuthorityIsOptional(c *C) { withTimestamp := strings.Replace(modelExample, "TSLINE", mods.tsLine, 1) encoded := strings.Replace(withTimestamp, sysUserAuths, "", 1) a, err := asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) model := a.(*asserts.Model) // the default is just to accept the brand itself c.Check(model.SystemUserAuthority(), DeepEquals, []string{"brand-id1"}) encoded = strings.Replace(withTimestamp, sysUserAuths, "system-user-authority:\n - foo\n - bar\n", 1) a, err = asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) model = a.(*asserts.Model) c.Check(model.SystemUserAuthority(), DeepEquals, []string{"foo", "bar"}) }
func (s *Store) collectAssertions() (asserts.Backstore, error) { bs := asserts.NewMemoryBackstore() add := func(a asserts.Assertion) { bs.Put(a.Type(), a) } for _, t := range sysdb.Trusted() { add(t) } add(systestkeys.TestRootAccount) add(systestkeys.TestRootAccountKey) add(systestkeys.TestStoreAccountKey) aFiles, err := filepath.Glob(filepath.Join(s.assertDir, "*")) if err != nil { return nil, err } for _, fn := range aFiles { b, err := ioutil.ReadFile(fn) if err != nil { return nil, err } a, err := asserts.Decode(b) if err != nil { return nil, err } add(a) } return bs, nil }
func (s *SnapSignBuildSuite) TestSignBuildWorksDevelGrade(c *C) { snapFilename := "foo_1_amd64.snap" snapContent := []byte("sample") _err := ioutil.WriteFile(snapFilename, snapContent, 0644) c.Assert(_err, IsNil) defer os.Remove(snapFilename) tempdir := c.MkDir() for _, fileName := range []string{"pubring.gpg", "secring.gpg", "trustdb.gpg"} { data, err := ioutil.ReadFile(filepath.Join("test-data", fileName)) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(tempdir, fileName), data, 0644) c.Assert(err, IsNil) } os.Setenv("SNAP_GNUPG_HOME", tempdir) defer os.Unsetenv("SNAP_GNUPG_HOME") _, err := snap.Parser().ParseArgs([]string{"sign-build", snapFilename, "--developer-id", "dev-id1", "--snap-id", "snap-id-1", "--grade", "devel"}) c.Assert(err, IsNil) assertion, err := asserts.Decode([]byte(s.Stdout())) c.Assert(err, IsNil) c.Check(assertion.Type(), Equals, asserts.SnapBuildType) c.Check(assertion.HeaderString("grade"), Equals, "devel") // check for valid signature ?! c.Check(s.Stderr(), Equals, "") }
func decodeModelAssertion(opts *Options) (*asserts.Model, error) { fn := opts.ModelFile rawAssert, err := ioutil.ReadFile(fn) if err != nil { return nil, fmt.Errorf("cannot read model assertion: %s", err) } ass, err := asserts.Decode(rawAssert) if err != nil { return nil, fmt.Errorf("cannot decode model assertion %q: %s", fn, err) } modela, ok := ass.(*asserts.Model) if !ok { return nil, fmt.Errorf("assertion in %q is not a model assertion", fn) } for _, rsvd := range reserved { if modela.Header(rsvd) != nil { return nil, fmt.Errorf("model assertion cannot have reserved/unsupported header %q set", rsvd) } } return modela, nil }
func (aks *accountKeySuite) TestUntil(c *C) { untilSinceLine := "until: " + aks.since.Format(time.RFC3339) + "\n" tests := []struct { untilLine string until time.Time }{ {"", time.Time{}}, // zero time default {aks.untilLine, aks.until}, // in the future {untilSinceLine, aks.since}, // same as since } for _, test := range tests { c.Log(test) encoded := "type: account-key\n" + "authority-id: canonical\n" + "account-id: acc-id1\n" + "name: default\n" + "public-key-sha3-384: " + aks.keyID + "\n" + aks.sinceLine + test.untilLine + fmt.Sprintf("body-length: %v", len(aks.pubKeyBody)) + "\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + aks.pubKeyBody + "\n\n" + "openpgp c2ln" a, err := asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) accKey := a.(*asserts.AccountKey) c.Check(accKey.Until(), Equals, test.until) } }
func (ss *serialSuite) TestDeviceSessionRequestDecodeInvalid(c *C) { tsLine := "timestamp: " + time.Now().Format(time.RFC3339) + "\n" encoded := "type: device-session-request\n" + "brand-id: brand-id1\n" + "model: baz-3000\n" + "serial: 99990\n" + "nonce: NONCE\n" + tsLine + "body-length: 0\n" + "sign-key-sha3-384: " + ss.deviceKey.PublicKey().ID() + "\n\n" + "AXNpZw==" invalidTests := []struct{ original, invalid, expectedErr string }{ {"brand-id: brand-id1\n", "brand-id: \n", `"brand-id" header should not be empty`}, {"model: baz-3000\n", "model: \n", `"model" header should not be empty`}, {"serial: 99990\n", "", `"serial" header is mandatory`}, {"nonce: NONCE\n", "nonce: \n", `"nonce" header should not be empty`}, {tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`}, } for _, test := range invalidTests { invalid := strings.Replace(encoded, test.original, test.invalid, 1) _, err := asserts.Decode([]byte(invalid)) c.Check(err, ErrorMatches, deviceSessReqErrPrefix+test.expectedErr) } }
func (aks *accountKeySuite) TestAccountKeyRequestHappy(c *C) { akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType, map[string]interface{}{ "account-id": "acc-id1", "name": "default", "public-key-sha3-384": aks.keyID, "since": aks.since.Format(time.RFC3339), }, []byte(aks.pubKeyBody), aks.privKey) c.Assert(err, IsNil) // roundtrip a, err := asserts.Decode(asserts.Encode(akr)) c.Assert(err, IsNil) akr2, ok := a.(*asserts.AccountKeyRequest) c.Assert(ok, Equals, true) db := aks.openDB(c) aks.prereqAccount(c, db) err = db.Check(akr2) c.Check(err, IsNil) c.Check(akr2.AccountID(), Equals, "acc-id1") c.Check(akr2.Name(), Equals, "default") c.Check(akr2.PublicKeyID(), Equals, aks.keyID) c.Check(akr2.Since(), Equals, aks.since) }
func (ss *serialSuite) TestSerialRequestDecodeInvalid(c *C) { encoded := "type: serial-request\n" + "brand-id: brand-id1\n" + "model: baz-3000\n" + "device-key:\n DEVICEKEY\n" + "request-id: REQID\n" + "serial: S\n" + "body-length: 2\n" + "sign-key-sha3-384: " + ss.deviceKey.PublicKey().ID() + "\n\n" + "HW" + "\n\n" + "AXNpZw==" invalidTests := []struct{ original, invalid, expectedErr string }{ {"brand-id: brand-id1\n", "", `"brand-id" header is mandatory`}, {"brand-id: brand-id1\n", "brand-id: \n", `"brand-id" header should not be empty`}, {"model: baz-3000\n", "", `"model" header is mandatory`}, {"model: baz-3000\n", "model: \n", `"model" header should not be empty`}, {"request-id: REQID\n", "", `"request-id" header is mandatory`}, {"request-id: REQID\n", "request-id: \n", `"request-id" header should not be empty`}, {"device-key:\n DEVICEKEY\n", "", `"device-key" header is mandatory`}, {"device-key:\n DEVICEKEY\n", "device-key: \n", `"device-key" header should not be empty`}, {"device-key:\n DEVICEKEY\n", "device-key: $$$\n", `cannot decode public key: .*`}, {"serial: S\n", "serial:\n - xyz\n", `"serial" header must be a string`}, } for _, test := range invalidTests { invalid := strings.Replace(encoded, test.original, test.invalid, 1) invalid = strings.Replace(invalid, "DEVICEKEY", strings.Replace(ss.encodedDevKey, "\n", "\n ", -1), 1) _, err := asserts.Decode([]byte(invalid)) c.Check(err, ErrorMatches, serialReqErrPrefix+test.expectedErr) } }
func (mods *modelSuite) TestDecodeInvalid(c *C) { encoded := strings.Replace(modelExample, "TSLINE", mods.tsLine, 1) invalidTests := []struct{ original, invalid, expectedErr string }{ {"series: 16\n", "", `"series" header is mandatory`}, {"series: 16\n", "series: \n", `"series" header should not be empty`}, {"brand-id: brand-id1\n", "", `"brand-id" header is mandatory`}, {"brand-id: brand-id1\n", "brand-id: \n", `"brand-id" header should not be empty`}, {"brand-id: brand-id1\n", "brand-id: random\n", `authority-id and brand-id must match, model assertions are expected to be signed by the brand: "brand-id1" != "random"`}, {"model: baz-3000\n", "", `"model" header is mandatory`}, {"model: baz-3000\n", "model: \n", `"model" header should not be empty`}, {"model: baz-3000\n", "model: baz/3000\n", `"model" primary key header cannot contain '/'`}, {"architecture: amd64\n", "", `"architecture" header is mandatory`}, {"architecture: amd64\n", "architecture: \n", `"architecture" header should not be empty`}, {"gadget: brand-gadget\n", "", `"gadget" header is mandatory`}, {"gadget: brand-gadget\n", "gadget: \n", `"gadget" header should not be empty`}, {"kernel: baz-linux\n", "", `"kernel" header is mandatory`}, {"kernel: baz-linux\n", "kernel: \n", `"kernel" header should not be empty`}, {"store: brand-store\n", "store:\n - xyz\n", `"store" header must be a string`}, {mods.tsLine, "", `"timestamp" header is mandatory`}, {mods.tsLine, "timestamp: \n", `"timestamp" header should not be empty`}, {mods.tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`}, {reqSnaps, "required-snaps: foo\n", `"required-snaps" header must be a list of strings`}, {reqSnaps, "required-snaps:\n -\n - nested\n", `"required-snaps" header must be a list of strings`}, } for _, test := range invalidTests { invalid := strings.Replace(encoded, test.original, test.invalid, 1) _, err := asserts.Decode([]byte(invalid)) c.Check(err, ErrorMatches, modelErrPrefix+test.expectedErr) } }
func (srs *snapRevSuite) TestDecodeInvalid(c *C) { encoded := srs.makeValidEncoded() digestHdr := "snap-sha3-384: " + blobSHA3_384 + "\n" invalidTests := []struct{ original, invalid, expectedErr string }{ {"snap-id: snap-id-1\n", "", `"snap-id" header is mandatory`}, {"snap-id: snap-id-1\n", "snap-id: \n", `"snap-id" header should not be empty`}, {digestHdr, "", `"snap-sha3-384" header is mandatory`}, {digestHdr, "snap-sha3-384: \n", `"snap-sha3-384" header should not be empty`}, {digestHdr, "snap-sha3-384: #\n", `"snap-sha3-384" header cannot be decoded:.*`}, {digestHdr, "snap-sha3-384: eHl6\n", `"snap-sha3-384" header does not have the expected bit length: 24`}, {"snap-size: 123\n", "", `"snap-size" header is mandatory`}, {"snap-size: 123\n", "snap-size: \n", `"snap-size" header should not be empty`}, {"snap-size: 123\n", "snap-size: -1\n", `"snap-size" header is not an unsigned integer: -1`}, {"snap-size: 123\n", "snap-size: zzz\n", `"snap-size" header is not an unsigned integer: zzz`}, {"snap-revision: 1\n", "", `"snap-revision" header is mandatory`}, {"snap-revision: 1\n", "snap-revision: \n", `"snap-revision" header should not be empty`}, {"snap-revision: 1\n", "snap-revision: -1\n", `"snap-revision" header must be >=1: -1`}, {"snap-revision: 1\n", "snap-revision: 0\n", `"snap-revision" header must be >=1: 0`}, {"snap-revision: 1\n", "snap-revision: zzz\n", `"snap-revision" header is not an integer: zzz`}, {"developer-id: dev-id1\n", "", `"developer-id" header is mandatory`}, {"developer-id: dev-id1\n", "developer-id: \n", `"developer-id" header should not be empty`}, {srs.tsLine, "", `"timestamp" header is mandatory`}, {srs.tsLine, "timestamp: \n", `"timestamp" header should not be empty`}, {srs.tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`}, } for _, test := range invalidTests { invalid := strings.Replace(encoded, test.original, test.invalid, 1) _, err := asserts.Decode([]byte(invalid)) c.Check(err, ErrorMatches, snapRevErrPrefix+test.expectedErr) } }
func (aks *accountKeySuite) TestAccountKeyRequestUntil(c *C) { db := aks.openDB(c) aks.prereqAccount(c, db) tests := []struct { untilHeader string until time.Time }{ {"", time.Time{}}, // zero time default {aks.until.Format(time.RFC3339), aks.until}, // in the future {aks.since.Format(time.RFC3339), aks.since}, // same as since } for _, test := range tests { c.Log(test) headers := map[string]interface{}{ "account-id": "acc-id1", "name": "default", "public-key-sha3-384": aks.keyID, "since": aks.since.Format(time.RFC3339), } if test.untilHeader != "" { headers["until"] = test.untilHeader } akr, err := asserts.SignWithoutAuthority(asserts.AccountKeyRequestType, headers, []byte(aks.pubKeyBody), aks.privKey) c.Assert(err, IsNil) a, err := asserts.Decode(asserts.Encode(akr)) c.Assert(err, IsNil) akr2 := a.(*asserts.AccountKeyRequest) c.Check(akr2.Until(), Equals, test.until) err = db.Check(akr2) c.Check(err, IsNil) } }
func (s *baseDeclSuite) TestDecodeInvalid(c *C) { tsLine := "timestamp: 2016-09-29T19:50:49Z\n" encoded := "type: base-declaration\n" + "authority-id: canonical\n" + "series: 16\n" + "plugs:\n interface1: true\n" + "slots:\n interface2: true\n" + tsLine + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==" invalidTests := []struct{ original, invalid, expectedErr string }{ {"series: 16\n", "", `"series" header is mandatory`}, {"series: 16\n", "series: \n", `"series" header should not be empty`}, {"plugs:\n interface1: true\n", "plugs: \n", `"plugs" header must be a map`}, {"plugs:\n interface1: true\n", "plugs:\n intf1:\n foo: bar\n", `plug rule for interface "intf1" must specify at least one of.*`}, {"slots:\n interface2: true\n", "slots: \n", `"slots" header must be a map`}, {"slots:\n interface2: true\n", "slots:\n intf1:\n foo: bar\n", `slot rule for interface "intf1" must specify at least one of.*`}, {tsLine, "", `"timestamp" header is mandatory`}, {tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`}, } for _, test := range invalidTests { invalid := strings.Replace(encoded, test.original, test.invalid, 1) _, err := asserts.Decode([]byte(invalid)) c.Check(err, ErrorMatches, baseDeclErrPrefix+test.expectedErr) } }
func (mods *modelSuite) TestDecodeDisplayNameIsOptional(c *C) { withTimestamp := strings.Replace(modelExample, "TSLINE", mods.tsLine, 1) encoded := strings.Replace(withTimestamp, "display-name: Baz 3000\n", "display-name: \n", 1) a, err := asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) model := a.(*asserts.Model) // optional but we fallback to Model c.Check(model.DisplayName(), Equals, "baz-3000") encoded = strings.Replace(withTimestamp, "display-name: Baz 3000\n", "", 1) a, err = asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) model = a.(*asserts.Model) // optional but we fallback to Model c.Check(model.DisplayName(), Equals, "baz-3000") }
func (aks *accountKeySuite) TestAccountKeyRequestDecodeInvalidPublicKey(c *C) { headers := "type: account-key-request\n" + "account-id: acc-id1\n" + "name: default\n" + "public-key-sha3-384: " + aks.keyID + "\n" + aks.sinceLine + aks.untilLine raw, err := base64.StdEncoding.DecodeString(aks.pubKeyBody) c.Assert(err, IsNil) spurious := base64.StdEncoding.EncodeToString(append(raw, "gorp"...)) invalidPublicKeyTests := []struct{ body, expectedErr string }{ {"", "cannot decode public key: no data"}, {"==", "cannot decode public key: .*"}, {"stuff", "cannot decode public key: .*"}, {"AnNpZw==", "unsupported public key format version: 2"}, {"AUJST0tFTg==", "cannot decode public key: .*"}, {spurious, "public key has spurious trailing data"}, } for _, test := range invalidPublicKeyTests { invalid := headers + fmt.Sprintf("body-length: %v", len(test.body)) + "\n" + "sign-key-sha3-384: " + aks.privKey.PublicKey().ID() + "\n\n" + test.body + "\n\n" + "AXNpZw==" _, err := asserts.Decode([]byte(invalid)) c.Check(err, ErrorMatches, accKeyReqErrPrefix+test.expectedErr) } }
func (s *SnapSignBuildSuite) TestSignBuildWorks(c *C) { snapFilename := "foo_1_amd64.snap" snapContent := []byte("sample") _err := ioutil.WriteFile(snapFilename, snapContent, 0644) c.Assert(_err, IsNil) defer os.Remove(snapFilename) tempdir := c.MkDir() for _, fileName := range []string{"pubring.gpg", "secring.gpg", "trustdb.gpg"} { data, err := ioutil.ReadFile(filepath.Join("test-data", fileName)) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(tempdir, fileName), data, 0644) c.Assert(err, IsNil) } os.Setenv("SNAP_GNUPG_HOME", tempdir) defer os.Unsetenv("SNAP_GNUPG_HOME") _, err := snap.Parser().ParseArgs([]string{"sign-build", snapFilename, "--developer-id", "dev-id1", "--snap-id", "snap-id-1"}) c.Assert(err, IsNil) assertion, err := asserts.Decode([]byte(s.Stdout())) c.Assert(err, IsNil) c.Check(assertion.Type(), Equals, asserts.SnapBuildType) c.Check(assertion.Revision(), Equals, 0) c.Check(assertion.HeaderString("authority-id"), Equals, "dev-id1") c.Check(assertion.HeaderString("developer-id"), Equals, "dev-id1") c.Check(assertion.HeaderString("grade"), Equals, "stable") c.Check(assertion.HeaderString("snap-id"), Equals, "snap-id-1") c.Check(assertion.HeaderString("snap-size"), Equals, fmt.Sprintf("%d", len(snapContent))) c.Check(assertion.HeaderString("snap-sha3-384"), Equals, "jyP7dUgb8HiRNd1SdYPp_il-YNrl6P6PgNAe-j6_7WytjKslENhMD3Of5XBU5bQK") // check for valid signature ?! c.Check(s.Stderr(), Equals, "") }
func (ss *serialSuite) TestDeviceSessionRequest(c *C) { ts := time.Now().UTC().Round(time.Second) sessReq, err := asserts.SignWithoutAuthority(asserts.DeviceSessionRequestType, map[string]interface{}{ "brand-id": "brand-id1", "model": "baz-3000", "serial": "99990", "nonce": "NONCE", "timestamp": ts.Format(time.RFC3339), }, nil, ss.deviceKey) c.Assert(err, IsNil) // roundtrip a, err := asserts.Decode(asserts.Encode(sessReq)) c.Assert(err, IsNil) sessReq2, ok := a.(*asserts.DeviceSessionRequest) c.Assert(ok, Equals, true) // standalone signature check err = asserts.SignatureCheck(sessReq2, ss.deviceKey.PublicKey()) c.Check(err, IsNil) c.Check(sessReq2.BrandID(), Equals, "brand-id1") c.Check(sessReq2.Model(), Equals, "baz-3000") c.Check(sessReq2.Serial(), Equals, "99990") c.Check(sessReq2.Nonce(), Equals, "NONCE") c.Check(sessReq2.Timestamp().Equal(ts), Equals, true) }
func (s *SnapKeysSuite) TestExportKeyAccount(c *C) { rootPrivKey, _ := assertstest.GenerateKey(1024) storePrivKey, _ := assertstest.GenerateKey(752) storeSigning := assertstest.NewStoreStack("canonical", rootPrivKey, storePrivKey) manager := asserts.NewGPGKeypairManager() assertstest.NewAccount(storeSigning, "developer1", nil, "") rest, err := snap.Parser().ParseArgs([]string{"export-key", "another", "--account=developer1"}) c.Assert(err, IsNil) c.Assert(rest, DeepEquals, []string{}) assertion, err := asserts.Decode(s.stdout.Bytes()) c.Assert(err, IsNil) c.Check(assertion.Type(), Equals, asserts.AccountKeyRequestType) c.Check(assertion.Revision(), Equals, 0) c.Check(assertion.HeaderString("account-id"), Equals, "developer1") c.Check(assertion.HeaderString("name"), Equals, "another") c.Check(assertion.HeaderString("public-key-sha3-384"), Equals, "DVQf1U4mIsuzlQqAebjjTPYtYJ-GEhJy0REuj3zvpQYTZ7EJj7adBxIXLJ7Vmk3L") since, err := time.Parse(time.RFC3339, assertion.HeaderString("since")) c.Assert(err, IsNil) zone, offset := since.Zone() c.Check(zone, Equals, "UTC") c.Check(offset, Equals, 0) c.Check(s.Stderr(), Equals, "") privKey, err := manager.Get(assertion.HeaderString("public-key-sha3-384")) c.Assert(err, IsNil) err = asserts.SignatureCheck(assertion, privKey.PublicKey()) c.Assert(err, IsNil) }
func (chks *checkSuite) TestCheckForgery(c *C) { trustedKey := testPrivKey0 cfg := &asserts.DatabaseConfig{ Backstore: chks.bs, Trusted: []asserts.Assertion{asserts.BootstrapAccountKeyForTest("canonical", trustedKey.PublicKey())}, } db, err := asserts.OpenDatabase(cfg) c.Assert(err, IsNil) encoded := asserts.Encode(chks.a) content, encodedSig := chks.a.Signature() // forgery forgedSig := new(packet.Signature) forgedSig.PubKeyAlgo = packet.PubKeyAlgoRSA forgedSig.Hash = crypto.SHA512 forgedSig.CreationTime = time.Now() h := crypto.SHA512.New() h.Write(content) pk1 := packet.NewRSAPrivateKey(time.Unix(1, 0), testPrivKey1RSA) err = forgedSig.Sign(h, pk1, &packet.Config{DefaultHash: crypto.SHA512}) c.Assert(err, IsNil) buf := new(bytes.Buffer) forgedSig.Serialize(buf) b := append([]byte{0x1}, buf.Bytes()...) forgedSigEncoded := base64.StdEncoding.EncodeToString(b) forgedEncoded := bytes.Replace(encoded, encodedSig, []byte(forgedSigEncoded), 1) c.Assert(forgedEncoded, Not(DeepEquals), encoded) forgedAssert, err := asserts.Decode(forgedEncoded) c.Assert(err, IsNil) err = db.Check(forgedAssert) c.Assert(err, ErrorMatches, "failed signature verification: .*") }
func (sds *snapDeclSuite) TestDecodeOK(c *C) { encoded := "type: snap-declaration\n" + "authority-id: canonical\n" + "series: 16\n" + "snap-id: snap-id-1\n" + "snap-name: first\n" + "publisher-id: dev-id1\n" + "refresh-control:\n - foo\n - bar\n" + "auto-aliases:\n - cmd1\n - cmd_2\n - Cmd-3\n - CMD.4\n" + sds.tsLine + "body-length: 0\n" + "sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" + "\n\n" + "AXNpZw==" a, err := asserts.Decode([]byte(encoded)) c.Assert(err, IsNil) c.Check(a.Type(), Equals, asserts.SnapDeclarationType) snapDecl := a.(*asserts.SnapDeclaration) c.Check(snapDecl.AuthorityID(), Equals, "canonical") c.Check(snapDecl.Timestamp(), Equals, sds.ts) c.Check(snapDecl.Series(), Equals, "16") c.Check(snapDecl.SnapID(), Equals, "snap-id-1") c.Check(snapDecl.SnapName(), Equals, "first") c.Check(snapDecl.PublisherID(), Equals, "dev-id1") c.Check(snapDecl.RefreshControl(), DeepEquals, []string{"foo", "bar"}) c.Check(snapDecl.AutoAliases(), DeepEquals, []string{"cmd1", "cmd_2", "Cmd-3", "CMD.4"}) }
func (ss *serialSuite) TestDecodeInvalid(c *C) { encoded := strings.Replace(serialExample, "TSLINE", ss.tsLine, 1) invalidTests := []struct{ original, invalid, expectedErr string }{ {"brand-id: brand-id1\n", "", `"brand-id" header is mandatory`}, {"brand-id: brand-id1\n", "brand-id: \n", `"brand-id" header should not be empty`}, {"authority-id: brand-id1\n", "authority-id: random\n", `authority-id and brand-id must match, serial assertions are expected to be signed by the brand: "random" != "brand-id1"`}, {"model: baz-3000\n", "", `"model" header is mandatory`}, {"model: baz-3000\n", "model: \n", `"model" header should not be empty`}, {"serial: 2700\n", "", `"serial" header is mandatory`}, {"serial: 2700\n", "serial: \n", `"serial" header should not be empty`}, {ss.tsLine, "", `"timestamp" header is mandatory`}, {ss.tsLine, "timestamp: \n", `"timestamp" header should not be empty`}, {ss.tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`}, {"device-key:\n DEVICEKEY\n", "", `"device-key" header is mandatory`}, {"device-key:\n DEVICEKEY\n", "device-key: \n", `"device-key" header should not be empty`}, {"device-key:\n DEVICEKEY\n", "device-key: $$$\n", `cannot decode public key: .*`}, {"device-key-sha3-384: KEYID\n", "", `"device-key-sha3-384" header is mandatory`}, } for _, test := range invalidTests { invalid := strings.Replace(encoded, test.original, test.invalid, 1) invalid = strings.Replace(invalid, "DEVICEKEY", strings.Replace(ss.encodedDevKey, "\n", "\n ", -1), 1) invalid = strings.Replace(invalid, "KEYID", ss.deviceKey.PublicKey().ID(), 1) _, err := asserts.Decode([]byte(invalid)) c.Check(err, ErrorMatches, serialErrPrefix+test.expectedErr) } }
func (vs *validationSuite) TestDecodeInvalid(c *C) { encoded := vs.makeValidEncoded() invalidTests := []struct{ original, invalid, expectedErr string }{ {"series: 16\n", "", `"series" header is mandatory`}, {"series: 16\n", "series: \n", `"series" header should not be empty`}, {"snap-id: snap-id-1\n", "", `"snap-id" header is mandatory`}, {"snap-id: snap-id-1\n", "snap-id: \n", `"snap-id" header should not be empty`}, {"approved-snap-id: snap-id-2\n", "", `"approved-snap-id" header is mandatory`}, {"approved-snap-id: snap-id-2\n", "approved-snap-id: \n", `"approved-snap-id" header should not be empty`}, {"approved-snap-revision: 42\n", "", `"approved-snap-revision" header is mandatory`}, {"approved-snap-revision: 42\n", "approved-snap-revision: z\n", `"approved-snap-revision" header is not an integer: z`}, {"approved-snap-revision: 42\n", "approved-snap-revision: 0\n", `"approved-snap-revision" header must be >=1: 0`}, {"approved-snap-revision: 42\n", "approved-snap-revision: -1\n", `"approved-snap-revision" header must be >=1: -1`}, {vs.tsLine, "", `"timestamp" header is mandatory`}, {vs.tsLine, "timestamp: \n", `"timestamp" header should not be empty`}, {vs.tsLine, "timestamp: 12:30\n", `"timestamp" header is not a RFC3339 date: .*`}, } for _, test := range invalidTests { invalid := strings.Replace(encoded, test.original, test.invalid, 1) _, err := asserts.Decode([]byte(invalid)) c.Check(err, ErrorMatches, validationErrPrefix+test.expectedErr) } }
func (ss *serialSuite) TestSerialRequestHappy(c *C) { sreq, err := asserts.SignWithoutAuthority(asserts.SerialRequestType, map[string]interface{}{ "brand-id": "brand-id1", "model": "baz-3000", "device-key": ss.encodedDevKey, "request-id": "REQID", }, []byte("HW-DETAILS"), ss.deviceKey) c.Assert(err, IsNil) // roundtrip a, err := asserts.Decode(asserts.Encode(sreq)) c.Assert(err, IsNil) sreq2, ok := a.(*asserts.SerialRequest) c.Assert(ok, Equals, true) // standalone signature check err = asserts.SignatureCheck(sreq2, sreq2.DeviceKey()) c.Check(err, IsNil) c.Check(sreq2.BrandID(), Equals, "brand-id1") c.Check(sreq2.Model(), Equals, "baz-3000") c.Check(sreq2.RequestID(), Equals, "REQID") c.Check(sreq2.Serial(), Equals, "") }