gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/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) TestRefreshAssertionsRefreshSnapDeclarationsAndValidationSets(c *C) {
   951  	s.state.Lock()
   952  	defer s.state.Unlock()
   953  
   954  	storeAs := s.setupModelAndStore(c)
   955  	snapDeclFoo := s.snapDecl(c, "foo", nil)
   956  
   957  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
   958  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
   959  
   960  	// previous state
   961  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
   962  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
   963  	c.Assert(assertstate.Add(s.state, snapDeclFoo), IsNil)
   964  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
   965  
   966  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
   967  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
   968  	tr := assertstate.ValidationSetTracking{
   969  		AccountID: s.dev1Acct.AccountID(),
   970  		Name:      "bar",
   971  		Mode:      assertstate.Monitor,
   972  		Current:   1,
   973  	}
   974  	assertstate.UpdateValidationSet(s.state, &tr)
   975  
   976  	// changed snap decl assertion
   977  	headers := map[string]interface{}{
   978  		"series":       "16",
   979  		"snap-id":      "foo-id",
   980  		"snap-name":    "fo-o",
   981  		"publisher-id": s.dev1Acct.AccountID(),
   982  		"timestamp":    time.Now().Format(time.RFC3339),
   983  		"revision":     "1",
   984  	}
   985  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
   986  	c.Assert(err, IsNil)
   987  	err = s.storeSigning.Add(snapDeclFoo1)
   988  	c.Assert(err, IsNil)
   989  
   990  	// changed validation set assertion
   991  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "3", "required")
   992  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
   993  
   994  	err = assertstate.RefreshSnapAssertions(s.state, 0)
   995  	c.Assert(err, IsNil)
   996  
   997  	a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
   998  		"series":  "16",
   999  		"snap-id": "foo-id",
  1000  	})
  1001  	c.Assert(err, IsNil)
  1002  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o")
  1003  
  1004  	a, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  1005  		"series":     "16",
  1006  		"account-id": s.dev1Acct.AccountID(),
  1007  		"name":       "bar",
  1008  		"sequence":   "2",
  1009  	})
  1010  	c.Assert(err, IsNil)
  1011  	c.Check(a.Revision(), Equals, 3)
  1012  
  1013  	c.Assert(err, IsNil)
  1014  	c.Check(s.fakeStore.(*fakeStore).opts.IsAutoRefresh, Equals, false)
  1015  }
  1016  
  1017  func (s *assertMgrSuite) TestRefreshSnapDeclarationsTooEarly(c *C) {
  1018  	s.state.Lock()
  1019  	defer s.state.Unlock()
  1020  
  1021  	r := snapstatetest.MockDeviceModel(nil)
  1022  	defer r()
  1023  
  1024  	err := assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1025  	c.Check(err, FitsTypeOf, &snapstate.ChangeConflictError{})
  1026  }
  1027  
  1028  func (s *assertMgrSuite) TestRefreshSnapDeclarationsNop(c *C) {
  1029  	s.state.Lock()
  1030  	defer s.state.Unlock()
  1031  
  1032  	s.setModel(sysdb.GenericClassicModel())
  1033  
  1034  	err := assertstate.RefreshSnapDeclarations(s.state, 0, &assertstate.RefreshAssertionsOptions{IsAutoRefresh: true})
  1035  	c.Assert(err, IsNil)
  1036  	c.Check(s.fakeStore.(*fakeStore).opts.IsAutoRefresh, Equals, true)
  1037  }
  1038  
  1039  func (s *assertMgrSuite) TestRefreshSnapDeclarationsNoStore(c *C) {
  1040  	s.state.Lock()
  1041  	defer s.state.Unlock()
  1042  
  1043  	s.setModel(sysdb.GenericClassicModel())
  1044  
  1045  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1046  	snapDeclBar := s.snapDecl(c, "bar", nil)
  1047  
  1048  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1049  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1050  	snapstate.Set(s.state, "local", &snapstate.SnapState{
  1051  		Active: false,
  1052  		Sequence: []*snap.SideInfo{
  1053  			{RealName: "local", Revision: snap.R(-1)},
  1054  		},
  1055  		Current: snap.R(-1),
  1056  	})
  1057  
  1058  	// previous state
  1059  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1060  	c.Assert(err, IsNil)
  1061  	err = assertstate.Add(s.state, s.dev1Acct)
  1062  	c.Assert(err, IsNil)
  1063  	err = assertstate.Add(s.state, snapDeclFoo)
  1064  	c.Assert(err, IsNil)
  1065  	err = assertstate.Add(s.state, snapDeclBar)
  1066  	c.Assert(err, IsNil)
  1067  
  1068  	// one changed assertion
  1069  	headers := map[string]interface{}{
  1070  		"series":       "16",
  1071  		"snap-id":      "foo-id",
  1072  		"snap-name":    "fo-o",
  1073  		"publisher-id": s.dev1Acct.AccountID(),
  1074  		"timestamp":    time.Now().Format(time.RFC3339),
  1075  		"revision":     "1",
  1076  	}
  1077  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1078  	c.Assert(err, IsNil)
  1079  	err = s.storeSigning.Add(snapDeclFoo1)
  1080  	c.Assert(err, IsNil)
  1081  
  1082  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1083  	c.Assert(err, IsNil)
  1084  
  1085  	a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1086  		"series":  "16",
  1087  		"snap-id": "foo-id",
  1088  	})
  1089  	c.Assert(err, IsNil)
  1090  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o")
  1091  
  1092  	// another one
  1093  	// one changed assertion
  1094  	headers = s.dev1Acct.Headers()
  1095  	headers["display-name"] = "Dev 1 edited display-name"
  1096  	headers["revision"] = "1"
  1097  	dev1Acct1, err := s.storeSigning.Sign(asserts.AccountType, headers, nil, "")
  1098  	c.Assert(err, IsNil)
  1099  	err = s.storeSigning.Add(dev1Acct1)
  1100  	c.Assert(err, IsNil)
  1101  
  1102  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1103  	c.Assert(err, IsNil)
  1104  
  1105  	a, err = assertstate.DB(s.state).Find(asserts.AccountType, map[string]string{
  1106  		"account-id": s.dev1Acct.AccountID(),
  1107  	})
  1108  	c.Assert(err, IsNil)
  1109  	c.Check(a.(*asserts.Account).DisplayName(), Equals, "Dev 1 edited display-name")
  1110  
  1111  	// change snap decl to something that has a too new format
  1112  	s.fakeStore.(*fakeStore).maxDeclSupportedFormat = 999
  1113  	(func() {
  1114  		restore := asserts.MockMaxSupportedFormat(asserts.SnapDeclarationType, 999)
  1115  		defer restore()
  1116  
  1117  		headers := map[string]interface{}{
  1118  			"format":       "999",
  1119  			"series":       "16",
  1120  			"snap-id":      "foo-id",
  1121  			"snap-name":    "foo",
  1122  			"publisher-id": s.dev1Acct.AccountID(),
  1123  			"timestamp":    time.Now().Format(time.RFC3339),
  1124  			"revision":     "2",
  1125  		}
  1126  
  1127  		snapDeclFoo2, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1128  		c.Assert(err, IsNil)
  1129  		err = s.storeSigning.Add(snapDeclFoo2)
  1130  		c.Assert(err, IsNil)
  1131  	})()
  1132  
  1133  	// no error, kept the old one
  1134  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1135  	c.Assert(err, IsNil)
  1136  
  1137  	a, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1138  		"series":  "16",
  1139  		"snap-id": "foo-id",
  1140  	})
  1141  	c.Assert(err, IsNil)
  1142  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o")
  1143  	c.Check(a.(*asserts.SnapDeclaration).Revision(), Equals, 1)
  1144  }
  1145  
  1146  func (s *assertMgrSuite) TestRefreshSnapDeclarationsChangingKey(c *C) {
  1147  	s.state.Lock()
  1148  	defer s.state.Unlock()
  1149  
  1150  	s.setModel(sysdb.GenericClassicModel())
  1151  
  1152  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1153  
  1154  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1155  
  1156  	// previous state
  1157  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1158  	c.Assert(err, IsNil)
  1159  	err = assertstate.Add(s.state, s.dev1Acct)
  1160  	c.Assert(err, IsNil)
  1161  	err = assertstate.Add(s.state, snapDeclFoo)
  1162  	c.Assert(err, IsNil)
  1163  
  1164  	storePrivKey2, _ := assertstest.GenerateKey(752)
  1165  	err = s.storeSigning.ImportKey(storePrivKey2)
  1166  	c.Assert(err, IsNil)
  1167  	storeKey2 := assertstest.NewAccountKey(s.storeSigning.RootSigning, s.storeSigning.TrustedAccount, map[string]interface{}{
  1168  		"name": "store2",
  1169  	}, storePrivKey2.PublicKey(), "")
  1170  	err = s.storeSigning.Add(storeKey2)
  1171  	c.Assert(err, IsNil)
  1172  
  1173  	// one changed assertion signed with different key
  1174  	headers := map[string]interface{}{
  1175  		"series":       "16",
  1176  		"snap-id":      "foo-id",
  1177  		"snap-name":    "foo",
  1178  		"publisher-id": s.dev1Acct.AccountID(),
  1179  		"timestamp":    time.Now().Format(time.RFC3339),
  1180  		"revision":     "1",
  1181  	}
  1182  	storeKey2ID := storePrivKey2.PublicKey().ID()
  1183  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, storeKey2ID)
  1184  	c.Assert(err, IsNil)
  1185  	c.Check(snapDeclFoo1.SignKeyID(), Not(Equals), snapDeclFoo.SignKeyID())
  1186  	err = s.storeSigning.Add(snapDeclFoo1)
  1187  	c.Assert(err, IsNil)
  1188  
  1189  	_, err = storeKey2.Ref().Resolve(assertstate.DB(s.state).Find)
  1190  	c.Check(asserts.IsNotFound(err), Equals, true)
  1191  
  1192  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1193  	c.Assert(err, IsNil)
  1194  
  1195  	a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1196  		"series":  "16",
  1197  		"snap-id": "foo-id",
  1198  	})
  1199  	c.Assert(err, IsNil)
  1200  	c.Check(a.Revision(), Equals, 1)
  1201  	c.Check(a.SignKeyID(), Equals, storeKey2ID)
  1202  
  1203  	// key was fetched as well
  1204  	_, err = storeKey2.Ref().Resolve(assertstate.DB(s.state).Find)
  1205  	c.Check(err, IsNil)
  1206  }
  1207  
  1208  func (s *assertMgrSuite) TestRefreshSnapDeclarationsWithStore(c *C) {
  1209  	s.state.Lock()
  1210  	defer s.state.Unlock()
  1211  
  1212  	storeAs := s.setupModelAndStore(c)
  1213  
  1214  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1215  
  1216  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1217  
  1218  	// previous state
  1219  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1220  	c.Assert(err, IsNil)
  1221  	err = assertstate.Add(s.state, s.dev1Acct)
  1222  	c.Assert(err, IsNil)
  1223  	err = assertstate.Add(s.state, snapDeclFoo)
  1224  	c.Assert(err, IsNil)
  1225  
  1226  	// one changed assertion
  1227  	headers := map[string]interface{}{
  1228  		"series":       "16",
  1229  		"snap-id":      "foo-id",
  1230  		"snap-name":    "fo-o",
  1231  		"publisher-id": s.dev1Acct.AccountID(),
  1232  		"timestamp":    time.Now().Format(time.RFC3339),
  1233  		"revision":     "1",
  1234  	}
  1235  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1236  	c.Assert(err, IsNil)
  1237  	err = s.storeSigning.Add(snapDeclFoo1)
  1238  	c.Assert(err, IsNil)
  1239  
  1240  	// store assertion is missing
  1241  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1242  	c.Assert(err, IsNil)
  1243  
  1244  	a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1245  		"series":  "16",
  1246  		"snap-id": "foo-id",
  1247  	})
  1248  	c.Assert(err, IsNil)
  1249  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "fo-o")
  1250  
  1251  	// changed again
  1252  	headers = map[string]interface{}{
  1253  		"series":       "16",
  1254  		"snap-id":      "foo-id",
  1255  		"snap-name":    "f-oo",
  1256  		"publisher-id": s.dev1Acct.AccountID(),
  1257  		"timestamp":    time.Now().Format(time.RFC3339),
  1258  		"revision":     "2",
  1259  	}
  1260  	snapDeclFoo2, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1261  	c.Assert(err, IsNil)
  1262  	err = s.storeSigning.Add(snapDeclFoo2)
  1263  	c.Assert(err, IsNil)
  1264  
  1265  	// store assertion is available
  1266  	err = s.storeSigning.Add(storeAs)
  1267  	c.Assert(err, IsNil)
  1268  
  1269  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1270  	c.Assert(err, IsNil)
  1271  
  1272  	a, err = assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1273  		"series":  "16",
  1274  		"snap-id": "foo-id",
  1275  	})
  1276  	c.Assert(err, IsNil)
  1277  	c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, "f-oo")
  1278  
  1279  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1280  		"store": "my-brand-store",
  1281  	})
  1282  	c.Assert(err, IsNil)
  1283  
  1284  	// store assertion has changed
  1285  	a, err = s.storeSigning.Sign(asserts.StoreType, map[string]interface{}{
  1286  		"authority-id": s.storeSigning.AuthorityID,
  1287  		"operator-id":  s.storeSigning.AuthorityID,
  1288  		"store":        "my-brand-store",
  1289  		"location":     "the-cloud",
  1290  		"revision":     "1",
  1291  		"timestamp":    time.Now().Format(time.RFC3339),
  1292  	}, nil, "")
  1293  	c.Assert(err, IsNil)
  1294  	storeAs = a.(*asserts.Store)
  1295  	err = s.storeSigning.Add(storeAs)
  1296  	c.Assert(err, IsNil)
  1297  
  1298  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1299  	c.Assert(err, IsNil)
  1300  	a, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1301  		"store": "my-brand-store",
  1302  	})
  1303  	c.Assert(err, IsNil)
  1304  	c.Check(a.(*asserts.Store).Location(), Equals, "the-cloud")
  1305  }
  1306  
  1307  func (s *assertMgrSuite) TestRefreshSnapDeclarationsDownloadError(c *C) {
  1308  	s.state.Lock()
  1309  	defer s.state.Unlock()
  1310  
  1311  	s.setModel(sysdb.GenericClassicModel())
  1312  
  1313  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1314  
  1315  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1316  
  1317  	// previous state
  1318  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1319  	c.Assert(err, IsNil)
  1320  	err = assertstate.Add(s.state, s.dev1Acct)
  1321  	c.Assert(err, IsNil)
  1322  	err = assertstate.Add(s.state, snapDeclFoo)
  1323  	c.Assert(err, IsNil)
  1324  
  1325  	// one changed assertion
  1326  	headers := map[string]interface{}{
  1327  		"series":       "16",
  1328  		"snap-id":      "foo-id",
  1329  		"snap-name":    "fo-o",
  1330  		"publisher-id": s.dev1Acct.AccountID(),
  1331  		"timestamp":    time.Now().Format(time.RFC3339),
  1332  		"revision":     "1",
  1333  	}
  1334  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1335  	c.Assert(err, IsNil)
  1336  	err = s.storeSigning.Add(snapDeclFoo1)
  1337  	c.Assert(err, IsNil)
  1338  
  1339  	s.fakeStore.(*fakeStore).downloadAssertionsErr = errors.New("download error")
  1340  
  1341  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1342  	c.Assert(err, ErrorMatches, `cannot refresh snap-declarations for snaps:
  1343   - foo: download error`)
  1344  }
  1345  
  1346  func (s *assertMgrSuite) TestRefreshSnapDeclarationsPersistentNetworkError(c *C) {
  1347  	s.state.Lock()
  1348  	defer s.state.Unlock()
  1349  
  1350  	s.setModel(sysdb.GenericClassicModel())
  1351  
  1352  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1353  
  1354  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1355  
  1356  	// previous state
  1357  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1358  	c.Assert(err, IsNil)
  1359  	err = assertstate.Add(s.state, s.dev1Acct)
  1360  	c.Assert(err, IsNil)
  1361  	err = assertstate.Add(s.state, snapDeclFoo)
  1362  	c.Assert(err, IsNil)
  1363  
  1364  	// one changed assertion
  1365  	headers := map[string]interface{}{
  1366  		"series":       "16",
  1367  		"snap-id":      "foo-id",
  1368  		"snap-name":    "fo-o",
  1369  		"publisher-id": s.dev1Acct.AccountID(),
  1370  		"timestamp":    time.Now().Format(time.RFC3339),
  1371  		"revision":     "1",
  1372  	}
  1373  	snapDeclFoo1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1374  	c.Assert(err, IsNil)
  1375  	err = s.storeSigning.Add(snapDeclFoo1)
  1376  	c.Assert(err, IsNil)
  1377  
  1378  	pne := new(httputil.PersistentNetworkError)
  1379  	s.fakeStore.(*fakeStore).snapActionErr = pne
  1380  
  1381  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1382  	c.Assert(err, Equals, pne)
  1383  }
  1384  
  1385  func (s *assertMgrSuite) TestRefreshSnapDeclarationsNoStoreFallback(c *C) {
  1386  	// test that if we get a 4xx or 500 error from the store trying bulk
  1387  	// assertion refresh we fall back to the old logic
  1388  	s.fakeStore.(*fakeStore).snapActionErr = &store.UnexpectedHTTPStatusError{StatusCode: 400}
  1389  
  1390  	logbuf, restore := logger.MockLogger()
  1391  	defer restore()
  1392  
  1393  	s.TestRefreshSnapDeclarationsNoStore(c)
  1394  
  1395  	c.Check(logbuf.String(), Matches, "(?m).*bulk refresh of snap-declarations failed, falling back to one-by-one assertion fetching:.*HTTP status code 400.*")
  1396  }
  1397  
  1398  func (s *assertMgrSuite) TestRefreshSnapDeclarationsNoStoreFallbackUnexpectedSnapActionError(c *C) {
  1399  	// test that if we get an unexpected SnapAction error from the
  1400  	// store trying bulk assertion refresh we fall back to the old
  1401  	// logic
  1402  	s.fakeStore.(*fakeStore).snapActionErr = &store.SnapActionError{
  1403  		NoResults: true,
  1404  		Other:     []error{errors.New("unexpected error")},
  1405  	}
  1406  
  1407  	logbuf, restore := logger.MockLogger()
  1408  	defer restore()
  1409  
  1410  	s.TestRefreshSnapDeclarationsNoStore(c)
  1411  
  1412  	c.Check(logbuf.String(), Matches, "(?m).*bulk refresh of snap-declarations failed, falling back to one-by-one assertion fetching:.*unexpected error.*")
  1413  }
  1414  
  1415  func (s *assertMgrSuite) TestRefreshSnapDeclarationsWithStoreFallback(c *C) {
  1416  	// test that if we get a 4xx or 500 error from the store trying bulk
  1417  	// assertion refresh we fall back to the old logic
  1418  	s.fakeStore.(*fakeStore).snapActionErr = &store.UnexpectedHTTPStatusError{StatusCode: 500}
  1419  
  1420  	logbuf, restore := logger.MockLogger()
  1421  	defer restore()
  1422  
  1423  	s.TestRefreshSnapDeclarationsWithStore(c)
  1424  
  1425  	c.Check(logbuf.String(), Matches, "(?m).*bulk refresh of snap-declarations failed, falling back to one-by-one assertion fetching:.*HTTP status code 500.*")
  1426  }
  1427  
  1428  // the following tests cover what happens when refreshing snap-declarations
  1429  // need to support overflowing the chosen asserts.Pool maximum groups
  1430  
  1431  func (s *assertMgrSuite) testRefreshSnapDeclarationsMany(c *C, n int) error {
  1432  	// reduce maxGroups to test and stress the logic that deals
  1433  	// with overflowing it
  1434  	s.AddCleanup(assertstate.MockMaxGroups(16))
  1435  
  1436  	// previous state
  1437  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1438  	c.Assert(err, IsNil)
  1439  	err = assertstate.Add(s.state, s.dev1Acct)
  1440  	c.Assert(err, IsNil)
  1441  
  1442  	for i := 1; i <= n; i++ {
  1443  		name := fmt.Sprintf("foo%d", i)
  1444  		snapDeclFooX := s.snapDecl(c, name, nil)
  1445  
  1446  		s.stateFromDecl(c, snapDeclFooX, "", snap.R(7+i))
  1447  
  1448  		// previous state
  1449  		err = assertstate.Add(s.state, snapDeclFooX)
  1450  		c.Assert(err, IsNil)
  1451  
  1452  		// make an update on top
  1453  		headers := map[string]interface{}{
  1454  			"series":       "16",
  1455  			"snap-id":      name + "-id",
  1456  			"snap-name":    fmt.Sprintf("fo-o-%d", i),
  1457  			"publisher-id": s.dev1Acct.AccountID(),
  1458  			"timestamp":    time.Now().Format(time.RFC3339),
  1459  			"revision":     "1",
  1460  		}
  1461  		snapDeclFooX1, err := s.storeSigning.Sign(asserts.SnapDeclarationType, headers, nil, "")
  1462  		c.Assert(err, IsNil)
  1463  		err = s.storeSigning.Add(snapDeclFooX1)
  1464  		c.Assert(err, IsNil)
  1465  	}
  1466  
  1467  	err = assertstate.RefreshSnapDeclarations(s.state, 0, nil)
  1468  	if err != nil {
  1469  		// fot the caller to check
  1470  		return err
  1471  	}
  1472  
  1473  	// check we got the updates
  1474  	for i := 1; i <= n; i++ {
  1475  		name := fmt.Sprintf("foo%d", i)
  1476  		a, err := assertstate.DB(s.state).Find(asserts.SnapDeclarationType, map[string]string{
  1477  			"series":  "16",
  1478  			"snap-id": name + "-id",
  1479  		})
  1480  		c.Assert(err, IsNil)
  1481  		c.Check(a.(*asserts.SnapDeclaration).SnapName(), Equals, fmt.Sprintf("fo-o-%d", i))
  1482  	}
  1483  
  1484  	return nil
  1485  }
  1486  
  1487  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany14NoStore(c *C) {
  1488  	s.state.Lock()
  1489  	defer s.state.Unlock()
  1490  	s.setModel(sysdb.GenericClassicModel())
  1491  
  1492  	err := s.testRefreshSnapDeclarationsMany(c, 14)
  1493  	c.Assert(err, IsNil)
  1494  
  1495  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1496  		{"account", "account-key", "snap-declaration"},
  1497  	})
  1498  }
  1499  
  1500  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany16NoStore(c *C) {
  1501  	s.state.Lock()
  1502  	defer s.state.Unlock()
  1503  	s.setModel(sysdb.GenericClassicModel())
  1504  
  1505  	err := s.testRefreshSnapDeclarationsMany(c, 16)
  1506  	c.Assert(err, IsNil)
  1507  
  1508  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1509  		{"account", "account-key", "snap-declaration"},
  1510  	})
  1511  }
  1512  
  1513  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany16WithStore(c *C) {
  1514  	s.state.Lock()
  1515  	defer s.state.Unlock()
  1516  	// have a model and the store assertion available
  1517  	storeAs := s.setupModelAndStore(c)
  1518  	err := s.storeSigning.Add(storeAs)
  1519  	c.Assert(err, IsNil)
  1520  
  1521  	err = s.testRefreshSnapDeclarationsMany(c, 16)
  1522  	c.Assert(err, IsNil)
  1523  
  1524  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1525  		// first 16 groups request
  1526  		{"account", "account-key", "snap-declaration"},
  1527  		// final separate request covering store only
  1528  		{"store"},
  1529  	})
  1530  
  1531  	// store assertion was also fetched
  1532  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1533  		"store": "my-brand-store",
  1534  	})
  1535  	c.Assert(err, IsNil)
  1536  }
  1537  
  1538  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany17NoStore(c *C) {
  1539  	s.state.Lock()
  1540  	defer s.state.Unlock()
  1541  	s.setModel(sysdb.GenericClassicModel())
  1542  
  1543  	err := s.testRefreshSnapDeclarationsMany(c, 17)
  1544  	c.Assert(err, IsNil)
  1545  
  1546  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1547  		// first 16 groups request
  1548  		{"account", "account-key", "snap-declaration"},
  1549  		// final separate request for the rest
  1550  		{"snap-declaration"},
  1551  	})
  1552  }
  1553  
  1554  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany17NoStoreMergeErrors(c *C) {
  1555  	s.state.Lock()
  1556  	defer s.state.Unlock()
  1557  	s.setModel(sysdb.GenericClassicModel())
  1558  
  1559  	s.fakeStore.(*fakeStore).downloadAssertionsErr = errors.New("download error")
  1560  
  1561  	err := s.testRefreshSnapDeclarationsMany(c, 17)
  1562  	c.Check(err, ErrorMatches, `(?s)cannot refresh snap-declarations for snaps:
  1563   - foo1: download error.* - foo9: download error`)
  1564  	// all foo* snaps accounted for
  1565  	c.Check(strings.Count(err.Error(), "foo"), Equals, 17)
  1566  
  1567  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1568  		// first 16 groups request
  1569  		{"account", "account-key", "snap-declaration"},
  1570  		// final separate request for the rest
  1571  		{"snap-declaration"},
  1572  	})
  1573  }
  1574  
  1575  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany31WithStore(c *C) {
  1576  	s.state.Lock()
  1577  	defer s.state.Unlock()
  1578  	// have a model and the store assertion available
  1579  	storeAs := s.setupModelAndStore(c)
  1580  	err := s.storeSigning.Add(storeAs)
  1581  	c.Assert(err, IsNil)
  1582  
  1583  	err = s.testRefreshSnapDeclarationsMany(c, 31)
  1584  	c.Assert(err, IsNil)
  1585  
  1586  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1587  		// first 16 groups request
  1588  		{"account", "account-key", "snap-declaration"},
  1589  		// final separate request for the rest and store
  1590  		{"snap-declaration", "store"},
  1591  	})
  1592  
  1593  	// store assertion was also fetched
  1594  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1595  		"store": "my-brand-store",
  1596  	})
  1597  	c.Assert(err, IsNil)
  1598  }
  1599  
  1600  func (s *assertMgrSuite) TestRefreshSnapDeclarationsMany32WithStore(c *C) {
  1601  	s.state.Lock()
  1602  	defer s.state.Unlock()
  1603  	// have a model and the store assertion available
  1604  	storeAs := s.setupModelAndStore(c)
  1605  	err := s.storeSigning.Add(storeAs)
  1606  	c.Assert(err, IsNil)
  1607  
  1608  	err = s.testRefreshSnapDeclarationsMany(c, 32)
  1609  	c.Assert(err, IsNil)
  1610  
  1611  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  1612  		// first 16 groups request
  1613  		{"account", "account-key", "snap-declaration"},
  1614  		// 2nd round request
  1615  		{"snap-declaration"},
  1616  		// final separate request covering store
  1617  		{"store"},
  1618  	})
  1619  
  1620  	// store assertion was also fetched
  1621  	_, err = assertstate.DB(s.state).Find(asserts.StoreType, map[string]string{
  1622  		"store": "my-brand-store",
  1623  	})
  1624  	c.Assert(err, IsNil)
  1625  }
  1626  
  1627  func (s *assertMgrSuite) TestValidateRefreshesNothing(c *C) {
  1628  	s.state.Lock()
  1629  	defer s.state.Unlock()
  1630  
  1631  	validated, err := assertstate.ValidateRefreshes(s.state, nil, nil, 0, s.trivialDeviceCtx)
  1632  	c.Assert(err, IsNil)
  1633  	c.Check(validated, HasLen, 0)
  1634  }
  1635  
  1636  func (s *assertMgrSuite) TestValidateRefreshesNoControl(c *C) {
  1637  	s.state.Lock()
  1638  	defer s.state.Unlock()
  1639  
  1640  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1641  	snapDeclBar := s.snapDecl(c, "bar", nil)
  1642  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1643  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1644  
  1645  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1646  	c.Assert(err, IsNil)
  1647  	err = assertstate.Add(s.state, s.dev1Acct)
  1648  	c.Assert(err, IsNil)
  1649  	err = assertstate.Add(s.state, snapDeclFoo)
  1650  	c.Assert(err, IsNil)
  1651  	err = assertstate.Add(s.state, snapDeclBar)
  1652  	c.Assert(err, IsNil)
  1653  
  1654  	fooRefresh := &snap.Info{
  1655  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1656  	}
  1657  
  1658  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx)
  1659  	c.Assert(err, IsNil)
  1660  	c.Check(validated, DeepEquals, []*snap.Info{fooRefresh})
  1661  }
  1662  
  1663  func (s *assertMgrSuite) TestValidateRefreshesMissingValidation(c *C) {
  1664  	s.state.Lock()
  1665  	defer s.state.Unlock()
  1666  
  1667  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1668  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1669  		"refresh-control": []interface{}{"foo-id"},
  1670  	})
  1671  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1672  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1673  
  1674  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1675  	c.Assert(err, IsNil)
  1676  	err = assertstate.Add(s.state, s.dev1Acct)
  1677  	c.Assert(err, IsNil)
  1678  	err = assertstate.Add(s.state, snapDeclFoo)
  1679  	c.Assert(err, IsNil)
  1680  	err = assertstate.Add(s.state, snapDeclBar)
  1681  	c.Assert(err, IsNil)
  1682  
  1683  	fooRefresh := &snap.Info{
  1684  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1685  	}
  1686  
  1687  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx)
  1688  	c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`)
  1689  	c.Check(validated, HasLen, 0)
  1690  }
  1691  
  1692  func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidation(c *C) {
  1693  	s.state.Lock()
  1694  	defer s.state.Unlock()
  1695  
  1696  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1697  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1698  		"refresh-control": []interface{}{"foo-id"},
  1699  	})
  1700  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1701  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1702  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1703  
  1704  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1705  	c.Assert(err, IsNil)
  1706  	err = assertstate.Add(s.state, s.dev1Acct)
  1707  	c.Assert(err, IsNil)
  1708  	err = assertstate.Add(s.state, snapDeclFoo)
  1709  	c.Assert(err, IsNil)
  1710  	err = assertstate.Add(s.state, snapDeclBar)
  1711  	c.Assert(err, IsNil)
  1712  
  1713  	fooInstanceRefresh := &snap.Info{
  1714  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1715  		InstanceKey: "instance",
  1716  	}
  1717  
  1718  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooInstanceRefresh}, nil, 0, s.trivialDeviceCtx)
  1719  	c.Assert(err, ErrorMatches, `cannot refresh "foo_instance" to revision 9: no validation by "bar"`)
  1720  	c.Check(validated, HasLen, 0)
  1721  }
  1722  
  1723  func (s *assertMgrSuite) TestValidateRefreshesMissingValidationButIgnore(c *C) {
  1724  	s.state.Lock()
  1725  	defer s.state.Unlock()
  1726  
  1727  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1728  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1729  		"refresh-control": []interface{}{"foo-id"},
  1730  	})
  1731  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1732  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1733  
  1734  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1735  	c.Assert(err, IsNil)
  1736  	err = assertstate.Add(s.state, s.dev1Acct)
  1737  	c.Assert(err, IsNil)
  1738  	err = assertstate.Add(s.state, snapDeclFoo)
  1739  	c.Assert(err, IsNil)
  1740  	err = assertstate.Add(s.state, snapDeclBar)
  1741  	c.Assert(err, IsNil)
  1742  
  1743  	fooRefresh := &snap.Info{
  1744  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1745  	}
  1746  
  1747  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, map[string]bool{"foo": true}, 0, s.trivialDeviceCtx)
  1748  	c.Assert(err, IsNil)
  1749  	c.Check(validated, DeepEquals, []*snap.Info{fooRefresh})
  1750  }
  1751  
  1752  func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnore(c *C) {
  1753  	s.state.Lock()
  1754  	defer s.state.Unlock()
  1755  
  1756  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1757  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1758  		"refresh-control": []interface{}{"foo-id"},
  1759  	})
  1760  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1761  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1762  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1763  
  1764  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1765  	c.Assert(err, IsNil)
  1766  	err = assertstate.Add(s.state, s.dev1Acct)
  1767  	c.Assert(err, IsNil)
  1768  	err = assertstate.Add(s.state, snapDeclFoo)
  1769  	c.Assert(err, IsNil)
  1770  	err = assertstate.Add(s.state, snapDeclBar)
  1771  	c.Assert(err, IsNil)
  1772  
  1773  	fooRefresh := &snap.Info{
  1774  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1775  	}
  1776  	fooInstanceRefresh := &snap.Info{
  1777  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1778  		InstanceKey: "instance",
  1779  	}
  1780  
  1781  	// validation is ignore for foo_instance but not for foo
  1782  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx)
  1783  	c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`)
  1784  	c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh})
  1785  }
  1786  
  1787  func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnoreInstanceKeyed(c *C) {
  1788  	s.state.Lock()
  1789  	defer s.state.Unlock()
  1790  
  1791  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1792  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1793  		"refresh-control": []interface{}{"foo-id"},
  1794  	})
  1795  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1796  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1797  
  1798  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1799  	c.Assert(err, IsNil)
  1800  	err = assertstate.Add(s.state, s.dev1Acct)
  1801  	c.Assert(err, IsNil)
  1802  	err = assertstate.Add(s.state, snapDeclFoo)
  1803  	c.Assert(err, IsNil)
  1804  	err = assertstate.Add(s.state, snapDeclBar)
  1805  	c.Assert(err, IsNil)
  1806  
  1807  	fooInstanceRefresh := &snap.Info{
  1808  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1809  		InstanceKey: "instance",
  1810  	}
  1811  
  1812  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx)
  1813  	c.Assert(err, IsNil)
  1814  	c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh})
  1815  }
  1816  
  1817  func (s *assertMgrSuite) TestParallelInstanceValidateRefreshesMissingValidationButIgnoreBothOneIgnored(c *C) {
  1818  	s.state.Lock()
  1819  	defer s.state.Unlock()
  1820  
  1821  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1822  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1823  		"refresh-control": []interface{}{"foo-id"},
  1824  	})
  1825  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1826  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1827  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1828  
  1829  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1830  	c.Assert(err, IsNil)
  1831  	err = assertstate.Add(s.state, s.dev1Acct)
  1832  	c.Assert(err, IsNil)
  1833  	err = assertstate.Add(s.state, snapDeclFoo)
  1834  	c.Assert(err, IsNil)
  1835  	err = assertstate.Add(s.state, snapDeclBar)
  1836  	c.Assert(err, IsNil)
  1837  
  1838  	fooRefresh := &snap.Info{
  1839  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1840  	}
  1841  	fooInstanceRefresh := &snap.Info{
  1842  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1843  		InstanceKey: "instance",
  1844  	}
  1845  
  1846  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, map[string]bool{"foo_instance": true}, 0, s.trivialDeviceCtx)
  1847  	c.Assert(err, ErrorMatches, `cannot refresh "foo" to revision 9: no validation by "bar"`)
  1848  	c.Check(validated, DeepEquals, []*snap.Info{fooInstanceRefresh})
  1849  }
  1850  
  1851  func (s *assertMgrSuite) TestValidateRefreshesValidationOK(c *C) {
  1852  	s.state.Lock()
  1853  	defer s.state.Unlock()
  1854  
  1855  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1856  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1857  		"refresh-control": []interface{}{"foo-id"},
  1858  	})
  1859  	snapDeclBaz := s.snapDecl(c, "baz", map[string]interface{}{
  1860  		"refresh-control": []interface{}{"foo-id"},
  1861  	})
  1862  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1863  	s.stateFromDecl(c, snapDeclFoo, "foo_instance", snap.R(7))
  1864  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1865  	s.stateFromDecl(c, snapDeclBaz, "", snap.R(1))
  1866  	snapstate.Set(s.state, "local", &snapstate.SnapState{
  1867  		Active: false,
  1868  		Sequence: []*snap.SideInfo{
  1869  			{RealName: "local", Revision: snap.R(-1)},
  1870  		},
  1871  		Current: snap.R(-1),
  1872  	})
  1873  
  1874  	// validation by bar
  1875  	headers := map[string]interface{}{
  1876  		"series":                 "16",
  1877  		"snap-id":                "bar-id",
  1878  		"approved-snap-id":       "foo-id",
  1879  		"approved-snap-revision": "9",
  1880  		"timestamp":              time.Now().Format(time.RFC3339),
  1881  	}
  1882  	barValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "")
  1883  	c.Assert(err, IsNil)
  1884  	err = s.storeSigning.Add(barValidation)
  1885  	c.Assert(err, IsNil)
  1886  
  1887  	// validation by baz
  1888  	headers = map[string]interface{}{
  1889  		"series":                 "16",
  1890  		"snap-id":                "baz-id",
  1891  		"approved-snap-id":       "foo-id",
  1892  		"approved-snap-revision": "9",
  1893  		"timestamp":              time.Now().Format(time.RFC3339),
  1894  	}
  1895  	bazValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "")
  1896  	c.Assert(err, IsNil)
  1897  	err = s.storeSigning.Add(bazValidation)
  1898  	c.Assert(err, IsNil)
  1899  
  1900  	err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1901  	c.Assert(err, IsNil)
  1902  	err = assertstate.Add(s.state, s.dev1Acct)
  1903  	c.Assert(err, IsNil)
  1904  	err = assertstate.Add(s.state, snapDeclFoo)
  1905  	c.Assert(err, IsNil)
  1906  	err = assertstate.Add(s.state, snapDeclBar)
  1907  	c.Assert(err, IsNil)
  1908  	err = assertstate.Add(s.state, snapDeclBaz)
  1909  	c.Assert(err, IsNil)
  1910  
  1911  	fooRefresh := &snap.Info{
  1912  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1913  	}
  1914  	fooInstanceRefresh := &snap.Info{
  1915  		SideInfo:    snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1916  		InstanceKey: "instance",
  1917  	}
  1918  
  1919  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh, fooInstanceRefresh}, nil, 0, s.trivialDeviceCtx)
  1920  	c.Assert(err, IsNil)
  1921  	c.Check(validated, DeepEquals, []*snap.Info{fooRefresh, fooInstanceRefresh})
  1922  }
  1923  
  1924  func (s *assertMgrSuite) TestValidateRefreshesRevokedValidation(c *C) {
  1925  	s.state.Lock()
  1926  	defer s.state.Unlock()
  1927  
  1928  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  1929  	snapDeclBar := s.snapDecl(c, "bar", map[string]interface{}{
  1930  		"refresh-control": []interface{}{"foo-id"},
  1931  	})
  1932  	snapDeclBaz := s.snapDecl(c, "baz", map[string]interface{}{
  1933  		"refresh-control": []interface{}{"foo-id"},
  1934  	})
  1935  	s.stateFromDecl(c, snapDeclFoo, "", snap.R(7))
  1936  	s.stateFromDecl(c, snapDeclBar, "", snap.R(3))
  1937  	s.stateFromDecl(c, snapDeclBaz, "", snap.R(1))
  1938  	snapstate.Set(s.state, "local", &snapstate.SnapState{
  1939  		Active: false,
  1940  		Sequence: []*snap.SideInfo{
  1941  			{RealName: "local", Revision: snap.R(-1)},
  1942  		},
  1943  		Current: snap.R(-1),
  1944  	})
  1945  
  1946  	// validation by bar
  1947  	headers := map[string]interface{}{
  1948  		"series":                 "16",
  1949  		"snap-id":                "bar-id",
  1950  		"approved-snap-id":       "foo-id",
  1951  		"approved-snap-revision": "9",
  1952  		"timestamp":              time.Now().Format(time.RFC3339),
  1953  	}
  1954  	barValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "")
  1955  	c.Assert(err, IsNil)
  1956  	err = s.storeSigning.Add(barValidation)
  1957  	c.Assert(err, IsNil)
  1958  
  1959  	// revoked validation by baz
  1960  	headers = map[string]interface{}{
  1961  		"series":                 "16",
  1962  		"snap-id":                "baz-id",
  1963  		"approved-snap-id":       "foo-id",
  1964  		"approved-snap-revision": "9",
  1965  		"revoked":                "true",
  1966  		"timestamp":              time.Now().Format(time.RFC3339),
  1967  	}
  1968  	bazValidation, err := s.dev1Signing.Sign(asserts.ValidationType, headers, nil, "")
  1969  	c.Assert(err, IsNil)
  1970  	err = s.storeSigning.Add(bazValidation)
  1971  	c.Assert(err, IsNil)
  1972  
  1973  	err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  1974  	c.Assert(err, IsNil)
  1975  	err = assertstate.Add(s.state, s.dev1Acct)
  1976  	c.Assert(err, IsNil)
  1977  	err = assertstate.Add(s.state, snapDeclFoo)
  1978  	c.Assert(err, IsNil)
  1979  	err = assertstate.Add(s.state, snapDeclBar)
  1980  	c.Assert(err, IsNil)
  1981  	err = assertstate.Add(s.state, snapDeclBaz)
  1982  	c.Assert(err, IsNil)
  1983  
  1984  	fooRefresh := &snap.Info{
  1985  		SideInfo: snap.SideInfo{RealName: "foo", SnapID: "foo-id", Revision: snap.R(9)},
  1986  	}
  1987  
  1988  	validated, err := assertstate.ValidateRefreshes(s.state, []*snap.Info{fooRefresh}, nil, 0, s.trivialDeviceCtx)
  1989  	c.Assert(err, ErrorMatches, `(?s).*cannot refresh "foo" to revision 9: validation by "baz" \(id "baz-id"\) revoked.*`)
  1990  	c.Check(validated, HasLen, 0)
  1991  }
  1992  
  1993  func (s *assertMgrSuite) TestBaseSnapDeclaration(c *C) {
  1994  	s.state.Lock()
  1995  	defer s.state.Unlock()
  1996  
  1997  	r1 := assertstest.MockBuiltinBaseDeclaration(nil)
  1998  	defer r1()
  1999  
  2000  	baseDecl, err := assertstate.BaseDeclaration(s.state)
  2001  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2002  	c.Check(baseDecl, IsNil)
  2003  
  2004  	r2 := assertstest.MockBuiltinBaseDeclaration([]byte(`
  2005  type: base-declaration
  2006  authority-id: canonical
  2007  series: 16
  2008  plugs:
  2009    iface: true
  2010  `))
  2011  	defer r2()
  2012  
  2013  	baseDecl, err = assertstate.BaseDeclaration(s.state)
  2014  	c.Assert(err, IsNil)
  2015  	c.Check(baseDecl, NotNil)
  2016  	c.Check(baseDecl.PlugRule("iface"), NotNil)
  2017  }
  2018  
  2019  func (s *assertMgrSuite) TestSnapDeclaration(c *C) {
  2020  	s.state.Lock()
  2021  	defer s.state.Unlock()
  2022  
  2023  	// have a declaration in the system db
  2024  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2025  	c.Assert(err, IsNil)
  2026  	err = assertstate.Add(s.state, s.dev1Acct)
  2027  	c.Assert(err, IsNil)
  2028  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  2029  	err = assertstate.Add(s.state, snapDeclFoo)
  2030  	c.Assert(err, IsNil)
  2031  
  2032  	_, err = assertstate.SnapDeclaration(s.state, "snap-id-other")
  2033  	c.Check(asserts.IsNotFound(err), Equals, true)
  2034  
  2035  	snapDecl, err := assertstate.SnapDeclaration(s.state, "foo-id")
  2036  	c.Assert(err, IsNil)
  2037  	c.Check(snapDecl.SnapName(), Equals, "foo")
  2038  }
  2039  
  2040  func (s *assertMgrSuite) TestAutoAliasesTemporaryFallback(c *C) {
  2041  	s.state.Lock()
  2042  	defer s.state.Unlock()
  2043  
  2044  	// prereqs for developer assertions in the system db
  2045  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2046  	c.Assert(err, IsNil)
  2047  	err = assertstate.Add(s.state, s.dev1Acct)
  2048  	c.Assert(err, IsNil)
  2049  
  2050  	// not from the store
  2051  	aliases, err := assertstate.AutoAliases(s.state, &snap.Info{SuggestedName: "local"})
  2052  	c.Assert(err, IsNil)
  2053  	c.Check(aliases, HasLen, 0)
  2054  
  2055  	// missing
  2056  	_, err = assertstate.AutoAliases(s.state, &snap.Info{
  2057  		SideInfo: snap.SideInfo{
  2058  			RealName: "baz",
  2059  			SnapID:   "baz-id",
  2060  		},
  2061  	})
  2062  	c.Check(err, ErrorMatches, `internal error: cannot find snap-declaration for installed snap "baz": snap-declaration \(baz-id; series:16\) not found`)
  2063  
  2064  	info := snaptest.MockInfo(c, `
  2065  name: foo
  2066  version: 0
  2067  apps:
  2068     cmd1:
  2069       aliases: [alias1]
  2070     cmd2:
  2071       aliases: [alias2]
  2072  `, &snap.SideInfo{
  2073  		RealName: "foo",
  2074  		SnapID:   "foo-id",
  2075  	})
  2076  
  2077  	// empty list
  2078  	// have a declaration in the system db
  2079  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  2080  	err = assertstate.Add(s.state, snapDeclFoo)
  2081  	c.Assert(err, IsNil)
  2082  	aliases, err = assertstate.AutoAliases(s.state, info)
  2083  	c.Assert(err, IsNil)
  2084  	c.Check(aliases, HasLen, 0)
  2085  
  2086  	// some aliases
  2087  	snapDeclFoo = s.snapDecl(c, "foo", map[string]interface{}{
  2088  		"auto-aliases": []interface{}{"alias1", "alias2", "alias3"},
  2089  		"revision":     "1",
  2090  	})
  2091  	err = assertstate.Add(s.state, snapDeclFoo)
  2092  	c.Assert(err, IsNil)
  2093  	aliases, err = assertstate.AutoAliases(s.state, info)
  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) TestAutoAliasesExplicit(c *C) {
  2102  	s.state.Lock()
  2103  	defer s.state.Unlock()
  2104  
  2105  	// prereqs for developer assertions 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  
  2111  	// not from the store
  2112  	aliases, err := assertstate.AutoAliases(s.state, &snap.Info{SuggestedName: "local"})
  2113  	c.Assert(err, IsNil)
  2114  	c.Check(aliases, HasLen, 0)
  2115  
  2116  	// missing
  2117  	_, err = assertstate.AutoAliases(s.state, &snap.Info{
  2118  		SideInfo: snap.SideInfo{
  2119  			RealName: "baz",
  2120  			SnapID:   "baz-id",
  2121  		},
  2122  	})
  2123  	c.Check(err, ErrorMatches, `internal error: cannot find snap-declaration for installed snap "baz": snap-declaration \(baz-id; series:16\) not found`)
  2124  
  2125  	// empty list
  2126  	// have a declaration in the system db
  2127  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  2128  	err = assertstate.Add(s.state, snapDeclFoo)
  2129  	c.Assert(err, IsNil)
  2130  	aliases, err = assertstate.AutoAliases(s.state, &snap.Info{
  2131  		SideInfo: snap.SideInfo{
  2132  			RealName: "foo",
  2133  			SnapID:   "foo-id",
  2134  		},
  2135  	})
  2136  	c.Assert(err, IsNil)
  2137  	c.Check(aliases, HasLen, 0)
  2138  
  2139  	// some aliases
  2140  	snapDeclFoo = s.snapDecl(c, "foo", map[string]interface{}{
  2141  		"aliases": []interface{}{
  2142  			map[string]interface{}{
  2143  				"name":   "alias1",
  2144  				"target": "cmd1",
  2145  			},
  2146  			map[string]interface{}{
  2147  				"name":   "alias2",
  2148  				"target": "cmd2",
  2149  			},
  2150  		},
  2151  		"revision": "1",
  2152  	})
  2153  	err = assertstate.Add(s.state, snapDeclFoo)
  2154  	c.Assert(err, IsNil)
  2155  	aliases, err = assertstate.AutoAliases(s.state, &snap.Info{
  2156  		SideInfo: snap.SideInfo{
  2157  			RealName: "foo",
  2158  			SnapID:   "foo-id",
  2159  		},
  2160  	})
  2161  	c.Assert(err, IsNil)
  2162  	c.Check(aliases, DeepEquals, map[string]string{
  2163  		"alias1": "cmd1",
  2164  		"alias2": "cmd2",
  2165  	})
  2166  }
  2167  
  2168  func (s *assertMgrSuite) TestPublisher(c *C) {
  2169  	s.state.Lock()
  2170  	defer s.state.Unlock()
  2171  
  2172  	// have a declaration in the system db
  2173  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2174  	c.Assert(err, IsNil)
  2175  	err = assertstate.Add(s.state, s.dev1Acct)
  2176  	c.Assert(err, IsNil)
  2177  	snapDeclFoo := s.snapDecl(c, "foo", nil)
  2178  	err = assertstate.Add(s.state, snapDeclFoo)
  2179  	c.Assert(err, IsNil)
  2180  
  2181  	_, err = assertstate.SnapDeclaration(s.state, "snap-id-other")
  2182  	c.Check(asserts.IsNotFound(err), Equals, true)
  2183  
  2184  	acct, err := assertstate.Publisher(s.state, "foo-id")
  2185  	c.Assert(err, IsNil)
  2186  	c.Check(acct.AccountID(), Equals, s.dev1Acct.AccountID())
  2187  	c.Check(acct.Username(), Equals, "developer1")
  2188  }
  2189  
  2190  func (s *assertMgrSuite) TestStore(c *C) {
  2191  	s.state.Lock()
  2192  	defer s.state.Unlock()
  2193  
  2194  	err := assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2195  	c.Assert(err, IsNil)
  2196  	err = assertstate.Add(s.state, s.dev1Acct)
  2197  	c.Assert(err, IsNil)
  2198  	storeHeaders := map[string]interface{}{
  2199  		"store":       "foo",
  2200  		"operator-id": s.dev1Acct.AccountID(),
  2201  		"timestamp":   time.Now().Format(time.RFC3339),
  2202  	}
  2203  	fooStore, err := s.storeSigning.Sign(asserts.StoreType, storeHeaders, nil, "")
  2204  	c.Assert(err, IsNil)
  2205  	err = assertstate.Add(s.state, fooStore)
  2206  	c.Assert(err, IsNil)
  2207  
  2208  	_, err = assertstate.Store(s.state, "bar")
  2209  	c.Check(asserts.IsNotFound(err), Equals, true)
  2210  
  2211  	store, err := assertstate.Store(s.state, "foo")
  2212  	c.Assert(err, IsNil)
  2213  	c.Check(store.Store(), Equals, "foo")
  2214  }
  2215  
  2216  // validation-sets related tests
  2217  
  2218  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsNop(c *C) {
  2219  	s.state.Lock()
  2220  	defer s.state.Unlock()
  2221  
  2222  	s.setModel(sysdb.GenericClassicModel())
  2223  
  2224  	err := assertstate.RefreshValidationSetAssertions(s.state, 0, nil)
  2225  	c.Assert(err, IsNil)
  2226  }
  2227  
  2228  func (s *assertMgrSuite) TestValidationSetAssertionsAutoRefresh(c *C) {
  2229  	s.state.Lock()
  2230  	defer s.state.Unlock()
  2231  
  2232  	// have a model and the store assertion available
  2233  	storeAs := s.setupModelAndStore(c)
  2234  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2235  
  2236  	// store key already present
  2237  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2238  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2239  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2240  
  2241  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2242  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2243  
  2244  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "3", "required")
  2245  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2246  
  2247  	tr := assertstate.ValidationSetTracking{
  2248  		AccountID: s.dev1Acct.AccountID(),
  2249  		Name:      "bar",
  2250  		Mode:      assertstate.Monitor,
  2251  		Current:   1,
  2252  	}
  2253  	assertstate.UpdateValidationSet(s.state, &tr)
  2254  
  2255  	c.Assert(assertstate.AutoRefreshAssertions(s.state, 0), IsNil)
  2256  	c.Check(s.fakeStore.(*fakeStore).opts.IsAutoRefresh, Equals, true)
  2257  
  2258  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2259  		"series":     "16",
  2260  		"account-id": s.dev1Acct.AccountID(),
  2261  		"name":       "bar",
  2262  		"sequence":   "2",
  2263  	})
  2264  	c.Assert(err, IsNil)
  2265  	c.Check(a.Revision(), Equals, 3)
  2266  }
  2267  
  2268  func (s *assertMgrSuite) TestValidationSetAssertionsAutoRefreshError(c *C) {
  2269  	s.state.Lock()
  2270  	defer s.state.Unlock()
  2271  
  2272  	// have a model and the store assertion available
  2273  	storeAs := s.setupModelAndStore(c)
  2274  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2275  
  2276  	tr := assertstate.ValidationSetTracking{
  2277  		AccountID: s.dev1Acct.AccountID(),
  2278  		Name:      "bar",
  2279  		Mode:      assertstate.Monitor,
  2280  		Current:   1,
  2281  	}
  2282  	assertstate.UpdateValidationSet(s.state, &tr)
  2283  	err := assertstate.AutoRefreshAssertions(s.state, 0)
  2284  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2285  }
  2286  
  2287  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsStoreError(c *C) {
  2288  	s.fakeStore.(*fakeStore).snapActionErr = &store.UnexpectedHTTPStatusError{StatusCode: 400}
  2289  	s.state.Lock()
  2290  	defer s.state.Unlock()
  2291  
  2292  	s.setModel(sysdb.GenericClassicModel())
  2293  
  2294  	// store key already present
  2295  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2296  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2297  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2298  
  2299  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2300  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2301  
  2302  	tr := assertstate.ValidationSetTracking{
  2303  		AccountID: s.dev1Acct.AccountID(),
  2304  		Name:      "bar",
  2305  		Mode:      assertstate.Monitor,
  2306  		Current:   1,
  2307  	}
  2308  	assertstate.UpdateValidationSet(s.state, &tr)
  2309  
  2310  	err := assertstate.RefreshValidationSetAssertions(s.state, 0, nil)
  2311  	c.Assert(err, ErrorMatches, `cannot refresh validation set assertions: cannot : got unexpected HTTP status code 400.*`)
  2312  }
  2313  
  2314  func (s *assertMgrSuite) TestRefreshValidationSetAssertions(c *C) {
  2315  	s.state.Lock()
  2316  	defer s.state.Unlock()
  2317  
  2318  	// have a model and the store assertion available
  2319  	storeAs := s.setupModelAndStore(c)
  2320  	err := s.storeSigning.Add(storeAs)
  2321  	c.Assert(err, IsNil)
  2322  
  2323  	// store key already present
  2324  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2325  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2326  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2327  
  2328  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2329  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2330  
  2331  	vsetAs2 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2332  	err = s.storeSigning.Add(vsetAs2)
  2333  	c.Assert(err, IsNil)
  2334  
  2335  	tr := assertstate.ValidationSetTracking{
  2336  		AccountID: s.dev1Acct.AccountID(),
  2337  		Name:      "bar",
  2338  		Mode:      assertstate.Monitor,
  2339  		Current:   1,
  2340  	}
  2341  	assertstate.UpdateValidationSet(s.state, &tr)
  2342  
  2343  	err = assertstate.RefreshValidationSetAssertions(s.state, 0, &assertstate.RefreshAssertionsOptions{IsAutoRefresh: true})
  2344  	c.Assert(err, IsNil)
  2345  
  2346  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2347  		"series":     "16",
  2348  		"account-id": s.dev1Acct.AccountID(),
  2349  		"name":       "bar",
  2350  		"sequence":   "1",
  2351  	})
  2352  	c.Assert(err, IsNil)
  2353  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2354  	c.Check(a.Revision(), Equals, 2)
  2355  
  2356  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2357  		{"account", "account-key", "validation-set"},
  2358  	})
  2359  	c.Check(s.fakeStore.(*fakeStore).opts.IsAutoRefresh, Equals, true)
  2360  
  2361  	// sequence changed in the store to 4
  2362  	vsetAs3 := s.validationSetAssert(c, "bar", "4", "3", "required")
  2363  	err = s.storeSigning.Add(vsetAs3)
  2364  	c.Assert(err, IsNil)
  2365  
  2366  	// sanity check - sequence 4 not available locally yet
  2367  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2368  		"series":     "16",
  2369  		"account-id": s.dev1Acct.AccountID(),
  2370  		"name":       "bar",
  2371  		"sequence":   "4",
  2372  	})
  2373  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2374  
  2375  	s.fakeStore.(*fakeStore).requestedTypes = nil
  2376  	err = assertstate.RefreshValidationSetAssertions(s.state, 0, nil)
  2377  	c.Assert(err, IsNil)
  2378  
  2379  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2380  		{"account", "account-key", "validation-set"},
  2381  	})
  2382  
  2383  	// new sequence is available in the db
  2384  	a, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2385  		"series":     "16",
  2386  		"account-id": s.dev1Acct.AccountID(),
  2387  		"name":       "bar",
  2388  		"sequence":   "4",
  2389  	})
  2390  	c.Assert(err, IsNil)
  2391  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2392  
  2393  	// tracking current was updated
  2394  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "bar", &tr), IsNil)
  2395  	c.Check(tr.Current, Equals, 4)
  2396  }
  2397  
  2398  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsPinned(c *C) {
  2399  	s.state.Lock()
  2400  	defer s.state.Unlock()
  2401  
  2402  	// have a model and the store assertion available
  2403  	storeAs := s.setupModelAndStore(c)
  2404  	err := s.storeSigning.Add(storeAs)
  2405  	c.Assert(err, IsNil)
  2406  
  2407  	// store key already present
  2408  	err = assertstate.Add(s.state, s.storeSigning.StoreAccountKey(""))
  2409  	c.Assert(err, IsNil)
  2410  
  2411  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2412  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2413  
  2414  	vsetAs1 := s.validationSetAssert(c, "bar", "2", "1", "required")
  2415  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2416  
  2417  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "5", "required")
  2418  	err = s.storeSigning.Add(vsetAs2)
  2419  	c.Assert(err, IsNil)
  2420  
  2421  	tr := assertstate.ValidationSetTracking{
  2422  		AccountID: s.dev1Acct.AccountID(),
  2423  		Name:      "bar",
  2424  		Mode:      assertstate.Monitor,
  2425  		Current:   2,
  2426  		PinnedAt:  2,
  2427  	}
  2428  	assertstate.UpdateValidationSet(s.state, &tr)
  2429  
  2430  	err = assertstate.RefreshValidationSetAssertions(s.state, 0, nil)
  2431  	c.Assert(err, IsNil)
  2432  
  2433  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2434  		"series":     "16",
  2435  		"account-id": s.dev1Acct.AccountID(),
  2436  		"name":       "bar",
  2437  		"sequence":   "2",
  2438  	})
  2439  	c.Assert(err, IsNil)
  2440  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2441  	c.Check(a.(*asserts.ValidationSet).Sequence(), Equals, 2)
  2442  	c.Check(a.Revision(), Equals, 5)
  2443  
  2444  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2445  		{"account", "account-key", "validation-set"},
  2446  	})
  2447  
  2448  	// sequence changed in the store to 7
  2449  	vsetAs3 := s.validationSetAssert(c, "bar", "7", "8", "required")
  2450  	err = s.storeSigning.Add(vsetAs3)
  2451  	c.Assert(err, IsNil)
  2452  
  2453  	s.fakeStore.(*fakeStore).requestedTypes = nil
  2454  	err = assertstate.RefreshValidationSetAssertions(s.state, 0, nil)
  2455  	c.Assert(err, IsNil)
  2456  
  2457  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2458  		{"account", "account-key", "validation-set"},
  2459  	})
  2460  
  2461  	// new sequence is not available in the db
  2462  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2463  		"series":     "16",
  2464  		"account-id": s.dev1Acct.AccountID(),
  2465  		"name":       "bar",
  2466  		"sequence":   "7",
  2467  	})
  2468  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2469  
  2470  	// tracking current remains at 2
  2471  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "bar", &tr), IsNil)
  2472  	c.Check(tr.Current, Equals, 2)
  2473  }
  2474  
  2475  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsLocalOnlyFailed(c *C) {
  2476  	st := s.state
  2477  	st.Lock()
  2478  	defer st.Unlock()
  2479  
  2480  	// have a model and the store assertion available
  2481  	storeAs := s.setupModelAndStore(c)
  2482  	err := s.storeSigning.Add(storeAs)
  2483  	c.Assert(err, IsNil)
  2484  
  2485  	// store key already present
  2486  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2487  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2488  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2489  
  2490  	// add to local database
  2491  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2492  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  2493  	vsetAs2 := s.validationSetAssert(c, "baz", "3", "1", "required")
  2494  	c.Assert(assertstate.Add(st, vsetAs2), IsNil)
  2495  
  2496  	// vset2 present and updated in the store
  2497  	vsetAs2_2 := s.validationSetAssert(c, "baz", "3", "2", "required")
  2498  	err = s.storeSigning.Add(vsetAs2_2)
  2499  	c.Assert(err, IsNil)
  2500  
  2501  	tr1 := assertstate.ValidationSetTracking{
  2502  		AccountID: s.dev1Acct.AccountID(),
  2503  		Name:      "bar",
  2504  		Mode:      assertstate.Monitor,
  2505  		Current:   1,
  2506  		PinnedAt:  1,
  2507  		LocalOnly: true,
  2508  	}
  2509  	tr2 := assertstate.ValidationSetTracking{
  2510  		AccountID: s.dev1Acct.AccountID(),
  2511  		Name:      "baz",
  2512  		Mode:      assertstate.Monitor,
  2513  		Current:   3,
  2514  		PinnedAt:  3,
  2515  	}
  2516  	assertstate.UpdateValidationSet(s.state, &tr1)
  2517  	assertstate.UpdateValidationSet(s.state, &tr2)
  2518  
  2519  	err = assertstate.RefreshValidationSetAssertions(s.state, 0, nil)
  2520  	c.Assert(err, IsNil)
  2521  
  2522  	// sanity - local assertion vsetAs1 is the latest
  2523  	a, err := assertstate.DB(s.state).FindSequence(asserts.ValidationSetType, map[string]string{
  2524  		"series":     "16",
  2525  		"account-id": s.dev1Acct.AccountID(),
  2526  		"name":       "bar",
  2527  		"sequence":   "1",
  2528  	}, -1, -1)
  2529  	c.Assert(err, IsNil)
  2530  	vs := a.(*asserts.ValidationSet)
  2531  	c.Check(vs.Name(), Equals, "bar")
  2532  	c.Check(vs.Sequence(), Equals, 1)
  2533  	c.Check(vs.Revision(), Equals, 1)
  2534  
  2535  	// but vsetAs2 was updated with vsetAs2_2
  2536  	a, err = assertstate.DB(s.state).FindSequence(asserts.ValidationSetType, map[string]string{
  2537  		"series":     "16",
  2538  		"account-id": s.dev1Acct.AccountID(),
  2539  		"name":       "baz",
  2540  		"sequence":   "1",
  2541  	}, -1, -1)
  2542  	c.Assert(err, IsNil)
  2543  	vs = a.(*asserts.ValidationSet)
  2544  	c.Check(vs.Name(), Equals, "baz")
  2545  	c.Check(vs.Sequence(), Equals, 3)
  2546  	c.Check(vs.Revision(), Equals, 2)
  2547  }
  2548  
  2549  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsEnforcingModeHappyNotPinned(c *C) {
  2550  	s.state.Lock()
  2551  	defer s.state.Unlock()
  2552  
  2553  	// have a model and the store assertion available
  2554  	storeAs := s.setupModelAndStore(c)
  2555  	err := s.storeSigning.Add(storeAs)
  2556  	c.Assert(err, IsNil)
  2557  
  2558  	// store key already present
  2559  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2560  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2561  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2562  
  2563  	vsetAs1 := s.validationSetAssert(c, "foo", "1", "1", "required")
  2564  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2565  
  2566  	vsetAs2 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2567  	c.Assert(assertstate.Add(s.state, vsetAs2), IsNil)
  2568  
  2569  	// in the store
  2570  	vsetAs3 := s.validationSetAssert(c, "foo", "1", "2", "required")
  2571  	c.Assert(s.storeSigning.Add(vsetAs3), IsNil)
  2572  
  2573  	vsetAs4 := s.validationSetAssert(c, "bar", "2", "3", "required")
  2574  	c.Assert(s.storeSigning.Add(vsetAs4), IsNil)
  2575  
  2576  	tr := assertstate.ValidationSetTracking{
  2577  		AccountID: s.dev1Acct.AccountID(),
  2578  		Name:      "foo",
  2579  		Mode:      assertstate.Enforce,
  2580  		Current:   1,
  2581  	}
  2582  	assertstate.UpdateValidationSet(s.state, &tr)
  2583  	tr = assertstate.ValidationSetTracking{
  2584  		AccountID: s.dev1Acct.AccountID(),
  2585  		Name:      "bar",
  2586  		Mode:      assertstate.Enforce,
  2587  		Current:   1,
  2588  	}
  2589  	assertstate.UpdateValidationSet(s.state, &tr)
  2590  
  2591  	err = assertstate.RefreshValidationSetAssertions(s.state, 0, nil)
  2592  	c.Assert(err, IsNil)
  2593  
  2594  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2595  		"series":     "16",
  2596  		"account-id": s.dev1Acct.AccountID(),
  2597  		"name":       "foo",
  2598  		"sequence":   "1",
  2599  	})
  2600  	c.Assert(err, IsNil)
  2601  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "foo")
  2602  	c.Check(a.Revision(), Equals, 2)
  2603  
  2604  	a, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2605  		"series":     "16",
  2606  		"account-id": s.dev1Acct.AccountID(),
  2607  		"name":       "bar",
  2608  		"sequence":   "2",
  2609  	})
  2610  	c.Assert(err, IsNil)
  2611  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2612  	c.Check(a.(*asserts.ValidationSet).Sequence(), Equals, 2)
  2613  	c.Check(a.Revision(), Equals, 3)
  2614  
  2615  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2616  		{"account", "account-key", "validation-set"},
  2617  	})
  2618  
  2619  	// tracking current was updated
  2620  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "bar", &tr), IsNil)
  2621  	c.Check(tr.Current, Equals, 2)
  2622  }
  2623  
  2624  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsEnforcingModeHappyPinned(c *C) {
  2625  	s.state.Lock()
  2626  	defer s.state.Unlock()
  2627  
  2628  	// have a model and the store assertion available
  2629  	storeAs := s.setupModelAndStore(c)
  2630  	err := s.storeSigning.Add(storeAs)
  2631  	c.Assert(err, IsNil)
  2632  
  2633  	// store key already present
  2634  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2635  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2636  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2637  
  2638  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2639  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2640  
  2641  	// in the store
  2642  	c.Assert(s.storeSigning.Add(vsetAs1), IsNil)
  2643  
  2644  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "3", "required")
  2645  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2646  
  2647  	tr := assertstate.ValidationSetTracking{
  2648  		AccountID: s.dev1Acct.AccountID(),
  2649  		Name:      "bar",
  2650  		Mode:      assertstate.Enforce,
  2651  		PinnedAt:  1,
  2652  		Current:   1,
  2653  	}
  2654  	assertstate.UpdateValidationSet(s.state, &tr)
  2655  
  2656  	c.Assert(assertstate.RefreshValidationSetAssertions(s.state, 0, nil), IsNil)
  2657  
  2658  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2659  		"series":     "16",
  2660  		"account-id": s.dev1Acct.AccountID(),
  2661  		"name":       "bar",
  2662  		"sequence":   "1",
  2663  	})
  2664  	c.Assert(err, IsNil)
  2665  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "bar")
  2666  	c.Check(a.(*asserts.ValidationSet).Sequence(), Equals, 1)
  2667  	c.Check(a.Revision(), Equals, 2)
  2668  
  2669  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2670  		{"account", "account-key", "validation-set"},
  2671  	})
  2672  
  2673  	// tracking current was updated
  2674  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "bar", &tr), IsNil)
  2675  	c.Check(tr.Current, Equals, 1)
  2676  }
  2677  
  2678  func (s *assertMgrSuite) TestRefreshValidationSetAssertionsEnforcingModeConflict(c *C) {
  2679  	s.state.Lock()
  2680  	defer s.state.Unlock()
  2681  
  2682  	logbuf, restore := logger.MockLogger()
  2683  	defer restore()
  2684  
  2685  	// have a model and the store assertion available
  2686  	storeAs := s.setupModelAndStore(c)
  2687  	err := s.storeSigning.Add(storeAs)
  2688  	c.Assert(err, IsNil)
  2689  
  2690  	// store key already present
  2691  	c.Assert(assertstate.Add(s.state, s.storeSigning.StoreAccountKey("")), IsNil)
  2692  	c.Assert(assertstate.Add(s.state, s.dev1Acct), IsNil)
  2693  	c.Assert(assertstate.Add(s.state, s.dev1AcctKey), IsNil)
  2694  
  2695  	vsetAs1 := s.validationSetAssert(c, "foo", "1", "1", "required")
  2696  	c.Assert(assertstate.Add(s.state, vsetAs1), IsNil)
  2697  
  2698  	vsetAs2 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2699  	c.Assert(assertstate.Add(s.state, vsetAs2), IsNil)
  2700  
  2701  	// in the store
  2702  	vsetAs3 := s.validationSetAssert(c, "foo", "2", "2", "invalid")
  2703  	c.Assert(s.storeSigning.Add(vsetAs3), IsNil)
  2704  
  2705  	tr := assertstate.ValidationSetTracking{
  2706  		AccountID: s.dev1Acct.AccountID(),
  2707  		Name:      "foo",
  2708  		Mode:      assertstate.Enforce,
  2709  		Current:   1,
  2710  	}
  2711  	assertstate.UpdateValidationSet(s.state, &tr)
  2712  	tr = assertstate.ValidationSetTracking{
  2713  		AccountID: s.dev1Acct.AccountID(),
  2714  		Name:      "bar",
  2715  		Mode:      assertstate.Enforce,
  2716  		Current:   1,
  2717  	}
  2718  	assertstate.UpdateValidationSet(s.state, &tr)
  2719  
  2720  	c.Assert(assertstate.RefreshValidationSetAssertions(s.state, 0, nil), IsNil)
  2721  	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`)
  2722  
  2723  	a, err := assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2724  		"series":     "16",
  2725  		"account-id": s.dev1Acct.AccountID(),
  2726  		"name":       "foo",
  2727  		"sequence":   "1",
  2728  	})
  2729  	c.Assert(err, IsNil)
  2730  	c.Check(a.(*asserts.ValidationSet).Name(), Equals, "foo")
  2731  	c.Check(a.Revision(), Equals, 1)
  2732  
  2733  	// new assertion wasn't committed to the database.
  2734  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2735  		"series":     "16",
  2736  		"account-id": s.dev1Acct.AccountID(),
  2737  		"name":       "foo",
  2738  		"sequence":   "2",
  2739  	})
  2740  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2741  
  2742  	c.Check(s.fakeStore.(*fakeStore).requestedTypes, DeepEquals, [][]string{
  2743  		{"account", "account-key", "validation-set"},
  2744  	})
  2745  
  2746  	// tracking current wasn't updated
  2747  	c.Assert(assertstate.GetValidationSet(s.state, s.dev1Acct.AccountID(), "foo", &tr), IsNil)
  2748  	c.Check(tr.Current, Equals, 1)
  2749  }
  2750  
  2751  func (s *assertMgrSuite) TestValidationSetAssertionForMonitorLocalFallbackForPinned(c *C) {
  2752  	st := s.state
  2753  
  2754  	st.Lock()
  2755  	defer st.Unlock()
  2756  
  2757  	// have a model and the store assertion available
  2758  	storeAs := s.setupModelAndStore(c)
  2759  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2760  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2761  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2762  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2763  
  2764  	// add to local database
  2765  	vsetAs := s.validationSetAssert(c, "bar", "1", "1", "required")
  2766  	c.Assert(assertstate.Add(st, vsetAs), IsNil)
  2767  
  2768  	opts := assertstate.ResolveOptions{AllowLocalFallback: true}
  2769  	vs, local, err := assertstate.ValidationSetAssertionForMonitor(st, s.dev1Acct.AccountID(), "bar", 1, true, 0, &opts)
  2770  	c.Assert(err, IsNil)
  2771  	c.Assert(vs, NotNil)
  2772  	c.Assert(local, Equals, true)
  2773  }
  2774  
  2775  func (s *assertMgrSuite) TestValidationSetAssertionForMonitorPinnedRefreshedFromStore(c *C) {
  2776  	st := s.state
  2777  
  2778  	st.Lock()
  2779  	defer st.Unlock()
  2780  
  2781  	// have a model and the store assertion available
  2782  	storeAs := s.setupModelAndStore(c)
  2783  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2784  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2785  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2786  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2787  
  2788  	// add to local database
  2789  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2790  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  2791  
  2792  	// newer revision available in the store
  2793  	vsetAs2 := s.validationSetAssert(c, "bar", "1", "2", "required")
  2794  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2795  
  2796  	vs, local, err := assertstate.ValidationSetAssertionForMonitor(st, s.dev1Acct.AccountID(), "bar", 1, true, 0, nil)
  2797  	c.Assert(err, IsNil)
  2798  	c.Assert(local, Equals, false)
  2799  	c.Check(vs.Revision(), Equals, 2)
  2800  	c.Check(vs.Sequence(), Equals, 1)
  2801  }
  2802  
  2803  func (s *assertMgrSuite) TestValidationSetAssertionForMonitorUnpinnedRefreshedFromStore(c *C) {
  2804  	st := s.state
  2805  
  2806  	st.Lock()
  2807  	defer st.Unlock()
  2808  
  2809  	// have a model and the store assertion available
  2810  	storeAs := s.setupModelAndStore(c)
  2811  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2812  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2813  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2814  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2815  
  2816  	// add to local database
  2817  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  2818  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  2819  
  2820  	// newer assertion available in the store
  2821  	vsetAs2 := s.validationSetAssert(c, "bar", "3", "1", "required")
  2822  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2823  
  2824  	vs, local, err := assertstate.ValidationSetAssertionForMonitor(st, s.dev1Acct.AccountID(), "bar", 0, false, 0, nil)
  2825  	c.Assert(err, IsNil)
  2826  	c.Assert(local, Equals, false)
  2827  	c.Check(vs.Revision(), Equals, 1)
  2828  	c.Check(vs.Sequence(), Equals, 3)
  2829  }
  2830  
  2831  func (s *assertMgrSuite) TestValidationSetAssertionForMonitorUnpinnedNotFound(c *C) {
  2832  	st := s.state
  2833  
  2834  	st.Lock()
  2835  	defer st.Unlock()
  2836  
  2837  	// have a model and the store assertion available
  2838  	storeAs := s.setupModelAndStore(c)
  2839  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2840  
  2841  	_, _, err := assertstate.ValidationSetAssertionForMonitor(st, s.dev1Acct.AccountID(), "bar", 0, false, 0, nil)
  2842  	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()))
  2843  }
  2844  
  2845  // Test for enforce mode
  2846  
  2847  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedHappy(c *C) {
  2848  	st := s.state
  2849  
  2850  	st.Lock()
  2851  	defer st.Unlock()
  2852  
  2853  	// have a model and the store assertion available
  2854  	storeAs := s.setupModelAndStore(c)
  2855  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2856  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2857  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2858  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2859  
  2860  	// add sequence to the store
  2861  	vsetAs := s.validationSetAssert(c, "bar", "2", "2", "required")
  2862  	c.Assert(s.storeSigning.Add(vsetAs), IsNil)
  2863  
  2864  	snaps := []*snapasserts.InstalledSnap{
  2865  		snapasserts.NewInstalledSnap("foo", "qOqKhntON3vR7kwEbVPsILm7bUViPDzz", snap.Revision{N: 1}),
  2866  		snapasserts.NewInstalledSnap("other", "ididididid", snap.Revision{N: 1}),
  2867  	}
  2868  
  2869  	sequence := 0
  2870  	vs, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2871  	c.Assert(err, IsNil)
  2872  	c.Check(vs.Revision(), Equals, 2)
  2873  	c.Check(vs.Sequence(), Equals, 2)
  2874  
  2875  	// and it has been committed
  2876  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2877  		"series":     "16",
  2878  		"account-id": s.dev1Acct.AccountID(),
  2879  		"name":       "bar",
  2880  		"sequence":   "2",
  2881  	})
  2882  	c.Assert(err, IsNil)
  2883  }
  2884  
  2885  func (s *assertMgrSuite) TestValidationSetAssertionForEnforcePinnedHappy(c *C) {
  2886  	st := s.state
  2887  
  2888  	st.Lock()
  2889  	defer st.Unlock()
  2890  
  2891  	// have a model and the store assertion available
  2892  	storeAs := s.setupModelAndStore(c)
  2893  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2894  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2895  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2896  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2897  
  2898  	// add sequence to the store
  2899  	vsetAs := s.validationSetAssert(c, "bar", "2", "2", "required")
  2900  	c.Assert(s.storeSigning.Add(vsetAs), IsNil)
  2901  
  2902  	snaps := []*snapasserts.InstalledSnap{
  2903  		snapasserts.NewInstalledSnap("foo", "qOqKhntON3vR7kwEbVPsILm7bUViPDzz", snap.Revision{N: 1}),
  2904  	}
  2905  
  2906  	sequence := 2
  2907  	vs, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2908  	c.Assert(err, IsNil)
  2909  	c.Check(vs.Revision(), Equals, 2)
  2910  	c.Check(vs.Sequence(), Equals, 2)
  2911  
  2912  	// and it has been committed
  2913  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2914  		"series":     "16",
  2915  		"account-id": s.dev1Acct.AccountID(),
  2916  		"name":       "bar",
  2917  		"sequence":   "2",
  2918  	})
  2919  	c.Assert(err, IsNil)
  2920  	c.Check(s.fakeStore.(*fakeStore).opts.IsAutoRefresh, Equals, false)
  2921  }
  2922  
  2923  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedUnhappyMissingSnap(c *C) {
  2924  	st := s.state
  2925  
  2926  	st.Lock()
  2927  	defer st.Unlock()
  2928  
  2929  	// have a model and the store assertion available
  2930  	storeAs := s.setupModelAndStore(c)
  2931  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2932  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2933  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2934  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2935  
  2936  	// add sequence to the store
  2937  	vsetAs := s.validationSetAssert(c, "bar", "2", "2", "required")
  2938  	c.Assert(s.storeSigning.Add(vsetAs), IsNil)
  2939  
  2940  	snaps := []*snapasserts.InstalledSnap{}
  2941  	sequence := 0
  2942  	_, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2943  	c.Assert(err, NotNil)
  2944  	verr, ok := err.(*snapasserts.ValidationSetsValidationError)
  2945  	c.Assert(ok, Equals, true)
  2946  	c.Check(verr.MissingSnaps, DeepEquals, map[string][]string{
  2947  		"foo": {fmt.Sprintf("%s/bar", s.dev1Acct.AccountID())},
  2948  	})
  2949  
  2950  	// and it hasn't been committed
  2951  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2952  		"series":     "16",
  2953  		"account-id": s.dev1Acct.AccountID(),
  2954  		"name":       "bar",
  2955  		"sequence":   "2",
  2956  	})
  2957  	c.Assert(asserts.IsNotFound(err), Equals, true)
  2958  }
  2959  
  2960  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedUnhappyConflict(c *C) {
  2961  	st := s.state
  2962  
  2963  	st.Lock()
  2964  	defer st.Unlock()
  2965  
  2966  	// have a model and the store assertion available
  2967  	storeAs := s.setupModelAndStore(c)
  2968  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  2969  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  2970  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  2971  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  2972  
  2973  	// add an assertion to local database
  2974  	vsetAs := s.validationSetAssert(c, "boo", "4", "4", "invalid")
  2975  	c.Assert(assertstate.Add(st, vsetAs), IsNil)
  2976  	// and to the store (for refresh to be happy)
  2977  	c.Assert(s.storeSigning.Add(vsetAs), IsNil)
  2978  
  2979  	// and pretend it was tracked already
  2980  	tr := assertstate.ValidationSetTracking{
  2981  		AccountID: s.dev1Acct.AccountID(),
  2982  		Name:      "boo",
  2983  		Mode:      assertstate.Enforce,
  2984  		Current:   4,
  2985  	}
  2986  	assertstate.UpdateValidationSet(st, &tr)
  2987  
  2988  	// add sequence to the store, it conflicts with boo
  2989  	vsetAs2 := s.validationSetAssert(c, "bar", "2", "2", "required")
  2990  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  2991  
  2992  	snaps := []*snapasserts.InstalledSnap{}
  2993  	sequence := 0
  2994  	_, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  2995  	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()))
  2996  
  2997  	// and it hasn't been committed
  2998  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  2999  		"series":     "16",
  3000  		"account-id": s.dev1Acct.AccountID(),
  3001  		"name":       "bar",
  3002  		"sequence":   "2",
  3003  	})
  3004  	c.Assert(asserts.IsNotFound(err), Equals, true)
  3005  }
  3006  
  3007  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedAfterForgetHappy(c *C) {
  3008  	st := s.state
  3009  
  3010  	st.Lock()
  3011  	defer st.Unlock()
  3012  
  3013  	// have a model and the store assertion available
  3014  	storeAs := s.setupModelAndStore(c)
  3015  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  3016  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  3017  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  3018  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  3019  
  3020  	// add an old assertion to local database; it's not tracked which is the
  3021  	// case after 'snap validate --forget' (we don't prune assertions from db).
  3022  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  3023  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  3024  
  3025  	// newer sequence available in the store
  3026  	vsetAs2 := s.validationSetAssert(c, "bar", "3", "5", "required")
  3027  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  3028  
  3029  	snaps := []*snapasserts.InstalledSnap{
  3030  		snapasserts.NewInstalledSnap("foo", "qOqKhntON3vR7kwEbVPsILm7bUViPDzz", snap.Revision{N: 1}),
  3031  	}
  3032  
  3033  	sequence := 0
  3034  	vs, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  3035  	c.Assert(err, IsNil)
  3036  	// new assertion got fetched
  3037  	c.Check(vs.Revision(), Equals, 5)
  3038  	c.Check(vs.Sequence(), Equals, 3)
  3039  
  3040  	// and it has been committed
  3041  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  3042  		"series":     "16",
  3043  		"account-id": s.dev1Acct.AccountID(),
  3044  		"name":       "bar",
  3045  		"sequence":   "3",
  3046  	})
  3047  	c.Assert(err, IsNil)
  3048  }
  3049  
  3050  func (s *assertMgrSuite) TestValidationSetAssertionForEnforceNotPinnedAfterMonitorHappy(c *C) {
  3051  	st := s.state
  3052  
  3053  	st.Lock()
  3054  	defer st.Unlock()
  3055  
  3056  	// have a model and the store assertion available
  3057  	storeAs := s.setupModelAndStore(c)
  3058  	c.Assert(s.storeSigning.Add(storeAs), IsNil)
  3059  	c.Assert(assertstate.Add(st, s.storeSigning.StoreAccountKey("")), IsNil)
  3060  	c.Assert(assertstate.Add(st, s.dev1Acct), IsNil)
  3061  	c.Assert(assertstate.Add(st, s.dev1AcctKey), IsNil)
  3062  
  3063  	// add and old assertion to local database
  3064  	vsetAs1 := s.validationSetAssert(c, "bar", "1", "1", "required")
  3065  	c.Assert(assertstate.Add(st, vsetAs1), IsNil)
  3066  
  3067  	// and pretend it was tracked already in monitor mode
  3068  	tr := assertstate.ValidationSetTracking{
  3069  		AccountID: s.dev1Acct.AccountID(),
  3070  		Name:      "bar",
  3071  		Mode:      assertstate.Monitor,
  3072  		Current:   1,
  3073  	}
  3074  	assertstate.UpdateValidationSet(st, &tr)
  3075  
  3076  	// newer sequence available in the store
  3077  	vsetAs2 := s.validationSetAssert(c, "bar", "3", "5", "required")
  3078  	c.Assert(s.storeSigning.Add(vsetAs2), IsNil)
  3079  
  3080  	snaps := []*snapasserts.InstalledSnap{
  3081  		snapasserts.NewInstalledSnap("foo", "qOqKhntON3vR7kwEbVPsILm7bUViPDzz", snap.Revision{N: 1}),
  3082  	}
  3083  
  3084  	sequence := 0
  3085  	vs, err := assertstate.ValidationSetAssertionForEnforce(st, s.dev1Acct.AccountID(), "bar", sequence, 0, snaps)
  3086  	c.Assert(err, IsNil)
  3087  	// new assertion got fetched
  3088  	c.Check(vs.Revision(), Equals, 5)
  3089  	c.Check(vs.Sequence(), Equals, 3)
  3090  
  3091  	// and it has been committed
  3092  	_, err = assertstate.DB(s.state).Find(asserts.ValidationSetType, map[string]string{
  3093  		"series":     "16",
  3094  		"account-id": s.dev1Acct.AccountID(),
  3095  		"name":       "bar",
  3096  		"sequence":   "3",
  3097  	})
  3098  	c.Assert(err, IsNil)
  3099  }
  3100  
  3101  func (s *assertMgrSuite) TestTemporaryDB(c *C) {
  3102  	st := s.state
  3103  
  3104  	st.Lock()
  3105  	defer st.Unlock()
  3106  
  3107  	err := assertstate.Add(st, s.storeSigning.StoreAccountKey(""))
  3108  	c.Assert(err, IsNil)
  3109  
  3110  	a, err := s.storeSigning.Sign(asserts.ModelType, map[string]interface{}{
  3111  		"type":         "model",
  3112  		"series":       "16",
  3113  		"authority-id": s.storeSigning.AuthorityID,
  3114  		"brand-id":     s.storeSigning.AuthorityID,
  3115  		"model":        "my-model",
  3116  		"architecture": "amd64",
  3117  		"gadget":       "gadget",
  3118  		"kernel":       "krnl",
  3119  		"timestamp":    time.Now().Format(time.RFC3339),
  3120  	}, nil, "")
  3121  	c.Assert(err, IsNil)
  3122  	model := a.(*asserts.Model)
  3123  
  3124  	aRev2, err := s.storeSigning.Sign(asserts.ModelType, map[string]interface{}{
  3125  		"type":         "model",
  3126  		"series":       "16",
  3127  		"authority-id": s.storeSigning.AuthorityID,
  3128  		"brand-id":     s.storeSigning.AuthorityID,
  3129  		"model":        "my-model",
  3130  		"architecture": "amd64",
  3131  		"gadget":       "gadget",
  3132  		"kernel":       "krnl",
  3133  		"timestamp":    time.Now().Format(time.RFC3339),
  3134  		"revision":     "2",
  3135  	}, nil, "")
  3136  	c.Assert(err, IsNil)
  3137  	modelRev2 := aRev2.(*asserts.Model)
  3138  
  3139  	hdrs := map[string]string{
  3140  		"series":   "16",
  3141  		"model":    "my-model",
  3142  		"brand-id": s.storeSigning.AuthorityID,
  3143  	}
  3144  	// model isn't found in the main DB
  3145  	_, err = assertstate.DB(st).Find(asserts.ModelType, hdrs)
  3146  	c.Assert(err, NotNil)
  3147  	c.Assert(asserts.IsNotFound(err), Equals, true)
  3148  	// let's get a temporary DB
  3149  	tempDB := assertstate.TemporaryDB(st)
  3150  	c.Assert(tempDB, NotNil)
  3151  	// and add the model to it
  3152  	err = tempDB.Add(model)
  3153  	c.Assert(err, IsNil)
  3154  	fromTemp, err := tempDB.Find(asserts.ModelType, hdrs)
  3155  	c.Assert(err, IsNil)
  3156  	c.Assert(fromTemp.(*asserts.Model), DeepEquals, model)
  3157  	// the model is only in the temp database
  3158  	_, err = assertstate.DB(st).Find(asserts.ModelType, hdrs)
  3159  	c.Assert(err, NotNil)
  3160  	c.Assert(asserts.IsNotFound(err), Equals, true)
  3161  
  3162  	// let's add it to the DB now
  3163  	err = assertstate.Add(st, model)
  3164  	c.Assert(err, IsNil)
  3165  	// such that we can lookup the revision 2 in a temporary DB
  3166  	tempDB = assertstate.TemporaryDB(st)
  3167  	c.Assert(tempDB, NotNil)
  3168  	err = tempDB.Add(modelRev2)
  3169  	c.Assert(err, IsNil)
  3170  	fromTemp, err = tempDB.Find(asserts.ModelType, hdrs)
  3171  	c.Assert(err, IsNil)
  3172  	c.Assert(fromTemp.(*asserts.Model), DeepEquals, modelRev2)
  3173  	// but the main DB still returns the old model
  3174  	fromDB, err := assertstate.DB(st).Find(asserts.ModelType, hdrs)
  3175  	c.Assert(err, IsNil)
  3176  	c.Assert(fromDB.(*asserts.Model), DeepEquals, model)
  3177  }