github.com/tompreston/snapd@v0.0.0-20210817193607-954edfcb9611/overlord/assertstate/assertstate_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016-2021 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  	"context"
    25  	"crypto"
    26  	"errors"
    27  	"fmt"
    28  	"io/ioutil"
    29  	"path/filepath"
    30  	"sort"
    31  	"strings"
    32  	"testing"
    33  	"time"
    34  
    35  	"golang.org/x/crypto/sha3"
    36  	. "gopkg.in/check.v1"
    37  
    38  	"github.com/snapcore/snapd/asserts"
    39  	"github.com/snapcore/snapd/asserts/assertstest"
    40  	"github.com/snapcore/snapd/asserts/snapasserts"
    41  	"github.com/snapcore/snapd/asserts/sysdb"
    42  	"github.com/snapcore/snapd/dirs"
    43  	"github.com/snapcore/snapd/httputil"
    44  	"github.com/snapcore/snapd/logger"
    45  	"github.com/snapcore/snapd/overlord"
    46  	"github.com/snapcore/snapd/overlord/assertstate"
    47  	"github.com/snapcore/snapd/overlord/auth"
    48  	"github.com/snapcore/snapd/overlord/snapstate"
    49  	"github.com/snapcore/snapd/overlord/snapstate/snapstatetest"
    50  	"github.com/snapcore/snapd/overlord/state"
    51  	"github.com/snapcore/snapd/snap"
    52  	"github.com/snapcore/snapd/snap/snaptest"
    53  	"github.com/snapcore/snapd/store"
    54  	"github.com/snapcore/snapd/store/storetest"
    55  	"github.com/snapcore/snapd/testutil"
    56  )
    57  
    58  func TestAssertManager(t *testing.T) { TestingT(t) }
    59  
    60  type assertMgrSuite struct {
    61  	testutil.BaseTest
    62  
    63  	o     *overlord.Overlord
    64  	state *state.State
    65  	se    *overlord.StateEngine
    66  	mgr   *assertstate.AssertManager
    67  
    68  	storeSigning *assertstest.StoreStack
    69  	dev1Acct     *asserts.Account
    70  	dev1AcctKey  *asserts.AccountKey
    71  	dev1Signing  *assertstest.SigningDB
    72  
    73  	fakeStore        snapstate.StoreService
    74  	trivialDeviceCtx snapstate.DeviceContext
    75  }
    76  
    77  var _ = Suite(&assertMgrSuite{})
    78  
    79  type fakeStore struct {
    80  	storetest.Store
    81  	state                           *state.State
    82  	db                              asserts.RODatabase
    83  	maxDeclSupportedFormat          int
    84  	maxValidationSetSupportedFormat int
    85  
    86  	requestedTypes [][]string
    87  
    88  	snapActionErr         error
    89  	downloadAssertionsErr error
    90  }
    91  
    92  func (sto *fakeStore) pokeStateLock() {
    93  	// the store should be called without the state lock held. Try
    94  	// to acquire it.
    95  	sto.state.Lock()
    96  	sto.state.Unlock()
    97  }
    98  
    99  func (sto *fakeStore) Assertion(assertType *asserts.AssertionType, key []string, _ *auth.UserState) (asserts.Assertion, error) {
   100  	sto.pokeStateLock()
   101  
   102  	restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, sto.maxDeclSupportedFormat)
   103  	defer restore()
   104  
   105  	ref := &asserts.Ref{Type: assertType, PrimaryKey: key}
   106  	return ref.Resolve(sto.db.Find)
   107  }
   108  
   109  func (sto *fakeStore) SnapAction(_ context.Context, currentSnaps []*store.CurrentSnap, actions []*store.SnapAction, assertQuery store.AssertionQuery, user *auth.UserState, opts *store.RefreshOptions) ([]store.SnapActionResult, []store.AssertionResult, error) {
   110  	sto.pokeStateLock()
   111  
   112  	if len(currentSnaps) != 0 || len(actions) != 0 {
   113  		panic("only assertion query supported")
   114  	}
   115  
   116  	toResolve, toResolveSeq, err := assertQuery.ToResolve()
   117  	if err != nil {
   118  		return nil, nil, err
   119  	}
   120  
   121  	if sto.snapActionErr != nil {
   122  		return nil, nil, sto.snapActionErr
   123  	}
   124  
   125  	restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, sto.maxDeclSupportedFormat)
   126  	defer restore()
   127  
   128  	restoreSeq := asserts.MockMaxSupportedFormat(asserts.ValidationSetType, sto.maxValidationSetSupportedFormat)
   129  	defer restoreSeq()
   130  
   131  	reqTypes := make(map[string]bool)
   132  	ares := make([]store.AssertionResult, 0, len(toResolve)+len(toResolveSeq))
   133  	for g, ats := range toResolve {
   134  		urls := make([]string, 0, len(ats))
   135  		for _, at := range ats {
   136  			reqTypes[at.Ref.Type.Name] = true
   137  			a, err := at.Ref.Resolve(sto.db.Find)
   138  			if err != nil {
   139  				assertQuery.AddError(err, &at.Ref)
   140  				continue
   141  			}
   142  			if a.Revision() > at.Revision {
   143  				urls = append(urls, fmt.Sprintf("/assertions/%s", at.Unique()))
   144  			}
   145  		}
   146  		ares = append(ares, store.AssertionResult{
   147  			Grouping:   asserts.Grouping(g),
   148  			StreamURLs: urls,
   149  		})
   150  	}
   151  
   152  	for g, ats := range toResolveSeq {
   153  		urls := make([]string, 0, len(ats))
   154  		for _, at := range ats {
   155  			reqTypes[at.Type.Name] = true
   156  			var a asserts.Assertion
   157  			headers, err := asserts.HeadersFromSequenceKey(at.Type, at.SequenceKey)
   158  			if err != nil {
   159  				return nil, nil, err
   160  			}
   161  			if !at.Pinned {
   162  				a, err = sto.db.FindSequence(at.Type, headers, -1, asserts.ValidationSetType.MaxSupportedFormat())
   163  			} else {
   164  				a, err = at.Resolve(sto.db.Find)
   165  			}
   166  			if err != nil {
   167  				assertQuery.AddSequenceError(err, at)
   168  				continue
   169  			}
   170  			storeVs := a.(*asserts.ValidationSet)
   171  			if storeVs.Sequence() > at.Sequence || (storeVs.Sequence() == at.Sequence && storeVs.Revision() >= at.Revision) {
   172  				urls = append(urls, fmt.Sprintf("/assertions/%s/%s", a.Type().Name, strings.Join(a.At().PrimaryKey, "/")))
   173  			}
   174  		}
   175  		ares = append(ares, store.AssertionResult{
   176  			Grouping:   asserts.Grouping(g),
   177  			StreamURLs: urls,
   178  		})
   179  	}
   180  
   181  	// behave like the actual SnapAction if there are no results
   182  	if len(ares) == 0 {
   183  		return nil, ares, &store.SnapActionError{
   184  			NoResults: true,
   185  		}
   186  	}
   187  
   188  	typeNames := make([]string, 0, len(reqTypes))
   189  	for k := range reqTypes {
   190  		typeNames = append(typeNames, k)
   191  	}
   192  	sort.Strings(typeNames)
   193  	sto.requestedTypes = append(sto.requestedTypes, typeNames)
   194  
   195  	return nil, ares, nil
   196  }
   197  
   198  func (sto *fakeStore) DownloadAssertions(urls []string, b *asserts.Batch, user *auth.UserState) error {
   199  	sto.pokeStateLock()
   200  
   201  	if sto.downloadAssertionsErr != nil {
   202  		return sto.downloadAssertionsErr
   203  	}
   204  
   205  	resolve := func(ref *asserts.Ref) (asserts.Assertion, error) {
   206  		restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, sto.maxDeclSupportedFormat)
   207  		defer restore()
   208  
   209  		restoreSeq := asserts.MockMaxSupportedFormat(asserts.ValidationSetType, sto.maxValidationSetSupportedFormat)
   210  		defer restoreSeq()
   211  		return ref.Resolve(sto.db.Find)
   212  	}
   213  
   214  	for _, u := range urls {
   215  		comps := strings.Split(u, "/")
   216  
   217  		if len(comps) < 4 {
   218  			return fmt.Errorf("cannot use URL: %s", u)
   219  		}
   220  
   221  		assertType := asserts.Type(comps[2])
   222  		key := comps[3:]
   223  		ref := &asserts.Ref{Type: assertType, PrimaryKey: key}
   224  		a, err := resolve(ref)
   225  		if err != nil {
   226  			return err
   227  		}
   228  		if err := b.Add(a); err != nil {
   229  			return err
   230  		}
   231  	}
   232  
   233  	return nil
   234  }
   235  
   236  var (
   237  	dev1PrivKey, _ = assertstest.GenerateKey(752)
   238  )
   239  
   240  func (s *assertMgrSuite) SetUpTest(c *C) {
   241  	dirs.SetRootDir(c.MkDir())
   242  
   243  	s.storeSigning = assertstest.NewStoreStack("can0nical", nil)
   244  	s.AddCleanup(sysdb.InjectTrusted(s.storeSigning.Trusted))
   245  
   246  	s.dev1Acct = assertstest.NewAccount(s.storeSigning, "developer1", nil, "")
   247  	err := s.storeSigning.Add(s.dev1Acct)
   248  	c.Assert(err, IsNil)
   249  
   250  	// developer signing
   251  	s.dev1AcctKey = assertstest.NewAccountKey(s.storeSigning, s.dev1Acct, nil, dev1PrivKey.PublicKey(), "")
   252  	err = s.storeSigning.Add(s.dev1AcctKey)
   253  	c.Assert(err, IsNil)
   254  
   255  	s.dev1Signing = assertstest.NewSigningDB(s.dev1Acct.AccountID(), dev1PrivKey)
   256  
   257  	s.o = overlord.Mock()
   258  	s.state = s.o.State()
   259  	s.se = s.o.StateEngine()
   260  	mgr, err := assertstate.Manager(s.state, s.o.TaskRunner())
   261  	c.Assert(err, IsNil)
   262  	s.mgr = mgr
   263  	s.o.AddManager(s.mgr)
   264  
   265  	s.o.AddManager(s.o.TaskRunner())
   266  
   267  	s.fakeStore = &fakeStore{
   268  		state: s.state,
   269  		db:    s.storeSigning,
   270  		// leave this comment to keep old gofmt happy
   271  		maxDeclSupportedFormat:          asserts.SnapDeclarationType.MaxSupportedFormat(),
   272  		maxValidationSetSupportedFormat: asserts.ValidationSetType.MaxSupportedFormat(),
   273  	}
   274  	s.trivialDeviceCtx = &snapstatetest.TrivialDeviceContext{
   275  		CtxStore: s.fakeStore,
   276  	}
   277  }
   278  
   279  func (s *assertMgrSuite) TestDB(c *C) {
   280  	s.state.Lock()
   281  	defer s.state.Unlock()
   282  
   283  	db := assertstate.DB(s.state)
   284  	c.Check(db, FitsTypeOf, (*asserts.Database)(nil))
   285  }
   286  
   287  func (s *assertMgrSuite) TestAdd(c *C) {
   288  	s.state.Lock()
   289  	defer s.state.Unlock()
   290  
   291  	// prereq store key
   292  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
   293  	c.Assert(err, IsNil)
   294  
   295  	err = assertstate.Add(s.state, s.dev1Acct)
   296  	c.Assert(err, IsNil)
   297  
   298  	db := assertstate.DB(s.state)
   299  	devAcct, err := db.Find(asserts.AccountType, map[string]string{
   300  		"account-id": s.dev1Acct.AccountID(),
   301  	})
   302  	c.Assert(err, IsNil)
   303  	c.Check(devAcct.(*asserts.Account).Username(), Equals, "developer1")
   304  }
   305  
   306  func (s *assertMgrSuite) TestAddBatch(c *C) {
   307  	s.state.Lock()
   308  	defer s.state.Unlock()
   309  
   310  	b := &bytes.Buffer{}
   311  	enc := asserts.NewEncoder(b)
   312  	// wrong order is ok
   313  	err := enc.Encode(s.dev1Acct)
   314  	c.Assert(err, IsNil)
   315  	enc.Encode(s.storeSigning.StoreAccountKey(""))
   316  	c.Assert(err, IsNil)
   317  
   318  	batch := asserts.NewBatch(nil)
   319  	refs, err := batch.AddStream(b)
   320  	c.Assert(err, IsNil)
   321  	c.Check(refs, DeepEquals, []*asserts.Ref{
   322  		{Type: asserts.AccountType, PrimaryKey: []string{s.dev1Acct.AccountID()}},
   323  		{Type: asserts.AccountKeyType, PrimaryKey: []string{s.storeSigning.StoreAccountKey("").PublicKeyID()}},
   324  	})
   325  
   326  	// noop
   327  	err = batch.Add(s.storeSigning.StoreAccountKey(""))
   328  	c.Assert(err, IsNil)
   329  
   330  	err = assertstate.AddBatch(s.state, batch, nil)
   331  	c.Assert(err, IsNil)
   332  
   333  	db := assertstate.DB(s.state)
   334  	devAcct, err := db.Find(asserts.AccountType, map[string]string{
   335  		"account-id": s.dev1Acct.AccountID(),
   336  	})
   337  	c.Assert(err, IsNil)
   338  	c.Check(devAcct.(*asserts.Account).Username(), Equals, "developer1")
   339  }
   340  
   341  func (s *assertMgrSuite) TestAddBatchPartial(c *C) {
   342  	// Commit does add any successful assertion until the first error
   343  	s.state.Lock()
   344  	defer s.state.Unlock()
   345  
   346  	// store key already present
   347  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
   348  	c.Assert(err, IsNil)
   349  
   350  	batch := asserts.NewBatch(nil)
   351  
   352  	snapDeclFoo := s.snapDecl(c, "foo", nil)
   353  
   354  	err = batch.Add(snapDeclFoo)
   355  	c.Assert(err, IsNil)
   356  	err = batch.Add(s.dev1Acct)
   357  	c.Assert(err, IsNil)
   358  
   359  	// too old
   360  	rev := 1
   361  	headers := map[string]interface{}{
   362  		"snap-id":       "foo-id",
   363  		"snap-sha3-384": makeDigest(rev),
   364  		"snap-size":     fmt.Sprintf("%d", len(fakeSnap(rev))),
   365  		"snap-revision": fmt.Sprintf("%d", rev),
   366  		"developer-id":  s.dev1Acct.AccountID(),
   367  		"timestamp":     time.Time{}.Format(time.RFC3339),
   368  	}
   369  	snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "")
   370  	c.Assert(err, IsNil)
   371  
   372  	err = batch.Add(snapRev)
   373  	c.Assert(err, IsNil)
   374  
   375  	err = assertstate.AddBatch(s.state, batch, nil)
   376  	c.Check(err, ErrorMatches, `(?ms).*validity.*`)
   377  
   378  	// snap-declaration was added anyway
   379  	_, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
   380  		"series":  "16",
   381  		"snap-id": "foo-id",
   382  	})
   383  	c.Assert(err, IsNil)
   384  }
   385  
   386  func (s *assertMgrSuite) TestAddBatchPrecheckPartial(c *C) {
   387  	s.state.Lock()
   388  	defer s.state.Unlock()
   389  
   390  	// store key already present
   391  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
   392  	c.Assert(err, IsNil)
   393  
   394  	batch := asserts.NewBatch(nil)
   395  
   396  	snapDeclFoo := s.snapDecl(c, "foo", nil)
   397  
   398  	err = batch.Add(snapDeclFoo)
   399  	c.Assert(err, IsNil)
   400  	err = batch.Add(s.dev1Acct)
   401  	c.Assert(err, IsNil)
   402  
   403  	// too old
   404  	rev := 1
   405  	headers := map[string]interface{}{
   406  		"snap-id":       "foo-id",
   407  		"snap-sha3-384": makeDigest(rev),
   408  		"snap-size":     fmt.Sprintf("%d", len(fakeSnap(rev))),
   409  		"snap-revision": fmt.Sprintf("%d", rev),
   410  		"developer-id":  s.dev1Acct.AccountID(),
   411  		"timestamp":     time.Time{}.Format(time.RFC3339),
   412  	}
   413  	snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "")
   414  	c.Assert(err, IsNil)
   415  
   416  	err = batch.Add(snapRev)
   417  	c.Assert(err, IsNil)
   418  
   419  	err = assertstate.AddBatch(s.state, batch, &asserts.CommitOptions{
   420  		Precheck: true,
   421  	})
   422  	c.Check(err, ErrorMatches, `(?ms).*validity.*`)
   423  
   424  	// nothing was added
   425  	_, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
   426  		"series":  "16",
   427  		"snap-id": "foo-id",
   428  	})
   429  	c.Assert(asserts.IsNotFound(err), Equals, true)
   430  }
   431  
   432  func (s *assertMgrSuite) TestAddBatchPrecheckHappy(c *C) {
   433  	s.state.Lock()
   434  	defer s.state.Unlock()
   435  
   436  	// store key already present
   437  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
   438  	c.Assert(err, IsNil)
   439  
   440  	batch := asserts.NewBatch(nil)
   441  
   442  	snapDeclFoo := s.snapDecl(c, "foo", nil)
   443  
   444  	err = batch.Add(snapDeclFoo)
   445  	c.Assert(err, IsNil)
   446  	err = batch.Add(s.dev1Acct)
   447  	c.Assert(err, IsNil)
   448  
   449  	rev := 1
   450  	revDigest := makeDigest(rev)
   451  	headers := map[string]interface{}{
   452  		"snap-id":       "foo-id",
   453  		"snap-sha3-384": revDigest,
   454  		"snap-size":     fmt.Sprintf("%d", len(fakeSnap(rev))),
   455  		"snap-revision": fmt.Sprintf("%d", rev),
   456  		"developer-id":  s.dev1Acct.AccountID(),
   457  		"timestamp":     time.Now().Format(time.RFC3339),
   458  	}
   459  	snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "")
   460  	c.Assert(err, IsNil)
   461  
   462  	err = batch.Add(snapRev)
   463  	c.Assert(err, IsNil)
   464  
   465  	err = assertstate.AddBatch(s.state, batch, &asserts.CommitOptions{
   466  		Precheck: true,
   467  	})
   468  	c.Assert(err, IsNil)
   469  
   470  	_, err = assertstate.DB(s.state).Find(asserts.SnapRevisionType, map[string]string{
   471  		"snap-sha3-384": revDigest,
   472  	})
   473  	c.Check(err, IsNil)
   474  }
   475  
   476  func fakeSnap(rev int) []byte {
   477  	fake := fmt.Sprintf("hsqs________________%d", rev)
   478  	return []byte(fake)
   479  }
   480  
   481  func fakeHash(rev int) []byte {
   482  	h := sha3.Sum384(fakeSnap(rev))
   483  	return h[:]
   484  }
   485  
   486  func makeDigest(rev int) string {
   487  	d, err := asserts.EncodeDigest(crypto.SHA3_384, fakeHash(rev))
   488  	if err != nil {
   489  		panic(err)
   490  	}
   491  	return string(d)
   492  }
   493  
   494  func (s *assertMgrSuite) prereqSnapAssertions(c *C, revisions ...int) {
   495  	headers := map[string]interface{}{
   496  		"series":       "16",
   497  		"snap-id":      "snap-id-1",
   498  		"snap-name":    "foo",
   499  		"publisher-id": s.dev1Acct.AccountID(),
   500  		"timestamp":    time.Now().Format(time.RFC3339),
   501  	}
   502  	snapDecl, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
   503  	c.Assert(err, IsNil)
   504  	err = s.storeSigning.Add(snapDecl)
   505  	c.Assert(err, IsNil)
   506  
   507  	for _, rev := range revisions {
   508  		headers = map[string]interface{}{
   509  			"snap-id":       "snap-id-1",
   510  			"snap-sha3-384": makeDigest(rev),
   511  			"snap-size":     fmt.Sprintf("%d", len(fakeSnap(rev))),
   512  			"snap-revision": fmt.Sprintf("%d", rev),
   513  			"developer-id":  s.dev1Acct.AccountID(),
   514  			"timestamp":     time.Now().Format(time.RFC3339),
   515  		}
   516  		snapRev, err := s.storeSigning.Sign(asserts.SnapRevisionType, headers, nil, "")
   517  		c.Assert(err, IsNil)
   518  		err = s.storeSigning.Add(snapRev)
   519  		c.Assert(err, IsNil)
   520  	}
   521  }
   522  
   523  func (s *assertMgrSuite) TestDoFetch(c *C) {
   524  	s.prereqSnapAssertions(c, 10)
   525  
   526  	s.state.Lock()
   527  	defer s.state.Unlock()
   528  
   529  	ref := &asserts.Ref{
   530  		Type:       asserts.SnapRevisionType,
   531  		PrimaryKey: []string{makeDigest(10)},
   532  	}
   533  
   534  	err := assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, func(f asserts.Fetcher) error {
   535  		return f.Fetch(ref)
   536  	})
   537  	c.Assert(err, IsNil)
   538  
   539  	snapRev, err := ref.Resolve(assertstate.DB(s.state).Find)
   540  	c.Assert(err, IsNil)
   541  	c.Check(snapRev.(*asserts.SnapRevision).SnapRevision(), Equals, 10)
   542  }
   543  
   544  func (s *assertMgrSuite) TestFetchIdempotent(c *C) {
   545  	s.prereqSnapAssertions(c, 10, 11)
   546  
   547  	s.state.Lock()
   548  	defer s.state.Unlock()
   549  
   550  	ref := &asserts.Ref{
   551  		Type:       asserts.SnapRevisionType,
   552  		PrimaryKey: []string{makeDigest(10)},
   553  	}
   554  	fetching := func(f asserts.Fetcher) error {
   555  		return f.Fetch(ref)
   556  	}
   557  
   558  	err := assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, fetching)
   559  	c.Assert(err, IsNil)
   560  
   561  	ref = &asserts.Ref{
   562  		Type:       asserts.SnapRevisionType,
   563  		PrimaryKey: []string{makeDigest(11)},
   564  	}
   565  
   566  	err = assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, fetching)
   567  	c.Assert(err, IsNil)
   568  
   569  	snapRev, err := ref.Resolve(assertstate.DB(s.state).Find)
   570  	c.Assert(err, IsNil)
   571  	c.Check(snapRev.(*asserts.SnapRevision).SnapRevision(), Equals, 11)
   572  }
   573  
   574  func (s *assertMgrSuite) settle(c *C) {
   575  	err := s.o.Settle(5 * time.Second)
   576  	c.Assert(err, IsNil)
   577  }
   578  
   579  func (s *assertMgrSuite) TestFetchUnsupportedUpdateIgnored(c *C) {
   580  	// ATM in principle we ignore updated assertions with unsupported formats
   581  	// NB: this scenario can only happen if there is a bug
   582  	// we ask the store to filter what is returned by max supported format!
   583  	restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 111)
   584  	defer restore()
   585  
   586  	logbuf, restore := logger.MockLogger()
   587  	defer restore()
   588  
   589  	snapDeclFoo0 := s.snapDecl(c, "foo", nil)
   590  
   591  	s.state.Lock()
   592  	defer s.state.Unlock()
   593  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
   594  	c.Assert(err, IsNil)
   595  
   596  	err = assertstate.Add(s.state, s.dev1Acct)
   597  	c.Assert(err, IsNil)
   598  	err = assertstate.Add(s.state, snapDeclFoo0)
   599  	c.Assert(err, IsNil)
   600  
   601  	var snapDeclFoo1 *asserts.SnapDeclaration
   602  	(func() {
   603  		restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 999)
   604  		defer restore()
   605  		snapDeclFoo1 = s.snapDecl(c, "foo", map[string]interface{}{
   606  			"format":   "999",
   607  			"revision": "1",
   608  		})
   609  	})()
   610  	c.Check(snapDeclFoo1.Revision(), Equals, 1)
   611  
   612  	ref := &asserts.Ref{
   613  		Type:       asserts.SnapDeclarationType,
   614  		PrimaryKey: []string{"16", "foo-id"},
   615  	}
   616  	fetching := func(f asserts.Fetcher) error {
   617  		return f.Fetch(ref)
   618  	}
   619  
   620  	s.fakeStore.(*fakeStore).maxDeclSupportedFormat = 999
   621  	err = assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, fetching)
   622  	// no error and the old one was kept
   623  	c.Assert(err, IsNil)
   624  	snapDecl, err := ref.Resolve(assertstate.DB(s.state).Find)
   625  	c.Assert(err, IsNil)
   626  	c.Check(snapDecl.Revision(), Equals, 0)
   627  
   628  	// we log the issue
   629  	c.Check(logbuf.String(), testutil.Contains, `Cannot update assertion snap-declaration (foo-id;`)
   630  }
   631  
   632  func (s *assertMgrSuite) TestFetchUnsupportedError(c *C) {
   633  	// NB: this scenario can only happen if there is a bug
   634  	// we ask the store to filter what is returned by max supported format!
   635  
   636  	restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 111)
   637  	defer restore()
   638  
   639  	s.state.Lock()
   640  	defer s.state.Unlock()
   641  
   642  	var snapDeclFoo1 *asserts.SnapDeclaration
   643  	(func() {
   644  		restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 999)
   645  		defer restore()
   646  		snapDeclFoo1 = s.snapDecl(c, "foo", map[string]interface{}{
   647  			"format":   "999",
   648  			"revision": "1",
   649  		})
   650  	})()
   651  	c.Check(snapDeclFoo1.Revision(), Equals, 1)
   652  
   653  	ref := &asserts.Ref{
   654  		Type:       asserts.SnapDeclarationType,
   655  		PrimaryKey: []string{"16", "foo-id"},
   656  	}
   657  	fetching := func(f asserts.Fetcher) error {
   658  		return f.Fetch(ref)
   659  	}
   660  
   661  	s.fakeStore.(*fakeStore).maxDeclSupportedFormat = 999
   662  	err := assertstate.DoFetch(s.state, 0, s.trivialDeviceCtx, fetching)
   663  	c.Check(err, ErrorMatches, `(?s).*proposed "snap-declaration" assertion has format 999 but 111 is latest supported.*`)
   664  }
   665  
   666  func (s *assertMgrSuite) setModel(model *asserts.Model) {
   667  	deviceCtx := &snapstatetest.TrivialDeviceContext{
   668  		DeviceModel: model,
   669  		CtxStore:    s.fakeStore,
   670  	}
   671  	s.AddCleanup(snapstatetest.MockDeviceContext(deviceCtx))
   672  	s.state.Set("seeded", true)
   673  }
   674  
   675  func (s *assertMgrSuite) setupModelAndStore(c *C) *asserts.Store {
   676  	// setup a model and store assertion
   677  	a := assertstest.FakeAssertion(map[string]interface{}{
   678  		"type":         "model",
   679  		"authority-id": "my-brand",
   680  		"series":       "16",
   681  		"brand-id":     "my-brand",
   682  		"model":        "my-model",
   683  		"architecture": "amd64",
   684  		"store":        "my-brand-store",
   685  		"gadget":       "gadget",
   686  		"kernel":       "krnl",
   687  	})
   688  	s.setModel(a.(*asserts.Model))
   689  
   690  	a, err := s.storeSigning.Sign(asserts.StoreType, map[string]interface{}{
   691  		"authority-id": s.storeSigning.AuthorityID,
   692  		"operator-id":  s.storeSigning.AuthorityID,
   693  		"store":        "my-brand-store",
   694  		"timestamp":    time.Now().Format(time.RFC3339),
   695  	}, nil, "")
   696  	c.Assert(err, IsNil)
   697  	return a.(*asserts.Store)
   698  }
   699  
   700  func (s *assertMgrSuite) TestValidateSnap(c *C) {
   701  	s.prereqSnapAssertions(c, 10)
   702  
   703  	tempdir := c.MkDir()
   704  	snapPath := filepath.Join(tempdir, "foo.snap")
   705  	err := ioutil.WriteFile(snapPath, fakeSnap(10), 0644)
   706  	c.Assert(err, IsNil)
   707  
   708  	s.state.Lock()
   709  	defer s.state.Unlock()
   710  
   711  	// have a model and the store assertion available
   712  	storeAs := s.setupModelAndStore(c)
   713  	err = s.storeSigning.Add(storeAs)
   714  	c.Assert(err, IsNil)
   715  
   716  	chg := s.state.NewChange("install", "...")
   717  	t := s.state.NewTask("validate-snap", "Fetch and check snap assertions")
   718  	snapsup := snapstate.SnapSetup{
   719  		SnapPath: snapPath,
   720  		UserID:   0,
   721  		SideInfo: &snap.SideInfo{
   722  			RealName: "foo",
   723  			SnapID:   "snap-id-1",
   724  			Revision: snap.R(10),
   725  		},
   726  	}
   727  	t.Set("snap-setup", snapsup)
   728  	chg.AddTask(t)
   729  
   730  	s.state.Unlock()
   731  	defer s.se.Stop()
   732  	s.settle(c)
   733  	s.state.Lock()
   734  
   735  	c.Assert(chg.Err(), IsNil)
   736  
   737  	snapRev, err := assertstate.DB(s.state).Find(asserts.SnapRevisionType, map[string]string{
   738  		"snap-id":       "snap-id-1",
   739  		"snap-sha3-384": makeDigest(10),
   740  	})
   741  	c.Assert(err, IsNil)
   742  	c.Check(snapRev.(*asserts.SnapRevision).SnapRevision(), Equals, 10)
   743  
   744  	// store assertion was also fetched
   745  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
   746  		"store": "my-brand-store",
   747  	})
   748  	c.Assert(err, IsNil)
   749  }
   750  
   751  func (s *assertMgrSuite) TestValidateSnapStoreNotFound(c *C) {
   752  	s.prereqSnapAssertions(c, 10)
   753  
   754  	tempdir := c.MkDir()
   755  	snapPath := filepath.Join(tempdir, "foo.snap")
   756  	err := ioutil.WriteFile(snapPath, fakeSnap(10), 0644)
   757  	c.Assert(err, IsNil)
   758  
   759  	s.state.Lock()
   760  	defer s.state.Unlock()
   761  
   762  	// have a model and store but store assertion is not made available
   763  	s.setupModelAndStore(c)
   764  
   765  	chg := s.state.NewChange("install", "...")
   766  	t := s.state.NewTask("validate-snap", "Fetch and check snap assertions")
   767  	snapsup := snapstate.SnapSetup{
   768  		SnapPath: snapPath,
   769  		UserID:   0,
   770  		SideInfo: &snap.SideInfo{
   771  			RealName: "foo",
   772  			SnapID:   "snap-id-1",
   773  			Revision: snap.R(10),
   774  		},
   775  	}
   776  	t.Set("snap-setup", snapsup)
   777  	chg.AddTask(t)
   778  
   779  	s.state.Unlock()
   780  	defer s.se.Stop()
   781  	s.settle(c)
   782  	s.state.Lock()
   783  
   784  	c.Assert(chg.Err(), IsNil)
   785  
   786  	snapRev, err := assertstate.DB(s.state).Find(asserts.SnapRevisionType, map[string]string{
   787  		"snap-id":       "snap-id-1",
   788  		"snap-sha3-384": makeDigest(10),
   789  	})
   790  	c.Assert(err, IsNil)
   791  	c.Check(snapRev.(*asserts.SnapRevision).SnapRevision(), Equals, 10)
   792  
   793  	// store assertion was not found and ignored
   794  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
   795  		"store": "my-brand-store",
   796  	})
   797  	c.Assert(asserts.IsNotFound(err), Equals, true)
   798  }
   799  
   800  func (s *assertMgrSuite) TestValidateSnapMissingSnapSetup(c *C) {
   801  	s.state.Lock()
   802  	defer s.state.Unlock()
   803  
   804  	chg := s.state.NewChange("install", "...")
   805  	t := s.state.NewTask("validate-snap", "Fetch and check snap assertions")
   806  	chg.AddTask(t)
   807  
   808  	s.state.Unlock()
   809  	defer s.se.Stop()
   810  	s.settle(c)
   811  	s.state.Lock()
   812  
   813  	c.Assert(chg.Err(), ErrorMatches, `(?s).*internal error: cannot obtain snap setup: no state entry for key.*`)
   814  }
   815  
   816  func (s *assertMgrSuite) TestValidateSnapNotFound(c *C) {
   817  	tempdir := c.MkDir()
   818  	snapPath := filepath.Join(tempdir, "foo.snap")
   819  	err := ioutil.WriteFile(snapPath, fakeSnap(33), 0644)
   820  	c.Assert(err, IsNil)
   821  
   822  	s.state.Lock()
   823  	defer s.state.Unlock()
   824  
   825  	s.setModel(sysdb.GenericClassicModel())
   826  
   827  	chg := s.state.NewChange("install", "...")
   828  	t := s.state.NewTask("validate-snap", "Fetch and check snap assertions")
   829  	snapsup := snapstate.SnapSetup{
   830  		SnapPath: snapPath,
   831  		UserID:   0,
   832  		SideInfo: &snap.SideInfo{
   833  			RealName: "foo",
   834  			SnapID:   "snap-id-1",
   835  			Revision: snap.R(33),
   836  		},
   837  	}
   838  	t.Set("snap-setup", snapsup)
   839  	chg.AddTask(t)
   840  
   841  	s.state.Unlock()
   842  	defer s.se.Stop()
   843  	s.settle(c)
   844  	s.state.Lock()
   845  
   846  	c.Assert(chg.Err(), ErrorMatches, `(?s).*cannot verify snap "foo", no matching signatures found.*`)
   847  }
   848  
   849  func (s *assertMgrSuite) TestValidateSnapCrossCheckFail(c *C) {
   850  	s.prereqSnapAssertions(c, 10)
   851  
   852  	tempdir := c.MkDir()
   853  	snapPath := filepath.Join(tempdir, "foo.snap")
   854  	err := ioutil.WriteFile(snapPath, fakeSnap(10), 0644)
   855  	c.Assert(err, IsNil)
   856  
   857  	s.state.Lock()
   858  	defer s.state.Unlock()
   859  
   860  	s.setModel(sysdb.GenericClassicModel())
   861  
   862  	chg := s.state.NewChange("install", "...")
   863  	t := s.state.NewTask("validate-snap", "Fetch and check snap assertions")
   864  	snapsup := snapstate.SnapSetup{
   865  		SnapPath: snapPath,
   866  		UserID:   0,
   867  		SideInfo: &snap.SideInfo{
   868  			RealName: "f",
   869  			SnapID:   "snap-id-1",
   870  			Revision: snap.R(10),
   871  		},
   872  	}
   873  	t.Set("snap-setup", snapsup)
   874  	chg.AddTask(t)
   875  
   876  	s.state.Unlock()
   877  	defer s.se.Stop()
   878  	s.settle(c)
   879  	s.state.Lock()
   880  
   881  	c.Assert(chg.Err(), ErrorMatches, `(?s).*cannot install "f", snap "f" is undergoing a rename to "foo".*`)
   882  }
   883  
   884  func (s *assertMgrSuite) validationSetAssert(c *C, name, sequence, revision string, snapPresence string) *asserts.ValidationSet {
   885  	snaps := []interface{}{map[string]interface{}{
   886  		"id":       "qOqKhntON3vR7kwEbVPsILm7bUViPDzz",
   887  		"name":     "foo",
   888  		"presence": snapPresence,
   889  	}}
   890  	if snapPresence != "invalid" {
   891  		snaps[0].(map[string]interface{})["revision"] = "1"
   892  	}
   893  	headers := map[string]interface{}{
   894  		"series":       "16",
   895  		"account-id":   s.dev1Acct.AccountID(),
   896  		"authority-id": s.dev1Acct.AccountID(),
   897  		"publisher-id": s.dev1Acct.AccountID(),
   898  		"name":         name,
   899  		"sequence":     sequence,
   900  		"snaps":        snaps,
   901  		"timestamp":    time.Now().Format(time.RFC3339),
   902  		"revision":     revision,
   903  	}
   904  	a, err := s.dev1Signing.Sign(asserts.ValidationSetType, headers, nil, "")
   905  	c.Assert(err, IsNil)
   906  	return a.(*asserts.ValidationSet)
   907  }
   908  
   909  func (s *assertMgrSuite) snapDecl(c *C, name string, extraHeaders map[string]interface{}) *asserts.SnapDeclaration {
   910  	headers := map[string]interface{}{
   911  		"series":       "16",
   912  		"snap-id":      name + "-id",
   913  		"snap-name":    name,
   914  		"publisher-id": s.dev1Acct.AccountID(),
   915  		"timestamp":    time.Now().Format(time.RFC3339),
   916  	}
   917  	for h, v := range extraHeaders {
   918  		headers[h] = v
   919  	}
   920  	decl, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
   921  	c.Assert(err, IsNil)
   922  	err = s.storeSigning.Add(decl)
   923  	c.Assert(err, IsNil)
   924  	return decl.(*asserts.SnapDeclaration)
   925  }
   926  
   927  func (s *assertMgrSuite) stateFromDecl(c *C, decl *asserts.SnapDeclaration, instanceName string, revno snap.Revision) {
   928  	snapName, instanceKey := snap.SplitInstanceName(instanceName)
   929  	if snapName == "" {
   930  		snapName = decl.SnapName()
   931  		instanceName = snapName
   932  	}
   933  
   934  	c.Assert(snapName, Equals, decl.SnapName())
   935  
   936  	snapID := decl.SnapID()
   937  	snapstate.Set(s.state, instanceName, &snapstate.SnapState{
   938  		Active: true,
   939  		Sequence: []*snap.SideInfo{
   940  			{RealName: snapName, SnapID: snapID, Revision: revno},
   941  		},
   942  		Current:     revno,
   943  		InstanceKey: instanceKey,
   944  	})
   945  }
   946  
   947  func (s *assertMgrSuite) TestRefreshSnapDeclarationsTooEarly(c *C) {
   948  	s.state.Lock()
   949  	defer s.state.Unlock()
   950  
   951  	r := snapstatetest.MockDeviceModel(nil)
   952  	defer r()
   953  
   954  	err := assertstate.RefreshSnapDeclarations(s.state, 0)
   955  	c.Check(err, FitsTypeOf, &snapstate.ChangeConflictError{})
   956  }
   957  
   958  func (s *assertMgrSuite) TestRefreshSnapDeclarationsNop(c *C) {
   959  	s.state.Lock()
   960  	defer s.state.Unlock()
   961  
   962  	s.setModel(sysdb.GenericClassicModel())
   963  
   964  	err := assertstate.RefreshSnapDeclarations(s.state, 0)
   965  	c.Assert(err, IsNil)
   966  }
   967  
   968  func (s *assertMgrSuite) TestRefreshSnapDeclarationsNoStore(c *C) {
   969  	s.state.Lock()
   970  	defer s.state.Unlock()
   971  
   972  	s.setModel(sysdb.GenericClassicModel())
   973  
   974  	snapDeclFoo := s.snapDecl(c, "foo", nil)
   975  	snapDeclBar := s.snapDecl(c, "bar", nil)
   976  
   977  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
   978  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
   979  	snapstate.Set(s.state, "local", &snapstate.SnapState{
   980  		Active: false,
   981  		Sequence: []*snap.SideInfo{
   982  			{RealName: "local", Revision: snap.R(-1)},
   983  		},
   984  		Current: snap.R(-1),
   985  	})
   986  
   987  	// previous state
   988  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
   989  	c.Assert(err, IsNil)
   990  	err = assertstate.Add(s.state, s.dev1Acct)
   991  	c.Assert(err, IsNil)
   992  	err = assertstate.Add(s.state, snapDeclFoo)
   993  	c.Assert(err, IsNil)
   994  	err = assertstate.Add(s.state, snapDeclBar)
   995  	c.Assert(err, IsNil)
   996  
   997  	// one changed assertion
   998  	headers := map[string]interface{}{
   999  		"series":       "16",
  1000  		"snap-id":      "foo-id",
  1001  		"snap-name":    "fo-o",
  1002  		"publisher-id": s.dev1Acct.AccountID(),
  1003  		"timestamp":    time.Now().Format(time.RFC3339),
  1004  		"revision":     "1",
  1005  	}
  1006  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1007  	c.Assert(err, IsNil)
  1008  	err = s.storeSigning.Add(snapDeclFoo1)
  1009  	c.Assert(err, IsNil)
  1010  
  1011  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1012  	c.Assert(err, IsNil)
  1013  
  1014  	a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1015  		"series":  "16",
  1016  		"snap-id": "foo-id",
  1017  	})
  1018  	c.Assert(err, IsNil)
  1019  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o")
  1020  
  1021  	// another one
  1022  	// one changed assertion
  1023  	headers = s.dev1Acct.Headers()
  1024  	headers["display-name"] = "Dev 1 edited display-name"
  1025  	headers["revision"] = "1"
  1026  	dev1Acct1, err := s.storeSigning.Sign(asserts.AccountType, headers, nil, "")
  1027  	c.Assert(err, IsNil)
  1028  	err = s.storeSigning.Add(dev1Acct1)
  1029  	c.Assert(err, IsNil)
  1030  
  1031  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1032  	c.Assert(err, IsNil)
  1033  
  1034  	a, err = assertstate.DB(s.state).Find(asserts.AccountType, map[string]string{
  1035  		"account-id": s.dev1Acct.AccountID(),
  1036  	})
  1037  	c.Assert(err, IsNil)
  1038  	c.Check(a.(*asserts.Account).DisplayName(), Equals, "Dev 1 edited display-name")
  1039  
  1040  	// change snap decl to something that has a too new format
  1041  	s.fakeStore.(*fakeStore).maxDeclSupportedFormat = 999
  1042  	(func() {
  1043  		restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 999)
  1044  		defer restore()
  1045  
  1046  		headers := map[string]interface{}{
  1047  			"format":       "999",
  1048  			"series":       "16",
  1049  			"snap-id":      "foo-id",
  1050  			"snap-name":    "foo",
  1051  			"publisher-id": s.dev1Acct.AccountID(),
  1052  			"timestamp":    time.Now().Format(time.RFC3339),
  1053  			"revision":     "2",
  1054  		}
  1055  
  1056  		snapDeclFoo2, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1057  		c.Assert(err, IsNil)
  1058  		err = s.storeSigning.Add(snapDeclFoo2)
  1059  		c.Assert(err, IsNil)
  1060  	})()
  1061  
  1062  	// no error, kept the old one
  1063  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1064  	c.Assert(err, IsNil)
  1065  
  1066  	a, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1067  		"series":  "16",
  1068  		"snap-id": "foo-id",
  1069  	})
  1070  	c.Assert(err, IsNil)
  1071  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o")
  1072  	c.Check(a.(*asserts.SnapDeclaration).Revision(), Equals, 1)
  1073  }
  1074  
  1075  func (s *assertMgrSuite) TestRefreshSnapDeclarationsChangingKey(c *C) {
  1076  	s.state.Lock()
  1077  	defer s.state.Unlock()
  1078  
  1079  	s.setModel(sysdb.GenericClassicModel())
  1080  
  1081  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1082  
  1083  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1084  
  1085  	// previous state
  1086  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1087  	c.Assert(err, IsNil)
  1088  	err = assertstate.Add(s.state, s.dev1Acct)
  1089  	c.Assert(err, IsNil)
  1090  	err = assertstate.Add(s.state, snapDeclFoo)
  1091  	c.Assert(err, IsNil)
  1092  
  1093  	storePrivKey2, _ := assertstest.GenerateKey(752)
  1094  	err = s.storeSigning.ImportKey(storePrivKey2)
  1095  	c.Assert(err, IsNil)
  1096  	storeKey2 := assertstest.NewAccountKey(s.storeSigning.RootSigning, s.storeSigning.TrustedAccount, map[string]interface{}{
  1097  		"name": "store2",
  1098  	}, storePrivKey2.PublicKey(), "")
  1099  	err = s.storeSigning.Add(storeKey2)
  1100  	c.Assert(err, IsNil)
  1101  
  1102  	// one changed assertion signed with different key
  1103  	headers := map[string]interface{}{
  1104  		"series":       "16",
  1105  		"snap-id":      "foo-id",
  1106  		"snap-name":    "foo",
  1107  		"publisher-id": s.dev1Acct.AccountID(),
  1108  		"timestamp":    time.Now().Format(time.RFC3339),
  1109  		"revision":     "1",
  1110  	}
  1111  	storeKey2ID := storePrivKey2.PublicKey().ID()
  1112  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, storeKey2ID)
  1113  	c.Assert(err, IsNil)
  1114  	c.Check(snapDeclFoo1.SignKeyID(), Not(Equals), snapDeclFoo.SignKeyID())
  1115  	err = s.storeSigning.Add(snapDeclFoo1)
  1116  	c.Assert(err, IsNil)
  1117  
  1118  	_, err = storeKey2.Ref().Resolve(assertstate.DB(s.state).Find)
  1119  	c.Check(asserts.IsNotFound(err), Equals, true)
  1120  
  1121  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1122  	c.Assert(err, IsNil)
  1123  
  1124  	a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1125  		"series":  "16",
  1126  		"snap-id": "foo-id",
  1127  	})
  1128  	c.Assert(err, IsNil)
  1129  	c.Check(a.Revision(), Equals, 1)
  1130  	c.Check(a.SignKeyID(), Equals, storeKey2ID)
  1131  
  1132  	// key was fetched as well
  1133  	_, err = storeKey2.Ref().Resolve(assertstate.DB(s.state).Find)
  1134  	c.Check(err, IsNil)
  1135  }
  1136  
  1137  func (s *assertMgrSuite) TestRefreshSnapDeclarationsWithStore(c *C) {
  1138  	s.state.Lock()
  1139  	defer s.state.Unlock()
  1140  
  1141  	storeAs := s.setupModelAndStore(c)
  1142  
  1143  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1144  
  1145  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1146  
  1147  	// previous state
  1148  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1149  	c.Assert(err, IsNil)
  1150  	err = assertstate.Add(s.state, s.dev1Acct)
  1151  	c.Assert(err, IsNil)
  1152  	err = assertstate.Add(s.state, snapDeclFoo)
  1153  	c.Assert(err, IsNil)
  1154  
  1155  	// one changed assertion
  1156  	headers := map[string]interface{}{
  1157  		"series":       "16",
  1158  		"snap-id":      "foo-id",
  1159  		"snap-name":    "fo-o",
  1160  		"publisher-id": s.dev1Acct.AccountID(),
  1161  		"timestamp":    time.Now().Format(time.RFC3339),
  1162  		"revision":     "1",
  1163  	}
  1164  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1165  	c.Assert(err, IsNil)
  1166  	err = s.storeSigning.Add(snapDeclFoo1)
  1167  	c.Assert(err, IsNil)
  1168  
  1169  	// store assertion is missing
  1170  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1171  	c.Assert(err, IsNil)
  1172  
  1173  	a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1174  		"series":  "16",
  1175  		"snap-id": "foo-id",
  1176  	})
  1177  	c.Assert(err, IsNil)
  1178  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o")
  1179  
  1180  	// changed again
  1181  	headers = map[string]interface{}{
  1182  		"series":       "16",
  1183  		"snap-id":      "foo-id",
  1184  		"snap-name":    "f-oo",
  1185  		"publisher-id": s.dev1Acct.AccountID(),
  1186  		"timestamp":    time.Now().Format(time.RFC3339),
  1187  		"revision":     "2",
  1188  	}
  1189  	snapDeclFoo2, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1190  	c.Assert(err, IsNil)
  1191  	err = s.storeSigning.Add(snapDeclFoo2)
  1192  	c.Assert(err, IsNil)
  1193  
  1194  	// store assertion is available
  1195  	err = s.storeSigning.Add(storeAs)
  1196  	c.Assert(err, IsNil)
  1197  
  1198  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1199  	c.Assert(err, IsNil)
  1200  
  1201  	a, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1202  		"series":  "16",
  1203  		"snap-id": "foo-id",
  1204  	})
  1205  	c.Assert(err, IsNil)
  1206  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "f-oo")
  1207  
  1208  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1209  		"store": "my-brand-store",
  1210  	})
  1211  	c.Assert(err, IsNil)
  1212  
  1213  	// store assertion has changed
  1214  	a, err = s.storeSigning.Sign(asserts.StoreType, map[string]interface{}{
  1215  		"authority-id": s.storeSigning.AuthorityID,
  1216  		"operator-id":  s.storeSigning.AuthorityID,
  1217  		"store":        "my-brand-store",
  1218  		"location":     "the-cloud",
  1219  		"revision":     "1",
  1220  		"timestamp":    time.Now().Format(time.RFC3339),
  1221  	}, nil, "")
  1222  	c.Assert(err, IsNil)
  1223  	storeAs = a.(*asserts.Store)
  1224  	err = s.storeSigning.Add(storeAs)
  1225  	c.Assert(err, IsNil)
  1226  
  1227  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1228  	c.Assert(err, IsNil)
  1229  	a, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1230  		"store": "my-brand-store",
  1231  	})
  1232  	c.Assert(err, IsNil)
  1233  	c.Check(a.(*asserts.Store).Location(), Equals, "the-cloud")
  1234  }
  1235  
  1236  func (s *assertMgrSuite) TestRefreshSnapDeclarationsDownloadError(c *C) {
  1237  	s.state.Lock()
  1238  	defer s.state.Unlock()
  1239  
  1240  	s.setModel(sysdb.GenericClassicModel())
  1241  
  1242  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1243  
  1244  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1245  
  1246  	// previous state
  1247  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1248  	c.Assert(err, IsNil)
  1249  	err = assertstate.Add(s.state, s.dev1Acct)
  1250  	c.Assert(err, IsNil)
  1251  	err = assertstate.Add(s.state, snapDeclFoo)
  1252  	c.Assert(err, IsNil)
  1253  
  1254  	// one changed assertion
  1255  	headers := map[string]interface{}{
  1256  		"series":       "16",
  1257  		"snap-id":      "foo-id",
  1258  		"snap-name":    "fo-o",
  1259  		"publisher-id": s.dev1Acct.AccountID(),
  1260  		"timestamp":    time.Now().Format(time.RFC3339),
  1261  		"revision":     "1",
  1262  	}
  1263  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1264  	c.Assert(err, IsNil)
  1265  	err = s.storeSigning.Add(snapDeclFoo1)
  1266  	c.Assert(err, IsNil)
  1267  
  1268  	s.fakeStore.(*fakeStore).downloadAssertionsErr = errors.New("download error")
  1269  
  1270  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1271  	c.Assert(err, ErrorMatches, `cannot refresh snap-declarations for snaps:
  1272   - foo: download error`)
  1273  }
  1274  
  1275  func (s *assertMgrSuite) TestRefreshSnapDeclarationsPersistentNetworkError(c *C) {
  1276  	s.state.Lock()
  1277  	defer s.state.Unlock()
  1278  
  1279  	s.setModel(sysdb.GenericClassicModel())
  1280  
  1281  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1282  
  1283  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1284  
  1285  	// previous state
  1286  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1287  	c.Assert(err, IsNil)
  1288  	err = assertstate.Add(s.state, s.dev1Acct)
  1289  	c.Assert(err, IsNil)
  1290  	err = assertstate.Add(s.state, snapDeclFoo)
  1291  	c.Assert(err, IsNil)
  1292  
  1293  	// one changed assertion
  1294  	headers := map[string]interface{}{
  1295  		"series":       "16",
  1296  		"snap-id":      "foo-id",
  1297  		"snap-name":    "fo-o",
  1298  		"publisher-id": s.dev1Acct.AccountID(),
  1299  		"timestamp":    time.Now().Format(time.RFC3339),
  1300  		"revision":     "1",
  1301  	}
  1302  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1303  	c.Assert(err, IsNil)
  1304  	err = s.storeSigning.Add(snapDeclFoo1)
  1305  	c.Assert(err, IsNil)
  1306  
  1307  	pne := new(httputil.PersistentNetworkError)
  1308  	s.fakeStore.(*fakeStore).snapActionErr = pne
  1309  
  1310  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1311  	c.Assert(err, Equals, pne)
  1312  }
  1313  
  1314  func (s *assertMgrSuite) TestRefreshSnapDeclarationsNoStoreFallback(c *C) {
  1315  	// test that if we get a 4xx or 500 error from the store trying bulk
  1316  	// assertion refresh we fall back to the old logic
  1317  	s.fakeStore.(*fakeStore).snapActionErr = &store.UnexpectedHTTPStatusError{StatusCode: 400}
  1318  
  1319  	logbuf, restore := logger.MockLogger()
  1320  	defer restore()
  1321  
  1322  	s.TestRefreshSnapDeclarationsNoStore(c)
  1323  
  1324  	c.Check(logbuf.String(), Matches, "(?m).*bulk refresh of snap-declarations failed, falling back to one-by-one assertion fetching:.*HTTP status code 400.*")
  1325  }
  1326  
  1327  func (s *assertMgrSuite) TestRefreshSnapDeclarationsNoStoreFallbackUnexpectedSnapActionError(c *C) {
  1328  	// test that if we get an unexpected SnapAction error from the
  1329  	// store trying bulk assertion refresh we fall back to the old
  1330  	// logic
  1331  	s.fakeStore.(*fakeStore).snapActionErr = &store.SnapActionError{
  1332  		NoResults: true,
  1333  		Other:     []error{errors.New("unexpected error")},
  1334  	}
  1335  
  1336  	logbuf, restore := logger.MockLogger()
  1337  	defer restore()
  1338  
  1339  	s.TestRefreshSnapDeclarationsNoStore(c)
  1340  
  1341  	c.Check(logbuf.String(), Matches, "(?m).*bulk refresh of snap-declarations failed, falling back to one-by-one assertion fetching:.*unexpected error.*")
  1342  }
  1343  
  1344  func (s *assertMgrSuite) TestRefreshSnapDeclarationsWithStoreFallback(c *C) {
  1345  	// test that if we get a 4xx or 500 error from the store trying bulk
  1346  	// assertion refresh we fall back to the old logic
  1347  	s.fakeStore.(*fakeStore).snapActionErr = &store.UnexpectedHTTPStatusError{StatusCode: 500}
  1348  
  1349  	logbuf, restore := logger.MockLogger()
  1350  	defer restore()
  1351  
  1352  	s.TestRefreshSnapDeclarationsWithStore(c)
  1353  
  1354  	c.Check(logbuf.String(), Matches, "(?m).*bulk refresh of snap-declarations failed, falling back to one-by-one assertion fetching:.*HTTP status code 500.*")
  1355  }
  1356  
  1357  // the following tests cover what happens when refreshing snap-declarations
  1358  // need to support overflowing the chosen asserts.Pool maximum groups
  1359  
  1360  func (s *assertMgrSuite) testRefreshSnapDeclarationsMany(c *C, n int) error {
  1361  	// reduce maxGroups to test and stress the logic that deals
  1362  	// with overflowing it
  1363  	s.AddCleanup(assertstate.MockMaxGroups(16))
  1364  
  1365  	// previous state
  1366  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1367  	c.Assert(err, IsNil)
  1368  	err = assertstate.Add(s.state, s.dev1Acct)
  1369  	c.Assert(err, IsNil)
  1370  
  1371  	for i := 1; i <= n; i++ {
  1372  		name := fmt.Sprintf("foo%d", i)
  1373  		snapDeclFooX := s.snapDecl(c, name, nil)
  1374  
  1375  		s.stateFromDecl(c, snapDeclFooX, "", snap.R(7+i))
  1376  
  1377  		// previous state
  1378  		err = assertstate.Add(s.state, snapDeclFooX)
  1379  		c.Assert(err, IsNil)
  1380  
  1381  		// make an update on top
  1382  		headers := map[string]interface{}{
  1383  			"series":       "16",
  1384  			"snap-id":      name + "-id",
  1385  			"snap-name":    fmt.Sprintf("fo-o-%d", i),
  1386  			"publisher-id": s.dev1Acct.AccountID(),
  1387  			"timestamp":    time.Now().Format(time.RFC3339),
  1388  			"revision":     "1",
  1389  		}
  1390  		snapDeclFooX1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1391  		c.Assert(err, IsNil)
  1392  		err = s.storeSigning.Add(snapDeclFooX1)
  1393  		c.Assert(err, IsNil)
  1394  	}
  1395  
  1396  	err = assertstate.RefreshSnapDeclarations(s.state, 0)
  1397  	if err != nil {
  1398  		// fot the caller to check
  1399  		return err
  1400  	}
  1401  
  1402  	// check we got the updates
  1403  	for i := 1; i <= n; i++ {
  1404  		name := fmt.Sprintf("foo%d", i)
  1405  		a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1406  			"series":  "16",
  1407  			"snap-id": name + "-id",
  1408  		})
  1409  		c.Assert(err, IsNil)
  1410  		c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, fmt.Sprintf("fo-o-%d", i))
  1411  	}
  1412  
  1413  	return nil
  1414  }
  1415  
  1416  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany14NoStore(c *C) {
  1417  	s.state.Lock()
  1418  	defer s.state.Unlock()
  1419  	s.setModel(sysdb.GenericClassicModel())
  1420  
  1421  	err := s.testRefreshSnapDeclarationsMany(c, 14)
  1422  	c.Assert(err, IsNil)
  1423  
  1424  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1425  		{"account", "account-key", "snap-declaration"},
  1426  	})
  1427  }
  1428  
  1429  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany16NoStore(c *C) {
  1430  	s.state.Lock()
  1431  	defer s.state.Unlock()
  1432  	s.setModel(sysdb.GenericClassicModel())
  1433  
  1434  	err := s.testRefreshSnapDeclarationsMany(c, 16)
  1435  	c.Assert(err, IsNil)
  1436  
  1437  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1438  		{"account", "account-key", "snap-declaration"},
  1439  	})
  1440  }
  1441  
  1442  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany16WithStore(c *C) {
  1443  	s.state.Lock()
  1444  	defer s.state.Unlock()
  1445  	// have a model and the store assertion available
  1446  	storeAs := s.setupModelAndStore(c)
  1447  	err := s.storeSigning.Add(storeAs)
  1448  	c.Assert(err, IsNil)
  1449  
  1450  	err = s.testRefreshSnapDeclarationsMany(c, 16)
  1451  	c.Assert(err, IsNil)
  1452  
  1453  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1454  		// first 16 groups request
  1455  		{"account", "account-key", "snap-declaration"},
  1456  		// final separate request covering store only
  1457  		{"store"},
  1458  	})
  1459  
  1460  	// store assertion was also fetched
  1461  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1462  		"store": "my-brand-store",
  1463  	})
  1464  	c.Assert(err, IsNil)
  1465  }
  1466  
  1467  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany17NoStore(c *C) {
  1468  	s.state.Lock()
  1469  	defer s.state.Unlock()
  1470  	s.setModel(sysdb.GenericClassicModel())
  1471  
  1472  	err := s.testRefreshSnapDeclarationsMany(c, 17)
  1473  	c.Assert(err, IsNil)
  1474  
  1475  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1476  		// first 16 groups request
  1477  		{"account", "account-key", "snap-declaration"},
  1478  		// final separate request for the rest
  1479  		{"snap-declaration"},
  1480  	})
  1481  }
  1482  
  1483  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany17NoStoreMergeErrors(c *C) {
  1484  	s.state.Lock()
  1485  	defer s.state.Unlock()
  1486  	s.setModel(sysdb.GenericClassicModel())
  1487  
  1488  	s.fakeStore.(*fakeStore).downloadAssertionsErr = errors.New("download error")
  1489  
  1490  	err := s.testRefreshSnapDeclarationsMany(c, 17)
  1491  	c.Check(err, ErrorMatches, `(?s)cannot refresh snap-declarations for snaps:
  1492   - foo1: download error.* - foo9: download error`)
  1493  	// all foo* snaps accounted for
  1494  	c.Check(strings.Count(err.Error(), "foo"), Equals, 17)
  1495  
  1496  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1497  		// first 16 groups request
  1498  		{"account", "account-key", "snap-declaration"},
  1499  		// final separate request for the rest
  1500  		{"snap-declaration"},
  1501  	})
  1502  }
  1503  
  1504  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany31WithStore(c *C) {
  1505  	s.state.Lock()
  1506  	defer s.state.Unlock()
  1507  	// have a model and the store assertion available
  1508  	storeAs := s.setupModelAndStore(c)
  1509  	err := s.storeSigning.Add(storeAs)
  1510  	c.Assert(err, IsNil)
  1511  
  1512  	err = s.testRefreshSnapDeclarationsMany(c, 31)
  1513  	c.Assert(err, IsNil)
  1514  
  1515  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1516  		// first 16 groups request
  1517  		{"account", "account-key", "snap-declaration"},
  1518  		// final separate request for the rest and store
  1519  		{"snap-declaration", "store"},
  1520  	})
  1521  
  1522  	// store assertion was also fetched
  1523  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1524  		"store": "my-brand-store",
  1525  	})
  1526  	c.Assert(err, IsNil)
  1527  }
  1528  
  1529  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany32WithStore(c *C) {
  1530  	s.state.Lock()
  1531  	defer s.state.Unlock()
  1532  	// have a model and the store assertion available
  1533  	storeAs := s.setupModelAndStore(c)
  1534  	err := s.storeSigning.Add(storeAs)
  1535  	c.Assert(err, IsNil)
  1536  
  1537  	err = s.testRefreshSnapDeclarationsMany(c, 32)
  1538  	c.Assert(err, IsNil)
  1539  
  1540  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1541  		// first 16 groups request
  1542  		{"account", "account-key", "snap-declaration"},
  1543  		// 2nd round request
  1544  		{"snap-declaration"},
  1545  		// final separate request covering store
  1546  		{"store"},
  1547  	})
  1548  
  1549  	// store assertion was also fetched
  1550  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1551  		"store": "my-brand-store",
  1552  	})
  1553  	c.Assert(err, IsNil)
  1554  }
  1555  
  1556  func (s *assertMgrSuite) TestValidateRefreshesNothing(c *C) {
  1557  	s.state.Lock()
  1558  	defer s.state.Unlock()
  1559  
  1560  	validated, err := assertstate.ValidateRefreshes(s.state, nil, nil, 0, s.trivialDeviceCtx)
  1561  	c.Assert(err, IsNil)
  1562  	c.Check(validated, HasLen, 0)
  1563  }
  1564  
  1565  func (s *assertMgrSuite) TestValidateRefreshesNoControl(c *C) {
  1566  	s.state.Lock()
  1567  	defer s.state.Unlock()
  1568  
  1569  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1570  	snapDeclBar := s.snapDecl(c, "bar", nil)
  1571  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1572  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1573  
  1574  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1575  	c.Assert(err, IsNil)
  1576  	err = assertstate.Add(s.state, s.dev1Acct)
  1577  	c.Assert(err, IsNil)
  1578  	err = assertstate.Add(s.state, snapDeclFoo)
  1579  	c.Assert(err, IsNil)
  1580  	err = assertstate.Add(s.state, snapDeclBar)
  1581  	c.Assert(err, IsNil)
  1582  
  1583  	fooRefresh := &snap.Info{
  1584  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1585  	}
  1586  
  1587  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx)
  1588  	c.Assert(err, IsNil)
  1589  	c.Check(validated, DeepEquals, []*snap.Info{fooRefresh})
  1590  }
  1591  
  1592  func (s *assertMgrSuite) TestValidateRefreshesMissingValidation(c *C) {
  1593  	s.state.Lock()
  1594  	defer s.state.Unlock()
  1595  
  1596  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1597  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1598  		"refresh-control": []interface{}{"foo-id"},
  1599  	})
  1600  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1601  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1602  
  1603  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1604  	c.Assert(err, IsNil)
  1605  	err = assertstate.Add(s.state, s.dev1Acct)
  1606  	c.Assert(err, IsNil)
  1607  	err = assertstate.Add(s.state, snapDeclFoo)
  1608  	c.Assert(err, IsNil)
  1609  	err = assertstate.Add(s.state, snapDeclBar)
  1610  	c.Assert(err, IsNil)
  1611  
  1612  	fooRefresh := &snap.Info{
  1613  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1614  	}
  1615  
  1616  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx)
  1617  	c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`)
  1618  	c.Check(validated, HasLen, 0)
  1619  }
  1620  
  1621  func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidation(c *C) {
  1622  	s.state.Lock()
  1623  	defer s.state.Unlock()
  1624  
  1625  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1626  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1627  		"refresh-control": []interface{}{"foo-id"},
  1628  	})
  1629  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1630  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1631  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1632  
  1633  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1634  	c.Assert(err, IsNil)
  1635  	err = assertstate.Add(s.state, s.dev1Acct)
  1636  	c.Assert(err, IsNil)
  1637  	err = assertstate.Add(s.state, snapDeclFoo)
  1638  	c.Assert(err, IsNil)
  1639  	err = assertstate.Add(s.state, snapDeclBar)
  1640  	c.Assert(err, IsNil)
  1641  
  1642  	fooInstanceRefresh := &snap.Info{
  1643  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1644  		InstanceKey: "instance",
  1645  	}
  1646  
  1647  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooInstanceRefresh}, nil, 0, s.trivialDeviceCtx)
  1648  	c.Assert(err, ErrorMatches, `cannot refresh "foo_instance" to revision 9: no validation by "bar"`)
  1649  	c.Check(validated, HasLen, 0)
  1650  }
  1651  
  1652  func (s *assertMgrSuite) TestValidateRefreshesMissingValidationButIgnore(c *C) {
  1653  	s.state.Lock()
  1654  	defer s.state.Unlock()
  1655  
  1656  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1657  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1658  		"refresh-control": []interface{}{"foo-id"},
  1659  	})
  1660  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1661  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1662  
  1663  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1664  	c.Assert(err, IsNil)
  1665  	err = assertstate.Add(s.state, s.dev1Acct)
  1666  	c.Assert(err, IsNil)
  1667  	err = assertstate.Add(s.state, snapDeclFoo)
  1668  	c.Assert(err, IsNil)
  1669  	err = assertstate.Add(s.state, snapDeclBar)
  1670  	c.Assert(err, IsNil)
  1671  
  1672  	fooRefresh := &snap.Info{
  1673  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1674  	}
  1675  
  1676  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, map[string]bool{"foo": true}, 0, s.trivialDeviceCtx)
  1677  	c.Assert(err, IsNil)
  1678  	c.Check(validated, DeepEquals, []*snap.Info{fooRefresh})
  1679  }
  1680  
  1681  func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnore(c *C) {
  1682  	s.state.Lock()
  1683  	defer s.state.Unlock()
  1684  
  1685  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1686  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1687  		"refresh-control": []interface{}{"foo-id"},
  1688  	})
  1689  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1690  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1691  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1692  
  1693  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1694  	c.Assert(err, IsNil)
  1695  	err = assertstate.Add(s.state, s.dev1Acct)
  1696  	c.Assert(err, IsNil)
  1697  	err = assertstate.Add(s.state, snapDeclFoo)
  1698  	c.Assert(err, IsNil)
  1699  	err = assertstate.Add(s.state, snapDeclBar)
  1700  	c.Assert(err, IsNil)
  1701  
  1702  	fooRefresh := &snap.Info{
  1703  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1704  	}
  1705  	fooInstanceRefresh := &snap.Info{
  1706  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1707  		InstanceKey: "instance",
  1708  	}
  1709  
  1710  	// validation is ignore for foo_instance but not for foo
  1711  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx)
  1712  	c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`)
  1713  	c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh})
  1714  }
  1715  
  1716  func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnoreInstanceKeyed(c *C) {
  1717  	s.state.Lock()
  1718  	defer s.state.Unlock()
  1719  
  1720  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1721  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1722  		"refresh-control": []interface{}{"foo-id"},
  1723  	})
  1724  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1725  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1726  
  1727  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1728  	c.Assert(err, IsNil)
  1729  	err = assertstate.Add(s.state, s.dev1Acct)
  1730  	c.Assert(err, IsNil)
  1731  	err = assertstate.Add(s.state, snapDeclFoo)
  1732  	c.Assert(err, IsNil)
  1733  	err = assertstate.Add(s.state, snapDeclBar)
  1734  	c.Assert(err, IsNil)
  1735  
  1736  	fooInstanceRefresh := &snap.Info{
  1737  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1738  		InstanceKey: "instance",
  1739  	}
  1740  
  1741  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx)
  1742  	c.Assert(err, IsNil)
  1743  	c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh})
  1744  }
  1745  
  1746  func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnoreBothOneIgnored(c *C) {
  1747  	s.state.Lock()
  1748  	defer s.state.Unlock()
  1749  
  1750  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1751  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1752  		"refresh-control": []interface{}{"foo-id"},
  1753  	})
  1754  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1755  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1756  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1757  
  1758  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1759  	c.Assert(err, IsNil)
  1760  	err = assertstate.Add(s.state, s.dev1Acct)
  1761  	c.Assert(err, IsNil)
  1762  	err = assertstate.Add(s.state, snapDeclFoo)
  1763  	c.Assert(err, IsNil)
  1764  	err = assertstate.Add(s.state, snapDeclBar)
  1765  	c.Assert(err, IsNil)
  1766  
  1767  	fooRefresh := &snap.Info{
  1768  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1769  	}
  1770  	fooInstanceRefresh := &snap.Info{
  1771  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1772  		InstanceKey: "instance",
  1773  	}
  1774  
  1775  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx)
  1776  	c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`)
  1777  	c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh})
  1778  }
  1779  
  1780  func (s *assertMgrSuite) TestValidateRefreshesValidationOK(c *C) {
  1781  	s.state.Lock()
  1782  	defer s.state.Unlock()
  1783  
  1784  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1785  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1786  		"refresh-control": []interface{}{"foo-id"},
  1787  	})
  1788  	snapDeclBaz := s.snapDecl(c, "baz", map[string]interface{}{
  1789  		"refresh-control": []interface{}{"foo-id"},
  1790  	})
  1791  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1792  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1793  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1794  	s.stateFromDecl(c, snapDeclBaz, "", snap.R(1))
  1795  	snapstate.Set(s.state, "local", &snapstate.SnapState{
  1796  		Active: false,
  1797  		Sequence: []*snap.SideInfo{
  1798  			{RealName: "local", Revision: snap.R(-1)},
  1799  		},
  1800  		Current: snap.R(-1),
  1801  	})
  1802  
  1803  	// validation by bar
  1804  	headers := map[string]interface{}{
  1805  		"series":                 "16",
  1806  		"snap-id":                "bar-id",
  1807  		"approved-snap-id":       "foo-id",
  1808  		"approved-snap-revision": "9",
  1809  		"timestamp":              time.Now().Format(time.RFC3339),
  1810  	}
  1811  	barValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "")
  1812  	c.Assert(err, IsNil)
  1813  	err = s.storeSigning.Add(barValidation)
  1814  	c.Assert(err, IsNil)
  1815  
  1816  	// validation by baz
  1817  	headers = map[string]interface{}{
  1818  		"series":                 "16",
  1819  		"snap-id":                "baz-id",
  1820  		"approved-snap-id":       "foo-id",
  1821  		"approved-snap-revision": "9",
  1822  		"timestamp":              time.Now().Format(time.RFC3339),
  1823  	}
  1824  	bazValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "")
  1825  	c.Assert(err, IsNil)
  1826  	err = s.storeSigning.Add(bazValidation)
  1827  	c.Assert(err, IsNil)
  1828  
  1829  	err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1830  	c.Assert(err, IsNil)
  1831  	err = assertstate.Add(s.state, s.dev1Acct)
  1832  	c.Assert(err, IsNil)
  1833  	err = assertstate.Add(s.state, snapDeclFoo)
  1834  	c.Assert(err, IsNil)
  1835  	err = assertstate.Add(s.state, snapDeclBar)
  1836  	c.Assert(err, IsNil)
  1837  	err = assertstate.Add(s.state, snapDeclBaz)
  1838  	c.Assert(err, IsNil)
  1839  
  1840  	fooRefresh := &snap.Info{
  1841  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1842  	}
  1843  	fooInstanceRefresh := &snap.Info{
  1844  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1845  		InstanceKey: "instance",
  1846  	}
  1847  
  1848  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, nil, 0, s.trivialDeviceCtx)
  1849  	c.Assert(err, IsNil)
  1850  	c.Check(validated, DeepEquals, []*snap.Info{fooRefresh, fooInstanceRefresh})
  1851  }
  1852  
  1853  func (s *assertMgrSuite) TestValidateRefreshesRevokedValidation(c *C) {
  1854  	s.state.Lock()
  1855  	defer s.state.Unlock()
  1856  
  1857  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1858  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1859  		"refresh-control": []interface{}{"foo-id"},
  1860  	})
  1861  	snapDeclBaz := s.snapDecl(c, "baz", map[string]interface{}{
  1862  		"refresh-control": []interface{}{"foo-id"},
  1863  	})
  1864  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1865  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1866  	s.stateFromDecl(c, snapDeclBaz, "", snap.R(1))
  1867  	snapstate.Set(s.state, "local", &snapstate.SnapState{
  1868  		Active: false,
  1869  		Sequence: []*snap.SideInfo{
  1870  			{RealName: "local", Revision: snap.R(-1)},
  1871  		},
  1872  		Current: snap.R(-1),
  1873  	})
  1874  
  1875  	// validation by bar
  1876  	headers := map[string]interface{}{
  1877  		"series":                 "16",
  1878  		"snap-id":                "bar-id",
  1879  		"approved-snap-id":       "foo-id",
  1880  		"approved-snap-revision": "9",
  1881  		"timestamp":              time.Now().Format(time.RFC3339),
  1882  	}
  1883  	barValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "")
  1884  	c.Assert(err, IsNil)
  1885  	err = s.storeSigning.Add(barValidation)
  1886  	c.Assert(err, IsNil)
  1887  
  1888  	// revoked validation by baz
  1889  	headers = map[string]interface{}{
  1890  		"series":                 "16",
  1891  		"snap-id":                "baz-id",
  1892  		"approved-snap-id":       "foo-id",
  1893  		"approved-snap-revision": "9",
  1894  		"revoked":                "true",
  1895  		"timestamp":              time.Now().Format(time.RFC3339),
  1896  	}
  1897  	bazValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "")
  1898  	c.Assert(err, IsNil)
  1899  	err = s.storeSigning.Add(bazValidation)
  1900  	c.Assert(err, IsNil)
  1901  
  1902  	err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1903  	c.Assert(err, IsNil)
  1904  	err = assertstate.Add(s.state, s.dev1Acct)
  1905  	c.Assert(err, IsNil)
  1906  	err = assertstate.Add(s.state, snapDeclFoo)
  1907  	c.Assert(err, IsNil)
  1908  	err = assertstate.Add(s.state, snapDeclBar)
  1909  	c.Assert(err, IsNil)
  1910  	err = assertstate.Add(s.state, snapDeclBaz)
  1911  	c.Assert(err, IsNil)
  1912  
  1913  	fooRefresh := &snap.Info{
  1914  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1915  	}
  1916  
  1917  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx)
  1918  	c.Assert(err, ErrorMatches, `(?s).*cannot refresh "foo" to revision 9: validation by "baz" \(id "baz-id"\) revoked.*`)
  1919  	c.Check(validated, HasLen, 0)
  1920  }
  1921  
  1922  func (s *assertMgrSuite) TestBaseSnapDeclaration(c *C) {
  1923  	s.state.Lock()
  1924  	defer s.state.Unlock()
  1925  
  1926  	r1 := assertstest.MockBuiltinBaseDeclaration(nil)
  1927  	defer r1()
  1928  
  1929  	baseDecl, err := assertstate.BaseDeclaration(s.state)
  1930  	c.Assert(asserts.IsNotFound(err), Equals, true)
  1931  	c.Check(baseDecl, IsNil)
  1932  
  1933  	r2 := assertstest.MockBuiltinBaseDeclaration([]byte(`
  1934  type: base-declaration
  1935  authority-id: canonical
  1936  series: 16
  1937  plugs:
  1938    iface: true
  1939  `))
  1940  	defer r2()
  1941  
  1942  	baseDecl, err = assertstate.BaseDeclaration(s.state)
  1943  	c.Assert(err, IsNil)
  1944  	c.Check(baseDecl, NotNil)
  1945  	c.Check(baseDecl.PlugRule("iface"), NotNil)
  1946  }
  1947  
  1948  func (s *assertMgrSuite) TestSnapDeclaration(c *C) {
  1949  	s.state.Lock()
  1950  	defer s.state.Unlock()
  1951  
  1952  	// have a declaration in the system db
  1953  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1954  	c.Assert(err, IsNil)
  1955  	err = assertstate.Add(s.state, s.dev1Acct)
  1956  	c.Assert(err, IsNil)
  1957  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1958  	err = assertstate.Add(s.state, snapDeclFoo)
  1959  	c.Assert(err, IsNil)
  1960  
  1961  	_, err = assertstate.SnapDeclaration(s.state, "snap-id-other")
  1962  	c.Check(asserts.IsNotFound(err), Equals, true)
  1963  
  1964  	snapDecl, err := assertstate.SnapDeclaration(s.state, "foo-id")
  1965  	c.Assert(err, IsNil)
  1966  	c.Check(snapDecl.SnapName(), Equals, "foo")
  1967  }
  1968  
  1969  func (s *assertMgrSuite) TestAutoAliasesTemporaryFallback(c *C) {
  1970  	s.state.Lock()
  1971  	defer s.state.Unlock()
  1972  
  1973  	// prereqs for developer assertions in the system db
  1974  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1975  	c.Assert(err, IsNil)
  1976  	err = assertstate.Add(s.state, s.dev1Acct)
  1977  	c.Assert(err, IsNil)
  1978  
  1979  	// not from the store
  1980  	aliases, err := assertstate.AutoAliases(s.state, &snap.Info{SuggestedName: "local"})
  1981  	c.Assert(err, IsNil)
  1982  	c.Check(aliases, HasLen, 0)
  1983  
  1984  	// missing
  1985  	_, err = assertstate.AutoAliases(s.state, &snap.Info{
  1986  		SideInfo: snap.SideInfo{
  1987  			RealName: "baz",
  1988  			SnapID:   "baz-id",
  1989  		},
  1990  	})
  1991  	c.Check(err, ErrorMatches, `internal error: cannot find snap-declaration for installed snap "baz": snap-declaration \(baz-id; series:16\) not found`)
  1992  
  1993  	info := snaptest.MockInfo(c, `
  1994  name: foo
  1995  version: 0
  1996  apps:
  1997     cmd1:
  1998       aliases: [alias1]
  1999     cmd2:
  2000       aliases: [alias2]
  2001  `, &snap.SideInfo{
  2002  		RealName: "foo",
  2003  		SnapID:   "foo-id",
  2004  	})
  2005  
  2006  	// empty list
  2007  	// have a declaration in the system db
  2008  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  2009  	err = assertstate.Add(s.state, snapDeclFoo)
  2010  	c.Assert(err, IsNil)
  2011  	aliases, err = assertstate.AutoAliases(s.state, info)
  2012  	c.Assert(err, IsNil)
  2013  	c.Check(aliases, HasLen, 0)
  2014  
  2015  	// some aliases
  2016  	snapDeclFoo = s.snapDecl(c, "foo", map[string]interface{}{
  2017  		"auto-aliases": []interface{}{"alias1", "alias2", "alias3"},
  2018  		"revision":     "1",
  2019  	})
  2020  	err = assertstate.Add(s.state, snapDeclFoo)
  2021  	c.Assert(err, IsNil)
  2022  	aliases, err = assertstate.AutoAliases(s.state, info)
  2023  	c.Assert(err, IsNil)
  2024  	c.Check(aliases, DeepEquals, map[string]string{
  2025  		"alias1": "cmd1",
  2026  		"alias2": "cmd2",
  2027  	})
  2028  }
  2029  
  2030  func (s *assertMgrSuite) TestAutoAliasesExplicit(c *C) {
  2031  	s.state.Lock()
  2032  	defer s.state.Unlock()
  2033  
  2034  	// prereqs for developer assertions in the system db
  2035  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2036  	c.Assert(err, IsNil)
  2037  	err = assertstate.Add(s.state, s.dev1Acct)
  2038  	c.Assert(err, IsNil)
  2039  
  2040  	// not from the store
  2041  	aliases, err := assertstate.AutoAliases(s.state, &snap.Info{SuggestedName: "local"})
  2042  	c.Assert(err, IsNil)
  2043  	c.Check(aliases, HasLen, 0)
  2044  
  2045  	// missing
  2046  	_, err = assertstate.AutoAliases(s.state, &snap.Info{
  2047  		SideInfo: snap.SideInfo{
  2048  			RealName: "baz",
  2049  			SnapID:   "baz-id",
  2050  		},
  2051  	})
  2052  	c.Check(err, ErrorMatches, `internal error: cannot find snap-declaration for installed snap "baz": snap-declaration \(baz-id; series:16\) not found`)
  2053  
  2054  	// empty list
  2055  	// have a declaration in the system db
  2056  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  2057  	err = assertstate.Add(s.state, snapDeclFoo)
  2058  	c.Assert(err, IsNil)
  2059  	aliases, err = assertstate.AutoAliases(s.state, &snap.Info{
  2060  		SideInfo: snap.SideInfo{
  2061  			RealName: "foo",
  2062  			SnapID:   "foo-id",
  2063  		},
  2064  	})
  2065  	c.Assert(err, IsNil)
  2066  	c.Check(aliases, HasLen, 0)
  2067  
  2068  	// some aliases
  2069  	snapDeclFoo = s.snapDecl(c, "foo", map[string]interface{}{
  2070  		"aliases": []interface{}{
  2071  			map[string]interface{}{
  2072  				"name":   "alias1",
  2073  				"target": "cmd1",
  2074  			},
  2075  			map[string]interface{}{
  2076  				"name":   "alias2",
  2077  				"target": "cmd2",
  2078  			},
  2079  		},
  2080  		"revision": "1",
  2081  	})
  2082  	err = assertstate.Add(s.state, snapDeclFoo)
  2083  	c.Assert(err, IsNil)
  2084  	aliases, err = assertstate.AutoAliases(s.state, &snap.Info{
  2085  		SideInfo: snap.SideInfo{
  2086  			RealName: "foo",
  2087  			SnapID:   "foo-id",
  2088  		},
  2089  	})
  2090  	c.Assert(err, IsNil)
  2091  	c.Check(aliases, DeepEquals, map[string]string{
  2092  		"alias1": "cmd1",
  2093  		"alias2": "cmd2",
  2094  	})
  2095  }
  2096  
  2097  func (s *assertMgrSuite) TestPublisher(c *C) {
  2098  	s.state.Lock()
  2099  	defer s.state.Unlock()
  2100  
  2101  	// have a declaration in the system db
  2102  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2103  	c.Assert(err, IsNil)
  2104  	err = assertstate.Add(s.state, s.dev1Acct)
  2105  	c.Assert(err, IsNil)
  2106  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  2107  	err = assertstate.Add(s.state, snapDeclFoo)
  2108  	c.Assert(err, IsNil)
  2109  
  2110  	_, err = assertstate.SnapDeclaration(s.state, "snap-id-other")
  2111  	c.Check(asserts.IsNotFound(err), Equals, true)
  2112  
  2113  	acct, err := assertstate.Publisher(s.state, "foo-id")
  2114  	c.Assert(err, IsNil)
  2115  	c.Check(acct.AccountID(), Equals, s.dev1Acct.AccountID())
  2116  	c.Check(acct.Username(), Equals, "developer1")
  2117  }
  2118  
  2119  func (s *assertMgrSuite) TestStore(c *C) {
  2120  	s.state.Lock()
  2121  	defer s.state.Unlock()
  2122  
  2123  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2124  	c.Assert(err, IsNil)
  2125  	err = assertstate.Add(s.state, s.dev1Acct)
  2126  	c.Assert(err, IsNil)
  2127  	storeHeaders := map[string]interface{}{
  2128  		"store":       "foo",
  2129  		"operator-id": s.dev1Acct.AccountID(),
  2130  		"timestamp":   time.Now().Format(time.RFC3339),
  2131  	}
  2132  	fooStore, err := s.storeSigning.Sign(asserts.StoreType, storeHeaders, nil, "")
  2133  	c.Assert(err, IsNil)
  2134  	err = assertstate.Add(s.state, fooStore)
  2135  	c.Assert(err, IsNil)
  2136  
  2137  	_, err = assertstate.Store(s.state, "bar")
  2138  	c.Check(asserts.IsNotFound(err), Equals, true)
  2139  
  2140  	store, err := assertstate.Store(s.state, "foo")
  2141  	c.Assert(err, IsNil)
  2142  	c.Check(store.Store(), Equals, "foo")
  2143  }
  2144  
  2145  // validation-sets related tests
  2146  
  2147  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsNop(c *C) {
  2148  	s.state.Lock()
  2149  	defer s.state.Unlock()
  2150  
  2151  	s.setModel(sysdb.GenericClassicModel())
  2152  
  2153  	err := assertstate.RefreshValidationSetAssertions(s.state, 0)
  2154  	c.Assert(err, IsNil)
  2155  }
  2156  
  2157  func (s *assertMgrSuite) TestValidationSetAssertionsAutoRefresh(c *C) {
  2158  	s.state.Lock()
  2159  	defer s.state.Unlock()
  2160  
  2161  	// have a model and the store assertion available
  2162  	storeAs := s.setupModelAndStore(c)
  2163  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2164  
  2165  	// store key already present
  2166  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2167  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2168  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2169  
  2170  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2171  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2172  
  2173  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "3", "required")
  2174  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2175  
  2176  	tr := assertstate.ValidationSetTracking{
  2177  		AccountID: s.dev1Acct.AccountID(),
  2178  		Name:      "bar",
  2179  		Mode:      assertstate.Monitor,
  2180  		Current:   1,
  2181  	}
  2182  	assertstate.UpdateValidationSet(s.state, &tr)
  2183  
  2184  	c.Assert(assertstate.AutoRefreshAssertions(s.state, 0), IsNil)
  2185  
  2186  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2187  		"series":     "16",
  2188  		"account-id": s.dev1Acct.AccountID(),
  2189  		"name":       "bar",
  2190  		"sequence":   "2",
  2191  	})
  2192  	c.Assert(err, IsNil)
  2193  	c.Check(a.Revision(), Equals, 3)
  2194  }
  2195  
  2196  func (s *assertMgrSuite) TestValidationSetAssertionsAutoRefreshError(c *C) {
  2197  	s.state.Lock()
  2198  	defer s.state.Unlock()
  2199  
  2200  	// have a model and the store assertion available
  2201  	storeAs := s.setupModelAndStore(c)
  2202  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2203  
  2204  	tr := assertstate.ValidationSetTracking{
  2205  		AccountID: s.dev1Acct.AccountID(),
  2206  		Name:      "bar",
  2207  		Mode:      assertstate.Monitor,
  2208  		Current:   1,
  2209  	}
  2210  	assertstate.UpdateValidationSet(s.state, &tr)
  2211  	err := assertstate.AutoRefreshAssertions(s.state, 0)
  2212  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2213  }
  2214  
  2215  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsStoreError(c *C) {
  2216  	s.fakeStore.(*fakeStore).snapActionErr = &store.UnexpectedHTTPStatusError{StatusCode: 400}
  2217  	s.state.Lock()
  2218  	defer s.state.Unlock()
  2219  
  2220  	s.setModel(sysdb.GenericClassicModel())
  2221  
  2222  	// store key already present
  2223  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2224  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2225  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2226  
  2227  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2228  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2229  
  2230  	tr := assertstate.ValidationSetTracking{
  2231  		AccountID: s.dev1Acct.AccountID(),
  2232  		Name:      "bar",
  2233  		Mode:      assertstate.Monitor,
  2234  		Current:   1,
  2235  	}
  2236  	assertstate.UpdateValidationSet(s.state, &tr)
  2237  
  2238  	err := assertstate.RefreshValidationSetAssertions(s.state, 0)
  2239  	c.Assert(err, ErrorMatches, `cannot refresh validation set assertions: cannot : got unexpected HTTP status code 400.*`)
  2240  }
  2241  
  2242  func (s *assertMgrSuite) TestRefreshValidationSetAssertions(c *C) {
  2243  	s.state.Lock()
  2244  	defer s.state.Unlock()
  2245  
  2246  	// have a model and the store assertion available
  2247  	storeAs := s.setupModelAndStore(c)
  2248  	err := s.storeSigning.Add(storeAs)
  2249  	c.Assert(err, IsNil)
  2250  
  2251  	// store key already present
  2252  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2253  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2254  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2255  
  2256  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2257  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2258  
  2259  	vsetAs2 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2260  	err = s.storeSigning.Add(vsetAs2)
  2261  	c.Assert(err, IsNil)
  2262  
  2263  	tr := assertstate.ValidationSetTracking{
  2264  		AccountID: s.dev1Acct.AccountID(),
  2265  		Name:      "bar",
  2266  		Mode:      assertstate.Monitor,
  2267  		Current:   1,
  2268  	}
  2269  	assertstate.UpdateValidationSet(s.state, &tr)
  2270  
  2271  	err = assertstate.RefreshValidationSetAssertions(s.state, 0)
  2272  	c.Assert(err, IsNil)
  2273  
  2274  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2275  		"series":     "16",
  2276  		"account-id": s.dev1Acct.AccountID(),
  2277  		"name":       "bar",
  2278  		"sequence":   "1",
  2279  	})
  2280  	c.Assert(err, IsNil)
  2281  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2282  	c.Check(a.Revision(), Equals, 2)
  2283  
  2284  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2285  		{"account", "account-key", "validation-set"},
  2286  	})
  2287  
  2288  	// sequence changed in the store to 4
  2289  	vsetAs3 := s.validationSetAssert(c, "bar", "4", "3", "required")
  2290  	err = s.storeSigning.Add(vsetAs3)
  2291  	c.Assert(err, IsNil)
  2292  
  2293  	// sanity check - sequence 4 not available locally yet
  2294  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2295  		"series":     "16",
  2296  		"account-id": s.dev1Acct.AccountID(),
  2297  		"name":       "bar",
  2298  		"sequence":   "4",
  2299  	})
  2300  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2301  
  2302  	s.fakeStore.(*fakeStore).requestedTypes = nil
  2303  	err = assertstate.RefreshValidationSetAssertions(s.state, 0)
  2304  	c.Assert(err, IsNil)
  2305  
  2306  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2307  		{"account", "account-key", "validation-set"},
  2308  	})
  2309  
  2310  	// new sequence is available in the db
  2311  	a, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2312  		"series":     "16",
  2313  		"account-id": s.dev1Acct.AccountID(),
  2314  		"name":       "bar",
  2315  		"sequence":   "4",
  2316  	})
  2317  	c.Assert(err, IsNil)
  2318  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2319  
  2320  	// tracking current was updated
  2321  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "bar", &tr), IsNil)
  2322  	c.Check(tr.Current, Equals, 4)
  2323  }
  2324  
  2325  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsPinned(c *C) {
  2326  	s.state.Lock()
  2327  	defer s.state.Unlock()
  2328  
  2329  	// have a model and the store assertion available
  2330  	storeAs := s.setupModelAndStore(c)
  2331  	err := s.storeSigning.Add(storeAs)
  2332  	c.Assert(err, IsNil)
  2333  
  2334  	// store key already present
  2335  	err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2336  	c.Assert(err, IsNil)
  2337  
  2338  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2339  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2340  
  2341  	vsetAs1 := s.validationSetAssert(c, "bar", "2", "1", "required")
  2342  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2343  
  2344  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "5", "required")
  2345  	err = s.storeSigning.Add(vsetAs2)
  2346  	c.Assert(err, IsNil)
  2347  
  2348  	tr := assertstate.ValidationSetTracking{
  2349  		AccountID: s.dev1Acct.AccountID(),
  2350  		Name:      "bar",
  2351  		Mode:      assertstate.Monitor,
  2352  		Current:   2,
  2353  		PinnedAt:  2,
  2354  	}
  2355  	assertstate.UpdateValidationSet(s.state, &tr)
  2356  
  2357  	err = assertstate.RefreshValidationSetAssertions(s.state, 0)
  2358  	c.Assert(err, IsNil)
  2359  
  2360  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2361  		"series":     "16",
  2362  		"account-id": s.dev1Acct.AccountID(),
  2363  		"name":       "bar",
  2364  		"sequence":   "2",
  2365  	})
  2366  	c.Assert(err, IsNil)
  2367  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2368  	c.Check(a.(*asserts.ValidationSet).Sequence(), Equals, 2)
  2369  	c.Check(a.Revision(), Equals, 5)
  2370  
  2371  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2372  		{"account", "account-key", "validation-set"},
  2373  	})
  2374  
  2375  	// sequence changed in the store to 7
  2376  	vsetAs3 := s.validationSetAssert(c, "bar", "7", "8", "required")
  2377  	err = s.storeSigning.Add(vsetAs3)
  2378  	c.Assert(err, IsNil)
  2379  
  2380  	s.fakeStore.(*fakeStore).requestedTypes = nil
  2381  	err = assertstate.RefreshValidationSetAssertions(s.state, 0)
  2382  	c.Assert(err, IsNil)
  2383  
  2384  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2385  		{"account", "account-key", "validation-set"},
  2386  	})
  2387  
  2388  	// new sequence is not available in the db
  2389  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2390  		"series":     "16",
  2391  		"account-id": s.dev1Acct.AccountID(),
  2392  		"name":       "bar",
  2393  		"sequence":   "7",
  2394  	})
  2395  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2396  
  2397  	// tracking current remains at 2
  2398  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "bar", &tr), IsNil)
  2399  	c.Check(tr.Current, Equals, 2)
  2400  }
  2401  
  2402  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsLocalOnlyFailed(c *C) {
  2403  	st := s.state
  2404  	st.Lock()
  2405  	defer st.Unlock()
  2406  
  2407  	// have a model and the store assertion available
  2408  	storeAs := s.setupModelAndStore(c)
  2409  	err := s.storeSigning.Add(storeAs)
  2410  	c.Assert(err, IsNil)
  2411  
  2412  	// store key already present
  2413  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2414  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2415  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2416  
  2417  	// add to local database
  2418  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2419  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  2420  	vsetAs2 := s.validationSetAssert(c, "baz", "3", "1", "required")
  2421  	c.Assert(assertstate.Add(st, vsetAs2), IsNil)
  2422  
  2423  	// vset2 present and updated in the store
  2424  	vsetAs2_2 := s.validationSetAssert(c, "baz", "3", "2", "required")
  2425  	err = s.storeSigning.Add(vsetAs2_2)
  2426  	c.Assert(err, IsNil)
  2427  
  2428  	tr1 := assertstate.ValidationSetTracking{
  2429  		AccountID: s.dev1Acct.AccountID(),
  2430  		Name:      "bar",
  2431  		Mode:      assertstate.Monitor,
  2432  		Current:   1,
  2433  		PinnedAt:  1,
  2434  		LocalOnly: true,
  2435  	}
  2436  	tr2 := assertstate.ValidationSetTracking{
  2437  		AccountID: s.dev1Acct.AccountID(),
  2438  		Name:      "baz",
  2439  		Mode:      assertstate.Monitor,
  2440  		Current:   3,
  2441  		PinnedAt:  3,
  2442  	}
  2443  	assertstate.UpdateValidationSet(s.state, &tr1)
  2444  	assertstate.UpdateValidationSet(s.state, &tr2)
  2445  
  2446  	err = assertstate.RefreshValidationSetAssertions(s.state, 0)
  2447  	c.Assert(err, IsNil)
  2448  
  2449  	// sanity - local assertion vsetAs1 is the latest
  2450  	a, err := assertstate.DB(s.state).FindSequence(asserts.ValidationSetType, map[string]string{
  2451  		"series":     "16",
  2452  		"account-id": s.dev1Acct.AccountID(),
  2453  		"name":       "bar",
  2454  		"sequence":   "1",
  2455  	}, -1, -1)
  2456  	c.Assert(err, IsNil)
  2457  	vs := a.(*asserts.ValidationSet)
  2458  	c.Check(vs.Name(), Equals, "bar")
  2459  	c.Check(vs.Sequence(), Equals, 1)
  2460  	c.Check(vs.Revision(), Equals, 1)
  2461  
  2462  	// but vsetAs2 was updated with vsetAs2_2
  2463  	a, err = assertstate.DB(s.state).FindSequence(asserts.ValidationSetType, map[string]string{
  2464  		"series":     "16",
  2465  		"account-id": s.dev1Acct.AccountID(),
  2466  		"name":       "baz",
  2467  		"sequence":   "1",
  2468  	}, -1, -1)
  2469  	c.Assert(err, IsNil)
  2470  	vs = a.(*asserts.ValidationSet)
  2471  	c.Check(vs.Name(), Equals, "baz")
  2472  	c.Check(vs.Sequence(), Equals, 3)
  2473  	c.Check(vs.Revision(), Equals, 2)
  2474  }
  2475  
  2476  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsEnforcingModeHappyNotPinned(c *C) {
  2477  	s.state.Lock()
  2478  	defer s.state.Unlock()
  2479  
  2480  	// have a model and the store assertion available
  2481  	storeAs := s.setupModelAndStore(c)
  2482  	err := s.storeSigning.Add(storeAs)
  2483  	c.Assert(err, IsNil)
  2484  
  2485  	// store key already present
  2486  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2487  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2488  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2489  
  2490  	vsetAs1 := s.validationSetAssert(c, "foo", "1", "1", "required")
  2491  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2492  
  2493  	vsetAs2 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2494  	c.Assert(assertstate.Add(s.state, vsetAs2), IsNil)
  2495  
  2496  	// in the store
  2497  	vsetAs3 := s.validationSetAssert(c, "foo", "1", "2", "required")
  2498  	c.Assert(s.storeSigning.Add(vsetAs3), IsNil)
  2499  
  2500  	vsetAs4 := s.validationSetAssert(c, "bar", "2", "3", "required")
  2501  	c.Assert(s.storeSigning.Add(vsetAs4), IsNil)
  2502  
  2503  	tr := assertstate.ValidationSetTracking{
  2504  		AccountID: s.dev1Acct.AccountID(),
  2505  		Name:      "foo",
  2506  		Mode:      assertstate.Enforce,
  2507  		Current:   1,
  2508  	}
  2509  	assertstate.UpdateValidationSet(s.state, &tr)
  2510  	tr = assertstate.ValidationSetTracking{
  2511  		AccountID: s.dev1Acct.AccountID(),
  2512  		Name:      "bar",
  2513  		Mode:      assertstate.Enforce,
  2514  		Current:   1,
  2515  	}
  2516  	assertstate.UpdateValidationSet(s.state, &tr)
  2517  
  2518  	err = assertstate.RefreshValidationSetAssertions(s.state, 0)
  2519  	c.Assert(err, IsNil)
  2520  
  2521  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2522  		"series":     "16",
  2523  		"account-id": s.dev1Acct.AccountID(),
  2524  		"name":       "foo",
  2525  		"sequence":   "1",
  2526  	})
  2527  	c.Assert(err, IsNil)
  2528  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "foo")
  2529  	c.Check(a.Revision(), Equals, 2)
  2530  
  2531  	a, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2532  		"series":     "16",
  2533  		"account-id": s.dev1Acct.AccountID(),
  2534  		"name":       "bar",
  2535  		"sequence":   "2",
  2536  	})
  2537  	c.Assert(err, IsNil)
  2538  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2539  	c.Check(a.(*asserts.ValidationSet).Sequence(), Equals, 2)
  2540  	c.Check(a.Revision(), Equals, 3)
  2541  
  2542  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2543  		{"account", "account-key", "validation-set"},
  2544  	})
  2545  
  2546  	// tracking current was updated
  2547  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "bar", &tr), IsNil)
  2548  	c.Check(tr.Current, Equals, 2)
  2549  }
  2550  
  2551  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsEnforcingModeHappyPinned(c *C) {
  2552  	s.state.Lock()
  2553  	defer s.state.Unlock()
  2554  
  2555  	// have a model and the store assertion available
  2556  	storeAs := s.setupModelAndStore(c)
  2557  	err := s.storeSigning.Add(storeAs)
  2558  	c.Assert(err, IsNil)
  2559  
  2560  	// store key already present
  2561  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2562  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2563  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2564  
  2565  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2566  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2567  
  2568  	// in the store
  2569  	c.Assert(s.storeSigning.Add(vsetAs1), IsNil)
  2570  
  2571  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "3", "required")
  2572  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2573  
  2574  	tr := assertstate.ValidationSetTracking{
  2575  		AccountID: s.dev1Acct.AccountID(),
  2576  		Name:      "bar",
  2577  		Mode:      assertstate.Enforce,
  2578  		PinnedAt:  1,
  2579  		Current:   1,
  2580  	}
  2581  	assertstate.UpdateValidationSet(s.state, &tr)
  2582  
  2583  	c.Assert(assertstate.RefreshValidationSetAssertions(s.state, 0), IsNil)
  2584  
  2585  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2586  		"series":     "16",
  2587  		"account-id": s.dev1Acct.AccountID(),
  2588  		"name":       "bar",
  2589  		"sequence":   "1",
  2590  	})
  2591  	c.Assert(err, IsNil)
  2592  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2593  	c.Check(a.(*asserts.ValidationSet).Sequence(), Equals, 1)
  2594  	c.Check(a.Revision(), Equals, 2)
  2595  
  2596  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2597  		{"account", "account-key", "validation-set"},
  2598  	})
  2599  
  2600  	// tracking current was updated
  2601  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "bar", &tr), IsNil)
  2602  	c.Check(tr.Current, Equals, 1)
  2603  }
  2604  
  2605  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsEnforcingModeConflict(c *C) {
  2606  	s.state.Lock()
  2607  	defer s.state.Unlock()
  2608  
  2609  	logbuf, restore := logger.MockLogger()
  2610  	defer restore()
  2611  
  2612  	// have a model and the store assertion available
  2613  	storeAs := s.setupModelAndStore(c)
  2614  	err := s.storeSigning.Add(storeAs)
  2615  	c.Assert(err, IsNil)
  2616  
  2617  	// store key already present
  2618  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2619  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2620  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2621  
  2622  	vsetAs1 := s.validationSetAssert(c, "foo", "1", "1", "required")
  2623  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2624  
  2625  	vsetAs2 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2626  	c.Assert(assertstate.Add(s.state, vsetAs2), IsNil)
  2627  
  2628  	// in the store
  2629  	vsetAs3 := s.validationSetAssert(c, "foo", "2", "2", "invalid")
  2630  	c.Assert(s.storeSigning.Add(vsetAs3), IsNil)
  2631  
  2632  	tr := assertstate.ValidationSetTracking{
  2633  		AccountID: s.dev1Acct.AccountID(),
  2634  		Name:      "foo",
  2635  		Mode:      assertstate.Enforce,
  2636  		Current:   1,
  2637  	}
  2638  	assertstate.UpdateValidationSet(s.state, &tr)
  2639  	tr = assertstate.ValidationSetTracking{
  2640  		AccountID: s.dev1Acct.AccountID(),
  2641  		Name:      "bar",
  2642  		Mode:      assertstate.Enforce,
  2643  		Current:   1,
  2644  	}
  2645  	assertstate.UpdateValidationSet(s.state, &tr)
  2646  
  2647  	c.Assert(assertstate.RefreshValidationSetAssertions(s.state, 0), IsNil)
  2648  	c.Assert(logbuf.String(), Matches, `.*cannot refresh to conflicting validation set assertions: validation sets are in conflict:\n- cannot constrain snap "foo" as both invalid .* and required at revision 1.*\n`)
  2649  
  2650  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2651  		"series":     "16",
  2652  		"account-id": s.dev1Acct.AccountID(),
  2653  		"name":       "foo",
  2654  		"sequence":   "1",
  2655  	})
  2656  	c.Assert(err, IsNil)
  2657  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "foo")
  2658  	c.Check(a.Revision(), Equals, 1)
  2659  
  2660  	// new assertion wasn't committed to the database.
  2661  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2662  		"series":     "16",
  2663  		"account-id": s.dev1Acct.AccountID(),
  2664  		"name":       "foo",
  2665  		"sequence":   "2",
  2666  	})
  2667  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2668  
  2669  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2670  		{"account", "account-key", "validation-set"},
  2671  	})
  2672  
  2673  	// tracking current wasn't updated
  2674  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "foo", &tr), IsNil)
  2675  	c.Check(tr.Current, Equals, 1)
  2676  }
  2677  
  2678  func (s *assertMgrSuite) TestValidationSetAssertionForMonitorLocalFallbackForPinned(c *C) {
  2679  	st := s.state
  2680  
  2681  	st.Lock()
  2682  	defer st.Unlock()
  2683  
  2684  	// have a model and the store assertion available
  2685  	storeAs := s.setupModelAndStore(c)
  2686  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2687  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2688  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2689  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2690  
  2691  	// add to local database
  2692  	vsetAs := s.validationSetAssert(c, "bar", "1", "1", "required")
  2693  	c.Assert(assertstate.Add(st, vsetAs), IsNil)
  2694  
  2695  	opts := assertstate.ResolveOptions{AllowLocalFallback: true}
  2696  	vs, local, err := assertstate.ValidationSetAssertionForMonitor(st, s.dev1Acct.AccountID(), "bar", 1, true, 0, &opts)
  2697  	c.Assert(err, IsNil)
  2698  	c.Assert(vs, NotNil)
  2699  	c.Assert(local, Equals, true)
  2700  }
  2701  
  2702  func (s *assertMgrSuite) TestValidationSetAssertionForMonitorPinnedRefreshedFromStore(c *C) {
  2703  	st := s.state
  2704  
  2705  	st.Lock()
  2706  	defer st.Unlock()
  2707  
  2708  	// have a model and the store assertion available
  2709  	storeAs := s.setupModelAndStore(c)
  2710  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2711  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2712  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2713  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2714  
  2715  	// add to local database
  2716  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2717  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  2718  
  2719  	// newer revision available in the store
  2720  	vsetAs2 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2721  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2722  
  2723  	vs, local, err := assertstate.ValidationSetAssertionForMonitor(st, s.dev1Acct.AccountID(), "bar", 1, true, 0, nil)
  2724  	c.Assert(err, IsNil)
  2725  	c.Assert(local, Equals, false)
  2726  	c.Check(vs.Revision(), Equals, 2)
  2727  	c.Check(vs.Sequence(), Equals, 1)
  2728  }
  2729  
  2730  func (s *assertMgrSuite) TestValidationSetAssertionForMonitorUnpinnedRefreshedFromStore(c *C) {
  2731  	st := s.state
  2732  
  2733  	st.Lock()
  2734  	defer st.Unlock()
  2735  
  2736  	// have a model and the store assertion available
  2737  	storeAs := s.setupModelAndStore(c)
  2738  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2739  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2740  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2741  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2742  
  2743  	// add to local database
  2744  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2745  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  2746  
  2747  	// newer assertion available in the store
  2748  	vsetAs2 := s.validationSetAssert(c, "bar", "3", "1", "required")
  2749  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2750  
  2751  	vs, local, err := assertstate.ValidationSetAssertionForMonitor(st, s.dev1Acct.AccountID(), "bar", 0, false, 0, nil)
  2752  	c.Assert(err, IsNil)
  2753  	c.Assert(local, Equals, false)
  2754  	c.Check(vs.Revision(), Equals, 1)
  2755  	c.Check(vs.Sequence(), Equals, 3)
  2756  }
  2757  
  2758  func (s *assertMgrSuite) TestValidationSetAssertionForMonitorUnpinnedNotFound(c *C) {
  2759  	st := s.state
  2760  
  2761  	st.Lock()
  2762  	defer st.Unlock()
  2763  
  2764  	// have a model and the store assertion available
  2765  	storeAs := s.setupModelAndStore(c)
  2766  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2767  
  2768  	_, _, err := assertstate.ValidationSetAssertionForMonitor(st, s.dev1Acct.AccountID(), "bar", 0, false, 0, nil)
  2769  	c.Assert(err, ErrorMatches, fmt.Sprintf(`cannot fetch and resolve assertions:\n - validation-set/16/%s/bar: validation-set assertion not found.*`, s.dev1Acct.AccountID()))
  2770  }
  2771  
  2772  // Test for enforce mode
  2773  
  2774  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedHappy(c *C) {
  2775  	st := s.state
  2776  
  2777  	st.Lock()
  2778  	defer st.Unlock()
  2779  
  2780  	// have a model and the store assertion available
  2781  	storeAs := s.setupModelAndStore(c)
  2782  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2783  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2784  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2785  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2786  
  2787  	// add sequence to the store
  2788  	vsetAs := s.validationSetAssert(c, "bar", "2", "2", "required")
  2789  	c.Assert(s.storeSigning.Add(vsetAs), IsNil)
  2790  
  2791  	snaps := []*snapasserts.InstalledSnap{
  2792  		snapasserts.NewInstalledSnap("foo", "qOqKhntON3vR7kwEbVPsILm7bUViPDzz", snap.Revision{N: 1}),
  2793  		snapasserts.NewInstalledSnap("other", "ididididid", snap.Revision{N: 1}),
  2794  	}
  2795  
  2796  	sequence := 0
  2797  	vs, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2798  	c.Assert(err, IsNil)
  2799  	c.Check(vs.Revision(), Equals, 2)
  2800  	c.Check(vs.Sequence(), Equals, 2)
  2801  
  2802  	// and it has been committed
  2803  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2804  		"series":     "16",
  2805  		"account-id": s.dev1Acct.AccountID(),
  2806  		"name":       "bar",
  2807  		"sequence":   "2",
  2808  	})
  2809  	c.Assert(err, IsNil)
  2810  }
  2811  
  2812  func (s *assertMgrSuite) TestValidationSetAssertionForEnforcePinnedHappy(c *C) {
  2813  	st := s.state
  2814  
  2815  	st.Lock()
  2816  	defer st.Unlock()
  2817  
  2818  	// have a model and the store assertion available
  2819  	storeAs := s.setupModelAndStore(c)
  2820  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2821  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2822  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2823  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2824  
  2825  	// add sequence to the store
  2826  	vsetAs := s.validationSetAssert(c, "bar", "2", "2", "required")
  2827  	c.Assert(s.storeSigning.Add(vsetAs), IsNil)
  2828  
  2829  	snaps := []*snapasserts.InstalledSnap{
  2830  		snapasserts.NewInstalledSnap("foo", "qOqKhntON3vR7kwEbVPsILm7bUViPDzz", snap.Revision{N: 1}),
  2831  	}
  2832  
  2833  	sequence := 2
  2834  	vs, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2835  	c.Assert(err, IsNil)
  2836  	c.Check(vs.Revision(), Equals, 2)
  2837  	c.Check(vs.Sequence(), Equals, 2)
  2838  
  2839  	// and it has been committed
  2840  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2841  		"series":     "16",
  2842  		"account-id": s.dev1Acct.AccountID(),
  2843  		"name":       "bar",
  2844  		"sequence":   "2",
  2845  	})
  2846  	c.Assert(err, IsNil)
  2847  }
  2848  
  2849  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedUnhappyMissingSnap(c *C) {
  2850  	st := s.state
  2851  
  2852  	st.Lock()
  2853  	defer st.Unlock()
  2854  
  2855  	// have a model and the store assertion available
  2856  	storeAs := s.setupModelAndStore(c)
  2857  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2858  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2859  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2860  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2861  
  2862  	// add sequence to the store
  2863  	vsetAs := s.validationSetAssert(c, "bar", "2", "2", "required")
  2864  	c.Assert(s.storeSigning.Add(vsetAs), IsNil)
  2865  
  2866  	snaps := []*snapasserts.InstalledSnap{}
  2867  	sequence := 0
  2868  	_, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2869  	c.Assert(err, NotNil)
  2870  	verr, ok := err.(*snapasserts.ValidationSetsValidationError)
  2871  	c.Assert(ok, Equals, true)
  2872  	c.Check(verr.MissingSnaps, DeepEquals, map[string][]string{
  2873  		"foo": {fmt.Sprintf("%s/bar", s.dev1Acct.AccountID())},
  2874  	})
  2875  
  2876  	// and it hasn't been committed
  2877  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2878  		"series":     "16",
  2879  		"account-id": s.dev1Acct.AccountID(),
  2880  		"name":       "bar",
  2881  		"sequence":   "2",
  2882  	})
  2883  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2884  }
  2885  
  2886  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedUnhappyConflict(c *C) {
  2887  	st := s.state
  2888  
  2889  	st.Lock()
  2890  	defer st.Unlock()
  2891  
  2892  	// have a model and the store assertion available
  2893  	storeAs := s.setupModelAndStore(c)
  2894  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2895  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2896  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2897  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2898  
  2899  	// add an assertion to local database
  2900  	vsetAs := s.validationSetAssert(c, "boo", "4", "4", "invalid")
  2901  	c.Assert(assertstate.Add(st, vsetAs), IsNil)
  2902  	// and to the store (for refresh to be happy)
  2903  	c.Assert(s.storeSigning.Add(vsetAs), IsNil)
  2904  
  2905  	// and pretend it was tracked already
  2906  	tr := assertstate.ValidationSetTracking{
  2907  		AccountID: s.dev1Acct.AccountID(),
  2908  		Name:      "boo",
  2909  		Mode:      assertstate.Enforce,
  2910  		Current:   4,
  2911  	}
  2912  	assertstate.UpdateValidationSet(st, &tr)
  2913  
  2914  	// add sequence to the store, it conflicts with boo
  2915  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "2", "required")
  2916  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2917  
  2918  	snaps := []*snapasserts.InstalledSnap{}
  2919  	sequence := 0
  2920  	_, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2921  	c.Check(err, ErrorMatches, fmt.Sprintf(`validation sets are in conflict:\n- cannot constrain snap "foo" as both invalid \(%s/boo\) and required at revision 1 \(%s/bar\)`, s.dev1Acct.AccountID(), s.dev1Acct.AccountID()))
  2922  
  2923  	// and it hasn't been committed
  2924  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2925  		"series":     "16",
  2926  		"account-id": s.dev1Acct.AccountID(),
  2927  		"name":       "bar",
  2928  		"sequence":   "2",
  2929  	})
  2930  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2931  }
  2932  
  2933  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedAfterForgetHappy(c *C) {
  2934  	st := s.state
  2935  
  2936  	st.Lock()
  2937  	defer st.Unlock()
  2938  
  2939  	// have a model and the store assertion available
  2940  	storeAs := s.setupModelAndStore(c)
  2941  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2942  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2943  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2944  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2945  
  2946  	// add an old assertion to local database; it's not tracked which is the
  2947  	// case after 'snap validate --forget' (we don't prune assertions from db).
  2948  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2949  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  2950  
  2951  	// newer sequence available in the store
  2952  	vsetAs2 := s.validationSetAssert(c, "bar", "3", "5", "required")
  2953  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2954  
  2955  	snaps := []*snapasserts.InstalledSnap{
  2956  		snapasserts.NewInstalledSnap("foo", "qOqKhntON3vR7kwEbVPsILm7bUViPDzz", snap.Revision{N: 1}),
  2957  	}
  2958  
  2959  	sequence := 0
  2960  	vs, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2961  	c.Assert(err, IsNil)
  2962  	// new assertion got fetched
  2963  	c.Check(vs.Revision(), Equals, 5)
  2964  	c.Check(vs.Sequence(), Equals, 3)
  2965  
  2966  	// and it has been committed
  2967  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2968  		"series":     "16",
  2969  		"account-id": s.dev1Acct.AccountID(),
  2970  		"name":       "bar",
  2971  		"sequence":   "3",
  2972  	})
  2973  	c.Assert(err, IsNil)
  2974  }
  2975  
  2976  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedAfterMonitorHappy(c *C) {
  2977  	st := s.state
  2978  
  2979  	st.Lock()
  2980  	defer st.Unlock()
  2981  
  2982  	// have a model and the store assertion available
  2983  	storeAs := s.setupModelAndStore(c)
  2984  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2985  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2986  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2987  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2988  
  2989  	// add and old assertion to local database
  2990  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2991  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  2992  
  2993  	// and pretend it was tracked already in monitor mode
  2994  	tr := assertstate.ValidationSetTracking{
  2995  		AccountID: s.dev1Acct.AccountID(),
  2996  		Name:      "bar",
  2997  		Mode:      assertstate.Monitor,
  2998  		Current:   1,
  2999  	}
  3000  	assertstate.UpdateValidationSet(st, &tr)
  3001  
  3002  	// newer sequence available in the store
  3003  	vsetAs2 := s.validationSetAssert(c, "bar", "3", "5", "required")
  3004  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  3005  
  3006  	snaps := []*snapasserts.InstalledSnap{
  3007  		snapasserts.NewInstalledSnap("foo", "qOqKhntON3vR7kwEbVPsILm7bUViPDzz", snap.Revision{N: 1}),
  3008  	}
  3009  
  3010  	sequence := 0
  3011  	vs, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  3012  	c.Assert(err, IsNil)
  3013  	// new assertion got fetched
  3014  	c.Check(vs.Revision(), Equals, 5)
  3015  	c.Check(vs.Sequence(), Equals, 3)
  3016  
  3017  	// and it has been committed
  3018  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  3019  		"series":     "16",
  3020  		"account-id": s.dev1Acct.AccountID(),
  3021  		"name":       "bar",
  3022  		"sequence":   "3",
  3023  	})
  3024  	c.Assert(err, IsNil)
  3025  }
  3026  
  3027  func (s *assertMgrSuite) TestTemporaryDB(c *C) {
  3028  	st := s.state
  3029  
  3030  	st.Lock()
  3031  	defer st.Unlock()
  3032  
  3033  	err := assertstate.Add(st, s.storeSigning.StoreAccountKey(""))
  3034  	c.Assert(err, IsNil)
  3035  
  3036  	a, err := s.storeSigning.Sign(asserts.ModelType, map[string]interface{}{
  3037  		"type":         "model",
  3038  		"series":       "16",
  3039  		"authority-id": s.storeSigning.AuthorityID,
  3040  		"brand-id":     s.storeSigning.AuthorityID,
  3041  		"model":        "my-model",
  3042  		"architecture": "amd64",
  3043  		"gadget":       "gadget",
  3044  		"kernel":       "krnl",
  3045  		"timestamp":    time.Now().Format(time.RFC3339),
  3046  	}, nil, "")
  3047  	c.Assert(err, IsNil)
  3048  	model := a.(*asserts.Model)
  3049  
  3050  	aRev2, err := s.storeSigning.Sign(asserts.ModelType, map[string]interface{}{
  3051  		"type":         "model",
  3052  		"series":       "16",
  3053  		"authority-id": s.storeSigning.AuthorityID,
  3054  		"brand-id":     s.storeSigning.AuthorityID,
  3055  		"model":        "my-model",
  3056  		"architecture": "amd64",
  3057  		"gadget":       "gadget",
  3058  		"kernel":       "krnl",
  3059  		"timestamp":    time.Now().Format(time.RFC3339),
  3060  		"revision":     "2",
  3061  	}, nil, "")
  3062  	c.Assert(err, IsNil)
  3063  	modelRev2 := aRev2.(*asserts.Model)
  3064  
  3065  	hdrs := map[string]string{
  3066  		"series":   "16",
  3067  		"model":    "my-model",
  3068  		"brand-id": s.storeSigning.AuthorityID,
  3069  	}
  3070  	// model isn't found in the main DB
  3071  	_, err = assertstate.DB(st).Find(asserts.ModelType, hdrs)
  3072  	c.Assert(err, NotNil)
  3073  	c.Assert(asserts.IsNotFound(err), Equals, true)
  3074  	// let's get a temporary DB
  3075  	tempDB := assertstate.TemporaryDB(st)
  3076  	c.Assert(tempDB, NotNil)
  3077  	// and add the model to it
  3078  	err = tempDB.Add(model)
  3079  	c.Assert(err, IsNil)
  3080  	fromTemp, err := tempDB.Find(asserts.ModelType, hdrs)
  3081  	c.Assert(err, IsNil)
  3082  	c.Assert(fromTemp.(*asserts.Model), DeepEquals, model)
  3083  	// the model is only in the temp database
  3084  	_, err = assertstate.DB(st).Find(asserts.ModelType, hdrs)
  3085  	c.Assert(err, NotNil)
  3086  	c.Assert(asserts.IsNotFound(err), Equals, true)
  3087  
  3088  	// let's add it to the DB now
  3089  	err = assertstate.Add(st, model)
  3090  	c.Assert(err, IsNil)
  3091  	// such that we can lookup the revision 2 in a temporary DB
  3092  	tempDB = assertstate.TemporaryDB(st)
  3093  	c.Assert(tempDB, NotNil)
  3094  	err = tempDB.Add(modelRev2)
  3095  	c.Assert(err, IsNil)
  3096  	fromTemp, err = tempDB.Find(asserts.ModelType, hdrs)
  3097  	c.Assert(err, IsNil)
  3098  	c.Assert(fromTemp.(*asserts.Model), DeepEquals, modelRev2)
  3099  	// but the main DB still returns the old model
  3100  	fromDB, err := assertstate.DB(st).Find(asserts.ModelType, hdrs)
  3101  	c.Assert(err, IsNil)
  3102  	c.Assert(fromDB.(*asserts.Model), DeepEquals, model)
  3103  }