diff --git a/go.mod b/go.mod index ecc6b48..ce3fef1 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( ) require ( + github.com/google/uuid v1.3.0 golang.org/x/net v0.0.0-20191009170851-d66e71096ffb // indirect golang.org/x/text v0.3.0 // indirect ) diff --git a/go.sum b/go.sum index 9c62244..424907f 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/RobotsAndPencils/buford v0.14.0/go.mod h1:F5FvdB/nkMby8Pge6HFpPHgLOeU github.com/aai/gocrypto v0.0.0-20160205191751-93df0c47f8b8/go.mod h1:nE/FnVUmtbP0EbgMVCUtDrm1+86H47QfJIdcmZb+J1s= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/groob/plist v0.0.0-20220217120414-63fa881b19a5 h1:saaSiB25B1wgaxrshQhurfPKUGJ4It3OxNJUy0rdOjU= github.com/groob/plist v0.0.0-20220217120414-63fa881b19a5/go.mod h1:itkABA+w2cw7x5nYUS/pLRef6ludkZKOigbROmCTaFw= diff --git a/storage/internal/test/device.go b/storage/internal/test/device.go new file mode 100644 index 0000000..6126179 --- /dev/null +++ b/storage/internal/test/device.go @@ -0,0 +1,90 @@ +package test + +import ( + "context" + "errors" + "io/ioutil" + + "github.com/google/uuid" + "github.com/micromdm/nanomdm/mdm" + "github.com/micromdm/nanomdm/storage" +) + +type DeviceInterfaces interface { + storage.CheckinStore +} + +type Device struct { + Uuid string +} + +func NewDevice() Device { + return Device{Uuid: uuid.NewString()} +} + +func (d *Device) EnrollID() *mdm.EnrollID { + return &mdm.EnrollID{Type: mdm.Device, ID: d.Uuid} +} + +func loadAuthMsg() (*mdm.Authenticate, error) { + b, err := ioutil.ReadFile("../../mdm/testdata/Authenticate.2.plist") + if err != nil { + return nil, err + } + r, err := mdm.DecodeCheckin(b) + if err != nil { + return nil, err + } + a, ok := r.(*mdm.Authenticate) + if !ok { + return nil, errors.New("not an Authenticate message") + } + return a, nil +} + +func loadTokenMsg() (*mdm.TokenUpdate, error) { + b, err := ioutil.ReadFile("../../mdm/testdata/TokenUpdate.2.plist") + if err != nil { + return nil, err + } + r, err := mdm.DecodeCheckin(b) + if err != nil { + return nil, err + } + a, ok := r.(*mdm.TokenUpdate) + if !ok { + return nil, errors.New("not a TokenUpdate message") + } + return a, nil +} + +func (d *Device) newMdmReq() *mdm.Request { + return &mdm.Request{ + Context: context.Background(), + EnrollID: &mdm.EnrollID{ + Type: mdm.Device, + ID: d.Uuid, + }, + } +} + +func EnrollTestDevice(storage DeviceInterfaces) (Device, error) { + d := NewDevice() + authMsg, err := loadAuthMsg() + if err != nil { + return d, err + } + err = storage.StoreAuthenticate(d.newMdmReq(), authMsg) + if err != nil { + return d, err + } + tokenMsg, err := loadTokenMsg() + if err != nil { + return d, err + } + err = storage.StoreTokenUpdate(d.newMdmReq(), tokenMsg) + if err != nil { + return d, err + } + return d, nil +} diff --git a/storage/mysql/bstoken_test.go b/storage/mysql/bstoken_test.go new file mode 100644 index 0000000..b98aecc --- /dev/null +++ b/storage/mysql/bstoken_test.go @@ -0,0 +1,61 @@ +//go:build integration +// +build integration + +package mysql + +import ( + "bytes" + "context" + "encoding/base64" + "testing" + + "github.com/micromdm/nanomdm/mdm" + "github.com/micromdm/nanomdm/storage/internal/test" +) + +func TestBSToken(t *testing.T) { + if *flDSN == "" { + t.Fatal("MySQL DSN flag not provided to test") + } + + storage, err := New(WithDSN(*flDSN), WithDeleteCommands()) + if err != nil { + t.Fatal(err) + } + + var d test.Device + d, err = test.EnrollTestDevice(storage) + if err != nil { + t.Fatal(err) + } + + ctx := context.Background() + + t.Run("BSToken nil", func(t *testing.T) { + tok, err := storage.RetrieveBootstrapToken(&mdm.Request{Context: ctx, EnrollID: d.EnrollID()}, nil) + if err != nil { + t.Fatal(err) + } + if tok != nil { + t.Fatal("Token for new device was nonnull") + } + }) + t.Run("BSToken set/get", func(t *testing.T) { + data := []byte("test token") + bsToken := mdm.BootstrapToken{BootstrapToken: make([]byte, base64.StdEncoding.EncodedLen(len(data)))} + base64.StdEncoding.Encode(bsToken.BootstrapToken, data) + testReq := &mdm.Request{Context: ctx, EnrollID: d.EnrollID()} + err := storage.StoreBootstrapToken(testReq, &mdm.SetBootstrapToken{BootstrapToken: bsToken}) + if err != nil { + t.Fatal(err) + } + + tok, err := storage.RetrieveBootstrapToken(testReq, nil) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(bsToken.BootstrapToken, tok.BootstrapToken) { + t.Fatalf("Bootstap tokens disequal after roundtrip: %v!=%v", bsToken, tok) + } + }) +} diff --git a/storage/mysql/common_test.go b/storage/mysql/common_test.go new file mode 100644 index 0000000..84e9a89 --- /dev/null +++ b/storage/mysql/common_test.go @@ -0,0 +1,8 @@ +//go:build integration +// +build integration + +package mysql + +import "flag" + +var flDSN = flag.String("dsn", "", "DSN of test MySQL instance") diff --git a/storage/mysql/queue_test.go b/storage/mysql/queue_test.go index 49ee203..338fb91 100644 --- a/storage/mysql/queue_test.go +++ b/storage/mysql/queue_test.go @@ -4,84 +4,13 @@ package mysql import ( - "context" - "errors" - "flag" - "io/ioutil" "testing" - "github.com/micromdm/nanomdm/mdm" "github.com/micromdm/nanomdm/storage/internal/test" _ "github.com/go-sql-driver/mysql" ) -var flDSN = flag.String("dsn", "", "DSN of test MySQL instance") - -func loadAuthMsg() (*mdm.Authenticate, error) { - b, err := ioutil.ReadFile("../../mdm/testdata/Authenticate.2.plist") - if err != nil { - return nil, err - } - r, err := mdm.DecodeCheckin(b) - if err != nil { - return nil, err - } - a, ok := r.(*mdm.Authenticate) - if !ok { - return nil, errors.New("not an Authenticate message") - } - return a, nil -} - -func loadTokenMsg() (*mdm.TokenUpdate, error) { - b, err := ioutil.ReadFile("../../mdm/testdata/TokenUpdate.2.plist") - if err != nil { - return nil, err - } - r, err := mdm.DecodeCheckin(b) - if err != nil { - return nil, err - } - a, ok := r.(*mdm.TokenUpdate) - if !ok { - return nil, errors.New("not a TokenUpdate message") - } - return a, nil -} - -const deviceUDID = "66ADE930-5FDF-5EC4-8429-15640684C489" - -func newMdmReq() *mdm.Request { - return &mdm.Request{ - Context: context.Background(), - EnrollID: &mdm.EnrollID{ - Type: mdm.Device, - ID: deviceUDID, - }, - } -} - -func enrollTestDevice(storage *MySQLStorage) error { - authMsg, err := loadAuthMsg() - if err != nil { - return err - } - err = storage.StoreAuthenticate(newMdmReq(), authMsg) - if err != nil { - return err - } - tokenMsg, err := loadTokenMsg() - if err != nil { - return err - } - err = storage.StoreTokenUpdate(newMdmReq(), tokenMsg) - if err != nil { - return err - } - return nil -} - func TestQueue(t *testing.T) { if *flDSN == "" { t.Fatal("MySQL DSN flag not provided to test") @@ -92,13 +21,14 @@ func TestQueue(t *testing.T) { t.Fatal(err) } - err = enrollTestDevice(storage) + var d test.Device + d, err = test.EnrollTestDevice(storage) if err != nil { t.Fatal(err) } t.Run("WithDeleteCommands()", func(t *testing.T) { - test.TestQueue(t, deviceUDID, storage) + test.TestQueue(t, d.Uuid, storage) }) storage, err = New(WithDSN(*flDSN)) @@ -107,6 +37,6 @@ func TestQueue(t *testing.T) { } t.Run("normal", func(t *testing.T) { - test.TestQueue(t, deviceUDID, storage) + test.TestQueue(t, d.Uuid, storage) }) }