Skip to content

Commit 40c5d34

Browse files
committed
overlord/fdestate/activate_state.go: give inactive state on classic
1 parent 6ef8a8e commit 40c5d34

8 files changed

Lines changed: 214 additions & 25 deletions

File tree

daemon/api_general.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,14 @@ func sysInfoStorageEnc(c *Command, r *http.Request, user *auth.UserState) Respon
572572
st.Lock()
573573
defer st.Unlock()
574574

575-
state, err := fdestateSystemState(st)
575+
devmgr := c.d.overlord.DeviceManager()
576+
577+
model, err := devmgr.Model()
578+
if err != nil && !errors.Is(err, state.ErrNoState) {
579+
return InternalError("cannot find model: %v", err)
580+
}
581+
582+
state, err := fdestateSystemState(st, model)
576583
if err != nil {
577584
return InternalError("cannot determine system encrypted state: %s", err)
578585
}

daemon/api_general_test.go

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,20 @@ import (
3333
"gopkg.in/check.v1"
3434

3535
"github.com/snapcore/snapd/arch"
36+
"github.com/snapcore/snapd/asserts"
3637
"github.com/snapcore/snapd/boot"
3738
"github.com/snapcore/snapd/daemon"
3839
"github.com/snapcore/snapd/dirs"
3940
"github.com/snapcore/snapd/dirs/dirstest"
4041
"github.com/snapcore/snapd/features"
4142
"github.com/snapcore/snapd/interfaces"
4243
"github.com/snapcore/snapd/interfaces/ifacetest"
44+
"github.com/snapcore/snapd/overlord/assertstate/assertstatetest"
4345
"github.com/snapcore/snapd/overlord/auth"
4446
"github.com/snapcore/snapd/overlord/configstate/config"
47+
"github.com/snapcore/snapd/overlord/devicestate"
4548
"github.com/snapcore/snapd/overlord/fdestate"
49+
"github.com/snapcore/snapd/overlord/hookstate"
4650
"github.com/snapcore/snapd/overlord/state"
4751
"github.com/snapcore/snapd/release"
4852
"github.com/snapcore/snapd/sandbox"
@@ -1232,10 +1236,84 @@ func (s *generalSuite) TestAckWarnings(c *check.C) {
12321236
c.Check(result, check.DeepEquals, 0)
12331237
}
12341238

1235-
func (s *generalSuite) TestSysInfoStorageEncHappy(c *check.C) {
1239+
func (s *generalSuite) TestSysInfoStorageEncHappyWithoutModel(c *check.C) {
12361240
s.daemon(c)
1241+
1242+
expectedStatus := ""
1243+
expectedResponse := map[string]any{}
1244+
1245+
setExpectedStatus := func(status string) {
1246+
expectedStatus = status
1247+
expectedResponse["status"] = status
1248+
expectedResponse["auto-repair-result"] = "not-initialized"
1249+
}
1250+
1251+
defer daemon.MockFdestateSystemState(func(s *state.State, model *asserts.Model) (*fdestate.FDESystemState, error) {
1252+
switch expectedStatus {
1253+
case "active":
1254+
return &fdestate.FDESystemState{
1255+
Status: fdestate.FDEStatusActive,
1256+
AutoRepairResult: fdestate.AutoRepairNotInitialized,
1257+
}, nil
1258+
1259+
case "inactive":
1260+
return &fdestate.FDESystemState{
1261+
Status: fdestate.FDEStatusInactive,
1262+
AutoRepairResult: fdestate.AutoRepairNotInitialized,
1263+
}, nil
1264+
}
1265+
1266+
c.Check(model, check.IsNil)
1267+
1268+
return nil, errors.New("cannot set unsupported expected status")
1269+
})()
1270+
1271+
req, err := http.NewRequest("GET", "/v2/system-info/storage-encrypted", nil)
1272+
c.Assert(err, check.IsNil)
1273+
1274+
setExpectedStatus("active")
1275+
rsp := s.syncReq(c, req, nil, actionIsExpected)
1276+
c.Check(rsp.Status, check.Equals, 200)
1277+
c.Check(rsp.Type, check.Equals, daemon.ResponseTypeSync)
1278+
resultBytes, err := json.Marshal(rsp.Result)
1279+
c.Assert(err, check.IsNil)
1280+
var resultAbstract any
1281+
err = json.Unmarshal(resultBytes, &resultAbstract)
1282+
c.Assert(err, check.IsNil)
1283+
c.Check(resultAbstract, check.DeepEquals, expectedResponse)
1284+
1285+
setExpectedStatus("inactive")
1286+
rsp = s.syncReq(c, req, nil, actionIsExpected)
1287+
c.Assert(err, check.IsNil)
1288+
resultBytes, err = json.Marshal(rsp.Result)
1289+
c.Assert(err, check.IsNil)
1290+
err = json.Unmarshal(resultBytes, &resultAbstract)
1291+
c.Assert(err, check.IsNil)
1292+
c.Check(resultAbstract, check.DeepEquals, expectedResponse)
1293+
}
1294+
1295+
func (s *generalSuite) TestSysInfoStorageEncHappyWithModel(c *check.C) {
1296+
d := s.daemonWithOverlordMockAndStore()
12371297
s.expectSystemInfoStorageEncReadAccess()
12381298

1299+
hookMgr, err := hookstate.Manager(d.Overlord().State(), d.Overlord().TaskRunner())
1300+
c.Assert(err, check.IsNil)
1301+
deviceMgr, err := devicestate.Manager(d.Overlord().State(), hookMgr, d.Overlord().TaskRunner(), nil)
1302+
c.Assert(err, check.IsNil)
1303+
d.Overlord().AddManager(deviceMgr)
1304+
func() {
1305+
st := d.Overlord().State()
1306+
st.Lock()
1307+
defer st.Unlock()
1308+
assertstatetest.AddMany(st, s.StoreSigning.StoreAccountKey(""))
1309+
assertstatetest.AddMany(st, s.Brands.AccountsAndKeys("my-brand")...)
1310+
s.mockModel(st, s.Brands.Model("my-brand", "my-model", map[string]any{
1311+
"architecture": "amd64",
1312+
"gadget": "gadget",
1313+
"kernel": "kernel",
1314+
}))
1315+
}()
1316+
12391317
expectedStatus := ""
12401318
expectedResponse := map[string]any{}
12411319

@@ -1245,7 +1323,7 @@ func (s *generalSuite) TestSysInfoStorageEncHappy(c *check.C) {
12451323
expectedResponse["auto-repair-result"] = "not-initialized"
12461324
}
12471325

1248-
defer daemon.MockFdestateSystemState(func(*state.State) (*fdestate.FDESystemState, error) {
1326+
defer daemon.MockFdestateSystemState(func(s *state.State, model *asserts.Model) (*fdestate.FDESystemState, error) {
12491327
switch expectedStatus {
12501328
case "active":
12511329
return &fdestate.FDESystemState{
@@ -1260,6 +1338,8 @@ func (s *generalSuite) TestSysInfoStorageEncHappy(c *check.C) {
12601338
}, nil
12611339
}
12621340

1341+
c.Check(model, check.NotNil)
1342+
12631343
return nil, errors.New("cannot set unsupported expected status")
12641344
})()
12651345

@@ -1290,7 +1370,7 @@ func (s *generalSuite) TestSysInfoStorageEncHappy(c *check.C) {
12901370
func (s *generalSuite) TestSysInfoStorageEncErrorImpl(c *check.C) {
12911371
s.daemon(c)
12921372

1293-
defer daemon.MockFdestateSystemState(func(*state.State) (*fdestate.FDESystemState, error) {
1373+
defer daemon.MockFdestateSystemState(func(*state.State, *asserts.Model) (*fdestate.FDESystemState, error) {
12941374
return nil, errors.New("cannot calculate status")
12951375
})()
12961376

daemon/export_api_general_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package daemon
2222
import (
2323
"time"
2424

25+
"github.com/snapcore/snapd/asserts"
2526
"github.com/snapcore/snapd/overlord/fdestate"
2627
"github.com/snapcore/snapd/overlord/state"
2728
"github.com/snapcore/snapd/testutil"
@@ -71,7 +72,7 @@ func MockSnapdtoolsIsReexecd(f func() (bool, error)) (restore func()) {
7172
return testutil.Mock(&snapdtoolIsReexecd, f)
7273
}
7374

74-
func MockFdestateSystemState(f func(*state.State) (*fdestate.FDESystemState, error)) (restore func()) {
75+
func MockFdestateSystemState(f func(*state.State, *asserts.Model) (*fdestate.FDESystemState, error)) (restore func()) {
7576
old := fdestateSystemState
7677
fdestateSystemState = f
7778
return func() { fdestateSystemState = old }

overlord/fdestate/activate_state.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"errors"
2323
"os"
2424

25+
"github.com/snapcore/snapd/asserts"
2526
"github.com/snapcore/snapd/boot"
2627
"github.com/snapcore/snapd/logger"
2728
"github.com/snapcore/snapd/overlord/state"
@@ -99,7 +100,7 @@ type FDESystemState struct {
99100

100101
// SystemState returns a json serializable FDE state of the booted
101102
// system.
102-
func SystemState(st *state.State) (*FDESystemState, error) {
103+
func SystemState(st *state.State, model *asserts.Model) (*FDESystemState, error) {
103104
ret := &FDESystemState{}
104105

105106
repairResult, err := getRepairAttemptResult(st)
@@ -126,10 +127,19 @@ func SystemState(st *state.State) (*FDESystemState, error) {
126127
// unlocked.json does not exist, we are in either case:
127128
// * classic with kernel from deb.
128129
// * hybrid/core where snap-bootstrap is too old.
129-
ret.Status = FDEStatusIndeterminate
130-
// New classic version will still not support this,
131-
// so we should be a bit more quiet.
132-
logger.Debugf("while reading activate state: %v", err)
130+
if model == nil {
131+
// If the model is not yet available, they will have to request it again
132+
logger.Debugf("activate state was not found, and the model is not set yet; the state will remain indeterminate until the model is set")
133+
ret.Status = FDEStatusIndeterminate
134+
} else if model.Classic() && !model.HybridClassic() {
135+
// This expected that no activate state file
136+
// is found. And we know in that case we never
137+
// use platform-protected (i.e. TPM backed) encryption.
138+
ret.Status = FDEStatusInactive
139+
} else {
140+
logger.Noticef("WARNING: activate state not found")
141+
ret.Status = FDEStatusIndeterminate
142+
}
133143
return ret, nil
134144
} else if err != nil {
135145
// Unexpected errors should fail explicitly.

0 commit comments

Comments
 (0)