Skip to content

Commit

Permalink
o/devicestate,asserts: add deviceSigner tests
Browse files Browse the repository at this point in the history
  • Loading branch information
st3v3nmw committed Dec 10, 2024
1 parent 4ae7fad commit 52f3add
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 26 deletions.
6 changes: 1 addition & 5 deletions asserts/confdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,11 @@ func (cc *ConfdbControl) signKey(db RODatabase) (PublicKey, error) {
"model": cc.Model(),
"serial": cc.Serial(),
})
if errors.Is(err, &NotFoundError{}) {
return nil, errors.New("no matching serial assertion found")
}
if err != nil {
return nil, err
return nil, fmt.Errorf("cannot find matching serial: %w", err)
}

serial := a.(*Serial)

key := serial.DeviceKey()
if key.ID() != cc.SignKeyID() {
return nil, errors.New("confdb-control's signing key doesn't match the device's key")
Expand Down
12 changes: 12 additions & 0 deletions asserts/confdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,15 @@ func (s *confdbCtrlSuite) TestDecodeInvalid(c *C) {
c.Assert(err, ErrorMatches, validationSetErrPrefix+test.expectedErr, Commentf("test %d/%d failed", i+1, len(invalidTests)))
}
}

func (s *confdbCtrlSuite) TestPrerequisites(c *C) {
a, err := asserts.Decode([]byte(confdbControlExample))
c.Assert(err, IsNil)

prereqs := a.Prerequisites()
c.Assert(prereqs, HasLen, 1)
c.Check(prereqs[0], DeepEquals, &asserts.Ref{
Type: asserts.SerialType,
PrimaryKey: []string{"generic", "generic-classic", "03961d5d-26e5-443f-838d-6db046126bea"},
})
}
2 changes: 1 addition & 1 deletion asserts/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ func CheckSignature(assert Assertion, signingKey *AccountKey, roDB RODatabase, c
var err error
pubKey, err = signer.signKey(roDB)
if err != nil {
return err
return fmt.Errorf("cannot check signature: %w", err)
}
default:
return fmt.Errorf("cannot check no-authority assertion type %q", assert.Type().Name)
Expand Down
52 changes: 52 additions & 0 deletions asserts/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,58 @@ func (safs *signAddFindSuite) TestCheckConstraints(c *C) {
c.Check(err, ErrorMatches, `assertion does not match signing constraints for public key ".*" from "my-brand"`)
}

func (safs *signAddFindSuite) TestCheckSignatureDeviceKey(c *C) {
headers := map[string]interface{}{
"brand-id": "canonical",
"model": "pc",
"serial": "42",
"groups": []interface{}{},
}

// No serial assertion
a, err := asserts.AssembleAndSignInTest(asserts.ConfdbControlType, headers, nil, testPrivKey0)
c.Assert(err, IsNil)

err = safs.db.Add(a)
c.Assert(
err,
ErrorMatches,
"cannot check signature: cannot find matching serial: .* not found",
)

// Add serial
encodedPubKey, err := asserts.EncodePublicKey(testPrivKey0.PublicKey())
c.Assert(err, IsNil)

serial, err := asserts.AssembleAndSignInTest(asserts.SerialType, map[string]interface{}{
"authority-id": "canonical",
"brand-id": "canonical",
"model": "pc",
"serial": "42",
"device-key": string(encodedPubKey),
"device-key-sha3-384": safs.signingKeyID,
"timestamp": time.Now().Format(time.RFC3339),
}, nil, testPrivKey0)
c.Assert(err, IsNil)

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

// Keys don't match
a, err = asserts.AssembleAndSignInTest(asserts.ConfdbControlType, headers, nil, testPrivKey2)
c.Assert(err, IsNil)

err = safs.db.Add(a)
c.Assert(err, ErrorMatches, "cannot check signature: confdb-control's signing key doesn't match the device's key")

// OK
a, err = asserts.AssembleAndSignInTest(asserts.ConfdbControlType, headers, nil, testPrivKey0)
c.Assert(err, IsNil)

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

type revisionErrorSuite struct{}

func (res *revisionErrorSuite) TestErrorText(c *C) {
Expand Down
7 changes: 2 additions & 5 deletions overlord/devicestate/devicemgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -1967,15 +1967,12 @@ func (m *DeviceManager) keyPair() (asserts.PrivateKey, error) {
func (m *DeviceManager) SignConfdbControl(groups []interface{}) (*asserts.ConfdbControl, error) {
serial, err := m.Serial()
if err != nil {
return nil, fmt.Errorf("internal error: cannot sign confdb-control without a serial: %w", err)
return nil, fmt.Errorf("cannot sign confdb-control without a serial: %w", err)
}

privKey, err := m.keyPair()
if errors.Is(err, state.ErrNoState) {
return nil, fmt.Errorf("internal error: inconsistent state with serial but no device key")
}
if err != nil {
return nil, err
return nil, fmt.Errorf("cannot sign confdb-control without device key: %w", err)
}

a, err := asserts.SignWithoutAuthority(asserts.ConfdbControlType, map[string]interface{}{
Expand Down
39 changes: 24 additions & 15 deletions overlord/devicestate/devicestate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2796,19 +2796,9 @@ func (s *deviceMgrSuite) TestSignConfdbControl(c *C) {
"gadget": "pc",
})

jane := map[string]interface{}{
"operator-id": "jane",
"authentication": []interface{}{"operator-key"},
"views": []interface{}{
"canonical/network/observe-interfaces",
"canonical/network/control-interfaces",
},
}
groups := []interface{}{jane}

// No serial assertion exists yet
_, err := s.mgr.SignConfdbControl(groups)
c.Assert(err, ErrorMatches, "internal error: cannot sign confdb-control without a serial: no state entry for key")
_, err := s.mgr.SignConfdbControl([]interface{}{})
c.Assert(err, ErrorMatches, "cannot sign confdb-control without a serial: no state entry for key")

// Add serial assertion
encDevKey, err := asserts.EncodePublicKey(devKey.PublicKey())
Expand All @@ -2830,8 +2820,8 @@ func (s *deviceMgrSuite) TestSignConfdbControl(c *C) {
Serial: "42",
})

_, err = s.mgr.SignConfdbControl(groups)
c.Assert(err, ErrorMatches, "internal error: inconsistent state with serial but no device key")
_, err = s.mgr.SignConfdbControl([]interface{}{})
c.Assert(err, ErrorMatches, "cannot sign confdb-control without device key: no state entry for key")

// Add device key to manager
devicestate.KeypairManager(s.mgr).Put(devKey)
Expand All @@ -2843,7 +2833,26 @@ func (s *deviceMgrSuite) TestSignConfdbControl(c *C) {
KeyID: devKey.PublicKey().ID(),
})

// Sign assertion
// validation failure
groups := []interface{}{map[string]interface{}{"operator-id": "jane"}}
_, err = s.mgr.SignConfdbControl(groups)
c.Assert(
err,
ErrorMatches,
"cannot assemble assertion confdb-control: cannot parse group at position 1: \"authentication\" must be provided",
)

// OK
jane := map[string]interface{}{
"operator-id": "jane",
"authentication": []interface{}{"operator-key"},
"views": []interface{}{
"canonical/network/observe-interfaces",
"canonical/network/control-interfaces",
},
}
groups = []interface{}{jane}

cc, err := s.mgr.SignConfdbControl(groups)
c.Assert(err, IsNil)

Expand Down

0 comments on commit 52f3add

Please sign in to comment.