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