func (s *assertMgrSuite) TestValidateRefreshesMissingValidation(c *C) { s.state.Lock() defer s.state.Unlock() snapDeclFoo := s.snapDecl(c, "foo", nil) snapDeclBar := s.snapDecl(c, "bar", []interface{}{"foo-id"}) s.stateFromDecl(snapDeclFoo, snap.R(7)) s.stateFromDecl(snapDeclBar, snap.R(3)) err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(s.state, s.dev1Acct) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclFoo) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclBar) c.Assert(err, IsNil) fooRefresh := &snap.Info{ SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, } validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, 0) c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`) c.Check(validated, HasLen, 0) }
func (s *assertMgrSuite) TestValidateRefreshesNoControl(c *C) { s.state.Lock() defer s.state.Unlock() snapDeclFoo := s.snapDecl(c, "foo", nil) snapDeclBar := s.snapDecl(c, "bar", nil) s.stateFromDecl(snapDeclFoo, snap.R(7)) s.stateFromDecl(snapDeclBar, snap.R(3)) err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(s.state, s.dev1Acct) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclFoo) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclBar) c.Assert(err, IsNil) fooRefresh := &snap.Info{ SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, } validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, 0) c.Assert(err, IsNil) c.Check(validated, DeepEquals, []*snap.Info{fooRefresh}) }
func (s *assertMgrSuite) TestAutoAliases(c *C) { s.state.Lock() defer s.state.Unlock() // prereqs for developer assertions in the system db err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(s.state, s.dev1Acct) c.Assert(err, IsNil) // not from the store aliases, err := assertstate.AutoAliases(s.state, &snap.Info{SuggestedName: "local"}) c.Assert(err, IsNil) c.Check(aliases, HasLen, 0) // missing _, err = assertstate.AutoAliases(s.state, &snap.Info{ SideInfo: snap.SideInfo{ RealName: "baz", SnapID: "baz-id", }, }) c.Check(err, ErrorMatches, `internal error: cannot find snap-declaration for installed snap "baz": assertion not found`) // empty list // have a declaration in the system db snapDeclFoo := s.snapDecl(c, "foo", nil) err = assertstate.Add(s.state, snapDeclFoo) c.Assert(err, IsNil) aliases, err = assertstate.AutoAliases(s.state, &snap.Info{ SideInfo: snap.SideInfo{ RealName: "foo", SnapID: "foo-id", }, }) c.Assert(err, IsNil) c.Check(aliases, HasLen, 0) // some aliases snapDeclFoo = s.snapDecl(c, "foo", map[string]interface{}{ "auto-aliases": []interface{}{"alias1", "alias2"}, "revision": "1", }) err = assertstate.Add(s.state, snapDeclFoo) c.Assert(err, IsNil) aliases, err = assertstate.AutoAliases(s.state, &snap.Info{ SideInfo: snap.SideInfo{ RealName: "foo", SnapID: "foo-id", }, }) c.Assert(err, IsNil) c.Check(aliases, DeepEquals, []string{"alias1", "alias2"}) }
func (s *authContextSetupSuite) TestDeviceSessionRequest(c *C) { st := s.o.State() st.Lock() defer st.Unlock() st.Unlock() _, _, err := s.ac.DeviceSessionRequest("NONCE") st.Lock() c.Check(err, Equals, auth.ErrNoSerial) // setup serial and key in system state err = assertstate.Add(st, s.serial) c.Assert(err, IsNil) kpMgr, err := asserts.OpenFSKeypairManager(dirs.SnapDeviceDir) c.Assert(err, IsNil) err = kpMgr.Put(deviceKey) c.Assert(err, IsNil) auth.SetDevice(st, &auth.DeviceState{ Brand: s.serial.BrandID(), Model: s.serial.Model(), Serial: s.serial.Serial(), KeyID: deviceKey.PublicKey().ID(), }) st.Unlock() req, encSerial, err := s.ac.DeviceSessionRequest("NONCE") st.Lock() c.Assert(err, IsNil) c.Check(bytes.HasPrefix(req, []byte("type: device-session-request\n")), Equals, true) c.Check(encSerial, DeepEquals, asserts.Encode(s.serial)) }
func (s *authContextSetupSuite) TestStoreID(c *C) { st := s.o.State() st.Lock() defer st.Unlock() st.Unlock() storeID, err := s.ac.StoreID("fallback") st.Lock() c.Assert(err, IsNil) c.Check(storeID, Equals, "fallback") // setup model in system state auth.SetDevice(st, &auth.DeviceState{ Brand: s.serial.BrandID(), Model: s.serial.Model(), Serial: s.serial.Serial(), }) err = assertstate.Add(st, s.model) c.Assert(err, IsNil) st.Unlock() storeID, err = s.ac.StoreID("fallback") st.Lock() c.Assert(err, IsNil) c.Check(storeID, Equals, "my-brand-store-id") }
func (ms *mgrsSuite) TestCheckInterfaces(c *C) { snapDecl := ms.prereqSnapAssertions(c) snapYamlContent := `name: foo apps: bar: command: bin/bar slots: network: ` snapPath := makeTestSnap(c, snapYamlContent+"version: 1.5") si := &snap.SideInfo{ RealName: "foo", SnapID: fooSnapID, Revision: snap.R(55), DeveloperID: "devdevdevID", Developer: "devdevdev", } st := ms.o.State() st.Lock() defer st.Unlock() // have the snap-declaration in the system db err := assertstate.Add(st, ms.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(st, ms.devAcct) c.Assert(err, IsNil) err = assertstate.Add(st, snapDecl) c.Assert(err, IsNil) ts, err := snapstate.InstallPath(st, si, snapPath, "", snapstate.Flags{DevMode: true}) c.Assert(err, IsNil) chg := st.NewChange("install-snap", "...") chg.AddAll(ts) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Err(), ErrorMatches, `(?s).*installation not allowed by "network" slot rule of interface "network".*`) c.Check(chg.Status(), Equals, state.ErrorStatus) }
func (s *assertMgrSuite) TestAdd(c *C) { s.state.Lock() defer s.state.Unlock() // prereq store key err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(s.state, s.dev1Acct) c.Assert(err, IsNil) db := assertstate.DB(s.state) devAcct, err := db.Find(asserts.AccountType, map[string]string{ "account-id": s.dev1Acct.AccountID(), }) c.Assert(err, IsNil) c.Check(devAcct.(*asserts.Account).Username(), Equals, "developer1") }
func (s *assertMgrSuite) TestSnapDeclaration(c *C) { s.state.Lock() defer s.state.Unlock() // have a declaration in the system db err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(s.state, s.dev1Acct) c.Assert(err, IsNil) snapDeclFoo := s.snapDecl(c, "foo", nil) err = assertstate.Add(s.state, snapDeclFoo) c.Assert(err, IsNil) _, err = assertstate.SnapDeclaration(s.state, "snap-id-other") c.Check(err, Equals, asserts.ErrNotFound) snapDecl, err := assertstate.SnapDeclaration(s.state, "foo-id") c.Assert(err, IsNil) c.Check(snapDecl.SnapName(), Equals, "foo") }
func (s *deviceMgrSuite) TestDeviceAssertionsDeviceSessionRequest(c *C) { // nothing there _, _, err := s.mgr.DeviceSessionRequest("NONCE-1") c.Check(err, Equals, state.ErrNoState) // setup state as done by device initialisation s.state.Lock() devKey, _ := assertstest.GenerateKey(1024) encDevKey, err := asserts.EncodePublicKey(devKey.PublicKey()) c.Check(err, IsNil) seriala, err := s.storeSigning.Sign(asserts.SerialType, map[string]interface{}{ "brand-id": "canonical", "model": "pc", "serial": "8989", "device-key": string(encDevKey), "device-key-sha3-384": devKey.PublicKey().ID(), "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) err = assertstate.Add(s.state, seriala) c.Assert(err, IsNil) auth.SetDevice(s.state, &auth.DeviceState{ Brand: "canonical", Model: "pc", Serial: "8989", KeyID: devKey.PublicKey().ID(), }) s.mgr.KeypairManager().Put(devKey) s.state.Unlock() sessReq, serial, err := s.mgr.DeviceSessionRequest("NONCE-1") c.Assert(err, IsNil) c.Check(serial.Serial(), Equals, "8989") // correctly signed with device key err = asserts.SignatureCheck(sessReq, devKey.PublicKey()) c.Check(err, IsNil) c.Check(sessReq.BrandID(), Equals, "canonical") c.Check(sessReq.Model(), Equals, "pc") c.Check(sessReq.Serial(), Equals, "8989") c.Check(sessReq.Nonce(), Equals, "NONCE-1") }
func (s *deviceMgrSuite) TestCheckKernel(c *C) { release.OnClassic = false s.state.Lock() defer s.state.Unlock() // nothing is setup kernelInfo := snaptest.MockInfo(c, `type: kernel name: lnrk`, nil) err := devicestate.CheckGadgetOrKernel(s.state, kernelInfo, nil, snapstate.Flags{}) c.Check(err, ErrorMatches, `cannot install kernel without model assertion`) // setup model assertion model, err := s.storeSigning.Sign(asserts.ModelType, map[string]interface{}{ "series": "16", "brand-id": "canonical", "model": "pc", "gadget": "pc", "kernel": "krnl", "architecture": "amd64", "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) err = assertstate.Add(s.state, model) c.Assert(err, IsNil) err = auth.SetDevice(s.state, &auth.DeviceState{ Brand: "canonical", Model: "pc", }) c.Assert(err, IsNil) err = devicestate.CheckGadgetOrKernel(s.state, kernelInfo, nil, snapstate.Flags{}) c.Check(err, ErrorMatches, `cannot install kernel "lnrk", model assertion requests "krnl"`) // install krnl kernel krnlKernelInfo := snaptest.MockInfo(c, `type: kernel name: krnl`, nil) err = devicestate.CheckGadgetOrKernel(s.state, krnlKernelInfo, nil, snapstate.Flags{}) c.Check(err, IsNil) }
func (ms *mgrsSuite) TestHappyLocalInstallWithStoreMetadata(c *C) { snapDecl := ms.prereqSnapAssertions(c) snapYamlContent := `name: foo apps: bar: command: bin/bar ` snapPath := makeTestSnap(c, snapYamlContent+"version: 1.5") si := &snap.SideInfo{ RealName: "foo", SnapID: fooSnapID, Revision: snap.R(55), DeveloperID: "devdevdevID", Developer: "devdevdev", } st := ms.o.State() st.Lock() defer st.Unlock() // have the snap-declaration in the system db err := assertstate.Add(st, ms.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(st, ms.devAcct) c.Assert(err, IsNil) err = assertstate.Add(st, snapDecl) c.Assert(err, IsNil) ts, err := snapstate.InstallPath(st, si, snapPath, "", snapstate.Flags{DevMode: true}) c.Assert(err, IsNil) chg := st.NewChange("install-snap", "...") chg.AddAll(ts) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err())) info, err := snapstate.CurrentInfo(st, "foo") c.Assert(err, IsNil) c.Check(info.Revision, Equals, snap.R(55)) c.Check(info.SnapID, Equals, fooSnapID) c.Check(info.DeveloperID, Equals, "devdevdevID") c.Check(info.Developer, Equals, "devdevdev") c.Check(info.Version, Equals, "1.5") // ensure that the binary wrapper file got generated with the right // name binaryWrapper := filepath.Join(dirs.SnapBinariesDir, "foo.bar") c.Assert(osutil.IsSymlink(binaryWrapper), Equals, true) // data dirs c.Assert(osutil.IsDirectory(info.DataDir()), Equals, true) c.Assert(osutil.IsDirectory(info.CommonDataDir()), Equals, true) // snap file and its mounting // after install the snap file is in the right dir c.Assert(osutil.FileExists(filepath.Join(dirs.SnapBlobDir, "foo_55.snap")), Equals, true) // ensure the right unit is created mup := systemd.MountUnitPath("/snap/foo/55") content, err := ioutil.ReadFile(mup) c.Assert(err, IsNil) c.Assert(string(content), Matches, "(?ms).*^Where=/snap/foo/55") c.Assert(string(content), Matches, "(?ms).*^What=/var/lib/snapd/snaps/foo_55.snap") }
func (s *assertMgrSuite) TestValidateRefreshesRevokedValidation(c *C) { s.state.Lock() defer s.state.Unlock() snapDeclFoo := s.snapDecl(c, "foo", nil) snapDeclBar := s.snapDecl(c, "bar", []interface{}{"foo-id"}) snapDeclBaz := s.snapDecl(c, "baz", []interface{}{"foo-id"}) s.stateFromDecl(snapDeclFoo, snap.R(7)) s.stateFromDecl(snapDeclBar, snap.R(3)) s.stateFromDecl(snapDeclBaz, snap.R(1)) snapstate.Set(s.state, "local", &snapstate.SnapState{ Active: false, Sequence: []*snap.SideInfo{ {RealName: "local", Revision: snap.R(-1)}, }, Current: snap.R(-1), }) // validation by bar headers := map[string]interface{}{ "series": "16", "snap-id": "bar-id", "approved-snap-id": "foo-id", "approved-snap-revision": "9", "timestamp": time.Now().Format(time.RFC3339), } barValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "") c.Assert(err, IsNil) err = s.storeSigning.Add(barValidation) c.Assert(err, IsNil) // revoked validation by baz headers = map[string]interface{}{ "series": "16", "snap-id": "baz-id", "approved-snap-id": "foo-id", "approved-snap-revision": "9", "revoked": "true", "timestamp": time.Now().Format(time.RFC3339), } bazValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "") c.Assert(err, IsNil) err = s.storeSigning.Add(bazValidation) c.Assert(err, IsNil) err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(s.state, s.dev1Acct) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclFoo) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclBar) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclBaz) c.Assert(err, IsNil) fooRefresh := &snap.Info{ SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, } validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, 0) c.Assert(err, ErrorMatches, `(?s).*cannot refresh "foo" to revision 9: validation by "baz" \(id "baz-id"\) revoked.*`) c.Check(validated, HasLen, 0) }
func (ms *mgrsSuite) TestHappyRefreshControl(c *C) { // test install through store and update, plus some mechanics // of update // TODO: ok to split if it gets too messy to maintain ms.prereqSnapAssertions(c) snapYamlContent := `name: foo version: @VERSION@ ` ver := "1.0" revno := "42" snapPath, _ := ms.makeStoreTestSnap(c, strings.Replace(snapYamlContent, "@VERSION@", ver, -1), revno) ms.serveSnap(snapPath, revno) mockServer := ms.mockStore(c) defer mockServer.Close() st := ms.o.State() st.Lock() defer st.Unlock() ts, err := snapstate.Install(st, "foo", "stable", snap.R(0), 0, snapstate.Flags{}) c.Assert(err, IsNil) chg := st.NewChange("install-snap", "...") chg.AddAll(ts) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err())) info, err := snapstate.CurrentInfo(st, "foo") c.Assert(err, IsNil) c.Check(info.Revision, Equals, snap.R(42)) // Refresh // Setup refresh control headers := map[string]interface{}{ "series": "16", "snap-id": "bar-id", "snap-name": "bar", "publisher-id": "devdevdev", "refresh-control": []interface{}{fooSnapID}, "timestamp": time.Now().Format(time.RFC3339), } snapDeclBar, err := ms.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") c.Assert(err, IsNil) err = ms.storeSigning.Add(snapDeclBar) c.Assert(err, IsNil) err = assertstate.Add(st, snapDeclBar) c.Assert(err, IsNil) snapstate.Set(st, "bar", &snapstate.SnapState{ Active: true, Sequence: []*snap.SideInfo{ {RealName: "bar", SnapID: "bar-id", Revision: snap.R(1)}, }, Current: snap.R(1), SnapType: "app", }) develSigning := assertstest.NewSigningDB("devdevdev", develPrivKey) develAccKey := assertstest.NewAccountKey(ms.storeSigning, ms.devAcct, nil, develPrivKey.PublicKey(), "") err = ms.storeSigning.Add(develAccKey) c.Assert(err, IsNil) ver = "2.0" revno = "50" snapPath, _ = ms.makeStoreTestSnap(c, strings.Replace(snapYamlContent, "@VERSION@", ver, -1), revno) ms.serveSnap(snapPath, revno) updated, tss, err := snapstate.UpdateMany(st, []string{"foo"}, 0) c.Check(updated, IsNil) c.Check(tss, IsNil) // no validation we, get an error c.Check(err, ErrorMatches, `cannot refresh "foo" to revision 50: no validation by "bar"`) // setup validation headers = map[string]interface{}{ "series": "16", "snap-id": "bar-id", "approved-snap-id": fooSnapID, "approved-snap-revision": "50", "timestamp": time.Now().Format(time.RFC3339), } barValidation, err := develSigning.Sign(asserts.ValidationType, headers, nil, "") c.Assert(err, IsNil) err = ms.storeSigning.Add(barValidation) c.Assert(err, IsNil) // ... and try again updated, tss, err = snapstate.UpdateMany(st, []string{"foo"}, 0) c.Assert(err, IsNil) c.Assert(updated, DeepEquals, []string{"foo"}) c.Assert(tss, HasLen, 1) chg = st.NewChange("upgrade-snaps", "...") chg.AddAll(tss[0]) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Err(), IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("upgrade-snap change failed with: %v", chg.Err())) info, err = snapstate.CurrentInfo(st, "foo") c.Assert(err, IsNil) c.Check(info.Revision, Equals, snap.R(50)) }
func (s *assertMgrSuite) TestRefreshSnapDeclarations(c *C) { s.state.Lock() defer s.state.Unlock() snapDeclFoo := s.snapDecl(c, "foo", nil) snapDeclBar := s.snapDecl(c, "bar", nil) s.stateFromDecl(snapDeclFoo, snap.R(7)) s.stateFromDecl(snapDeclBar, snap.R(3)) snapstate.Set(s.state, "local", &snapstate.SnapState{ Active: false, Sequence: []*snap.SideInfo{ {RealName: "local", Revision: snap.R(-1)}, }, Current: snap.R(-1), }) // previous state err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(s.state, s.dev1Acct) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclFoo) c.Assert(err, IsNil) err = assertstate.Add(s.state, snapDeclBar) c.Assert(err, IsNil) // one changed assertion headers := map[string]interface{}{ "series": "16", "snap-id": "foo-id", "snap-name": "fo-o", "publisher-id": s.dev1Acct.AccountID(), "timestamp": time.Now().Format(time.RFC3339), "revision": "1", } snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") c.Assert(err, IsNil) err = s.storeSigning.Add(snapDeclFoo1) c.Assert(err, IsNil) err = assertstate.RefreshSnapDeclarations(s.state, 0) c.Assert(err, IsNil) a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{ "series": "16", "snap-id": "foo-id", }) c.Assert(err, IsNil) c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o") // another one // one changed assertion headers = s.dev1Acct.Headers() headers["display-name"] = "Dev 1 edited display-name" headers["revision"] = "1" dev1Acct1, err := s.storeSigning.Sign(asserts.AccountType, headers, nil, "") c.Assert(err, IsNil) err = s.storeSigning.Add(dev1Acct1) c.Assert(err, IsNil) err = assertstate.RefreshSnapDeclarations(s.state, 0) c.Assert(err, IsNil) a, err = assertstate.DB(s.state).Find(asserts.AccountType, map[string]string{ "account-id": s.dev1Acct.AccountID(), }) c.Assert(err, IsNil) c.Check(a.(*asserts.Account).DisplayName(), Equals, "Dev 1 edited display-name") // change snap decl to something that has a too new format (func() { restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 999) defer restore() headers := map[string]interface{}{ "format": "999", "series": "16", "snap-id": "foo-id", "snap-name": "foo", "publisher-id": s.dev1Acct.AccountID(), "timestamp": time.Now().Format(time.RFC3339), "revision": "2", } snapDeclFoo2, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") c.Assert(err, IsNil) err = s.storeSigning.Add(snapDeclFoo2) c.Assert(err, IsNil) })() // no error, kept the old one err = assertstate.RefreshSnapDeclarations(s.state, 0) c.Assert(err, IsNil) a, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{ "series": "16", "snap-id": "foo-id", }) c.Assert(err, IsNil) c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o") c.Check(a.(*asserts.SnapDeclaration).Revision(), Equals, 1) }
func (ms *mgrsSuite) TestInstallKernelSnapUpdatesBootloader(c *C) { bootloader := boottest.NewMockBootloader("mock", c.MkDir()) partition.ForceBootloader(bootloader) defer partition.ForceBootloader(nil) restore := release.MockOnClassic(false) defer restore() brandAcct := assertstest.NewAccount(ms.storeSigning, "my-brand", map[string]interface{}{ "account-id": "my-brand", "verification": "certified", }, "") brandAccKey := assertstest.NewAccountKey(ms.storeSigning, brandAcct, nil, brandPrivKey.PublicKey(), "") brandSigning := assertstest.NewSigningDB("my-brand", brandPrivKey) model, err := brandSigning.Sign(asserts.ModelType, map[string]interface{}{ "series": "16", "authority-id": "my-brand", "brand-id": "my-brand", "model": "my-model", "architecture": "amd64", "store": "my-brand-store-id", "gadget": "gadget", "kernel": "krnl", "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) const packageKernel = ` name: krnl version: 4.0-1 type: kernel` files := [][]string{ {"kernel.img", "I'm a kernel"}, {"initrd.img", "...and I'm an initrd"}, {"meta/kernel.yaml", "version: 4.2"}, } snapPath := snaptest.MakeTestSnapWithFiles(c, packageKernel, files) st := ms.o.State() st.Lock() defer st.Unlock() // setup model assertion err = assertstate.Add(st, ms.storeSigning.StoreAccountKey("")) c.Assert(err, IsNil) err = assertstate.Add(st, brandAcct) c.Assert(err, IsNil) err = assertstate.Add(st, brandAccKey) c.Assert(err, IsNil) auth.SetDevice(st, &auth.DeviceState{ Brand: "my-brand", Model: "my-model", }) err = assertstate.Add(st, model) c.Assert(err, IsNil) ts, err := snapstate.InstallPath(st, &snap.SideInfo{RealName: "krnl"}, snapPath, "", snapstate.Flags{}) c.Assert(err, IsNil) chg := st.NewChange("install-snap", "...") chg.AddAll(ts) st.Unlock() err = ms.o.Settle() st.Lock() c.Assert(err, IsNil) c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("install-snap change failed with: %v", chg.Err())) c.Assert(bootloader.BootVars, DeepEquals, map[string]string{ "snap_try_kernel": "krnl_x1.snap", "snap_mode": "try", }) }
func (s *deviceMgrSuite) TestDeviceManagerEnsureSeedYamlRecover(c *C) { release.OnClassic = false restore := devicestate.MockPopulateStateFromSeed(func(*state.State) (ts []*state.TaskSet, err error) { return nil, errors.New("should not be called") }) defer restore() s.state.Lock() defer s.state.Unlock() s.setupCore(c, "ubuntu-core", ` name: ubuntu-core type: os version: ubuntu-core `, "") // have a model assertion model, err := s.storeSigning.Sign(asserts.ModelType, map[string]interface{}{ "series": "16", "brand-id": "canonical", "model": "pc", "gadget": "pc", "kernel": "kernel", "architecture": "amd64", "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) err = assertstate.Add(s.state, model) c.Assert(err, IsNil) // have a serial assertion devKey, _ := assertstest.GenerateKey(752) encDevKey, err := asserts.EncodePublicKey(devKey.PublicKey()) keyID := devKey.PublicKey().ID() c.Assert(err, IsNil) serial, err := s.storeSigning.Sign(asserts.SerialType, map[string]interface{}{ "brand-id": "canonical", "model": "pc", "serial": "8989", "device-key": string(encDevKey), "device-key-sha3-384": keyID, "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) err = assertstate.Add(s.state, serial) c.Assert(err, IsNil) // forgotten key id and serial auth.SetDevice(s.state, &auth.DeviceState{ Brand: "canonical", Model: "pc", }) // put key on disk err = s.mgr.KeypairManager().Put(devKey) c.Assert(err, IsNil) // extra unused stuff junk1 := filepath.Join(dirs.SnapDeviceDir, "private-keys-v1", "junkjunk1") err = ioutil.WriteFile(junk1, nil, 0644) c.Assert(err, IsNil) junk2 := filepath.Join(dirs.SnapDeviceDir, "private-keys-v1", "junkjunk2") err = ioutil.WriteFile(junk2, nil, 0644) c.Assert(err, IsNil) // double check pat := filepath.Join(dirs.SnapDeviceDir, "private-keys-v1", "*") onDisk, err := filepath.Glob(pat) c.Assert(err, IsNil) c.Check(onDisk, HasLen, 3) s.state.Unlock() err = s.mgr.EnsureSeedYaml() s.state.Lock() c.Assert(err, IsNil) c.Check(s.state.Changes(), HasLen, 0) var seeded bool err = s.state.Get("seeded", &seeded) c.Assert(err, IsNil) c.Check(seeded, Equals, true) device, err := auth.Device(s.state) c.Assert(err, IsNil) c.Check(device, DeepEquals, &auth.DeviceState{ Brand: "canonical", Model: "pc", KeyID: keyID, Serial: "8989", }) // key is still there _, err = s.mgr.KeypairManager().Get(keyID) c.Assert(err, IsNil) onDisk, err = filepath.Glob(pat) c.Assert(err, IsNil) // junk was removed c.Check(onDisk, HasLen, 1) }
func (s *authContextSetupSuite) SetUpTest(c *C) { tempdir := c.MkDir() dirs.SetRootDir(tempdir) err := os.MkdirAll(filepath.Dir(dirs.SnapStateFile), 0755) c.Assert(err, IsNil) captureAuthContext := func(_ *store.Config, ac auth.AuthContext) *store.Store { s.ac = ac return nil } r := overlord.MockStoreNew(captureAuthContext) defer r() s.storeSigning = assertstest.NewStoreStack("can0nical", rootPrivKey, storePrivKey) s.restoreTrusted = sysdb.InjectTrusted(s.storeSigning.Trusted) s.brandSigning = assertstest.NewSigningDB("my-brand", brandPrivKey) brandAcct := assertstest.NewAccount(s.storeSigning, "my-brand", map[string]interface{}{ "account-id": "my-brand", "verification": "certified", }, "") s.storeSigning.Add(brandAcct) brandAccKey := assertstest.NewAccountKey(s.storeSigning, brandAcct, nil, brandPrivKey.PublicKey(), "") s.storeSigning.Add(brandAccKey) model, err := s.brandSigning.Sign(asserts.ModelType, map[string]interface{}{ "series": "16", "authority-id": "my-brand", "brand-id": "my-brand", "model": "my-model", "architecture": "amd64", "store": "my-brand-store-id", "gadget": "pc", "kernel": "pc-kernel", "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) s.model = model.(*asserts.Model) encDevKey, err := asserts.EncodePublicKey(deviceKey.PublicKey()) c.Assert(err, IsNil) serial, err := s.brandSigning.Sign(asserts.SerialType, map[string]interface{}{ "authority-id": "my-brand", "brand-id": "my-brand", "model": "my-model", "serial": "7878", "device-key": string(encDevKey), "device-key-sha3-384": deviceKey.PublicKey().ID(), "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) s.serial = serial.(*asserts.Serial) o, err := overlord.New() c.Assert(err, IsNil) s.o = o st := o.State() st.Lock() defer st.Unlock() prereqs := []asserts.Assertion{s.storeSigning.StoreAccountKey(""), brandAcct, brandAccKey} for _, a := range prereqs { err = assertstate.Add(st, a) c.Assert(err, IsNil) } }
func (m *DeviceManager) doRequestSerial(t *state.Task, _ *tomb.Tomb) error { st := t.State() st.Lock() defer st.Unlock() cfg, err := getSerialRequestConfig(t) if err != nil { return err } device, err := auth.Device(st) if err != nil { return err } privKey, err := m.keyPair() if err == state.ErrNoState { return fmt.Errorf("internal error: cannot find device key pair") } if err != nil { return err } // make this idempotent, look if we have already a serial assertion // for privKey serials, err := assertstate.DB(st).FindMany(asserts.SerialType, map[string]string{ "brand-id": device.Brand, "model": device.Model, "device-key-sha3-384": privKey.PublicKey().ID(), }) if err != nil && err != asserts.ErrNotFound { return err } if len(serials) == 1 { // means we saved the assertion but didn't get to the end of the task device.Serial = serials[0].(*asserts.Serial).Serial() err := auth.SetDevice(st, device) if err != nil { return err } t.SetStatus(state.DoneStatus) return nil } if len(serials) > 1 { return fmt.Errorf("internal error: multiple serial assertions for the same device key") } serial, err := getSerial(t, privKey, device, cfg) if err == errPoll { t.Logf("Will poll for device serial assertion in 60 seconds") return &state.Retry{After: retryInterval} } if err != nil { // errors & retries return err } sto := snapstate.Store(st) // try to fetch the signing key of the serial st.Unlock() a, errAcctKey := sto.Assertion(asserts.AccountKeyType, []string{serial.SignKeyID()}, nil) st.Lock() if errAcctKey == nil { err := assertstate.Add(st, a) if err != nil { if !asserts.IsUnaccceptedUpdate(err) { return err } } } // add the serial assertion to the system assertion db err = assertstate.Add(st, serial) if err != nil { // if we had failed to fetch the signing key, retry in a bit if errAcctKey != nil { t.Errorf("cannot fetch signing key for the serial: %v", errAcctKey) return &state.Retry{After: retryInterval} } return err } if repeatRequestSerial == "after-add-serial" { // For testing purposes, ensure a crash in this state works. return &state.Retry{} } device.Serial = serial.Serial() err = auth.SetDevice(st, device) if err != nil { return err } t.SetStatus(state.DoneStatus) return nil }
func (s *deviceMgrSuite) TestDeviceAssertionsModelAndSerial(c *C) { // nothing in the state s.state.Lock() _, err := devicestate.Model(s.state) s.state.Unlock() c.Check(err, Equals, state.ErrNoState) s.state.Lock() _, err = devicestate.Serial(s.state) s.state.Unlock() c.Check(err, Equals, state.ErrNoState) _, err = s.mgr.Model() c.Check(err, Equals, state.ErrNoState) _, err = s.mgr.Serial() c.Check(err, Equals, state.ErrNoState) // just brand and model s.state.Lock() auth.SetDevice(s.state, &auth.DeviceState{ Brand: "canonical", Model: "pc", }) s.state.Unlock() _, err = s.mgr.Model() c.Check(err, Equals, state.ErrNoState) _, err = s.mgr.Serial() c.Check(err, Equals, state.ErrNoState) // have a model assertion model, err := s.storeSigning.Sign(asserts.ModelType, map[string]interface{}{ "series": "16", "brand-id": "canonical", "model": "pc", "gadget": "pc", "kernel": "kernel", "architecture": "amd64", "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) s.state.Lock() err = assertstate.Add(s.state, model) s.state.Unlock() c.Assert(err, IsNil) mod, err := s.mgr.Model() c.Assert(err, IsNil) c.Assert(mod.BrandID(), Equals, "canonical") s.state.Lock() mod, err = devicestate.Model(s.state) s.state.Unlock() c.Assert(err, IsNil) c.Assert(mod.BrandID(), Equals, "canonical") _, err = s.mgr.Serial() c.Check(err, Equals, state.ErrNoState) // have a serial as well s.state.Lock() auth.SetDevice(s.state, &auth.DeviceState{ Brand: "canonical", Model: "pc", Serial: "8989", }) s.state.Unlock() _, err = s.mgr.Model() c.Assert(err, IsNil) _, err = s.mgr.Serial() c.Check(err, Equals, state.ErrNoState) // have a serial assertion devKey, _ := assertstest.GenerateKey(752) encDevKey, err := asserts.EncodePublicKey(devKey.PublicKey()) c.Assert(err, IsNil) serial, err := s.storeSigning.Sign(asserts.SerialType, map[string]interface{}{ "brand-id": "canonical", "model": "pc", "serial": "8989", "device-key": string(encDevKey), "device-key-sha3-384": devKey.PublicKey().ID(), "timestamp": time.Now().Format(time.RFC3339), }, nil, "") c.Assert(err, IsNil) s.state.Lock() err = assertstate.Add(s.state, serial) s.state.Unlock() c.Assert(err, IsNil) _, err = s.mgr.Model() c.Assert(err, IsNil) ser, err := s.mgr.Serial() c.Assert(err, IsNil) c.Check(ser.Serial(), Equals, "8989") s.state.Lock() ser, err = devicestate.Serial(s.state) s.state.Unlock() c.Assert(err, IsNil) c.Check(ser.Serial(), Equals, "8989") }