Пример #1
0
func (safs *signAddFindSuite) TestAddUnsupportedFormat(c *C) {
	const unsupported = "type: test-only\n" +
		"format: 77\n" +
		"authority-id: canonical\n" +
		"primary-key: a\n" +
		"payload: unsupported\n" +
		"sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij" +
		"\n\n" +
		"AXNpZw=="
	headers := map[string]interface{}{
		"authority-id": "canonical",
		"primary-key":  "a",
		"format":       "77",
		"payload":      "unsupported",
	}
	aUnsupp, err := asserts.Decode([]byte(unsupported))
	c.Assert(err, IsNil)
	c.Assert(aUnsupp.SupportedFormat(), Equals, false)

	err = safs.db.Add(aUnsupp)
	c.Assert(err, FitsTypeOf, &asserts.UnsupportedFormatError{})
	c.Check(err.(*asserts.UnsupportedFormatError).Update, Equals, false)
	c.Check(err, ErrorMatches, `proposed "test-only" assertion has format 77 but 1 is latest supported`)
	c.Check(asserts.IsUnaccceptedUpdate(err), Equals, false)

	headers = map[string]interface{}{
		"authority-id": "canonical",
		"primary-key":  "a",
		"format":       "1",
		"payload":      "supported",
	}
	aSupp, err := asserts.AssembleAndSignInTest(asserts.TestOnlyType, headers, nil, testPrivKey0)
	c.Assert(err, IsNil)

	err = safs.db.Add(aSupp)
	c.Assert(err, IsNil)

	err = safs.db.Add(aUnsupp)
	c.Assert(err, FitsTypeOf, &asserts.UnsupportedFormatError{})
	c.Check(err.(*asserts.UnsupportedFormatError).Update, Equals, true)
	c.Check(err, ErrorMatches, `proposed "test-only" assertion has format 77 but 1 is latest supported \(current not updated\)`)
	c.Check(asserts.IsUnaccceptedUpdate(err), Equals, true)
}
Пример #2
0
func (s *isUnacceptedUpdateSuite) TestIsUnacceptedUpdate(c *C) {
	tests := []struct {
		err         error
		keptCurrent bool
	}{
		{&asserts.UnsupportedFormatError{}, false},
		{&asserts.UnsupportedFormatError{Update: true}, true},
		{&asserts.RevisionError{Used: 1, Current: 1}, true},
		{&asserts.RevisionError{Used: 1, Current: 5}, true},
		{&asserts.RevisionError{Used: 3, Current: 1}, false},
		{errors.New("other error"), false},
		{asserts.ErrNotFound, false},
	}

	for _, t := range tests {
		c.Check(asserts.IsUnaccceptedUpdate(t.err), Equals, t.keptCurrent, Commentf("%v", t.err))
	}
}
Пример #3
0
// commit does a best effort of adding all the fetched assertions to the system database.
func (f *fetcher) commit() error {
	var errs []error
	for _, a := range f.fetched {
		err := f.db.Add(a)
		if asserts.IsUnaccceptedUpdate(err) {
			if _, ok := err.(*asserts.UnsupportedFormatError); ok {
				// we kept the old one, but log the issue
				logger.Noticef("Cannot update assertion: %v", err)
			}
			// be idempotent
			// system db has already the same or newer
			continue
		}
		if err != nil {
			errs = append(errs, err)
		}
	}
	if len(errs) != 0 {
		return &commitError{errs: errs}
	}
	return nil
}
Пример #4
0
func (safs *signAddFindSuite) TestAddSuperseding(c *C) {
	headers := map[string]interface{}{
		"authority-id": "canonical",
		"primary-key":  "a",
	}
	a1, err := safs.signingDB.Sign(asserts.TestOnlyType, headers, nil, safs.signingKeyID)
	c.Assert(err, IsNil)

	err = safs.db.Add(a1)
	c.Assert(err, IsNil)

	retrieved1, err := safs.db.Find(asserts.TestOnlyType, map[string]string{
		"primary-key": "a",
	})
	c.Assert(err, IsNil)
	c.Check(retrieved1, NotNil)
	c.Check(retrieved1.Revision(), Equals, 0)

	headers["revision"] = "1"
	a2, err := safs.signingDB.Sign(asserts.TestOnlyType, headers, nil, safs.signingKeyID)
	c.Assert(err, IsNil)

	err = safs.db.Add(a2)
	c.Assert(err, IsNil)

	retrieved2, err := safs.db.Find(asserts.TestOnlyType, map[string]string{
		"primary-key": "a",
	})
	c.Assert(err, IsNil)
	c.Check(retrieved2, NotNil)
	c.Check(retrieved2.Revision(), Equals, 1)

	err = safs.db.Add(a1)
	c.Check(err, ErrorMatches, "revision 0 is older than current revision 1")
	c.Check(asserts.IsUnaccceptedUpdate(err), Equals, true)
}
Пример #5
0
func (m *DeviceManager) doRequestSerial(t *state.Task, _ *tomb.Tomb) error {
	st := t.State()
	st.Lock()
	defer st.Unlock()

	cfg, err := getSerialRequestConfig(t)
	if err != nil {
		return err
	}

	device, err := auth.Device(st)
	if err != nil {
		return err
	}

	privKey, err := m.keyPair()
	if err == state.ErrNoState {
		return fmt.Errorf("internal error: cannot find device key pair")
	}
	if err != nil {
		return err
	}

	// make this idempotent, look if we have already a serial assertion
	// for privKey
	serials, err := assertstate.DB(st).FindMany(asserts.SerialType, map[string]string{
		"brand-id":            device.Brand,
		"model":               device.Model,
		"device-key-sha3-384": privKey.PublicKey().ID(),
	})
	if err != nil && err != asserts.ErrNotFound {
		return err
	}

	if len(serials) == 1 {
		// means we saved the assertion but didn't get to the end of the task
		device.Serial = serials[0].(*asserts.Serial).Serial()
		err := auth.SetDevice(st, device)
		if err != nil {
			return err
		}
		t.SetStatus(state.DoneStatus)
		return nil
	}
	if len(serials) > 1 {
		return fmt.Errorf("internal error: multiple serial assertions for the same device key")
	}

	serial, err := getSerial(t, privKey, device, cfg)
	if err == errPoll {
		t.Logf("Will poll for device serial assertion in 60 seconds")
		return &state.Retry{After: retryInterval}
	}
	if err != nil { // errors & retries
		return err
	}

	sto := snapstate.Store(st)
	// try to fetch the signing key of the serial
	st.Unlock()
	a, errAcctKey := sto.Assertion(asserts.AccountKeyType, []string{serial.SignKeyID()}, nil)
	st.Lock()
	if errAcctKey == nil {
		err := assertstate.Add(st, a)
		if err != nil {
			if !asserts.IsUnaccceptedUpdate(err) {
				return err
			}
		}
	}

	// add the serial assertion to the system assertion db
	err = assertstate.Add(st, serial)
	if err != nil {
		// if we had failed to fetch the signing key, retry in a bit
		if errAcctKey != nil {
			t.Errorf("cannot fetch signing key for the serial: %v", errAcctKey)
			return &state.Retry{After: retryInterval}
		}
		return err
	}

	if repeatRequestSerial == "after-add-serial" {
		// For testing purposes, ensure a crash in this state works.
		return &state.Retry{}
	}

	device.Serial = serial.Serial()
	err = auth.SetDevice(st, device)
	if err != nil {
		return err
	}
	t.SetStatus(state.DoneStatus)
	return nil
}