github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/assertstate/assertstate_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2019 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package assertstate_test 21 22 import ( 23 "bytes" 24 "crypto" 25 "fmt" 26 "io/ioutil" 27 "path/filepath" 28 "testing" 29 "time" 30 31 "golang.org/x/crypto/sha3" 32 33 . "gopkg.in/check.v1" 34 35 "github.com/snapcore/snapd/asserts" 36 "github.com/snapcore/snapd/asserts/assertstest" 37 "github.com/snapcore/snapd/asserts/sysdb" 38 "github.com/snapcore/snapd/dirs" 39 "github.com/snapcore/snapd/logger" 40 "github.com/snapcore/snapd/overlord" 41 "github.com/snapcore/snapd/overlord/assertstate" 42 "github.com/snapcore/snapd/overlord/auth" 43 "github.com/snapcore/snapd/overlord/snapstate" 44 "github.com/snapcore/snapd/overlord/snapstate/snapstatetest" 45 "github.com/snapcore/snapd/overlord/state" 46 "github.com/snapcore/snapd/snap" 47 "github.com/snapcore/snapd/snap/snaptest" 48 "github.com/snapcore/snapd/store/storetest" 49 "github.com/snapcore/snapd/testutil" 50 ) 51 52 func TestAssertManager(t *testing.T) { TestingT(t) } 53 54 type assertMgrSuite struct { 55 testutil.BaseTest 56 57 o *overlord.Overlord 58 state *state.State 59 se *overlord.StateEngine 60 mgr *assertstate.AssertManager 61 62 storeSigning *assertstest.StoreStack 63 dev1Acct *asserts.Account 64 dev1Signing *assertstest.SigningDB 65 66 fakeStore snapstate.StoreService 67 trivialDeviceCtx snapstate.DeviceContext 68 } 69 70 var _ = Suite(&assertMgrSuite{}) 71 72 type fakeStore struct { 73 storetest.Store 74 state *state.State 75 db asserts.RODatabase 76 maxDeclSupportedFormat int 77 } 78 79 func (sto *fakeStore) pokeStateLock() { 80 // the store should be called without the state lock held. Try 81 // to acquire it. 82 sto.state.Lock() 83 sto.state.Unlock() 84 } 85 86 func (sto *fakeStore) Assertion(assertType *asserts.AssertionType, key []string, _ *auth.UserState) (asserts.Assertion, error) { 87 sto.pokeStateLock() 88 89 restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, sto.maxDeclSupportedFormat) 90 defer restore() 91 92 ref := &asserts.Ref{Type: assertType, PrimaryKey: key} 93 return ref.Resolve(sto.db.Find) 94 } 95 96 var ( 97 dev1PrivKey, _ = assertstest.GenerateKey(752) 98 ) 99 100 func (s *assertMgrSuite) SetUpTest(c *C) { 101 dirs.SetRootDir(c.MkDir()) 102 103 s.storeSigning = assertstest.NewStoreStack("can0nical", nil) 104 s.AddCleanup(sysdb.InjectTrusted(s.storeSigning.Trusted)) 105 106 s.dev1Acct = assertstest.NewAccount(s.storeSigning, "developer1", nil, "") 107 err := s.storeSigning.Add(s.dev1Acct) 108 c.Assert(err, IsNil) 109 110 // developer signing 111 dev1AcctKey := assertstest.NewAccountKey(s.storeSigning, s.dev1Acct, nil, dev1PrivKey.PublicKey(), "") 112 err = s.storeSigning.Add(dev1AcctKey) 113 c.Assert(err, IsNil) 114 115 s.dev1Signing = assertstest.NewSigningDB(s.dev1Acct.AccountID(), dev1PrivKey) 116 117 s.o = overlord.Mock() 118 s.state = s.o.State() 119 s.se = s.o.StateEngine() 120 mgr, err := assertstate.Manager(s.state, s.o.TaskRunner()) 121 c.Assert(err, IsNil) 122 s.mgr = mgr 123 s.o.AddManager(s.mgr) 124 125 s.o.AddManager(s.o.TaskRunner()) 126 127 s.fakeStore = &fakeStore{ 128 state: s.state, 129 db: s.storeSigning, 130 maxDeclSupportedFormat: asserts.SnapDeclarationType.MaxSupportedFormat(), 131 } 132 s.trivialDeviceCtx = &snapstatetest.TrivialDeviceContext{ 133 CtxStore: s.fakeStore, 134 } 135 } 136 137 func (s *assertMgrSuite) TestDB(c *C) { 138 s.state.Lock() 139 defer s.state.Unlock() 140 141 db := assertstate.DB(s.state) 142 c.Check(db, FitsTypeOf, (*asserts.Database)(nil)) 143 } 144 145 func (s *assertMgrSuite) TestAdd(c *C) { 146 s.state.Lock() 147 defer s.state.Unlock() 148 149 // prereq store key 150 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 151 c.Assert(err, IsNil) 152 153 err = assertstate.Add(s.state, s.dev1Acct) 154 c.Assert(err, IsNil) 155 156 db := assertstate.DB(s.state) 157 devAcct, err := db.Find(asserts.AccountType, map[string]string{ 158 "account-id": s.dev1Acct.AccountID(), 159 }) 160 c.Assert(err, IsNil) 161 c.Check(devAcct.(*asserts.Account).Username(), Equals, "developer1") 162 } 163 164 func (s *assertMgrSuite) TestAddBatch(c *C) { 165 s.state.Lock() 166 defer s.state.Unlock() 167 168 b := &bytes.Buffer{} 169 enc := asserts.NewEncoder(b) 170 // wrong order is ok 171 err := enc.Encode(s.dev1Acct) 172 c.Assert(err, IsNil) 173 enc.Encode(s.storeSigning.StoreAccountKey("")) 174 c.Assert(err, IsNil) 175 176 batch := asserts.NewBatch(nil) 177 refs, err := batch.AddStream(b) 178 c.Assert(err, IsNil) 179 c.Check(refs, DeepEquals, []*asserts.Ref{ 180 {Type: asserts.AccountType, PrimaryKey: []string{s.dev1Acct.AccountID()}}, 181 {Type: asserts.AccountKeyType, PrimaryKey: []string{s.storeSigning.StoreAccountKey("").PublicKeyID()}}, 182 }) 183 184 // noop 185 err = batch.Add(s.storeSigning.StoreAccountKey("")) 186 c.Assert(err, IsNil) 187 188 err = assertstate.AddBatch(s.state, batch, nil) 189 c.Assert(err, IsNil) 190 191 db := assertstate.DB(s.state) 192 devAcct, err := db.Find(asserts.AccountType, map[string]string{ 193 "account-id": s.dev1Acct.AccountID(), 194 }) 195 c.Assert(err, IsNil) 196 c.Check(devAcct.(*asserts.Account).Username(), Equals, "developer1") 197 } 198 199 func (s *assertMgrSuite) TestAddBatchPartial(c *C) { 200 // Commit does add any successful assertion until the first error 201 s.state.Lock() 202 defer s.state.Unlock() 203 204 // store key already present 205 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 206 c.Assert(err, IsNil) 207 208 batch := asserts.NewBatch(nil) 209 210 snapDeclFoo := s.snapDecl(c, "foo", nil) 211 212 err = batch.Add(snapDeclFoo) 213 c.Assert(err, IsNil) 214 err = batch.Add(s.dev1Acct) 215 c.Assert(err, IsNil) 216 217 // too old 218 rev := 1 219 headers := map[string]interface{}{ 220 "snap-id": "foo-id", 221 "snap-sha3-384": makeDigest(rev), 222 "snap-size": fmt.Sprintf("%d", len(fakeSnap(rev))), 223 "snap-revision": fmt.Sprintf("%d", rev), 224 "developer-id": s.dev1Acct.AccountID(), 225 "timestamp": time.Time{}.Format(time.RFC3339), 226 } 227 snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "") 228 c.Assert(err, IsNil) 229 230 err = batch.Add(snapRev) 231 c.Assert(err, IsNil) 232 233 err = assertstate.AddBatch(s.state, batch, nil) 234 c.Check(err, ErrorMatches, `(?ms).*validity.*`) 235 236 // snap-declaration was added anyway 237 _, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{ 238 "series": "16", 239 "snap-id": "foo-id", 240 }) 241 c.Assert(err, IsNil) 242 } 243 244 func (s *assertMgrSuite) TestAddBatchPrecheckPartial(c *C) { 245 s.state.Lock() 246 defer s.state.Unlock() 247 248 // store key already present 249 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 250 c.Assert(err, IsNil) 251 252 batch := asserts.NewBatch(nil) 253 254 snapDeclFoo := s.snapDecl(c, "foo", nil) 255 256 err = batch.Add(snapDeclFoo) 257 c.Assert(err, IsNil) 258 err = batch.Add(s.dev1Acct) 259 c.Assert(err, IsNil) 260 261 // too old 262 rev := 1 263 headers := map[string]interface{}{ 264 "snap-id": "foo-id", 265 "snap-sha3-384": makeDigest(rev), 266 "snap-size": fmt.Sprintf("%d", len(fakeSnap(rev))), 267 "snap-revision": fmt.Sprintf("%d", rev), 268 "developer-id": s.dev1Acct.AccountID(), 269 "timestamp": time.Time{}.Format(time.RFC3339), 270 } 271 snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "") 272 c.Assert(err, IsNil) 273 274 err = batch.Add(snapRev) 275 c.Assert(err, IsNil) 276 277 err = assertstate.AddBatch(s.state, batch, &asserts.CommitOptions{ 278 Precheck: true, 279 }) 280 c.Check(err, ErrorMatches, `(?ms).*validity.*`) 281 282 // nothing was added 283 _, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{ 284 "series": "16", 285 "snap-id": "foo-id", 286 }) 287 c.Assert(asserts.IsNotFound(err), Equals, true) 288 } 289 290 func (s *assertMgrSuite) TestAddBatchPrecheckHappy(c *C) { 291 s.state.Lock() 292 defer s.state.Unlock() 293 294 // store key already present 295 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 296 c.Assert(err, IsNil) 297 298 batch := asserts.NewBatch(nil) 299 300 snapDeclFoo := s.snapDecl(c, "foo", nil) 301 302 err = batch.Add(snapDeclFoo) 303 c.Assert(err, IsNil) 304 err = batch.Add(s.dev1Acct) 305 c.Assert(err, IsNil) 306 307 rev := 1 308 revDigest := makeDigest(rev) 309 headers := map[string]interface{}{ 310 "snap-id": "foo-id", 311 "snap-sha3-384": revDigest, 312 "snap-size": fmt.Sprintf("%d", len(fakeSnap(rev))), 313 "snap-revision": fmt.Sprintf("%d", rev), 314 "developer-id": s.dev1Acct.AccountID(), 315 "timestamp": time.Now().Format(time.RFC3339), 316 } 317 snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "") 318 c.Assert(err, IsNil) 319 320 err = batch.Add(snapRev) 321 c.Assert(err, IsNil) 322 323 err = assertstate.AddBatch(s.state, batch, &asserts.CommitOptions{ 324 Precheck: true, 325 }) 326 c.Assert(err, IsNil) 327 328 _, err = assertstate.DB(s.state).Find(asserts.SnapRevisionType, map[string]string{ 329 "snap-sha3-384": revDigest, 330 }) 331 c.Check(err, IsNil) 332 } 333 334 func fakeSnap(rev int) []byte { 335 fake := fmt.Sprintf("hsqs________________%d", rev) 336 return []byte(fake) 337 } 338 339 func fakeHash(rev int) []byte { 340 h := sha3.Sum384(fakeSnap(rev)) 341 return h[:] 342 } 343 344 func makeDigest(rev int) string { 345 d, err := asserts.EncodeDigest(crypto.SHA3_384, fakeHash(rev)) 346 if err != nil { 347 panic(err) 348 } 349 return string(d) 350 } 351 352 func (s *assertMgrSuite) prereqSnapAssertions(c *C, revisions ...int) { 353 headers := map[string]interface{}{ 354 "series": "16", 355 "snap-id": "snap-id-1", 356 "snap-name": "foo", 357 "publisher-id": s.dev1Acct.AccountID(), 358 "timestamp": time.Now().Format(time.RFC3339), 359 } 360 snapDecl, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") 361 c.Assert(err, IsNil) 362 err = s.storeSigning.Add(snapDecl) 363 c.Assert(err, IsNil) 364 365 for _, rev := range revisions { 366 headers = map[string]interface{}{ 367 "snap-id": "snap-id-1", 368 "snap-sha3-384": makeDigest(rev), 369 "snap-size": fmt.Sprintf("%d", len(fakeSnap(rev))), 370 "snap-revision": fmt.Sprintf("%d", rev), 371 "developer-id": s.dev1Acct.AccountID(), 372 "timestamp": time.Now().Format(time.RFC3339), 373 } 374 snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "") 375 c.Assert(err, IsNil) 376 err = s.storeSigning.Add(snapRev) 377 c.Assert(err, IsNil) 378 } 379 } 380 381 func (s *assertMgrSuite) TestDoFetch(c *C) { 382 s.prereqSnapAssertions(c, 10) 383 384 s.state.Lock() 385 defer s.state.Unlock() 386 387 ref := &asserts.Ref{ 388 Type: asserts.SnapRevisionType, 389 PrimaryKey: []string{makeDigest(10)}, 390 } 391 392 err := assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, func(f asserts.Fetcher) error { 393 return f.Fetch(ref) 394 }) 395 c.Assert(err, IsNil) 396 397 snapRev, err := ref.Resolve(assertstate.DB(s.state).Find) 398 c.Assert(err, IsNil) 399 c.Check(snapRev.(*asserts.SnapRevision).SnapRevision(), Equals, 10) 400 } 401 402 func (s *assertMgrSuite) TestFetchIdempotent(c *C) { 403 s.prereqSnapAssertions(c, 10, 11) 404 405 s.state.Lock() 406 defer s.state.Unlock() 407 408 ref := &asserts.Ref{ 409 Type: asserts.SnapRevisionType, 410 PrimaryKey: []string{makeDigest(10)}, 411 } 412 fetching := func(f asserts.Fetcher) error { 413 return f.Fetch(ref) 414 } 415 416 err := assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, fetching) 417 c.Assert(err, IsNil) 418 419 ref = &asserts.Ref{ 420 Type: asserts.SnapRevisionType, 421 PrimaryKey: []string{makeDigest(11)}, 422 } 423 424 err = assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, fetching) 425 c.Assert(err, IsNil) 426 427 snapRev, err := ref.Resolve(assertstate.DB(s.state).Find) 428 c.Assert(err, IsNil) 429 c.Check(snapRev.(*asserts.SnapRevision).SnapRevision(), Equals, 11) 430 } 431 432 func (s *assertMgrSuite) settle(c *C) { 433 err := s.o.Settle(5 * time.Second) 434 c.Assert(err, IsNil) 435 } 436 437 func (s *assertMgrSuite) TestFetchUnsupportedUpdateIgnored(c *C) { 438 // ATM in principle we ignore updated assertions with unsupported formats 439 // NB: this scenario can only happen if there is a bug 440 // we ask the store to filter what is returned by max supported format! 441 restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 111) 442 defer restore() 443 444 logbuf, restore := logger.MockLogger() 445 defer restore() 446 447 snapDeclFoo0 := s.snapDecl(c, "foo", nil) 448 449 s.state.Lock() 450 defer s.state.Unlock() 451 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 452 c.Assert(err, IsNil) 453 454 err = assertstate.Add(s.state, s.dev1Acct) 455 c.Assert(err, IsNil) 456 err = assertstate.Add(s.state, snapDeclFoo0) 457 c.Assert(err, IsNil) 458 459 var snapDeclFoo1 *asserts.SnapDeclaration 460 (func() { 461 restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 999) 462 defer restore() 463 snapDeclFoo1 = s.snapDecl(c, "foo", map[string]interface{}{ 464 "format": "999", 465 "revision": "1", 466 }) 467 })() 468 c.Check(snapDeclFoo1.Revision(), Equals, 1) 469 470 ref := &asserts.Ref{ 471 Type: asserts.SnapDeclarationType, 472 PrimaryKey: []string{"16", "foo-id"}, 473 } 474 fetching := func(f asserts.Fetcher) error { 475 return f.Fetch(ref) 476 } 477 478 s.fakeStore.(*fakeStore).maxDeclSupportedFormat = 999 479 err = assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, fetching) 480 // no error and the old one was kept 481 c.Assert(err, IsNil) 482 snapDecl, err := ref.Resolve(assertstate.DB(s.state).Find) 483 c.Assert(err, IsNil) 484 c.Check(snapDecl.Revision(), Equals, 0) 485 486 // we log the issue 487 c.Check(logbuf.String(), testutil.Contains, `Cannot update assertion snap-declaration (foo-id;`) 488 } 489 490 func (s *assertMgrSuite) TestFetchUnsupportedError(c *C) { 491 // NB: this scenario can only happen if there is a bug 492 // we ask the store to filter what is returned by max supported format! 493 494 restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 111) 495 defer restore() 496 497 s.state.Lock() 498 defer s.state.Unlock() 499 500 var snapDeclFoo1 *asserts.SnapDeclaration 501 (func() { 502 restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 999) 503 defer restore() 504 snapDeclFoo1 = s.snapDecl(c, "foo", map[string]interface{}{ 505 "format": "999", 506 "revision": "1", 507 }) 508 })() 509 c.Check(snapDeclFoo1.Revision(), Equals, 1) 510 511 ref := &asserts.Ref{ 512 Type: asserts.SnapDeclarationType, 513 PrimaryKey: []string{"16", "foo-id"}, 514 } 515 fetching := func(f asserts.Fetcher) error { 516 return f.Fetch(ref) 517 } 518 519 s.fakeStore.(*fakeStore).maxDeclSupportedFormat = 999 520 err := assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, fetching) 521 c.Check(err, ErrorMatches, `(?s).*proposed "snap-declaration" assertion has format 999 but 111 is latest supported.*`) 522 } 523 524 func (s *assertMgrSuite) setModel(model *asserts.Model) { 525 deviceCtx := &snapstatetest.TrivialDeviceContext{ 526 DeviceModel: model, 527 CtxStore: s.fakeStore, 528 } 529 s.AddCleanup(snapstatetest.MockDeviceContext(deviceCtx)) 530 s.state.Set("seeded", true) 531 } 532 533 func (s *assertMgrSuite) setupModelAndStore(c *C) *asserts.Store { 534 // setup a model and store assertion 535 a := assertstest.FakeAssertion(map[string]interface{}{ 536 "type": "model", 537 "authority-id": "my-brand", 538 "series": "16", 539 "brand-id": "my-brand", 540 "model": "my-model", 541 "architecture": "amd64", 542 "store": "my-brand-store", 543 "gadget": "gadget", 544 "kernel": "krnl", 545 }) 546 s.setModel(a.(*asserts.Model)) 547 548 a, err := s.storeSigning.Sign(asserts.StoreType, map[string]interface{}{ 549 "authority-id": s.storeSigning.AuthorityID, 550 "operator-id": s.storeSigning.AuthorityID, 551 "store": "my-brand-store", 552 "timestamp": time.Now().Format(time.RFC3339), 553 }, nil, "") 554 c.Assert(err, IsNil) 555 return a.(*asserts.Store) 556 } 557 558 func (s *assertMgrSuite) TestValidateSnap(c *C) { 559 s.prereqSnapAssertions(c, 10) 560 561 tempdir := c.MkDir() 562 snapPath := filepath.Join(tempdir, "foo.snap") 563 err := ioutil.WriteFile(snapPath, fakeSnap(10), 0644) 564 c.Assert(err, IsNil) 565 566 s.state.Lock() 567 defer s.state.Unlock() 568 569 // have a model and the store assertion available 570 storeAs := s.setupModelAndStore(c) 571 err = s.storeSigning.Add(storeAs) 572 c.Assert(err, IsNil) 573 574 chg := s.state.NewChange("install", "...") 575 t := s.state.NewTask("validate-snap", "Fetch and check snap assertions") 576 snapsup := snapstate.SnapSetup{ 577 SnapPath: snapPath, 578 UserID: 0, 579 SideInfo: &snap.SideInfo{ 580 RealName: "foo", 581 SnapID: "snap-id-1", 582 Revision: snap.R(10), 583 }, 584 } 585 t.Set("snap-setup", snapsup) 586 chg.AddTask(t) 587 588 s.state.Unlock() 589 defer s.se.Stop() 590 s.settle(c) 591 s.state.Lock() 592 593 c.Assert(chg.Err(), IsNil) 594 595 snapRev, err := assertstate.DB(s.state).Find(asserts.SnapRevisionType, map[string]string{ 596 "snap-id": "snap-id-1", 597 "snap-sha3-384": makeDigest(10), 598 }) 599 c.Assert(err, IsNil) 600 c.Check(snapRev.(*asserts.SnapRevision).SnapRevision(), Equals, 10) 601 602 // store assertion was also fetched 603 _, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{ 604 "store": "my-brand-store", 605 }) 606 c.Assert(err, IsNil) 607 } 608 609 func (s *assertMgrSuite) TestValidateSnapStoreNotFound(c *C) { 610 s.prereqSnapAssertions(c, 10) 611 612 tempdir := c.MkDir() 613 snapPath := filepath.Join(tempdir, "foo.snap") 614 err := ioutil.WriteFile(snapPath, fakeSnap(10), 0644) 615 c.Assert(err, IsNil) 616 617 s.state.Lock() 618 defer s.state.Unlock() 619 620 // have a model and store but store assertion is not made available 621 s.setupModelAndStore(c) 622 623 chg := s.state.NewChange("install", "...") 624 t := s.state.NewTask("validate-snap", "Fetch and check snap assertions") 625 snapsup := snapstate.SnapSetup{ 626 SnapPath: snapPath, 627 UserID: 0, 628 SideInfo: &snap.SideInfo{ 629 RealName: "foo", 630 SnapID: "snap-id-1", 631 Revision: snap.R(10), 632 }, 633 } 634 t.Set("snap-setup", snapsup) 635 chg.AddTask(t) 636 637 s.state.Unlock() 638 defer s.se.Stop() 639 s.settle(c) 640 s.state.Lock() 641 642 c.Assert(chg.Err(), IsNil) 643 644 snapRev, err := assertstate.DB(s.state).Find(asserts.SnapRevisionType, map[string]string{ 645 "snap-id": "snap-id-1", 646 "snap-sha3-384": makeDigest(10), 647 }) 648 c.Assert(err, IsNil) 649 c.Check(snapRev.(*asserts.SnapRevision).SnapRevision(), Equals, 10) 650 651 // store assertion was not found and ignored 652 _, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{ 653 "store": "my-brand-store", 654 }) 655 c.Assert(asserts.IsNotFound(err), Equals, true) 656 } 657 658 func (s *assertMgrSuite) TestValidateSnapMissingSnapSetup(c *C) { 659 s.state.Lock() 660 defer s.state.Unlock() 661 662 chg := s.state.NewChange("install", "...") 663 t := s.state.NewTask("validate-snap", "Fetch and check snap assertions") 664 chg.AddTask(t) 665 666 s.state.Unlock() 667 defer s.se.Stop() 668 s.settle(c) 669 s.state.Lock() 670 671 c.Assert(chg.Err(), ErrorMatches, `(?s).*internal error: cannot obtain snap setup: no state entry for key.*`) 672 } 673 674 func (s *assertMgrSuite) TestValidateSnapNotFound(c *C) { 675 tempdir := c.MkDir() 676 snapPath := filepath.Join(tempdir, "foo.snap") 677 err := ioutil.WriteFile(snapPath, fakeSnap(33), 0644) 678 c.Assert(err, IsNil) 679 680 s.state.Lock() 681 defer s.state.Unlock() 682 683 s.setModel(sysdb.GenericClassicModel()) 684 685 chg := s.state.NewChange("install", "...") 686 t := s.state.NewTask("validate-snap", "Fetch and check snap assertions") 687 snapsup := snapstate.SnapSetup{ 688 SnapPath: snapPath, 689 UserID: 0, 690 SideInfo: &snap.SideInfo{ 691 RealName: "foo", 692 SnapID: "snap-id-1", 693 Revision: snap.R(33), 694 }, 695 } 696 t.Set("snap-setup", snapsup) 697 chg.AddTask(t) 698 699 s.state.Unlock() 700 defer s.se.Stop() 701 s.settle(c) 702 s.state.Lock() 703 704 c.Assert(chg.Err(), ErrorMatches, `(?s).*cannot verify snap "foo", no matching signatures found.*`) 705 } 706 707 func (s *assertMgrSuite) TestValidateSnapCrossCheckFail(c *C) { 708 s.prereqSnapAssertions(c, 10) 709 710 tempdir := c.MkDir() 711 snapPath := filepath.Join(tempdir, "foo.snap") 712 err := ioutil.WriteFile(snapPath, fakeSnap(10), 0644) 713 c.Assert(err, IsNil) 714 715 s.state.Lock() 716 defer s.state.Unlock() 717 718 s.setModel(sysdb.GenericClassicModel()) 719 720 chg := s.state.NewChange("install", "...") 721 t := s.state.NewTask("validate-snap", "Fetch and check snap assertions") 722 snapsup := snapstate.SnapSetup{ 723 SnapPath: snapPath, 724 UserID: 0, 725 SideInfo: &snap.SideInfo{ 726 RealName: "f", 727 SnapID: "snap-id-1", 728 Revision: snap.R(10), 729 }, 730 } 731 t.Set("snap-setup", snapsup) 732 chg.AddTask(t) 733 734 s.state.Unlock() 735 defer s.se.Stop() 736 s.settle(c) 737 s.state.Lock() 738 739 c.Assert(chg.Err(), ErrorMatches, `(?s).*cannot install "f", snap "f" is undergoing a rename to "foo".*`) 740 } 741 742 func (s *assertMgrSuite) snapDecl(c *C, name string, extraHeaders map[string]interface{}) *asserts.SnapDeclaration { 743 headers := map[string]interface{}{ 744 "series": "16", 745 "snap-id": name + "-id", 746 "snap-name": name, 747 "publisher-id": s.dev1Acct.AccountID(), 748 "timestamp": time.Now().Format(time.RFC3339), 749 } 750 for h, v := range extraHeaders { 751 headers[h] = v 752 } 753 decl, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") 754 c.Assert(err, IsNil) 755 err = s.storeSigning.Add(decl) 756 c.Assert(err, IsNil) 757 return decl.(*asserts.SnapDeclaration) 758 } 759 760 func (s *assertMgrSuite) stateFromDecl(c *C, decl *asserts.SnapDeclaration, instanceName string, revno snap.Revision) { 761 snapName, instanceKey := snap.SplitInstanceName(instanceName) 762 if snapName == "" { 763 snapName = decl.SnapName() 764 instanceName = snapName 765 } 766 767 c.Assert(snapName, Equals, decl.SnapName()) 768 769 snapID := decl.SnapID() 770 snapstate.Set(s.state, instanceName, &snapstate.SnapState{ 771 Active: true, 772 Sequence: []*snap.SideInfo{ 773 {RealName: snapName, SnapID: snapID, Revision: revno}, 774 }, 775 Current: revno, 776 InstanceKey: instanceKey, 777 }) 778 } 779 780 func (s *assertMgrSuite) TestRefreshSnapDeclarationsTooEarly(c *C) { 781 s.state.Lock() 782 defer s.state.Unlock() 783 784 r := snapstatetest.MockDeviceModel(nil) 785 defer r() 786 787 err := assertstate.RefreshSnapDeclarations(s.state, 0) 788 c.Check(err, FitsTypeOf, &snapstate.ChangeConflictError{}) 789 } 790 791 func (s *assertMgrSuite) TestRefreshSnapDeclarationsNoStore(c *C) { 792 s.state.Lock() 793 defer s.state.Unlock() 794 795 s.setModel(sysdb.GenericClassicModel()) 796 797 snapDeclFoo := s.snapDecl(c, "foo", nil) 798 snapDeclBar := s.snapDecl(c, "bar", nil) 799 800 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 801 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 802 snapstate.Set(s.state, "local", &snapstate.SnapState{ 803 Active: false, 804 Sequence: []*snap.SideInfo{ 805 {RealName: "local", Revision: snap.R(-1)}, 806 }, 807 Current: snap.R(-1), 808 }) 809 810 // previous state 811 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 812 c.Assert(err, IsNil) 813 err = assertstate.Add(s.state, s.dev1Acct) 814 c.Assert(err, IsNil) 815 err = assertstate.Add(s.state, snapDeclFoo) 816 c.Assert(err, IsNil) 817 err = assertstate.Add(s.state, snapDeclBar) 818 c.Assert(err, IsNil) 819 820 // one changed assertion 821 headers := map[string]interface{}{ 822 "series": "16", 823 "snap-id": "foo-id", 824 "snap-name": "fo-o", 825 "publisher-id": s.dev1Acct.AccountID(), 826 "timestamp": time.Now().Format(time.RFC3339), 827 "revision": "1", 828 } 829 snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") 830 c.Assert(err, IsNil) 831 err = s.storeSigning.Add(snapDeclFoo1) 832 c.Assert(err, IsNil) 833 834 err = assertstate.RefreshSnapDeclarations(s.state, 0) 835 c.Assert(err, IsNil) 836 837 a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{ 838 "series": "16", 839 "snap-id": "foo-id", 840 }) 841 c.Assert(err, IsNil) 842 c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o") 843 844 // another one 845 // one changed assertion 846 headers = s.dev1Acct.Headers() 847 headers["display-name"] = "Dev 1 edited display-name" 848 headers["revision"] = "1" 849 dev1Acct1, err := s.storeSigning.Sign(asserts.AccountType, headers, nil, "") 850 c.Assert(err, IsNil) 851 err = s.storeSigning.Add(dev1Acct1) 852 c.Assert(err, IsNil) 853 854 err = assertstate.RefreshSnapDeclarations(s.state, 0) 855 c.Assert(err, IsNil) 856 857 a, err = assertstate.DB(s.state).Find(asserts.AccountType, map[string]string{ 858 "account-id": s.dev1Acct.AccountID(), 859 }) 860 c.Assert(err, IsNil) 861 c.Check(a.(*asserts.Account).DisplayName(), Equals, "Dev 1 edited display-name") 862 863 // change snap decl to something that has a too new format 864 865 (func() { 866 restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 999) 867 defer restore() 868 869 headers := map[string]interface{}{ 870 "format": "999", 871 "series": "16", 872 "snap-id": "foo-id", 873 "snap-name": "foo", 874 "publisher-id": s.dev1Acct.AccountID(), 875 "timestamp": time.Now().Format(time.RFC3339), 876 "revision": "2", 877 } 878 879 snapDeclFoo2, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") 880 c.Assert(err, IsNil) 881 err = s.storeSigning.Add(snapDeclFoo2) 882 c.Assert(err, IsNil) 883 })() 884 885 // no error, kept the old one 886 err = assertstate.RefreshSnapDeclarations(s.state, 0) 887 c.Assert(err, IsNil) 888 889 a, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{ 890 "series": "16", 891 "snap-id": "foo-id", 892 }) 893 c.Assert(err, IsNil) 894 c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o") 895 c.Check(a.(*asserts.SnapDeclaration).Revision(), Equals, 1) 896 } 897 898 func (s *assertMgrSuite) TestRefreshSnapDeclarationsWithStore(c *C) { 899 s.state.Lock() 900 defer s.state.Unlock() 901 902 storeAs := s.setupModelAndStore(c) 903 904 snapDeclFoo := s.snapDecl(c, "foo", nil) 905 906 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 907 908 // previous state 909 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 910 c.Assert(err, IsNil) 911 err = assertstate.Add(s.state, s.dev1Acct) 912 c.Assert(err, IsNil) 913 err = assertstate.Add(s.state, snapDeclFoo) 914 c.Assert(err, IsNil) 915 916 // one changed assertion 917 headers := map[string]interface{}{ 918 "series": "16", 919 "snap-id": "foo-id", 920 "snap-name": "fo-o", 921 "publisher-id": s.dev1Acct.AccountID(), 922 "timestamp": time.Now().Format(time.RFC3339), 923 "revision": "1", 924 } 925 snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") 926 c.Assert(err, IsNil) 927 err = s.storeSigning.Add(snapDeclFoo1) 928 c.Assert(err, IsNil) 929 930 // store assertion is missing 931 err = assertstate.RefreshSnapDeclarations(s.state, 0) 932 c.Assert(err, IsNil) 933 934 a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{ 935 "series": "16", 936 "snap-id": "foo-id", 937 }) 938 c.Assert(err, IsNil) 939 c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o") 940 941 // changed again 942 headers = map[string]interface{}{ 943 "series": "16", 944 "snap-id": "foo-id", 945 "snap-name": "f-oo", 946 "publisher-id": s.dev1Acct.AccountID(), 947 "timestamp": time.Now().Format(time.RFC3339), 948 "revision": "2", 949 } 950 snapDeclFoo2, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "") 951 c.Assert(err, IsNil) 952 err = s.storeSigning.Add(snapDeclFoo2) 953 c.Assert(err, IsNil) 954 955 // store assertion is available 956 err = s.storeSigning.Add(storeAs) 957 c.Assert(err, IsNil) 958 959 err = assertstate.RefreshSnapDeclarations(s.state, 0) 960 c.Assert(err, IsNil) 961 962 a, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{ 963 "series": "16", 964 "snap-id": "foo-id", 965 }) 966 c.Assert(err, IsNil) 967 c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "f-oo") 968 969 _, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{ 970 "store": "my-brand-store", 971 }) 972 c.Assert(err, IsNil) 973 974 // store assertion has changed 975 a, err = s.storeSigning.Sign(asserts.StoreType, map[string]interface{}{ 976 "authority-id": s.storeSigning.AuthorityID, 977 "operator-id": s.storeSigning.AuthorityID, 978 "store": "my-brand-store", 979 "location": "the-cloud", 980 "revision": "1", 981 "timestamp": time.Now().Format(time.RFC3339), 982 }, nil, "") 983 c.Assert(err, IsNil) 984 storeAs = a.(*asserts.Store) 985 err = s.storeSigning.Add(storeAs) 986 c.Assert(err, IsNil) 987 988 err = assertstate.RefreshSnapDeclarations(s.state, 0) 989 c.Assert(err, IsNil) 990 a, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{ 991 "store": "my-brand-store", 992 }) 993 c.Assert(err, IsNil) 994 c.Check(a.(*asserts.Store).Location(), Equals, "the-cloud") 995 } 996 997 func (s *assertMgrSuite) TestValidateRefreshesNothing(c *C) { 998 s.state.Lock() 999 defer s.state.Unlock() 1000 1001 validated, err := assertstate.ValidateRefreshes(s.state, nil, nil, 0, s.trivialDeviceCtx) 1002 c.Assert(err, IsNil) 1003 c.Check(validated, HasLen, 0) 1004 } 1005 1006 func (s *assertMgrSuite) TestValidateRefreshesNoControl(c *C) { 1007 s.state.Lock() 1008 defer s.state.Unlock() 1009 1010 snapDeclFoo := s.snapDecl(c, "foo", nil) 1011 snapDeclBar := s.snapDecl(c, "bar", nil) 1012 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 1013 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1014 1015 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1016 c.Assert(err, IsNil) 1017 err = assertstate.Add(s.state, s.dev1Acct) 1018 c.Assert(err, IsNil) 1019 err = assertstate.Add(s.state, snapDeclFoo) 1020 c.Assert(err, IsNil) 1021 err = assertstate.Add(s.state, snapDeclBar) 1022 c.Assert(err, IsNil) 1023 1024 fooRefresh := &snap.Info{ 1025 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1026 } 1027 1028 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx) 1029 c.Assert(err, IsNil) 1030 c.Check(validated, DeepEquals, []*snap.Info{fooRefresh}) 1031 } 1032 1033 func (s *assertMgrSuite) TestValidateRefreshesMissingValidation(c *C) { 1034 s.state.Lock() 1035 defer s.state.Unlock() 1036 1037 snapDeclFoo := s.snapDecl(c, "foo", nil) 1038 snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{ 1039 "refresh-control": []interface{}{"foo-id"}, 1040 }) 1041 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 1042 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1043 1044 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1045 c.Assert(err, IsNil) 1046 err = assertstate.Add(s.state, s.dev1Acct) 1047 c.Assert(err, IsNil) 1048 err = assertstate.Add(s.state, snapDeclFoo) 1049 c.Assert(err, IsNil) 1050 err = assertstate.Add(s.state, snapDeclBar) 1051 c.Assert(err, IsNil) 1052 1053 fooRefresh := &snap.Info{ 1054 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1055 } 1056 1057 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx) 1058 c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`) 1059 c.Check(validated, HasLen, 0) 1060 } 1061 1062 func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidation(c *C) { 1063 s.state.Lock() 1064 defer s.state.Unlock() 1065 1066 snapDeclFoo := s.snapDecl(c, "foo", nil) 1067 snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{ 1068 "refresh-control": []interface{}{"foo-id"}, 1069 }) 1070 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 1071 s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7)) 1072 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1073 1074 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1075 c.Assert(err, IsNil) 1076 err = assertstate.Add(s.state, s.dev1Acct) 1077 c.Assert(err, IsNil) 1078 err = assertstate.Add(s.state, snapDeclFoo) 1079 c.Assert(err, IsNil) 1080 err = assertstate.Add(s.state, snapDeclBar) 1081 c.Assert(err, IsNil) 1082 1083 fooInstanceRefresh := &snap.Info{ 1084 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1085 InstanceKey: "instance", 1086 } 1087 1088 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooInstanceRefresh}, nil, 0, s.trivialDeviceCtx) 1089 c.Assert(err, ErrorMatches, `cannot refresh "foo_instance" to revision 9: no validation by "bar"`) 1090 c.Check(validated, HasLen, 0) 1091 } 1092 1093 func (s *assertMgrSuite) TestValidateRefreshesMissingValidationButIgnore(c *C) { 1094 s.state.Lock() 1095 defer s.state.Unlock() 1096 1097 snapDeclFoo := s.snapDecl(c, "foo", nil) 1098 snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{ 1099 "refresh-control": []interface{}{"foo-id"}, 1100 }) 1101 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 1102 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1103 1104 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1105 c.Assert(err, IsNil) 1106 err = assertstate.Add(s.state, s.dev1Acct) 1107 c.Assert(err, IsNil) 1108 err = assertstate.Add(s.state, snapDeclFoo) 1109 c.Assert(err, IsNil) 1110 err = assertstate.Add(s.state, snapDeclBar) 1111 c.Assert(err, IsNil) 1112 1113 fooRefresh := &snap.Info{ 1114 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1115 } 1116 1117 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, map[string]bool{"foo": true}, 0, s.trivialDeviceCtx) 1118 c.Assert(err, IsNil) 1119 c.Check(validated, DeepEquals, []*snap.Info{fooRefresh}) 1120 } 1121 1122 func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnore(c *C) { 1123 s.state.Lock() 1124 defer s.state.Unlock() 1125 1126 snapDeclFoo := s.snapDecl(c, "foo", nil) 1127 snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{ 1128 "refresh-control": []interface{}{"foo-id"}, 1129 }) 1130 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 1131 s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7)) 1132 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1133 1134 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1135 c.Assert(err, IsNil) 1136 err = assertstate.Add(s.state, s.dev1Acct) 1137 c.Assert(err, IsNil) 1138 err = assertstate.Add(s.state, snapDeclFoo) 1139 c.Assert(err, IsNil) 1140 err = assertstate.Add(s.state, snapDeclBar) 1141 c.Assert(err, IsNil) 1142 1143 fooRefresh := &snap.Info{ 1144 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1145 } 1146 fooInstanceRefresh := &snap.Info{ 1147 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1148 InstanceKey: "instance", 1149 } 1150 1151 // validation is ignore for foo_instance but not for foo 1152 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx) 1153 c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`) 1154 c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh}) 1155 } 1156 1157 func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnoreInstanceKeyed(c *C) { 1158 s.state.Lock() 1159 defer s.state.Unlock() 1160 1161 snapDeclFoo := s.snapDecl(c, "foo", nil) 1162 snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{ 1163 "refresh-control": []interface{}{"foo-id"}, 1164 }) 1165 s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7)) 1166 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1167 1168 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1169 c.Assert(err, IsNil) 1170 err = assertstate.Add(s.state, s.dev1Acct) 1171 c.Assert(err, IsNil) 1172 err = assertstate.Add(s.state, snapDeclFoo) 1173 c.Assert(err, IsNil) 1174 err = assertstate.Add(s.state, snapDeclBar) 1175 c.Assert(err, IsNil) 1176 1177 fooInstanceRefresh := &snap.Info{ 1178 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1179 InstanceKey: "instance", 1180 } 1181 1182 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx) 1183 c.Assert(err, IsNil) 1184 c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh}) 1185 } 1186 1187 func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnoreBothOneIgnored(c *C) { 1188 s.state.Lock() 1189 defer s.state.Unlock() 1190 1191 snapDeclFoo := s.snapDecl(c, "foo", nil) 1192 snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{ 1193 "refresh-control": []interface{}{"foo-id"}, 1194 }) 1195 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 1196 s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7)) 1197 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1198 1199 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1200 c.Assert(err, IsNil) 1201 err = assertstate.Add(s.state, s.dev1Acct) 1202 c.Assert(err, IsNil) 1203 err = assertstate.Add(s.state, snapDeclFoo) 1204 c.Assert(err, IsNil) 1205 err = assertstate.Add(s.state, snapDeclBar) 1206 c.Assert(err, IsNil) 1207 1208 fooRefresh := &snap.Info{ 1209 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1210 } 1211 fooInstanceRefresh := &snap.Info{ 1212 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1213 InstanceKey: "instance", 1214 } 1215 1216 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx) 1217 c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`) 1218 c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh}) 1219 } 1220 1221 func (s *assertMgrSuite) TestValidateRefreshesValidationOK(c *C) { 1222 s.state.Lock() 1223 defer s.state.Unlock() 1224 1225 snapDeclFoo := s.snapDecl(c, "foo", nil) 1226 snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{ 1227 "refresh-control": []interface{}{"foo-id"}, 1228 }) 1229 snapDeclBaz := s.snapDecl(c, "baz", map[string]interface{}{ 1230 "refresh-control": []interface{}{"foo-id"}, 1231 }) 1232 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 1233 s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7)) 1234 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1235 s.stateFromDecl(c, snapDeclBaz, "", snap.R(1)) 1236 snapstate.Set(s.state, "local", &snapstate.SnapState{ 1237 Active: false, 1238 Sequence: []*snap.SideInfo{ 1239 {RealName: "local", Revision: snap.R(-1)}, 1240 }, 1241 Current: snap.R(-1), 1242 }) 1243 1244 // validation by bar 1245 headers := map[string]interface{}{ 1246 "series": "16", 1247 "snap-id": "bar-id", 1248 "approved-snap-id": "foo-id", 1249 "approved-snap-revision": "9", 1250 "timestamp": time.Now().Format(time.RFC3339), 1251 } 1252 barValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "") 1253 c.Assert(err, IsNil) 1254 err = s.storeSigning.Add(barValidation) 1255 c.Assert(err, IsNil) 1256 1257 // validation by baz 1258 headers = map[string]interface{}{ 1259 "series": "16", 1260 "snap-id": "baz-id", 1261 "approved-snap-id": "foo-id", 1262 "approved-snap-revision": "9", 1263 "timestamp": time.Now().Format(time.RFC3339), 1264 } 1265 bazValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "") 1266 c.Assert(err, IsNil) 1267 err = s.storeSigning.Add(bazValidation) 1268 c.Assert(err, IsNil) 1269 1270 err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1271 c.Assert(err, IsNil) 1272 err = assertstate.Add(s.state, s.dev1Acct) 1273 c.Assert(err, IsNil) 1274 err = assertstate.Add(s.state, snapDeclFoo) 1275 c.Assert(err, IsNil) 1276 err = assertstate.Add(s.state, snapDeclBar) 1277 c.Assert(err, IsNil) 1278 err = assertstate.Add(s.state, snapDeclBaz) 1279 c.Assert(err, IsNil) 1280 1281 fooRefresh := &snap.Info{ 1282 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1283 } 1284 fooInstanceRefresh := &snap.Info{ 1285 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1286 InstanceKey: "instance", 1287 } 1288 1289 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, nil, 0, s.trivialDeviceCtx) 1290 c.Assert(err, IsNil) 1291 c.Check(validated, DeepEquals, []*snap.Info{fooRefresh, fooInstanceRefresh}) 1292 } 1293 1294 func (s *assertMgrSuite) TestValidateRefreshesRevokedValidation(c *C) { 1295 s.state.Lock() 1296 defer s.state.Unlock() 1297 1298 snapDeclFoo := s.snapDecl(c, "foo", nil) 1299 snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{ 1300 "refresh-control": []interface{}{"foo-id"}, 1301 }) 1302 snapDeclBaz := s.snapDecl(c, "baz", map[string]interface{}{ 1303 "refresh-control": []interface{}{"foo-id"}, 1304 }) 1305 s.stateFromDecl(c, snapDeclFoo, "", snap.R(7)) 1306 s.stateFromDecl(c, snapDeclBar, "", snap.R(3)) 1307 s.stateFromDecl(c, snapDeclBaz, "", snap.R(1)) 1308 snapstate.Set(s.state, "local", &snapstate.SnapState{ 1309 Active: false, 1310 Sequence: []*snap.SideInfo{ 1311 {RealName: "local", Revision: snap.R(-1)}, 1312 }, 1313 Current: snap.R(-1), 1314 }) 1315 1316 // validation by bar 1317 headers := map[string]interface{}{ 1318 "series": "16", 1319 "snap-id": "bar-id", 1320 "approved-snap-id": "foo-id", 1321 "approved-snap-revision": "9", 1322 "timestamp": time.Now().Format(time.RFC3339), 1323 } 1324 barValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "") 1325 c.Assert(err, IsNil) 1326 err = s.storeSigning.Add(barValidation) 1327 c.Assert(err, IsNil) 1328 1329 // revoked validation by baz 1330 headers = map[string]interface{}{ 1331 "series": "16", 1332 "snap-id": "baz-id", 1333 "approved-snap-id": "foo-id", 1334 "approved-snap-revision": "9", 1335 "revoked": "true", 1336 "timestamp": time.Now().Format(time.RFC3339), 1337 } 1338 bazValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "") 1339 c.Assert(err, IsNil) 1340 err = s.storeSigning.Add(bazValidation) 1341 c.Assert(err, IsNil) 1342 1343 err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1344 c.Assert(err, IsNil) 1345 err = assertstate.Add(s.state, s.dev1Acct) 1346 c.Assert(err, IsNil) 1347 err = assertstate.Add(s.state, snapDeclFoo) 1348 c.Assert(err, IsNil) 1349 err = assertstate.Add(s.state, snapDeclBar) 1350 c.Assert(err, IsNil) 1351 err = assertstate.Add(s.state, snapDeclBaz) 1352 c.Assert(err, IsNil) 1353 1354 fooRefresh := &snap.Info{ 1355 SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)}, 1356 } 1357 1358 validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx) 1359 c.Assert(err, ErrorMatches, `(?s).*cannot refresh "foo" to revision 9: validation by "baz" \(id "baz-id"\) revoked.*`) 1360 c.Check(validated, HasLen, 0) 1361 } 1362 1363 func (s *assertMgrSuite) TestBaseSnapDeclaration(c *C) { 1364 s.state.Lock() 1365 defer s.state.Unlock() 1366 1367 r1 := assertstest.MockBuiltinBaseDeclaration(nil) 1368 defer r1() 1369 1370 baseDecl, err := assertstate.BaseDeclaration(s.state) 1371 c.Assert(asserts.IsNotFound(err), Equals, true) 1372 c.Check(baseDecl, IsNil) 1373 1374 r2 := assertstest.MockBuiltinBaseDeclaration([]byte(` 1375 type: base-declaration 1376 authority-id: canonical 1377 series: 16 1378 plugs: 1379 iface: true 1380 `)) 1381 defer r2() 1382 1383 baseDecl, err = assertstate.BaseDeclaration(s.state) 1384 c.Assert(err, IsNil) 1385 c.Check(baseDecl, NotNil) 1386 c.Check(baseDecl.PlugRule("iface"), NotNil) 1387 } 1388 1389 func (s *assertMgrSuite) TestSnapDeclaration(c *C) { 1390 s.state.Lock() 1391 defer s.state.Unlock() 1392 1393 // have a declaration in the system db 1394 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1395 c.Assert(err, IsNil) 1396 err = assertstate.Add(s.state, s.dev1Acct) 1397 c.Assert(err, IsNil) 1398 snapDeclFoo := s.snapDecl(c, "foo", nil) 1399 err = assertstate.Add(s.state, snapDeclFoo) 1400 c.Assert(err, IsNil) 1401 1402 _, err = assertstate.SnapDeclaration(s.state, "snap-id-other") 1403 c.Check(asserts.IsNotFound(err), Equals, true) 1404 1405 snapDecl, err := assertstate.SnapDeclaration(s.state, "foo-id") 1406 c.Assert(err, IsNil) 1407 c.Check(snapDecl.SnapName(), Equals, "foo") 1408 } 1409 1410 func (s *assertMgrSuite) TestAutoAliasesTemporaryFallback(c *C) { 1411 s.state.Lock() 1412 defer s.state.Unlock() 1413 1414 // prereqs for developer assertions in the system db 1415 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1416 c.Assert(err, IsNil) 1417 err = assertstate.Add(s.state, s.dev1Acct) 1418 c.Assert(err, IsNil) 1419 1420 // not from the store 1421 aliases, err := assertstate.AutoAliases(s.state, &snap.Info{SuggestedName: "local"}) 1422 c.Assert(err, IsNil) 1423 c.Check(aliases, HasLen, 0) 1424 1425 // missing 1426 _, err = assertstate.AutoAliases(s.state, &snap.Info{ 1427 SideInfo: snap.SideInfo{ 1428 RealName: "baz", 1429 SnapID: "baz-id", 1430 }, 1431 }) 1432 c.Check(err, ErrorMatches, `internal error: cannot find snap-declaration for installed snap "baz": snap-declaration \(baz-id; series:16\) not found`) 1433 1434 info := snaptest.MockInfo(c, ` 1435 name: foo 1436 version: 0 1437 apps: 1438 cmd1: 1439 aliases: [alias1] 1440 cmd2: 1441 aliases: [alias2] 1442 `, &snap.SideInfo{ 1443 RealName: "foo", 1444 SnapID: "foo-id", 1445 }) 1446 1447 // empty list 1448 // have a declaration in the system db 1449 snapDeclFoo := s.snapDecl(c, "foo", nil) 1450 err = assertstate.Add(s.state, snapDeclFoo) 1451 c.Assert(err, IsNil) 1452 aliases, err = assertstate.AutoAliases(s.state, info) 1453 c.Assert(err, IsNil) 1454 c.Check(aliases, HasLen, 0) 1455 1456 // some aliases 1457 snapDeclFoo = s.snapDecl(c, "foo", map[string]interface{}{ 1458 "auto-aliases": []interface{}{"alias1", "alias2", "alias3"}, 1459 "revision": "1", 1460 }) 1461 err = assertstate.Add(s.state, snapDeclFoo) 1462 c.Assert(err, IsNil) 1463 aliases, err = assertstate.AutoAliases(s.state, info) 1464 c.Assert(err, IsNil) 1465 c.Check(aliases, DeepEquals, map[string]string{ 1466 "alias1": "cmd1", 1467 "alias2": "cmd2", 1468 }) 1469 } 1470 1471 func (s *assertMgrSuite) TestAutoAliasesExplicit(c *C) { 1472 s.state.Lock() 1473 defer s.state.Unlock() 1474 1475 // prereqs for developer assertions in the system db 1476 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1477 c.Assert(err, IsNil) 1478 err = assertstate.Add(s.state, s.dev1Acct) 1479 c.Assert(err, IsNil) 1480 1481 // not from the store 1482 aliases, err := assertstate.AutoAliases(s.state, &snap.Info{SuggestedName: "local"}) 1483 c.Assert(err, IsNil) 1484 c.Check(aliases, HasLen, 0) 1485 1486 // missing 1487 _, err = assertstate.AutoAliases(s.state, &snap.Info{ 1488 SideInfo: snap.SideInfo{ 1489 RealName: "baz", 1490 SnapID: "baz-id", 1491 }, 1492 }) 1493 c.Check(err, ErrorMatches, `internal error: cannot find snap-declaration for installed snap "baz": snap-declaration \(baz-id; series:16\) not found`) 1494 1495 // empty list 1496 // have a declaration in the system db 1497 snapDeclFoo := s.snapDecl(c, "foo", nil) 1498 err = assertstate.Add(s.state, snapDeclFoo) 1499 c.Assert(err, IsNil) 1500 aliases, err = assertstate.AutoAliases(s.state, &snap.Info{ 1501 SideInfo: snap.SideInfo{ 1502 RealName: "foo", 1503 SnapID: "foo-id", 1504 }, 1505 }) 1506 c.Assert(err, IsNil) 1507 c.Check(aliases, HasLen, 0) 1508 1509 // some aliases 1510 snapDeclFoo = s.snapDecl(c, "foo", map[string]interface{}{ 1511 "aliases": []interface{}{ 1512 map[string]interface{}{ 1513 "name": "alias1", 1514 "target": "cmd1", 1515 }, 1516 map[string]interface{}{ 1517 "name": "alias2", 1518 "target": "cmd2", 1519 }, 1520 }, 1521 "revision": "1", 1522 }) 1523 err = assertstate.Add(s.state, snapDeclFoo) 1524 c.Assert(err, IsNil) 1525 aliases, err = assertstate.AutoAliases(s.state, &snap.Info{ 1526 SideInfo: snap.SideInfo{ 1527 RealName: "foo", 1528 SnapID: "foo-id", 1529 }, 1530 }) 1531 c.Assert(err, IsNil) 1532 c.Check(aliases, DeepEquals, map[string]string{ 1533 "alias1": "cmd1", 1534 "alias2": "cmd2", 1535 }) 1536 } 1537 1538 func (s *assertMgrSuite) TestPublisher(c *C) { 1539 s.state.Lock() 1540 defer s.state.Unlock() 1541 1542 // have a declaration in the system db 1543 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1544 c.Assert(err, IsNil) 1545 err = assertstate.Add(s.state, s.dev1Acct) 1546 c.Assert(err, IsNil) 1547 snapDeclFoo := s.snapDecl(c, "foo", nil) 1548 err = assertstate.Add(s.state, snapDeclFoo) 1549 c.Assert(err, IsNil) 1550 1551 _, err = assertstate.SnapDeclaration(s.state, "snap-id-other") 1552 c.Check(asserts.IsNotFound(err), Equals, true) 1553 1554 acct, err := assertstate.Publisher(s.state, "foo-id") 1555 c.Assert(err, IsNil) 1556 c.Check(acct.AccountID(), Equals, s.dev1Acct.AccountID()) 1557 c.Check(acct.Username(), Equals, "developer1") 1558 } 1559 1560 func (s *assertMgrSuite) TestStore(c *C) { 1561 s.state.Lock() 1562 defer s.state.Unlock() 1563 1564 err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")) 1565 c.Assert(err, IsNil) 1566 err = assertstate.Add(s.state, s.dev1Acct) 1567 c.Assert(err, IsNil) 1568 storeHeaders := map[string]interface{}{ 1569 "store": "foo", 1570 "operator-id": s.dev1Acct.AccountID(), 1571 "timestamp": time.Now().Format(time.RFC3339), 1572 } 1573 fooStore, err := s.storeSigning.Sign(asserts.StoreType, storeHeaders, nil, "") 1574 c.Assert(err, IsNil) 1575 err = assertstate.Add(s.state, fooStore) 1576 c.Assert(err, IsNil) 1577 1578 _, err = assertstate.Store(s.state, "bar") 1579 c.Check(asserts.IsNotFound(err), Equals, true) 1580 1581 store, err := assertstate.Store(s.state, "foo") 1582 c.Assert(err, IsNil) 1583 c.Check(store.Store(), Equals, "foo") 1584 }