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  }