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