diff --git a/Gopkg.lock b/Gopkg.lock
index bd8ac64f..b91d4da8 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -32,10 +32,10 @@
[[projects]]
name = "github.com/go-kit/kit"
packages = [
+ "auth/basic",
"endpoint",
"log",
"log/level",
- "metrics",
"transport/http"
]
revision = "4dc7be5d2d12881735283bcab7352178e190fc71"
@@ -60,10 +60,10 @@
version = "v0.5"
[[projects]]
- branch = "master"
name = "github.com/golang/protobuf"
packages = ["proto"]
- revision = "130e6b02ab059e7b717a096f397c5b60111cae74"
+ revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
+ version = "v1.1.0"
[[projects]]
name = "github.com/gorilla/context"
@@ -207,6 +207,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
- inputs-digest = "3d247c7533ff5f494f214cccd89d30e7eb426b30218ac166eac3ae75220a21d2"
+ inputs-digest = "5f587f612f4f5f3dbad6cf659cb4eadfee35f886ea4dd7b795cf9fe9bfeb99e0"
solver-name = "gps-cdcl"
solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
index 580e61a6..73190c18 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -1,4 +1,3 @@
-
[[constraint]]
name = "github.com/boltdb/bolt"
version = "v1.3.0"
@@ -26,3 +25,7 @@
[[constraint]]
name = "github.com/groob/plist"
branch = "master"
+
+[[constraint]]
+ name = "github.com/golang/protobuf"
+ version = "1.1.0"
diff --git a/cmd/micromdm/serve.go b/cmd/micromdm/serve.go
index 2f150a5d..952342bf 100644
--- a/cmd/micromdm/serve.go
+++ b/cmd/micromdm/serve.go
@@ -23,7 +23,6 @@ import (
"github.com/boltdb/bolt"
"github.com/fullsailor/pkcs7"
"github.com/go-kit/kit/auth/basic"
- "github.com/go-kit/kit/endpoint"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
httptransport "github.com/go-kit/kit/transport/http"
@@ -39,8 +38,7 @@ import (
"golang.org/x/crypto/pkcs12"
"github.com/micromdm/micromdm/dep/depsync"
- "github.com/micromdm/micromdm/mdm/checkin"
- "github.com/micromdm/micromdm/mdm/connect"
+ "github.com/micromdm/micromdm/mdm"
"github.com/micromdm/micromdm/mdm/enroll"
"github.com/micromdm/micromdm/pkg/crypto"
httputil2 "github.com/micromdm/micromdm/pkg/httputil"
@@ -163,7 +161,6 @@ func serve(args []string) error {
sm.setupConfigStore()
sm.loadPushCerts()
sm.setupSCEP(logger)
- sm.setupCheckinService()
sm.setupPushService(logger)
sm.setupCommandService()
sm.setupWebhooks()
@@ -213,42 +210,15 @@ func serve(args []string) error {
ctx := context.Background()
httpLogger := log.With(logger, "transport", "http")
- var checkinHandlers checkin.HTTPHandlers
- {
- e := checkin.Endpoints{
- CheckinEndpoint: checkin.MakeCheckinEndpoint(sm.checkinService),
- }
- opts := []httptransport.ServerOption{
- httptransport.ServerErrorLogger(httpLogger),
- httptransport.ServerErrorEncoder(checkin.EncodeError),
- }
- checkinHandlers = checkin.MakeHTTPHandlers(ctx, e, opts...)
- }
-
- connectOpts := []httptransport.ServerOption{
- httptransport.ServerErrorLogger(httpLogger),
- httptransport.ServerErrorEncoder(connect.EncodeError),
- }
-
- var connectEndpoint endpoint.Endpoint
- {
- connectEndpoint = connect.MakeConnectEndpoint(sm.connectService)
- }
- connectEndpoints := connect.Endpoints{
- ConnectEndpoint: connectEndpoint,
- }
-
dc := sm.depClient
appDB := &appsbuiltin.Repo{Path: *flRepoPath}
- connectHandlers := connect.MakeHTTPHandlers(ctx, connectEndpoints, connectOpts...)
scepHandler := scep.ServiceHandler(ctx, sm.scepService, httpLogger)
enrollHandlers := enroll.MakeHTTPHandlers(ctx, enroll.MakeServerEndpoints(sm.enrollService, sm.scepDepot), httptransport.ServerErrorLogger(httpLogger))
r, options := httputil2.NewRouter(logger)
+
r.Handle("/version", version.Handler())
- r.Handle("/mdm/checkin", mdmAuthSignMessageMiddleware(sm.scepDepot, checkinHandlers.CheckinHandler)).Methods("PUT")
- r.Handle("/mdm/connect", mdmAuthSignMessageMiddleware(sm.scepDepot, connectHandlers.ConnectHandler)).Methods("PUT")
r.Handle("/mdm/enroll", enrollHandlers.EnrollHandler).Methods("GET", "POST")
r.Handle("/ota/enroll", enrollHandlers.OTAEnrollHandler)
r.Handle("/ota/phase23", enrollHandlers.OTAPhase2Phase3Handler).Methods("POST")
@@ -259,6 +229,10 @@ func serve(args []string) error {
})
}
+ signatureVerifier := &mdmSignatureVerifier{db: sm.scepDepot}
+ mdmEndpoints := mdm.MakeServerEndpoints(sm.mdmService)
+ mdm.RegisterHTTPHandlers(r, mdmEndpoints, signatureVerifier, logger)
+
// API commands. Only handled if the user provides an api key.
if *flAPIKey != "" {
basicAuthEndpointMiddleware := basic.AuthMiddleware("micromdm", *flAPIKey, "micromdm")
@@ -411,8 +385,7 @@ type server struct {
PushService *push.Service // bufford push
pushService apns.Service
- checkinService checkin.Service
- connectService connect.Service
+ mdmService mdm.Service
enrollService enroll.Service
scepService scep.Service
commandService command.Service
@@ -447,7 +420,7 @@ func (c *server) setupWebhooks() {
return
}
- h, err := webhook.NewCommandWebhook(c.webhooksHTTPClient, connect.ConnectTopic, c.CommandWebhookURL)
+ h, err := webhook.NewCommandWebhook(c.webhooksHTTPClient, mdm.ConnectTopic, c.CommandWebhookURL)
if err != nil {
c.err = err
return
@@ -488,25 +461,13 @@ func (c *server) setupCommandQueue(logger log.Logger) {
return
}
- var connectService connect.Service
+ var mdmService mdm.Service
{
- svc, err := connect.New(q, c.pubclient)
- if err != nil {
- c.err = err
- return
- }
- connectService = svc
- connectService = connect.LoggingMiddleware(log.With(level.Info(logger), "component", "connect"))(svc)
- connectService = block.RemoveMiddleware(c.removeDB)(connectService)
+ svc := mdm.NewService(c.pubclient, q)
+ mdmService = svc
+ mdmService = block.RemoveMiddleware(c.removeDB)(mdmService)
}
- c.connectService = connectService
-}
-
-func (c *server) setupCheckinService() {
- if c.err != nil {
- return
- }
- c.checkinService, c.err = checkin.New(c.db, c.pubclient)
+ c.mdmService = mdmService
}
func (c *server) setupBolt() {
@@ -794,66 +755,38 @@ func (c *server) setupSCEP(logger log.Logger) {
}
}
-// TODO: move to separate package/library
-func mdmAuthSignMessageMiddleware(db *boltdepot.Depot, next http.Handler) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
- b64sig := r.Header.Get("Mdm-Signature")
- if b64sig == "" {
- http.Error(w, "Signature missing", http.StatusBadRequest)
- return
- }
- sig, err := base64.StdEncoding.DecodeString(b64sig)
- if err != nil {
- http.Error(w, "Signature decoding error", http.StatusBadRequest)
- return
- }
- p7, err := pkcs7.Parse(sig)
- if err != nil {
- http.Error(w, "Signature parsing error", http.StatusBadRequest)
- return
- }
- bodyBuf, err := ioutil.ReadAll(r.Body)
- if err != nil {
- fmt.Println(err)
- http.Error(w, "Problem reading request", http.StatusInternalServerError)
- return
- }
+type mdmSignatureVerifier struct {
+ db *boltdepot.Depot
+}
- // the signed data is the HTTP body message
- p7.Content = bodyBuf
-
- // reassign body to our already-read buffer
- r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBuf))
- // TODO: r.Body.Close() as we've ReadAll()'d it?
-
- err = p7.Verify()
- if err != nil {
- http.Error(w, "Signature verification error", http.StatusBadRequest)
- return
- }
-
- cert := p7.GetOnlySigner()
- if cert == nil {
- http.Error(w, "Invalid signer", http.StatusBadRequest)
- return
- }
-
- hasCN, err := HasCN(db, cert.Subject.CommonName, 0, cert, false)
- if err != nil {
- fmt.Println(err)
- http.Error(w, "Unable to validate signature", http.StatusInternalServerError)
- return
- }
- if !hasCN {
- fmt.Println("Unauthorized client signature from:", cert.Subject.CommonName)
- // NOTE: We're not returning 401 Unauthorized to avoid unenrolling a device
- // this may change in the future
- http.Error(w, "Unauthorized", http.StatusBadRequest)
- return
- }
-
- next.ServeHTTP(w, r)
+func (v *mdmSignatureVerifier) VerifySignature(b64sig string, message []byte) error {
+ if b64sig == "" {
+ return errors.New("signature missing")
}
+ sig, err := base64.StdEncoding.DecodeString(b64sig)
+ if err != nil {
+ return errors.Wrap(err, "decode MDM SignMessage header")
+ }
+ p7, err := pkcs7.Parse(sig)
+ if err != nil {
+ return errors.Wrap(err, "parse MDM SignMessage signature")
+ }
+ p7.Content = message
+ if err := p7.Verify(); err != nil {
+ return errors.Wrap(err, "verify MDM Signed Message")
+ }
+ cert := p7.GetOnlySigner()
+ if cert == nil {
+ return errors.New("invalid signer")
+ }
+ hasCN, err := HasCN(v.db, cert.Subject.CommonName, 0, cert, false)
+ if err != nil {
+ return errors.Wrap(err, "unable to validate signature")
+ }
+ if !hasCN {
+ return errors.Wrap(err, "Unauthorized client")
+ }
+ return nil
}
// implement HasCN function that belongs in micromdm/scep/depot/bolt
diff --git a/mdm/acknowledge.go b/mdm/acknowledge.go
new file mode 100644
index 00000000..3e1783df
--- /dev/null
+++ b/mdm/acknowledge.go
@@ -0,0 +1,73 @@
+package mdm
+
+import (
+ "context"
+ "net/http"
+ "time"
+
+ "github.com/go-kit/kit/endpoint"
+ "github.com/gorilla/mux"
+ "github.com/groob/plist"
+ "github.com/pkg/errors"
+ uuid "github.com/satori/go.uuid"
+)
+
+func (svc *MDMService) Acknowledge(ctx context.Context, req AcknowledgeEvent) (payload []byte, err error) {
+ msg, err := MarshalAcknowledgeEvent(&req)
+ if err != nil {
+ return nil, errors.Wrap(err, "marshal acknowledge response to proto")
+ }
+
+ if err := svc.pub.Publish(ctx, ConnectTopic, msg); err != nil {
+ return nil, errors.Wrap(err, "publish connect Response on pubsub")
+ }
+
+ payload, err = svc.queue.Next(ctx, req.Response)
+ return payload, errors.Wrap(err, "calling Next with mdm response")
+
+}
+
+type acknowledgeRequest struct {
+ Event AcknowledgeEvent
+}
+
+type acknowledgeResponse struct {
+ Payload []byte
+ Err error `plist:"error,omitempty"`
+}
+
+func (r acknowledgeResponse) Response() []byte { return r.Payload }
+func (r acknowledgeResponse) Failed() error { return r.Err }
+
+func (d *requestDecoder) decodeAcknowledgeRequest(ctx context.Context, r *http.Request) (interface{}, error) {
+ body, err := d.readBody(r)
+ if err != nil {
+ return nil, errors.Wrap(err, "read acknowledge request body")
+ }
+
+ var res Response
+ err = plist.Unmarshal(body, &res)
+ if err != nil {
+ return nil, errors.Wrap(err, "unmarshal MDM Response plist")
+ }
+
+ params := mux.Vars(r)
+
+ event := AcknowledgeEvent{
+ ID: uuid.NewV4().String(),
+ Time: time.Now().UTC(),
+ Response: res,
+ Params: params,
+ Raw: body,
+ }
+ req := acknowledgeRequest{Event: event}
+ return req, nil
+}
+
+func MakeAcknowledgeEndpoint(svc Service) endpoint.Endpoint {
+ return func(ctx context.Context, request interface{}) (interface{}, error) {
+ req := request.(acknowledgeRequest)
+ payload, err := svc.Acknowledge(ctx, req.Event)
+ return acknowledgeResponse{Payload: payload, Err: err}, nil
+ }
+}
diff --git a/mdm/connect/event.go b/mdm/acknowledge_event.go
similarity index 50%
rename from mdm/connect/event.go
rename to mdm/acknowledge_event.go
index 8546a1fb..e29ab21a 100644
--- a/mdm/connect/event.go
+++ b/mdm/acknowledge_event.go
@@ -1,33 +1,37 @@
-package connect
+package mdm
import (
"time"
"github.com/gogo/protobuf/proto"
- "github.com/micromdm/mdm"
- uuid "github.com/satori/go.uuid"
-
- "github.com/micromdm/micromdm/mdm/connect/internal/connectproto"
+ "github.com/micromdm/micromdm/mdm/internal/connectproto"
)
-type Event struct {
+type AcknowledgeEvent struct {
ID string
Time time.Time
- Response mdm.Response
+ Response Response
+ Params map[string]string
Raw []byte
}
-func NewEvent(resp MDMConnectRequest) *Event {
- event := Event{
- ID: uuid.NewV4().String(),
- Time: time.Now().UTC(),
- Response: resp.MDMResponse,
- Raw: resp.Raw,
- }
- return &event
+type Response struct {
+ RequestType string `json:"request_type,omitempty" plist:",omitempty"`
+ UDID string
+ UserID *string `json:"user_id,omitempty" plist:"UserID,omitempty"`
+ Status string
+ CommandUUID string
+ ErrorChain []ErrorChainItem `json:"error_chain" plist:",omitempty"`
}
-func MarshalEvent(e *Event) ([]byte, error) {
+type ErrorChainItem struct {
+ ErrorCode int `json:"error_code,omitempty"`
+ ErrorDomain string `json:"error_domain,omitempty"`
+ LocalizedDescription string `json:"localized_description,omitempty"`
+ USEnglishDescription string `json:"us_english_description,omitempty"`
+}
+
+func MarshalAcknowledgeEvent(e *AcknowledgeEvent) ([]byte, error) {
response := &connectproto.Response{
CommandUuid: e.Response.CommandUUID,
Udid: e.Response.UDID,
@@ -42,11 +46,12 @@ func MarshalEvent(e *Event) ([]byte, error) {
Id: e.ID,
Time: e.Time.UnixNano(),
Response: response,
+ Params: e.Params,
Raw: e.Raw,
})
}
-func UnmarshalEvent(data []byte, e *Event) error {
+func UnmarshalAcknowledgeEvent(data []byte, e *AcknowledgeEvent) error {
var pb connectproto.Event
if err := proto.Unmarshal(data, &pb); err != nil {
return err
@@ -57,14 +62,15 @@ func UnmarshalEvent(data []byte, e *Event) error {
return nil
}
r := pb.GetResponse()
- e.Response = mdm.Response{
+ e.Response = Response{
UDID: r.GetUdid(),
UserID: strPtr(r.GetUserId()),
Status: r.GetStatus(),
RequestType: r.GetRequestType(),
CommandUUID: r.GetCommandUuid(),
}
- e.Raw = pb.Raw
+ e.Raw = pb.GetRaw()
+ e.Params = pb.GetParams()
return nil
}
diff --git a/mdm/checkin.go b/mdm/checkin.go
new file mode 100644
index 00000000..7eae930b
--- /dev/null
+++ b/mdm/checkin.go
@@ -0,0 +1,105 @@
+package mdm
+
+import (
+ "context"
+ "net/http"
+ "time"
+
+ "github.com/go-kit/kit/endpoint"
+ "github.com/gorilla/mux"
+ "github.com/groob/plist"
+ "github.com/pkg/errors"
+ uuid "github.com/satori/go.uuid"
+)
+
+func (svc *MDMService) Checkin(ctx context.Context, event CheckinEvent) error {
+ if event.Command.MessageType == "UserAuthenticate" {
+ return &rejectUserAuth{}
+ }
+
+ msg, err := MarshalCheckinEvent(&event)
+ if err != nil {
+ return errors.Wrap(err, "marshal checkin event")
+ }
+
+ topic, err := topicFromMessage(event.Command.MessageType)
+ if err != nil {
+ return errors.Wrap(err, "get checkin topic from message")
+ }
+
+ err = svc.pub.Publish(ctx, topic, msg)
+ return errors.Wrapf(err, "publish checkin on topic: %s", topic)
+}
+
+func topicFromMessage(messageType string) (string, error) {
+ switch messageType {
+ case "Authenticate":
+ return AuthenticateTopic, nil
+ case "TokenUpdate":
+ return TokenUpdateTopic, nil
+ case "CheckOut":
+ return CheckoutTopic, nil
+ default:
+ return "", errors.Errorf("unknown checkin message type %s", messageType)
+ }
+}
+
+type rejectUserAuth struct{}
+
+func (e *rejectUserAuth) Error() string {
+ return "reject user auth"
+}
+func (e *rejectUserAuth) UserAuthReject() bool {
+ return true
+}
+
+func isRejectedUserAuth(err error) bool {
+ type rejectUserAuthError interface {
+ error
+ UserAuthReject() bool
+ }
+
+ _, ok := errors.Cause(err).(rejectUserAuthError)
+ return ok
+}
+
+type checkinRequest struct {
+ Event CheckinEvent
+}
+
+type checkinResponse struct {
+ Err error `plist:"error,omitempty"`
+}
+
+func (r checkinResponse) Failed() error { return r.Err }
+
+func (d *requestDecoder) decodeCheckinRequest(ctx context.Context, r *http.Request) (interface{}, error) {
+ body, err := d.readBody(r)
+ if err != nil {
+ return nil, errors.Wrap(err, "read checkin request body")
+ }
+
+ var cmd CheckinCommand
+ if err := plist.Unmarshal(body, &cmd); err != nil {
+ return nil, errors.Wrap(err, "unmarshal MDM Checkin Request plist")
+ }
+
+ params := mux.Vars(r)
+ event := CheckinEvent{
+ ID: uuid.NewV4().String(),
+ Time: time.Now().UTC(),
+ Command: cmd,
+ Params: params,
+ Raw: body,
+ }
+ req := checkinRequest{Event: event}
+ return req, nil
+}
+
+func MakeCheckinEndpoint(svc Service) endpoint.Endpoint {
+ return func(ctx context.Context, request interface{}) (interface{}, error) {
+ req := request.(checkinRequest)
+ err := svc.Checkin(ctx, req.Event)
+ return checkinResponse{Err: err}, nil
+ }
+}
diff --git a/mdm/checkin/checkin.go b/mdm/checkin/checkin.go
deleted file mode 100644
index f2c6d0f0..00000000
--- a/mdm/checkin/checkin.go
+++ /dev/null
@@ -1,99 +0,0 @@
-package checkin
-
-import (
- "fmt"
-
- "github.com/boltdb/bolt"
- "github.com/micromdm/mdm"
- "github.com/pkg/errors"
- "golang.org/x/net/context"
-
- "github.com/micromdm/micromdm/platform/pubsub"
-)
-
-// CheckinBucket is the *bolt.DB bucket where checkins are archived.
-const CheckinBucket = "mdm.Checkin.ARCHIVE"
-
-// PubSub Topics where MDM Checkin events are published to.
-const (
- AuthenticateTopic = "mdm.Authenticate"
- TokenUpdateTopic = "mdm.TokenUpdate"
- CheckoutTopic = "mdm.CheckOut"
-)
-
-type Checkin struct {
- db *bolt.DB
- publisher pubsub.Publisher
- archiveFn func(int64, []byte) error
-}
-
-func New(db *bolt.DB, pub pubsub.Publisher) (*Checkin, error) {
- err := db.Update(func(tx *bolt.Tx) error {
- _, err := tx.CreateBucketIfNotExists([]byte(CheckinBucket))
- return err
- })
- if err != nil {
- return nil, errors.Wrapf(err, "creating %s bucket", CheckinBucket)
- }
- svc := Checkin{
- db: db,
- publisher: pub,
- }
- svc.archiveFn = svc.archive
- return &svc, nil
-}
-
-func (svc *Checkin) Authenticate(ctx context.Context, cmd mdm.CheckinCommand) error {
- if cmd.MessageType != "Authenticate" {
- return fmt.Errorf("expected Authenticate, got %s MessageType", cmd.MessageType)
- }
- return svc.archiveAndPublish(AuthenticateTopic, cmd)
-}
-
-func (svc *Checkin) TokenUpdate(ctx context.Context, cmd mdm.CheckinCommand) error {
- if cmd.MessageType != "TokenUpdate" {
- return fmt.Errorf("expected TokenUpdate, got %s MessageType", cmd.MessageType)
- }
- return svc.archiveAndPublish(TokenUpdateTopic, cmd)
-}
-
-func (svc *Checkin) CheckOut(ctx context.Context, cmd mdm.CheckinCommand) error {
- if cmd.MessageType != "CheckOut" {
- return fmt.Errorf("expected CheckOut, but got %s MessageType", cmd.MessageType)
- }
- return svc.archiveAndPublish(CheckoutTopic, cmd)
-}
-
-// archive events to BoltDB bucket using timestamp as key to preserve order.
-func (svc *Checkin) archive(nano int64, msg []byte) error {
- tx, err := svc.db.Begin(true)
- if err != nil {
- return errors.Wrap(err, "begin transaction")
- }
- defer tx.Rollback()
-
- bkt := tx.Bucket([]byte(CheckinBucket))
- if bkt == nil {
- return fmt.Errorf("bucket %q not found!", CheckinBucket)
- }
- key := []byte(fmt.Sprintf("%d", nano))
- if err := bkt.Put(key, msg); err != nil {
- return errors.Wrap(err, "put checkin event to boltdb")
- }
- return tx.Commit()
-}
-
-func (svc *Checkin) archiveAndPublish(topic string, cmd mdm.CheckinCommand) error {
- event := NewEvent(cmd)
- msg, err := MarshalEvent(event)
- if err != nil {
- return errors.Wrap(err, "marshal checkin event")
- }
- if err := svc.archiveFn(event.Time.UnixNano(), msg); err != nil {
- return errors.Wrap(err, "archive checkin")
- }
- if err := svc.publisher.Publish(context.TODO(), topic, msg); err != nil {
- return errors.Wrapf(err, "publish checkin on topic: %s", topic)
- }
- return nil
-}
diff --git a/mdm/checkin/checkin_test.go b/mdm/checkin/checkin_test.go
deleted file mode 100644
index 20ffa262..00000000
--- a/mdm/checkin/checkin_test.go
+++ /dev/null
@@ -1,299 +0,0 @@
-package checkin
-
-import (
- "context"
- "errors"
- "fmt"
- "io/ioutil"
- "os"
- "reflect"
- "testing"
-
- "github.com/boltdb/bolt"
- "github.com/groob/plist"
- "github.com/micromdm/mdm"
-)
-
-func setupDB(t *testing.T) *Checkin {
- f, _ := ioutil.TempFile("", "bolt-")
- f.Close()
- os.Remove(f.Name())
-
- db, err := bolt.Open(f.Name(), 0777, nil)
- if err != nil {
- t.Fatalf("couldn't open bolt, err %s\n", err)
- }
- svc, err := New(db, nil)
- if err != nil {
- t.Fatalf("couldn't create service, err %s\n", err)
- }
- return svc
-}
-
-func mustLoadCommand(t *testing.T, name string) mdm.CheckinCommand {
- var payload mdm.CheckinCommand
- data, err := ioutil.ReadFile("testdata/" + name + ".plist")
- if err != nil {
- t.Fatalf("failed to open test file %q.plist, err: %s", name, err)
- }
- if err := plist.Unmarshal(data, &payload); err != nil {
- t.Fatalf("failed to unmarshal plist %q, err: %s", name, err)
- }
- return payload
-}
-
-type mockPublisher struct {
- Invoked bool
- PublishFn func(string, []byte) error
-}
-
-func (m *mockPublisher) Publish(ctx context.Context, s string, b []byte) error {
- m.Invoked = true
- return m.PublishFn(s, b)
-}
-
-var passPublisher = func(string, []byte) error { return nil }
-var failPublisher = func(string, []byte) error {
- return errors.New("failed")
-}
-
-// archiveFunc is the function signature for archiving events in BoltDB.
-type archiveFunc func(int64, []byte) error
-
-// override the timestamp with a custom value when saving to BoltDB.
-func archiveAt(timestamp int64, svc *Checkin) archiveFunc {
- return func(nano int64, event []byte) error {
- return svc.archive(timestamp, event)
- }
-}
-
-func archiveFail() archiveFunc {
- return func(nano int64, event []byte) error {
- return errors.New("archive failed")
- }
-}
-
-// load a specific event from the bolt bucket.
-func loadEvent(t *testing.T, db *bolt.DB, nano int64) *Event {
- var event Event
- err := db.View(func(tx *bolt.Tx) error {
- bkt := tx.Bucket([]byte(CheckinBucket))
- if bkt == nil {
- return fmt.Errorf("no such bucket: CheckinBucket")
- }
- key := []byte(fmt.Sprintf("%d", nano))
- ev := bkt.Get(key)
- if ev == nil {
- return fmt.Errorf("no event at %d timestamp", nano)
- }
- return UnmarshalEvent(ev, &event)
- })
- if err != nil {
- t.Fatalf("error loading event: err = %q", err)
- }
- return &event
-}
-
-func TestService_Authenticate(t *testing.T) {
- svc := setupDB(t)
- mock := &mockPublisher{}
- svc.publisher = mock
- tests := []struct {
- name string
- publisher func(string, []byte) error
- archiveFn archiveFunc
- request mdm.CheckinCommand
- timestamp int64
- wantErr bool
- }{
- {
- name: "happy_path",
- publisher: passPublisher,
- request: mustLoadCommand(t, "Authenticate"),
- archiveFn: archiveAt(1111, svc),
- timestamp: 1111,
- },
- {
- name: "archive_fail",
- publisher: passPublisher,
- request: mustLoadCommand(t, "Authenticate"),
- archiveFn: archiveFail(),
- wantErr: true,
- },
- {
- name: "publisher_fail",
- publisher: failPublisher,
- request: mustLoadCommand(t, "Authenticate"),
- archiveFn: svc.archive,
- wantErr: true,
- },
- {
- name: "messageType_fail",
- publisher: passPublisher,
- request: mustLoadCommand(t, "CheckOut"),
- archiveFn: svc.archive,
- wantErr: true,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- mock.PublishFn = tt.publisher
- mock.Invoked = false
- svc.archiveFn = tt.archiveFn
- err := svc.Authenticate(context.Background(), tt.request)
- if (err != nil) != tt.wantErr {
- t.Errorf("%q. Authenticate error = %v, wantErr %v",
- tt.name, err, tt.wantErr)
- return
- }
- if tt.wantErr {
- return
- }
-
- event := loadEvent(t, svc.db, tt.timestamp)
- if !reflect.DeepEqual(event.Command, tt.request) {
- t.Errorf("\nwant: %#v\n,\nhave: %#v\n", tt.request, event.Command)
- }
-
- if !mock.Invoked {
- t.Errorf("publisher not invoked")
- }
- })
- }
-}
-
-func TestService_TokenUpdate(t *testing.T) {
- svc := setupDB(t)
- mock := &mockPublisher{}
- svc.publisher = mock
- tests := []struct {
- name string
- publisher func(string, []byte) error
- archiveFn archiveFunc
- request mdm.CheckinCommand
- timestamp int64
- wantErr bool
- }{
- {
- name: "happy_path",
- publisher: passPublisher,
- request: mustLoadCommand(t, "TokenUpdate"),
- archiveFn: archiveAt(2222, svc),
- timestamp: 2222,
- },
- {
- name: "archive_fail",
- publisher: passPublisher,
- request: mustLoadCommand(t, "TokenUpdate"),
- archiveFn: archiveFail(),
- wantErr: true,
- },
- {
- name: "publisher_fail",
- publisher: failPublisher,
- request: mustLoadCommand(t, "TokenUpdate"),
- archiveFn: svc.archive,
- wantErr: true,
- },
- {
- name: "messageType_fail",
- publisher: passPublisher,
- request: mustLoadCommand(t, "CheckOut"),
- archiveFn: svc.archive,
- wantErr: true,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- mock.PublishFn = tt.publisher
- mock.Invoked = false
- svc.archiveFn = tt.archiveFn
- err := svc.TokenUpdate(context.Background(), tt.request)
- if (err != nil) != tt.wantErr {
- t.Errorf("%q. TokenUpdate error = %v, wantErr %v",
- tt.name, err, tt.wantErr)
- return
- }
- if tt.wantErr {
- return
- }
-
- event := loadEvent(t, svc.db, tt.timestamp)
- if !reflect.DeepEqual(event.Command, tt.request) {
- t.Errorf("\nwant: %#v\n,\nhave: %#v\n", tt.request, event.Command)
- }
-
- if !mock.Invoked {
- t.Errorf("publisher not invoked")
- }
- })
- }
-}
-
-func TestService_CheckOut(t *testing.T) {
- svc := setupDB(t)
- mock := &mockPublisher{}
- svc.publisher = mock
- tests := []struct {
- name string
- publisher func(string, []byte) error
- archiveFn archiveFunc
- request mdm.CheckinCommand
- timestamp int64
- wantErr bool
- }{
- {
- name: "happy_path",
- publisher: passPublisher,
- request: mustLoadCommand(t, "CheckOut"),
- archiveFn: archiveAt(1111, svc),
- timestamp: 1111,
- },
- {
- name: "archive_fail",
- publisher: passPublisher,
- request: mustLoadCommand(t, "CheckOut"),
- archiveFn: archiveFail(),
- wantErr: true,
- },
- {
- name: "publisher_fail",
- publisher: failPublisher,
- request: mustLoadCommand(t, "CheckOut"),
- archiveFn: svc.archive,
- wantErr: true,
- },
- {
- name: "messageType_fail",
- publisher: passPublisher,
- request: mustLoadCommand(t, "Authenticate"),
- archiveFn: svc.archive,
- wantErr: true,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- mock.PublishFn = tt.publisher
- mock.Invoked = false
- svc.archiveFn = tt.archiveFn
- err := svc.CheckOut(context.Background(), tt.request)
- if (err != nil) != tt.wantErr {
- t.Errorf("%q. CheckOut error = %v, wantErr %v",
- tt.name, err, tt.wantErr)
- return
- }
- if tt.wantErr {
- return
- }
-
- event := loadEvent(t, svc.db, tt.timestamp)
- if !reflect.DeepEqual(event.Command, tt.request) {
- t.Errorf("\nwant: %#v\n,\nhave: %#v\n", tt.request, event.Command)
- }
-
- if !mock.Invoked {
- t.Errorf("publisher not invoked")
- }
- })
- }
-}
diff --git a/mdm/checkin/endpoint.go b/mdm/checkin/endpoint.go
deleted file mode 100644
index d5ed9622..00000000
--- a/mdm/checkin/endpoint.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package checkin
-
-import (
- "context"
-
- "github.com/go-kit/kit/endpoint"
- "github.com/micromdm/mdm"
- "github.com/pkg/errors"
-)
-
-// errInvalidMessageType is an invalid checking command.
-var errInvalidMessageType = errors.New("invalid message type")
-
-type Endpoints struct {
- CheckinEndpoint endpoint.Endpoint
-}
-
-func MakeCheckinEndpoint(svc Service) endpoint.Endpoint {
- return func(ctx context.Context, request interface{}) (interface{}, error) {
- req := request.(checkinRequest)
- var err error
- switch req.MessageType {
- case "Authenticate":
- err = svc.Authenticate(ctx, req.CheckinCommand)
- case "TokenUpdate":
- err = svc.TokenUpdate(ctx, req.CheckinCommand)
- case "CheckOut":
- err = svc.CheckOut(ctx, req.CheckinCommand)
- case "UserAuthenticate":
- // TODO: to support per-user MDM. See #293
- err = &rejectUserAuth{}
- default:
- err = errInvalidMessageType
- }
- return checkinResponse{Err: err}, nil
- }
-}
-
-type checkinRequest struct {
- mdm.CheckinCommand
-}
-
-type checkinResponse struct {
- Err error `plist:"error,omitempty"`
-}
-
-func (r checkinResponse) error() error { return r.Err }
-
-type rejectUserAuth struct{}
-
-func (e *rejectUserAuth) Error() string {
- return "reject user auth"
-}
-
-func (e *rejectUserAuth) UserAuthReject() bool {
- return true
-}
-
-func isRejectedUserAuth(err error) bool {
- type rejectUserAuthError interface {
- error
- UserAuthReject() bool
- }
-
- _, ok := errors.Cause(err).(rejectUserAuthError)
- return ok
-}
diff --git a/mdm/checkin/event_test.go b/mdm/checkin/event_test.go
deleted file mode 100644
index 83599452..00000000
--- a/mdm/checkin/event_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package checkin_test
-
-import (
- "io/ioutil"
- "reflect"
- "testing"
-
- "github.com/groob/plist"
- "github.com/micromdm/mdm"
-
- "github.com/micromdm/micromdm/mdm/checkin"
-)
-
-var marshalTests = []string{
- "Authenticate",
- "TokenUpdate",
- "CheckOut",
-}
-
-func TestMarshalEvent(t *testing.T) {
- for _, tt := range marshalTests {
- name := tt
- t.Run(name, func(t *testing.T) {
- t.Parallel()
- v := checkin.NewEvent(mustLoadCommand(t, name))
- var other checkin.Event
- if buf, err := checkin.MarshalEvent(v); err != nil {
- t.Fatal(err)
- } else if err := checkin.UnmarshalEvent(buf, &other); err != nil {
- t.Fatal(err)
- } else if !reflect.DeepEqual(v, &other) {
- t.Fatalf("\nwant: %#v\n \nhave: %#v\n", v, &other)
- }
- })
- }
-
-}
-
-func mustLoadCommand(t *testing.T, name string) mdm.CheckinCommand {
- var payload mdm.CheckinCommand
- data, err := ioutil.ReadFile("testdata/" + name + ".plist")
- if err != nil {
- t.Fatalf("failed to open test file %q.plist, err: %s", name, err)
- }
- if err := plist.Unmarshal(data, &payload); err != nil {
- t.Fatalf("failed to unmarshal plist %q, err: %s", name, err)
- }
- return payload
-}
diff --git a/mdm/checkin/internal/checkinproto/checkin.pb.go b/mdm/checkin/internal/checkinproto/checkin.pb.go
deleted file mode 100644
index a37231bb..00000000
--- a/mdm/checkin/internal/checkinproto/checkin.pb.go
+++ /dev/null
@@ -1,319 +0,0 @@
-// Code generated by protoc-gen-go.
-// source: checkin.proto
-// DO NOT EDIT!
-
-/*
-Package checkinproto is a generated protocol buffer package.
-
-It is generated from these files:
- checkin.proto
-
-It has these top-level messages:
- Event
- Command
- Authenticate
- TokenUpdate
-*/
-package checkinproto
-
-import proto "github.com/golang/protobuf/proto"
-import fmt "fmt"
-import math "math"
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-type Event struct {
- Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
- Time int64 `protobuf:"varint,2,opt,name=time" json:"time,omitempty"`
- Command *Command `protobuf:"bytes,3,opt,name=command" json:"command,omitempty"`
-}
-
-func (m *Event) Reset() { *m = Event{} }
-func (m *Event) String() string { return proto.CompactTextString(m) }
-func (*Event) ProtoMessage() {}
-func (*Event) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
-
-func (m *Event) GetId() string {
- if m != nil {
- return m.Id
- }
- return ""
-}
-
-func (m *Event) GetTime() int64 {
- if m != nil {
- return m.Time
- }
- return 0
-}
-
-func (m *Event) GetCommand() *Command {
- if m != nil {
- return m.Command
- }
- return nil
-}
-
-type Command struct {
- MessageType string `protobuf:"bytes,1,opt,name=message_type,json=messageType" json:"message_type,omitempty"`
- Topic string `protobuf:"bytes,2,opt,name=topic" json:"topic,omitempty"`
- Udid string `protobuf:"bytes,3,opt,name=udid" json:"udid,omitempty"`
- Authenticate *Authenticate `protobuf:"bytes,4,opt,name=authenticate" json:"authenticate,omitempty"`
- TokenUpdate *TokenUpdate `protobuf:"bytes,5,opt,name=token_update,json=tokenUpdate" json:"token_update,omitempty"`
-}
-
-func (m *Command) Reset() { *m = Command{} }
-func (m *Command) String() string { return proto.CompactTextString(m) }
-func (*Command) ProtoMessage() {}
-func (*Command) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
-
-func (m *Command) GetMessageType() string {
- if m != nil {
- return m.MessageType
- }
- return ""
-}
-
-func (m *Command) GetTopic() string {
- if m != nil {
- return m.Topic
- }
- return ""
-}
-
-func (m *Command) GetUdid() string {
- if m != nil {
- return m.Udid
- }
- return ""
-}
-
-func (m *Command) GetAuthenticate() *Authenticate {
- if m != nil {
- return m.Authenticate
- }
- return nil
-}
-
-func (m *Command) GetTokenUpdate() *TokenUpdate {
- if m != nil {
- return m.TokenUpdate
- }
- return nil
-}
-
-type Authenticate struct {
- OsVersion string `protobuf:"bytes,1,opt,name=os_version,json=osVersion" json:"os_version,omitempty"`
- BuildVersion string `protobuf:"bytes,2,opt,name=build_version,json=buildVersion" json:"build_version,omitempty"`
- ProductName string `protobuf:"bytes,3,opt,name=product_name,json=productName" json:"product_name,omitempty"`
- SerialNumber string `protobuf:"bytes,4,opt,name=serial_number,json=serialNumber" json:"serial_number,omitempty"`
- Imei string `protobuf:"bytes,5,opt,name=imei" json:"imei,omitempty"`
- Meid string `protobuf:"bytes,6,opt,name=meid" json:"meid,omitempty"`
- DeviceName string `protobuf:"bytes,7,opt,name=device_name,json=deviceName" json:"device_name,omitempty"`
- Challenge []byte `protobuf:"bytes,8,opt,name=challenge,proto3" json:"challenge,omitempty"`
- Model string `protobuf:"bytes,9,opt,name=model" json:"model,omitempty"`
- ModelName string `protobuf:"bytes,10,opt,name=model_name,json=modelName" json:"model_name,omitempty"`
-}
-
-func (m *Authenticate) Reset() { *m = Authenticate{} }
-func (m *Authenticate) String() string { return proto.CompactTextString(m) }
-func (*Authenticate) ProtoMessage() {}
-func (*Authenticate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
-
-func (m *Authenticate) GetOsVersion() string {
- if m != nil {
- return m.OsVersion
- }
- return ""
-}
-
-func (m *Authenticate) GetBuildVersion() string {
- if m != nil {
- return m.BuildVersion
- }
- return ""
-}
-
-func (m *Authenticate) GetProductName() string {
- if m != nil {
- return m.ProductName
- }
- return ""
-}
-
-func (m *Authenticate) GetSerialNumber() string {
- if m != nil {
- return m.SerialNumber
- }
- return ""
-}
-
-func (m *Authenticate) GetImei() string {
- if m != nil {
- return m.Imei
- }
- return ""
-}
-
-func (m *Authenticate) GetMeid() string {
- if m != nil {
- return m.Meid
- }
- return ""
-}
-
-func (m *Authenticate) GetDeviceName() string {
- if m != nil {
- return m.DeviceName
- }
- return ""
-}
-
-func (m *Authenticate) GetChallenge() []byte {
- if m != nil {
- return m.Challenge
- }
- return nil
-}
-
-func (m *Authenticate) GetModel() string {
- if m != nil {
- return m.Model
- }
- return ""
-}
-
-func (m *Authenticate) GetModelName() string {
- if m != nil {
- return m.ModelName
- }
- return ""
-}
-
-type TokenUpdate struct {
- Token []byte `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
- PushMagic string `protobuf:"bytes,2,opt,name=push_magic,json=pushMagic" json:"push_magic,omitempty"`
- UnlockToken []byte `protobuf:"bytes,3,opt,name=unlock_token,json=unlockToken,proto3" json:"unlock_token,omitempty"`
- AwaitingConfiguration bool `protobuf:"varint,4,opt,name=awaiting_configuration,json=awaitingConfiguration" json:"awaiting_configuration,omitempty"`
- UserId string `protobuf:"bytes,5,opt,name=user_id,json=userId" json:"user_id,omitempty"`
- UserLongName string `protobuf:"bytes,6,opt,name=user_long_name,json=userLongName" json:"user_long_name,omitempty"`
- UserShortName string `protobuf:"bytes,7,opt,name=user_short_name,json=userShortName" json:"user_short_name,omitempty"`
- NotOnConsole bool `protobuf:"varint,8,opt,name=not_on_console,json=notOnConsole" json:"not_on_console,omitempty"`
-}
-
-func (m *TokenUpdate) Reset() { *m = TokenUpdate{} }
-func (m *TokenUpdate) String() string { return proto.CompactTextString(m) }
-func (*TokenUpdate) ProtoMessage() {}
-func (*TokenUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
-
-func (m *TokenUpdate) GetToken() []byte {
- if m != nil {
- return m.Token
- }
- return nil
-}
-
-func (m *TokenUpdate) GetPushMagic() string {
- if m != nil {
- return m.PushMagic
- }
- return ""
-}
-
-func (m *TokenUpdate) GetUnlockToken() []byte {
- if m != nil {
- return m.UnlockToken
- }
- return nil
-}
-
-func (m *TokenUpdate) GetAwaitingConfiguration() bool {
- if m != nil {
- return m.AwaitingConfiguration
- }
- return false
-}
-
-func (m *TokenUpdate) GetUserId() string {
- if m != nil {
- return m.UserId
- }
- return ""
-}
-
-func (m *TokenUpdate) GetUserLongName() string {
- if m != nil {
- return m.UserLongName
- }
- return ""
-}
-
-func (m *TokenUpdate) GetUserShortName() string {
- if m != nil {
- return m.UserShortName
- }
- return ""
-}
-
-func (m *TokenUpdate) GetNotOnConsole() bool {
- if m != nil {
- return m.NotOnConsole
- }
- return false
-}
-
-func init() {
- proto.RegisterType((*Event)(nil), "checkinproto.Event")
- proto.RegisterType((*Command)(nil), "checkinproto.Command")
- proto.RegisterType((*Authenticate)(nil), "checkinproto.Authenticate")
- proto.RegisterType((*TokenUpdate)(nil), "checkinproto.TokenUpdate")
-}
-
-func init() { proto.RegisterFile("checkin.proto", fileDescriptor0) }
-
-var fileDescriptor0 = []byte{
- // 536 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x54, 0x92, 0x6f, 0x8b, 0xd3, 0x4e,
- 0x10, 0xc7, 0x49, 0xef, 0x4f, 0x9b, 0xc9, 0xb6, 0x3f, 0x58, 0x7e, 0xa7, 0x51, 0x14, 0x7b, 0xf5,
- 0x90, 0x3e, 0xaa, 0xa0, 0xf8, 0x4c, 0x04, 0x29, 0x3e, 0x10, 0xf4, 0x84, 0xf5, 0xf4, 0x91, 0x10,
- 0xb6, 0xd9, 0x31, 0x5d, 0x9a, 0xec, 0x86, 0x64, 0x53, 0xb9, 0x97, 0xe4, 0x1b, 0xf0, 0x95, 0xf8,
- 0x82, 0x64, 0x67, 0xd3, 0xbb, 0xf4, 0xd9, 0xcc, 0x67, 0xbe, 0x33, 0xb3, 0xf3, 0x4d, 0x60, 0x9a,
- 0x6f, 0x31, 0xdf, 0x69, 0xb3, 0xaa, 0x1b, 0xeb, 0x2c, 0x67, 0x7d, 0x4a, 0xd9, 0xe2, 0x07, 0x9c,
- 0x7d, 0xd8, 0xa3, 0x71, 0x7c, 0x06, 0x23, 0xad, 0xd2, 0x68, 0x1e, 0x2d, 0x63, 0x31, 0xd2, 0x8a,
- 0x73, 0x38, 0x75, 0xba, 0xc2, 0x74, 0x34, 0x8f, 0x96, 0x27, 0x82, 0x62, 0xfe, 0x12, 0xc6, 0xb9,
- 0xad, 0x2a, 0x69, 0x54, 0x7a, 0x32, 0x8f, 0x96, 0xc9, 0xab, 0x8b, 0xd5, 0x70, 0xd8, 0x6a, 0x1d,
- 0x8a, 0xe2, 0xa0, 0x5a, 0xfc, 0x8d, 0x60, 0xdc, 0x43, 0x7e, 0x09, 0xac, 0xc2, 0xb6, 0x95, 0x05,
- 0x66, 0xee, 0xb6, 0xc6, 0x7e, 0x55, 0xd2, 0xb3, 0x9b, 0xdb, 0x1a, 0xf9, 0xff, 0x70, 0xe6, 0x6c,
- 0xad, 0x73, 0x5a, 0x1a, 0x8b, 0x90, 0xf8, 0x97, 0x74, 0x4a, 0x87, 0x95, 0xb1, 0xa0, 0x98, 0xbf,
- 0x03, 0x26, 0x3b, 0xb7, 0x45, 0xe3, 0x74, 0x2e, 0x1d, 0xa6, 0xa7, 0xf4, 0x9c, 0xc7, 0xc7, 0xcf,
- 0x79, 0x3f, 0x50, 0x88, 0x23, 0x3d, 0x7f, 0x0b, 0xcc, 0xd9, 0x1d, 0x9a, 0xac, 0xab, 0x95, 0xef,
- 0x3f, 0xa3, 0xfe, 0x47, 0xc7, 0xfd, 0x37, 0x5e, 0xf1, 0x8d, 0x04, 0x22, 0x71, 0xf7, 0xc9, 0xe2,
- 0xcf, 0x08, 0xd8, 0x70, 0x38, 0x7f, 0x0a, 0x60, 0xdb, 0x6c, 0x8f, 0x4d, 0xab, 0xad, 0xe9, 0x2f,
- 0x8b, 0x6d, 0xfb, 0x3d, 0x00, 0xfe, 0x1c, 0xa6, 0x9b, 0x4e, 0x97, 0xea, 0x4e, 0x11, 0xee, 0x63,
- 0x04, 0x0f, 0xa2, 0x4b, 0x60, 0x75, 0x63, 0x55, 0x97, 0xbb, 0xcc, 0xc8, 0x0a, 0xfb, 0x73, 0x93,
- 0x9e, 0x5d, 0xcb, 0x0a, 0xfd, 0x9c, 0x16, 0x1b, 0x2d, 0xcb, 0xcc, 0x74, 0xd5, 0x06, 0x1b, 0x3a,
- 0x3b, 0x16, 0x2c, 0xc0, 0x6b, 0x62, 0xde, 0x2e, 0x5d, 0xa1, 0xa6, 0x93, 0x62, 0x41, 0xb1, 0x67,
- 0x15, 0x6a, 0x95, 0x9e, 0x07, 0xe6, 0x63, 0xfe, 0x0c, 0x12, 0x85, 0x7b, 0x9d, 0x63, 0x58, 0x37,
- 0xa6, 0x12, 0x04, 0x44, 0xdb, 0x9e, 0x40, 0x9c, 0x6f, 0x65, 0x59, 0xa2, 0x29, 0x30, 0x9d, 0xcc,
- 0xa3, 0x25, 0x13, 0xf7, 0xc0, 0x7f, 0xab, 0xca, 0x2a, 0x2c, 0xd3, 0x38, 0x7c, 0x2b, 0x4a, 0xbc,
- 0x11, 0x14, 0x84, 0x99, 0x10, 0x8c, 0x20, 0xe2, 0x47, 0x2e, 0x7e, 0x8f, 0x20, 0x19, 0xb8, 0x1a,
- 0x3e, 0xf8, 0x0e, 0x83, 0x65, 0x4c, 0x84, 0xc4, 0x0f, 0xa9, 0xbb, 0x76, 0x9b, 0x55, 0xb2, 0xb8,
- 0xfb, 0x17, 0x62, 0x4f, 0x3e, 0x7b, 0xe0, 0x8d, 0xea, 0x4c, 0x69, 0xf3, 0x5d, 0x16, 0x7a, 0x4f,
- 0xa8, 0x37, 0x09, 0x8c, 0xa6, 0xf3, 0x37, 0xf0, 0x40, 0xfe, 0x92, 0xda, 0x69, 0x53, 0x64, 0xb9,
- 0x35, 0x3f, 0x75, 0xd1, 0x35, 0xd2, 0x79, 0xe7, 0xbd, 0x63, 0x13, 0x71, 0x71, 0xa8, 0xae, 0x87,
- 0x45, 0xfe, 0x10, 0xc6, 0x5d, 0x8b, 0x4d, 0xa6, 0x55, 0xef, 0xde, 0xb9, 0x4f, 0x3f, 0x2a, 0x7e,
- 0x05, 0x33, 0x2a, 0x94, 0xd6, 0x14, 0xe1, 0xb4, 0xe0, 0x24, 0xf3, 0xf4, 0x93, 0x35, 0x05, 0x19,
- 0xf6, 0x02, 0xfe, 0x23, 0x55, 0xbb, 0xb5, 0x8d, 0x1b, 0xba, 0x3a, 0xf5, 0xf8, 0xab, 0xa7, 0xa4,
- 0xbb, 0x82, 0x99, 0xb1, 0x2e, 0xb3, 0xc6, 0xbf, 0xad, 0xb5, 0x65, 0x70, 0x77, 0x22, 0x98, 0xb1,
- 0xee, 0x8b, 0x59, 0x07, 0xb6, 0x39, 0xa7, 0x9f, 0xf0, 0xf5, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff,
- 0xac, 0x19, 0x1f, 0x55, 0xbf, 0x03, 0x00, 0x00,
-}
diff --git a/mdm/checkin/service.go b/mdm/checkin/service.go
deleted file mode 100644
index b20a0665..00000000
--- a/mdm/checkin/service.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package checkin
-
-import (
- "github.com/micromdm/mdm"
- "golang.org/x/net/context"
-)
-
-// Service defines methods for and MDM Check-in service.
-type Service interface {
- Authenticate(ctx context.Context, cmd mdm.CheckinCommand) error
- TokenUpdate(ctx context.Context, cmd mdm.CheckinCommand) error
- CheckOut(ctx context.Context, cmd mdm.CheckinCommand) error
-}
diff --git a/mdm/checkin/testdata/Authenticate.plist b/mdm/checkin/testdata/Authenticate.plist
deleted file mode 100644
index fa926816..00000000
--- a/mdm/checkin/testdata/Authenticate.plist
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-AwaitingConfigurationBuildVersion15G31ChallengeYXBwbGU=DeviceNameHonest MistakeIMEIMEIDMessageTypeAuthenticateModelMacBookPro11,5ModelNameMacBook ProOSVersion10.11.6ProductNameMacBookPro11,5PushMagicSerialNumberC02RX6G8G8WPTokenTopiccom.apple.mgmt.XServer.8b4034c3-8cd9-4121-9999-cd2ddbf9a5b1UDIDFA01680E-98CA-5557-8F59-7716ECFEE964UnlockToken
diff --git a/mdm/checkin/testdata/CheckOut.plist b/mdm/checkin/testdata/CheckOut.plist
deleted file mode 100644
index d2be7150..00000000
--- a/mdm/checkin/testdata/CheckOut.plist
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-AwaitingConfigurationBuildVersionIMEIMEIDMessageTypeCheckOutModelOSVersionProductNamePushMagicSerialNumberTokenTopiccom.apple.mgmt.XServer.8b4034c3-8cd9-4121-9999-cd2ddbf9a5b1UDIDFA01680E-98CA-5557-8F59-7716ECFEE964UnlockToken
diff --git a/mdm/checkin/testdata/TokenUpdate.plist b/mdm/checkin/testdata/TokenUpdate.plist
deleted file mode 100644
index fa2296ff..00000000
--- a/mdm/checkin/testdata/TokenUpdate.plist
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-AwaitingConfigurationBuildVersionIMEIMEIDMessageTypeTokenUpdateModelOSVersionProductNamePushMagic5002D9F7-2FCC-45D0-BDFD-5CB0597F18B5SerialNumberTokenxEiNXIa4XVQOs+90kApgE8gTOAfEVQHPIURHRnJOv5Y=Topiccom.apple.mgmt.XServer.8b4034c3-8cd9-4121-9999-cd2ddbf9a5b1UDIDFA01680E-98CA-5557-8F59-7716ECFEE964UnlockToken
diff --git a/mdm/checkin/transport_http.go b/mdm/checkin/transport_http.go
deleted file mode 100644
index 5fc8484a..00000000
--- a/mdm/checkin/transport_http.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package checkin
-
-import (
- "context"
- "io"
- "net/http"
-
- httptransport "github.com/go-kit/kit/transport/http"
- "github.com/groob/plist"
-)
-
-type HTTPHandlers struct {
- // The CheckinHandler should accept PUT requests
- CheckinHandler http.Handler
-}
-
-func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
- h := HTTPHandlers{
- CheckinHandler: httptransport.NewServer(
- endpoints.CheckinEndpoint,
- decodeRequest,
- encodeResponse,
- opts...,
- ),
- }
- return h
-}
-
-type errorer interface {
- error() error
-}
-
-func decodeRequest(ctx context.Context, r *http.Request) (interface{}, error) {
- var req checkinRequest
- err := plist.NewDecoder(io.LimitReader(r.Body, 10000)).Decode(&req)
- return req, err
-}
-
-// According to the MDM Check-in protocol, the server must respond with 200 OK
-// to successful Check-in requests.
-func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
- if e, ok := response.(errorer); ok && e.error() != nil {
- EncodeError(ctx, e.error(), w)
- return nil
- }
-
- w.WriteHeader(http.StatusOK)
- return nil
-}
-
-// EncodeError is used by the HTTP transport to encode service errors in HTTP.
-// The EncodeError should be passed to the Go-Kit httptransport as the
-// ServerErrorEncoder to encode error responses.
-// According to the MDM Check-in protocol specification, the device only needs
-// a 401 (Unauthorized) response in case of failure.
-// In the case of a UserAuthenticate message we can also respond with 410 to
-// reject user authentication attempts
-func EncodeError(ctx context.Context, err error, w http.ResponseWriter) {
- if isRejectedUserAuth(err) {
- w.WriteHeader(http.StatusGone)
- return
- }
- w.WriteHeader(http.StatusUnauthorized)
-}
diff --git a/mdm/checkin/event.go b/mdm/checkin_event.go
similarity index 60%
rename from mdm/checkin/event.go
rename to mdm/checkin_event.go
index 28839c80..6322e7b0 100644
--- a/mdm/checkin/event.go
+++ b/mdm/checkin_event.go
@@ -1,33 +1,75 @@
-package checkin
+package mdm
import (
+ "encoding/hex"
"time"
"github.com/gogo/protobuf/proto"
- "github.com/micromdm/mdm"
- uuid "github.com/satori/go.uuid"
- "github.com/micromdm/micromdm/mdm/checkin/internal/checkinproto"
+ "github.com/micromdm/micromdm/mdm/internal/checkinproto"
)
-type Event struct {
+type CheckinEvent struct {
ID string
Time time.Time
- Command mdm.CheckinCommand
+ Command CheckinCommand
+ Params map[string]string
+ Raw []byte
}
-// NewEvent returns an Event with a unique ID and the current time.
-func NewEvent(cmd mdm.CheckinCommand) *Event {
- event := Event{
- ID: uuid.NewV4().String(),
- Time: time.Now().UTC(),
- Command: cmd,
- }
- return &event
+// CheckinRequest represents an MDM checkin command struct.
+type CheckinCommand struct {
+ // MessageType can be either Authenticate,
+ // TokenUpdate or CheckOut
+ MessageType string
+ Topic string
+ UDID string
+ auth
+ update
}
-// MarshalEvent serializes an event to a protocol buffer wire format.
-func MarshalEvent(e *Event) ([]byte, error) {
+// Authenticate Message Type
+type auth struct {
+ OSVersion string
+ BuildVersion string
+ ProductName string
+ SerialNumber string
+ IMEI string
+ MEID string
+ DeviceName string `plist:"DeviceName,omitempty"`
+ Challenge []byte `plist:"Challenge,omitempty"`
+ Model string `plist:"Model,omitpempty"`
+ ModelName string `plist:"ModelName,omitempty"`
+}
+
+// TokenUpdate Mesage Type
+type update struct {
+ Token hexData
+ PushMagic string
+ UnlockToken hexData
+ AwaitingConfiguration bool
+ userTokenUpdate
+}
+
+// TokenUpdate with user keys
+type userTokenUpdate struct {
+ UserID string `plist:",omitempty"`
+ UserLongName string `plist:",omitempty"`
+ UserShortName string `plist:",omitempty"`
+ NotOnConsole bool `plist:",omitempty"`
+}
+
+// data decodes to []byte,
+// we can then attach a string method to the type
+// Tokens are encoded as Hex Strings
+type hexData []byte
+
+func (d hexData) String() string {
+ return hex.EncodeToString(d)
+}
+
+// MarshalCheckinEvent serializes an event to a protocol buffer wire format.
+func MarshalCheckinEvent(e *CheckinEvent) ([]byte, error) {
command := &checkinproto.Command{
MessageType: e.Command.MessageType,
Topic: e.Command.Topic,
@@ -63,12 +105,14 @@ func MarshalEvent(e *Event) ([]byte, error) {
Id: e.ID,
Time: e.Time.UnixNano(),
Command: command,
+ Params: e.Params,
+ Raw: e.Raw,
})
}
-// UnmarshalEvent parses a protocol buffer representation of data into
+// UnmarshalCheckinEvent parses a protocol buffer representation of data into
// the Event.
-func UnmarshalEvent(data []byte, e *Event) error {
+func UnmarshalCheckinEvent(data []byte, e *CheckinEvent) error {
var pb checkinproto.Event
if err := proto.Unmarshal(data, &pb); err != nil {
return err
@@ -78,7 +122,7 @@ func UnmarshalEvent(data []byte, e *Event) error {
if pb.Command == nil {
return nil
}
- e.Command = mdm.CheckinCommand{
+ e.Command = CheckinCommand{
MessageType: pb.Command.MessageType,
Topic: pb.Command.Topic,
UDID: pb.Command.Udid,
@@ -105,5 +149,7 @@ func UnmarshalEvent(data []byte, e *Event) error {
e.Command.UserShortName = pb.Command.TokenUpdate.UserShortName
e.Command.NotOnConsole = pb.Command.TokenUpdate.NotOnConsole
}
+ e.Raw = pb.GetRaw()
+ e.Params = pb.GetParams()
return nil
}
diff --git a/mdm/connect/connect.go b/mdm/connect/connect.go
deleted file mode 100644
index ad6b9fea..00000000
--- a/mdm/connect/connect.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package connect
-
-import (
- "context"
-
- "github.com/micromdm/mdm"
- "github.com/pkg/errors"
-
- "github.com/micromdm/micromdm/platform/pubsub"
- "github.com/micromdm/micromdm/platform/queue"
-)
-
-const ConnectTopic = "mdm.Connect"
-
-// The Service accepts responses sent to an MDM server by an enrolled
-// device.
-type Service interface {
-
- // Acknowledge acknowledges a response sent by a device and returns
- // the next payload if one is available.
- Acknowledge(ctx context.Context, req MDMConnectRequest) (payload []byte, err error)
-}
-
-type ConnectService struct {
- queue Queue
- pub pubsub.Publisher
-}
-
-type Queue interface {
- Next(context.Context, mdm.Response) (*queue.Command, error)
-}
-
-func New(queue Queue, pub pubsub.Publisher) (*ConnectService, error) {
- return &ConnectService{
- queue: queue,
- pub: pub,
- }, nil
-}
-
-func (svc *ConnectService) Acknowledge(ctx context.Context, req MDMConnectRequest) (payload []byte, err error) {
- event := NewEvent(req)
- msg, err := MarshalEvent(event)
- if err != nil {
- return nil, errors.Wrap(err, "marshal connect response to proto")
- }
- if err := svc.pub.Publish(context.TODO(), ConnectTopic, msg); err != nil {
- return nil, errors.Wrap(err, "publish connect Response on pubsub")
- }
-
- cmd, err := svc.queue.Next(ctx, req.MDMResponse)
- if err != nil {
- return nil, errors.Wrap(err, "calling Next with mdm response")
- }
- // next can return no errors and no payload.
- if cmd == nil {
- return nil, nil
- }
- return cmd.Payload, nil
-}
diff --git a/mdm/connect/endpoint.go b/mdm/connect/endpoint.go
deleted file mode 100644
index 19869f41..00000000
--- a/mdm/connect/endpoint.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package connect
-
-import (
- "context"
-
- "github.com/go-kit/kit/endpoint"
- "github.com/micromdm/mdm"
-)
-
-type MDMConnectRequest struct {
- Raw []byte
- MDMResponse mdm.Response
-}
-
-type mdmConnectResponse struct {
- payload []byte
- Err error `plist:"error,omitempty"`
-}
-
-func (r mdmConnectResponse) error() error { return r.Err }
-
-type Endpoints struct {
- ConnectEndpoint endpoint.Endpoint
-}
-
-func MakeConnectEndpoint(svc Service) endpoint.Endpoint {
- return func(ctx context.Context, request interface{}) (interface{}, error) {
- req := request.(MDMConnectRequest)
- payload, err := svc.Acknowledge(ctx, req)
- return mdmConnectResponse{payload: payload, Err: err}, nil
- }
-}
diff --git a/mdm/connect/internal/connectproto/connect.pb.go b/mdm/connect/internal/connectproto/connect.pb.go
deleted file mode 100644
index a8cd321e..00000000
--- a/mdm/connect/internal/connectproto/connect.pb.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// source: connect.proto
-
-/*
-Package connectproto is a generated protocol buffer package.
-
-It is generated from these files:
- connect.proto
-
-It has these top-level messages:
- Event
- Response
-*/
-package connectproto
-
-import proto "github.com/golang/protobuf/proto"
-import fmt "fmt"
-import math "math"
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-type Event struct {
- Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
- Time int64 `protobuf:"varint,2,opt,name=time" json:"time,omitempty"`
- Response *Response `protobuf:"bytes,3,opt,name=response" json:"response,omitempty"`
- Raw []byte `protobuf:"bytes,4,opt,name=raw,proto3" json:"raw,omitempty"`
-}
-
-func (m *Event) Reset() { *m = Event{} }
-func (m *Event) String() string { return proto.CompactTextString(m) }
-func (*Event) ProtoMessage() {}
-func (*Event) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
-
-func (m *Event) GetId() string {
- if m != nil {
- return m.Id
- }
- return ""
-}
-
-func (m *Event) GetTime() int64 {
- if m != nil {
- return m.Time
- }
- return 0
-}
-
-func (m *Event) GetResponse() *Response {
- if m != nil {
- return m.Response
- }
- return nil
-}
-
-func (m *Event) GetRaw() []byte {
- if m != nil {
- return m.Raw
- }
- return nil
-}
-
-type Response struct {
- Udid string `protobuf:"bytes,1,opt,name=udid" json:"udid,omitempty"`
- UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId" json:"user_id,omitempty"`
- Status string `protobuf:"bytes,3,opt,name=status" json:"status,omitempty"`
- RequestType string `protobuf:"bytes,4,opt,name=request_type,json=requestType" json:"request_type,omitempty"`
- CommandUuid string `protobuf:"bytes,5,opt,name=command_uuid,json=commandUuid" json:"command_uuid,omitempty"`
-}
-
-func (m *Response) Reset() { *m = Response{} }
-func (m *Response) String() string { return proto.CompactTextString(m) }
-func (*Response) ProtoMessage() {}
-func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
-
-func (m *Response) GetUdid() string {
- if m != nil {
- return m.Udid
- }
- return ""
-}
-
-func (m *Response) GetUserId() string {
- if m != nil {
- return m.UserId
- }
- return ""
-}
-
-func (m *Response) GetStatus() string {
- if m != nil {
- return m.Status
- }
- return ""
-}
-
-func (m *Response) GetRequestType() string {
- if m != nil {
- return m.RequestType
- }
- return ""
-}
-
-func (m *Response) GetCommandUuid() string {
- if m != nil {
- return m.CommandUuid
- }
- return ""
-}
-
-func init() {
- proto.RegisterType((*Event)(nil), "connectproto.Event")
- proto.RegisterType((*Response)(nil), "connectproto.Response")
-}
-
-func init() { proto.RegisterFile("connect.proto", fileDescriptor0) }
-
-var fileDescriptor0 = []byte{
- // 225 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x8f, 0xb1, 0x4e, 0xc3, 0x30,
- 0x10, 0x86, 0xe5, 0xa4, 0x0d, 0xcd, 0x35, 0x20, 0x74, 0x43, 0xf1, 0x18, 0x3a, 0x65, 0xca, 0x50,
- 0x9e, 0x81, 0x81, 0xd5, 0x82, 0x39, 0x0a, 0xf1, 0x0d, 0x1e, 0x62, 0xa7, 0xf6, 0x19, 0xd4, 0x07,
- 0xe1, 0x7d, 0x51, 0x8c, 0xa9, 0xba, 0xfd, 0xff, 0xef, 0x4f, 0xfe, 0x74, 0x70, 0x3f, 0x39, 0x6b,
- 0x69, 0xe2, 0x7e, 0xf1, 0x8e, 0x1d, 0x36, 0xb9, 0xa6, 0x76, 0x3c, 0xc3, 0xf6, 0xf5, 0x8b, 0x2c,
- 0xe3, 0x03, 0x14, 0x46, 0x4b, 0xd1, 0x8a, 0xae, 0x56, 0x85, 0xd1, 0x88, 0xb0, 0x61, 0x33, 0x93,
- 0x2c, 0x5a, 0xd1, 0x95, 0x2a, 0x65, 0x3c, 0xc1, 0xce, 0x53, 0x58, 0x9c, 0x0d, 0x24, 0xcb, 0x56,
- 0x74, 0xfb, 0xd3, 0xa1, 0xbf, 0xfd, 0xad, 0x57, 0xf9, 0x55, 0x5d, 0x39, 0x7c, 0x84, 0xd2, 0x8f,
- 0xdf, 0x72, 0xd3, 0x8a, 0xae, 0x51, 0x6b, 0x3c, 0xfe, 0x08, 0xd8, 0xfd, 0x83, 0xab, 0x26, 0xea,
- 0xab, 0x38, 0x65, 0x7c, 0x82, 0xbb, 0x18, 0xc8, 0x0f, 0x46, 0x27, 0x7b, 0xad, 0xaa, 0xb5, 0xbe,
- 0x69, 0x3c, 0x40, 0x15, 0x78, 0xe4, 0x18, 0x92, 0xbd, 0x56, 0xb9, 0xe1, 0x33, 0x34, 0x9e, 0xce,
- 0x91, 0x02, 0x0f, 0x7c, 0x59, 0x28, 0xc9, 0x6a, 0xb5, 0xcf, 0xdb, 0xfb, 0x65, 0xa1, 0x15, 0x99,
- 0xdc, 0x3c, 0x8f, 0x56, 0x0f, 0x31, 0x1a, 0x2d, 0xb7, 0x7f, 0x48, 0xde, 0x3e, 0xa2, 0xd1, 0x9f,
- 0x55, 0xba, 0xe1, 0xe5, 0x37, 0x00, 0x00, 0xff, 0xff, 0x0e, 0x78, 0x53, 0x38, 0x30, 0x01, 0x00,
- 0x00,
-}
diff --git a/mdm/connect/middleware.go b/mdm/connect/middleware.go
deleted file mode 100644
index 45870d56..00000000
--- a/mdm/connect/middleware.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package connect
-
-import (
- "context"
- "time"
-
- "github.com/go-kit/kit/log"
-)
-
-type Middleware func(Service) Service
-
-func LoggingMiddleware(logger log.Logger) Middleware {
- return func(next Service) Service {
- return &loggingMiddleware{
- next: next,
- logger: logger,
- }
- }
-}
-
-type loggingMiddleware struct {
- next Service
- logger log.Logger
-}
-
-func (mw loggingMiddleware) Acknowledge(ctx context.Context, req MDMConnectRequest) (payload []byte, err error) {
- defer func(begin time.Time) {
- _ = mw.logger.Log(
- "method", "Acknowledge",
- "udid", req.MDMResponse.UDID,
- "command_uuid", req.MDMResponse.CommandUUID,
- "status", req.MDMResponse.Status,
- "request_type", req.MDMResponse.RequestType,
- "err", err,
- "took", time.Since(begin),
- )
- }(time.Now())
-
- payload, err = mw.next.Acknowledge(ctx, req)
- return
-}
diff --git a/mdm/connect/transport_http.go b/mdm/connect/transport_http.go
deleted file mode 100644
index fc59bf5e..00000000
--- a/mdm/connect/transport_http.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package connect
-
-import (
- "context"
- "io/ioutil"
- "log"
- "net/http"
-
- httptransport "github.com/go-kit/kit/transport/http"
- "github.com/groob/plist"
- "github.com/micromdm/mdm"
-)
-
-type HTTPHandlers struct {
- ConnectHandler http.Handler
-}
-
-func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
- h := HTTPHandlers{
- ConnectHandler: httptransport.NewServer(
- endpoints.ConnectEndpoint,
- decodeRequest,
- encodeResponse,
- opts...,
- ),
- }
- return h
-}
-
-type errorer interface {
- error() error
-}
-
-func decodeRequest(ctx context.Context, r *http.Request) (interface{}, error) {
- var res mdm.Response
-
- body, err := ioutil.ReadAll(r.Body)
- if err != nil {
- return nil, err
- }
- defer r.Body.Close()
-
- err = plist.Unmarshal(body, &res)
- if err != nil {
- return nil, err
- }
-
- req := MDMConnectRequest{MDMResponse: res, Raw: body}
- return req, nil
-}
-
-// According to the MDM Check-in protocol, the server must respond with 200 OK
-// to successful Check-in requests.
-func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
- if e, ok := response.(errorer); ok && e.error() != nil {
- EncodeError(ctx, e.error(), w)
- return nil
- }
-
- resp := response.(mdmConnectResponse)
-
- w.WriteHeader(http.StatusOK)
- w.Write(resp.payload)
- return nil
-}
-
-// EncodeError is used by the HTTP transport to encode service errors in HTTP.
-// The EncodeError should be passed to the Go-Kit httptransport as the
-// ServerErrorEncoder to encode error responses.
-func EncodeError(ctx context.Context, err error, w http.ResponseWriter) {
- type checkoutErr interface {
- error
- Checkout() bool
- }
- if e, ok := err.(checkoutErr); ok {
- if e.Checkout() {
- log.Printf("connect: forced checkout error: %s\n", err)
- w.WriteHeader(http.StatusUnauthorized)
- return
- }
- }
- log.Printf("connect error: %s\n", err)
- w.WriteHeader(http.StatusInternalServerError)
-}
diff --git a/mdm/checkin/internal/checkinproto/checkin.go b/mdm/internal/checkinproto/checkin.go
similarity index 100%
rename from mdm/checkin/internal/checkinproto/checkin.go
rename to mdm/internal/checkinproto/checkin.go
diff --git a/mdm/internal/checkinproto/checkin.pb.go b/mdm/internal/checkinproto/checkin.pb.go
new file mode 100644
index 00000000..4273c9b7
--- /dev/null
+++ b/mdm/internal/checkinproto/checkin.pb.go
@@ -0,0 +1,415 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: checkin.proto
+
+package checkinproto
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Event struct {
+ Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
+ Time int64 `protobuf:"varint,2,opt,name=time" json:"time,omitempty"`
+ Command *Command `protobuf:"bytes,3,opt,name=command" json:"command,omitempty"`
+ Raw []byte `protobuf:"bytes,4,opt,name=raw,proto3" json:"raw,omitempty"`
+ Params map[string]string `protobuf:"bytes,5,rep,name=params" json:"params,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Event) Reset() { *m = Event{} }
+func (m *Event) String() string { return proto.CompactTextString(m) }
+func (*Event) ProtoMessage() {}
+func (*Event) Descriptor() ([]byte, []int) {
+ return fileDescriptor_checkin_7e1d11c144d2ce7a, []int{0}
+}
+func (m *Event) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Event.Unmarshal(m, b)
+}
+func (m *Event) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Event.Marshal(b, m, deterministic)
+}
+func (dst *Event) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Event.Merge(dst, src)
+}
+func (m *Event) XXX_Size() int {
+ return xxx_messageInfo_Event.Size(m)
+}
+func (m *Event) XXX_DiscardUnknown() {
+ xxx_messageInfo_Event.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Event proto.InternalMessageInfo
+
+func (m *Event) GetId() string {
+ if m != nil {
+ return m.Id
+ }
+ return ""
+}
+
+func (m *Event) GetTime() int64 {
+ if m != nil {
+ return m.Time
+ }
+ return 0
+}
+
+func (m *Event) GetCommand() *Command {
+ if m != nil {
+ return m.Command
+ }
+ return nil
+}
+
+func (m *Event) GetRaw() []byte {
+ if m != nil {
+ return m.Raw
+ }
+ return nil
+}
+
+func (m *Event) GetParams() map[string]string {
+ if m != nil {
+ return m.Params
+ }
+ return nil
+}
+
+type Command struct {
+ MessageType string `protobuf:"bytes,1,opt,name=message_type,json=messageType" json:"message_type,omitempty"`
+ Topic string `protobuf:"bytes,2,opt,name=topic" json:"topic,omitempty"`
+ Udid string `protobuf:"bytes,3,opt,name=udid" json:"udid,omitempty"`
+ Authenticate *Authenticate `protobuf:"bytes,4,opt,name=authenticate" json:"authenticate,omitempty"`
+ TokenUpdate *TokenUpdate `protobuf:"bytes,5,opt,name=token_update,json=tokenUpdate" json:"token_update,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Command) Reset() { *m = Command{} }
+func (m *Command) String() string { return proto.CompactTextString(m) }
+func (*Command) ProtoMessage() {}
+func (*Command) Descriptor() ([]byte, []int) {
+ return fileDescriptor_checkin_7e1d11c144d2ce7a, []int{1}
+}
+func (m *Command) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Command.Unmarshal(m, b)
+}
+func (m *Command) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Command.Marshal(b, m, deterministic)
+}
+func (dst *Command) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Command.Merge(dst, src)
+}
+func (m *Command) XXX_Size() int {
+ return xxx_messageInfo_Command.Size(m)
+}
+func (m *Command) XXX_DiscardUnknown() {
+ xxx_messageInfo_Command.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Command proto.InternalMessageInfo
+
+func (m *Command) GetMessageType() string {
+ if m != nil {
+ return m.MessageType
+ }
+ return ""
+}
+
+func (m *Command) GetTopic() string {
+ if m != nil {
+ return m.Topic
+ }
+ return ""
+}
+
+func (m *Command) GetUdid() string {
+ if m != nil {
+ return m.Udid
+ }
+ return ""
+}
+
+func (m *Command) GetAuthenticate() *Authenticate {
+ if m != nil {
+ return m.Authenticate
+ }
+ return nil
+}
+
+func (m *Command) GetTokenUpdate() *TokenUpdate {
+ if m != nil {
+ return m.TokenUpdate
+ }
+ return nil
+}
+
+type Authenticate struct {
+ OsVersion string `protobuf:"bytes,1,opt,name=os_version,json=osVersion" json:"os_version,omitempty"`
+ BuildVersion string `protobuf:"bytes,2,opt,name=build_version,json=buildVersion" json:"build_version,omitempty"`
+ ProductName string `protobuf:"bytes,3,opt,name=product_name,json=productName" json:"product_name,omitempty"`
+ SerialNumber string `protobuf:"bytes,4,opt,name=serial_number,json=serialNumber" json:"serial_number,omitempty"`
+ Imei string `protobuf:"bytes,5,opt,name=imei" json:"imei,omitempty"`
+ Meid string `protobuf:"bytes,6,opt,name=meid" json:"meid,omitempty"`
+ DeviceName string `protobuf:"bytes,7,opt,name=device_name,json=deviceName" json:"device_name,omitempty"`
+ Challenge []byte `protobuf:"bytes,8,opt,name=challenge,proto3" json:"challenge,omitempty"`
+ Model string `protobuf:"bytes,9,opt,name=model" json:"model,omitempty"`
+ ModelName string `protobuf:"bytes,10,opt,name=model_name,json=modelName" json:"model_name,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Authenticate) Reset() { *m = Authenticate{} }
+func (m *Authenticate) String() string { return proto.CompactTextString(m) }
+func (*Authenticate) ProtoMessage() {}
+func (*Authenticate) Descriptor() ([]byte, []int) {
+ return fileDescriptor_checkin_7e1d11c144d2ce7a, []int{2}
+}
+func (m *Authenticate) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Authenticate.Unmarshal(m, b)
+}
+func (m *Authenticate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Authenticate.Marshal(b, m, deterministic)
+}
+func (dst *Authenticate) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Authenticate.Merge(dst, src)
+}
+func (m *Authenticate) XXX_Size() int {
+ return xxx_messageInfo_Authenticate.Size(m)
+}
+func (m *Authenticate) XXX_DiscardUnknown() {
+ xxx_messageInfo_Authenticate.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Authenticate proto.InternalMessageInfo
+
+func (m *Authenticate) GetOsVersion() string {
+ if m != nil {
+ return m.OsVersion
+ }
+ return ""
+}
+
+func (m *Authenticate) GetBuildVersion() string {
+ if m != nil {
+ return m.BuildVersion
+ }
+ return ""
+}
+
+func (m *Authenticate) GetProductName() string {
+ if m != nil {
+ return m.ProductName
+ }
+ return ""
+}
+
+func (m *Authenticate) GetSerialNumber() string {
+ if m != nil {
+ return m.SerialNumber
+ }
+ return ""
+}
+
+func (m *Authenticate) GetImei() string {
+ if m != nil {
+ return m.Imei
+ }
+ return ""
+}
+
+func (m *Authenticate) GetMeid() string {
+ if m != nil {
+ return m.Meid
+ }
+ return ""
+}
+
+func (m *Authenticate) GetDeviceName() string {
+ if m != nil {
+ return m.DeviceName
+ }
+ return ""
+}
+
+func (m *Authenticate) GetChallenge() []byte {
+ if m != nil {
+ return m.Challenge
+ }
+ return nil
+}
+
+func (m *Authenticate) GetModel() string {
+ if m != nil {
+ return m.Model
+ }
+ return ""
+}
+
+func (m *Authenticate) GetModelName() string {
+ if m != nil {
+ return m.ModelName
+ }
+ return ""
+}
+
+type TokenUpdate struct {
+ Token []byte `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
+ PushMagic string `protobuf:"bytes,2,opt,name=push_magic,json=pushMagic" json:"push_magic,omitempty"`
+ UnlockToken []byte `protobuf:"bytes,3,opt,name=unlock_token,json=unlockToken,proto3" json:"unlock_token,omitempty"`
+ AwaitingConfiguration bool `protobuf:"varint,4,opt,name=awaiting_configuration,json=awaitingConfiguration" json:"awaiting_configuration,omitempty"`
+ UserId string `protobuf:"bytes,5,opt,name=user_id,json=userId" json:"user_id,omitempty"`
+ UserLongName string `protobuf:"bytes,6,opt,name=user_long_name,json=userLongName" json:"user_long_name,omitempty"`
+ UserShortName string `protobuf:"bytes,7,opt,name=user_short_name,json=userShortName" json:"user_short_name,omitempty"`
+ NotOnConsole bool `protobuf:"varint,8,opt,name=not_on_console,json=notOnConsole" json:"not_on_console,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *TokenUpdate) Reset() { *m = TokenUpdate{} }
+func (m *TokenUpdate) String() string { return proto.CompactTextString(m) }
+func (*TokenUpdate) ProtoMessage() {}
+func (*TokenUpdate) Descriptor() ([]byte, []int) {
+ return fileDescriptor_checkin_7e1d11c144d2ce7a, []int{3}
+}
+func (m *TokenUpdate) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_TokenUpdate.Unmarshal(m, b)
+}
+func (m *TokenUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_TokenUpdate.Marshal(b, m, deterministic)
+}
+func (dst *TokenUpdate) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TokenUpdate.Merge(dst, src)
+}
+func (m *TokenUpdate) XXX_Size() int {
+ return xxx_messageInfo_TokenUpdate.Size(m)
+}
+func (m *TokenUpdate) XXX_DiscardUnknown() {
+ xxx_messageInfo_TokenUpdate.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TokenUpdate proto.InternalMessageInfo
+
+func (m *TokenUpdate) GetToken() []byte {
+ if m != nil {
+ return m.Token
+ }
+ return nil
+}
+
+func (m *TokenUpdate) GetPushMagic() string {
+ if m != nil {
+ return m.PushMagic
+ }
+ return ""
+}
+
+func (m *TokenUpdate) GetUnlockToken() []byte {
+ if m != nil {
+ return m.UnlockToken
+ }
+ return nil
+}
+
+func (m *TokenUpdate) GetAwaitingConfiguration() bool {
+ if m != nil {
+ return m.AwaitingConfiguration
+ }
+ return false
+}
+
+func (m *TokenUpdate) GetUserId() string {
+ if m != nil {
+ return m.UserId
+ }
+ return ""
+}
+
+func (m *TokenUpdate) GetUserLongName() string {
+ if m != nil {
+ return m.UserLongName
+ }
+ return ""
+}
+
+func (m *TokenUpdate) GetUserShortName() string {
+ if m != nil {
+ return m.UserShortName
+ }
+ return ""
+}
+
+func (m *TokenUpdate) GetNotOnConsole() bool {
+ if m != nil {
+ return m.NotOnConsole
+ }
+ return false
+}
+
+func init() {
+ proto.RegisterType((*Event)(nil), "checkinproto.Event")
+ proto.RegisterMapType((map[string]string)(nil), "checkinproto.Event.ParamsEntry")
+ proto.RegisterType((*Command)(nil), "checkinproto.Command")
+ proto.RegisterType((*Authenticate)(nil), "checkinproto.Authenticate")
+ proto.RegisterType((*TokenUpdate)(nil), "checkinproto.TokenUpdate")
+}
+
+func init() { proto.RegisterFile("checkin.proto", fileDescriptor_checkin_7e1d11c144d2ce7a) }
+
+var fileDescriptor_checkin_7e1d11c144d2ce7a = []byte{
+ // 602 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x92, 0xdf, 0x6e, 0xd3, 0x30,
+ 0x14, 0xc6, 0x95, 0x74, 0x6d, 0x97, 0x93, 0x6c, 0x20, 0x8b, 0x41, 0x98, 0x40, 0xeb, 0xca, 0x84,
+ 0x7a, 0x55, 0xa4, 0x21, 0xc4, 0x1f, 0x21, 0x24, 0x34, 0xed, 0x02, 0x09, 0x06, 0x32, 0x83, 0xdb,
+ 0xc8, 0x4d, 0x4c, 0x6a, 0x35, 0xb1, 0xa3, 0xc4, 0xe9, 0xd4, 0x47, 0xe2, 0x05, 0x78, 0x12, 0x9e,
+ 0x80, 0x27, 0x41, 0xe7, 0x38, 0xdd, 0xd2, 0xbb, 0x73, 0x7e, 0xfe, 0xfc, 0xe5, 0x9c, 0x2f, 0x86,
+ 0x83, 0x74, 0x29, 0xd3, 0x95, 0xd2, 0xf3, 0xaa, 0x36, 0xd6, 0xb0, 0xa8, 0x6b, 0xa9, 0x9b, 0xfe,
+ 0xf3, 0x60, 0x78, 0xb9, 0x96, 0xda, 0xb2, 0x43, 0xf0, 0x55, 0x16, 0x7b, 0x13, 0x6f, 0x16, 0x70,
+ 0x5f, 0x65, 0x8c, 0xc1, 0x9e, 0x55, 0xa5, 0x8c, 0xfd, 0x89, 0x37, 0x1b, 0x70, 0xaa, 0xd9, 0x0b,
+ 0x18, 0xa7, 0xa6, 0x2c, 0x85, 0xce, 0xe2, 0xc1, 0xc4, 0x9b, 0x85, 0xe7, 0x47, 0xf3, 0xbe, 0xdb,
+ 0xfc, 0xc2, 0x1d, 0xf2, 0xad, 0x8a, 0xdd, 0x87, 0x41, 0x2d, 0x6e, 0xe2, 0xbd, 0x89, 0x37, 0x8b,
+ 0x38, 0x96, 0xec, 0x35, 0x8c, 0x2a, 0x51, 0x8b, 0xb2, 0x89, 0x87, 0x93, 0xc1, 0x2c, 0x3c, 0x3f,
+ 0xd9, 0x75, 0xa0, 0x59, 0xe6, 0xdf, 0x48, 0x71, 0xa9, 0x6d, 0xbd, 0xe1, 0x9d, 0xfc, 0xf8, 0x2d,
+ 0x84, 0x3d, 0x8c, 0xce, 0x2b, 0xb9, 0xe9, 0xe6, 0xc5, 0x92, 0x3d, 0x80, 0xe1, 0x5a, 0x14, 0xad,
+ 0x9b, 0x38, 0xe0, 0xae, 0x79, 0xe7, 0xbf, 0xf1, 0xa6, 0x7f, 0x3d, 0x18, 0x77, 0xa3, 0xb1, 0x53,
+ 0x88, 0x4a, 0xd9, 0x34, 0x22, 0x97, 0x89, 0xdd, 0x54, 0xb2, 0x33, 0x08, 0x3b, 0x76, 0xbd, 0xa9,
+ 0x24, 0x1a, 0x59, 0x53, 0xa9, 0x74, 0x6b, 0x44, 0x0d, 0xe6, 0xd1, 0x66, 0xca, 0x2d, 0x1e, 0x70,
+ 0xaa, 0xd9, 0x07, 0x88, 0x44, 0x6b, 0x97, 0x52, 0x5b, 0x95, 0x0a, 0x2b, 0x69, 0xcf, 0xf0, 0xfc,
+ 0x78, 0x77, 0xa5, 0x8f, 0x3d, 0x05, 0xdf, 0xd1, 0xb3, 0xf7, 0x10, 0x59, 0xb3, 0x92, 0x3a, 0x69,
+ 0xab, 0x0c, 0xef, 0x0f, 0xe9, 0xfe, 0xe3, 0xdd, 0xfb, 0xd7, 0xa8, 0xf8, 0x41, 0x02, 0x1e, 0xda,
+ 0xbb, 0x66, 0xfa, 0xc7, 0x87, 0xa8, 0x6f, 0xce, 0x9e, 0x02, 0x98, 0x26, 0x59, 0xcb, 0xba, 0x51,
+ 0x46, 0x77, 0x9b, 0x05, 0xa6, 0xf9, 0xe9, 0x00, 0x7b, 0x06, 0x07, 0x8b, 0x56, 0x15, 0xd9, 0xad,
+ 0xc2, 0xed, 0x17, 0x11, 0xdc, 0x8a, 0x4e, 0x21, 0xaa, 0x6a, 0x93, 0xb5, 0xa9, 0x4d, 0xb4, 0x28,
+ 0x65, 0xb7, 0x6e, 0xd8, 0xb1, 0x2b, 0x51, 0x4a, 0xf4, 0x69, 0x64, 0xad, 0x44, 0x91, 0xe8, 0xb6,
+ 0x5c, 0xc8, 0x9a, 0xd6, 0x0e, 0x78, 0xe4, 0xe0, 0x15, 0x31, 0x8c, 0x4b, 0x95, 0x52, 0xd1, 0x4a,
+ 0x01, 0xa7, 0x1a, 0x59, 0x29, 0x55, 0x16, 0x8f, 0x1c, 0xc3, 0x9a, 0x9d, 0x40, 0x98, 0xc9, 0xb5,
+ 0x4a, 0xa5, 0xfb, 0xdc, 0x98, 0x8e, 0xc0, 0x21, 0xfa, 0xda, 0x13, 0x08, 0xd2, 0xa5, 0x28, 0x0a,
+ 0xa9, 0x73, 0x19, 0xef, 0xd3, 0x43, 0xba, 0x03, 0xf8, 0xaf, 0x4a, 0x93, 0xc9, 0x22, 0x0e, 0xdc,
+ 0xbf, 0xa2, 0x06, 0x83, 0xa0, 0xc2, 0x79, 0x82, 0x0b, 0x82, 0x08, 0x5a, 0x4e, 0x7f, 0xfb, 0x10,
+ 0xf6, 0x52, 0x75, 0x3f, 0x7c, 0x25, 0x5d, 0x64, 0x11, 0x77, 0x0d, 0x9a, 0x54, 0x6d, 0xb3, 0x4c,
+ 0x4a, 0x91, 0xdf, 0xbe, 0x85, 0x00, 0xc9, 0x17, 0x04, 0x18, 0x54, 0xab, 0x0b, 0x93, 0xae, 0x12,
+ 0x77, 0x77, 0x40, 0x77, 0x43, 0xc7, 0xc8, 0x9d, 0xbd, 0x82, 0x87, 0xe2, 0x46, 0x28, 0xab, 0x74,
+ 0x9e, 0xa4, 0x46, 0xff, 0x52, 0x79, 0x5b, 0x0b, 0x8b, 0xc9, 0x63, 0x62, 0xfb, 0xfc, 0x68, 0x7b,
+ 0x7a, 0xd1, 0x3f, 0x64, 0x8f, 0x60, 0xdc, 0x36, 0xb2, 0x4e, 0x54, 0xd6, 0xa5, 0x37, 0xc2, 0xf6,
+ 0x53, 0xc6, 0xce, 0xe0, 0x90, 0x0e, 0x0a, 0xa3, 0x73, 0xb7, 0x9a, 0x4b, 0x32, 0x42, 0xfa, 0xd9,
+ 0xe8, 0x9c, 0x02, 0x7b, 0x0e, 0xf7, 0x48, 0xd5, 0x2c, 0x4d, 0x6d, 0xfb, 0xa9, 0x1e, 0x20, 0xfe,
+ 0x8e, 0x94, 0x74, 0x67, 0x70, 0xa8, 0x8d, 0x4d, 0x8c, 0xc6, 0xd9, 0x1a, 0x53, 0xb8, 0x74, 0xf7,
+ 0x79, 0xa4, 0x8d, 0xfd, 0xaa, 0x2f, 0x1c, 0x5b, 0x8c, 0xe8, 0x11, 0xbe, 0xfc, 0x1f, 0x00, 0x00,
+ 0xff, 0xff, 0x87, 0xd1, 0x6a, 0xe1, 0x46, 0x04, 0x00, 0x00,
+}
diff --git a/mdm/checkin/internal/checkinproto/checkin.proto b/mdm/internal/checkinproto/checkin.proto
similarity index 93%
rename from mdm/checkin/internal/checkinproto/checkin.proto
rename to mdm/internal/checkinproto/checkin.proto
index 357b1bbe..bd3f4caf 100644
--- a/mdm/checkin/internal/checkinproto/checkin.proto
+++ b/mdm/internal/checkinproto/checkin.proto
@@ -6,6 +6,8 @@ message Event {
string id = 1;
int64 time = 2;
Command command = 3;
+ bytes raw = 4;
+ map params = 5;
}
message Command {
diff --git a/mdm/connect/internal/connectproto/connect.go b/mdm/internal/connectproto/connect.go
similarity index 100%
rename from mdm/connect/internal/connectproto/connect.go
rename to mdm/internal/connectproto/connect.go
diff --git a/mdm/internal/connectproto/connect.pb.go b/mdm/internal/connectproto/connect.pb.go
new file mode 100644
index 00000000..09e496c8
--- /dev/null
+++ b/mdm/internal/connectproto/connect.pb.go
@@ -0,0 +1,189 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: connect.proto
+
+package connectproto
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type Event struct {
+ Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
+ Time int64 `protobuf:"varint,2,opt,name=time" json:"time,omitempty"`
+ Response *Response `protobuf:"bytes,3,opt,name=response" json:"response,omitempty"`
+ Raw []byte `protobuf:"bytes,4,opt,name=raw,proto3" json:"raw,omitempty"`
+ Params map[string]string `protobuf:"bytes,5,rep,name=params" json:"params,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Event) Reset() { *m = Event{} }
+func (m *Event) String() string { return proto.CompactTextString(m) }
+func (*Event) ProtoMessage() {}
+func (*Event) Descriptor() ([]byte, []int) {
+ return fileDescriptor_connect_0a9da89ca45acccc, []int{0}
+}
+func (m *Event) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Event.Unmarshal(m, b)
+}
+func (m *Event) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Event.Marshal(b, m, deterministic)
+}
+func (dst *Event) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Event.Merge(dst, src)
+}
+func (m *Event) XXX_Size() int {
+ return xxx_messageInfo_Event.Size(m)
+}
+func (m *Event) XXX_DiscardUnknown() {
+ xxx_messageInfo_Event.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Event proto.InternalMessageInfo
+
+func (m *Event) GetId() string {
+ if m != nil {
+ return m.Id
+ }
+ return ""
+}
+
+func (m *Event) GetTime() int64 {
+ if m != nil {
+ return m.Time
+ }
+ return 0
+}
+
+func (m *Event) GetResponse() *Response {
+ if m != nil {
+ return m.Response
+ }
+ return nil
+}
+
+func (m *Event) GetRaw() []byte {
+ if m != nil {
+ return m.Raw
+ }
+ return nil
+}
+
+func (m *Event) GetParams() map[string]string {
+ if m != nil {
+ return m.Params
+ }
+ return nil
+}
+
+type Response struct {
+ Udid string `protobuf:"bytes,1,opt,name=udid" json:"udid,omitempty"`
+ UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId" json:"user_id,omitempty"`
+ Status string `protobuf:"bytes,3,opt,name=status" json:"status,omitempty"`
+ RequestType string `protobuf:"bytes,4,opt,name=request_type,json=requestType" json:"request_type,omitempty"`
+ CommandUuid string `protobuf:"bytes,5,opt,name=command_uuid,json=commandUuid" json:"command_uuid,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Response) Reset() { *m = Response{} }
+func (m *Response) String() string { return proto.CompactTextString(m) }
+func (*Response) ProtoMessage() {}
+func (*Response) Descriptor() ([]byte, []int) {
+ return fileDescriptor_connect_0a9da89ca45acccc, []int{1}
+}
+func (m *Response) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Response.Unmarshal(m, b)
+}
+func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Response.Marshal(b, m, deterministic)
+}
+func (dst *Response) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Response.Merge(dst, src)
+}
+func (m *Response) XXX_Size() int {
+ return xxx_messageInfo_Response.Size(m)
+}
+func (m *Response) XXX_DiscardUnknown() {
+ xxx_messageInfo_Response.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Response proto.InternalMessageInfo
+
+func (m *Response) GetUdid() string {
+ if m != nil {
+ return m.Udid
+ }
+ return ""
+}
+
+func (m *Response) GetUserId() string {
+ if m != nil {
+ return m.UserId
+ }
+ return ""
+}
+
+func (m *Response) GetStatus() string {
+ if m != nil {
+ return m.Status
+ }
+ return ""
+}
+
+func (m *Response) GetRequestType() string {
+ if m != nil {
+ return m.RequestType
+ }
+ return ""
+}
+
+func (m *Response) GetCommandUuid() string {
+ if m != nil {
+ return m.CommandUuid
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*Event)(nil), "connectproto.Event")
+ proto.RegisterMapType((map[string]string)(nil), "connectproto.Event.ParamsEntry")
+ proto.RegisterType((*Response)(nil), "connectproto.Response")
+}
+
+func init() { proto.RegisterFile("connect.proto", fileDescriptor_connect_0a9da89ca45acccc) }
+
+var fileDescriptor_connect_0a9da89ca45acccc = []byte{
+ // 285 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0xbd, 0x4e, 0xc3, 0x30,
+ 0x1c, 0xc4, 0xe5, 0xa4, 0x09, 0xcd, 0x3f, 0x05, 0x21, 0x0b, 0x15, 0x8b, 0x85, 0xd0, 0x29, 0x53,
+ 0x86, 0x32, 0xf0, 0xb1, 0x77, 0x60, 0x43, 0x16, 0xcc, 0x91, 0x89, 0x3d, 0x58, 0x10, 0x27, 0xf8,
+ 0xa3, 0x28, 0x0f, 0xc2, 0x23, 0xf2, 0x1e, 0xc8, 0x8e, 0xa9, 0xca, 0x76, 0xf7, 0xf7, 0xf9, 0x74,
+ 0x3f, 0x38, 0xed, 0x06, 0xa5, 0x44, 0x67, 0x9b, 0x51, 0x0f, 0x76, 0xc0, 0xab, 0x68, 0x83, 0xdb,
+ 0xfc, 0x20, 0xc8, 0x76, 0x7b, 0xa1, 0x2c, 0x3e, 0x83, 0x44, 0x72, 0x82, 0x2a, 0x54, 0x17, 0x34,
+ 0x91, 0x1c, 0x63, 0x58, 0x58, 0xd9, 0x0b, 0x92, 0x54, 0xa8, 0x4e, 0x69, 0xd0, 0x78, 0x0b, 0x4b,
+ 0x2d, 0xcc, 0x38, 0x28, 0x23, 0x48, 0x5a, 0xa1, 0xba, 0xdc, 0xae, 0x9b, 0xe3, 0xba, 0x86, 0xc6,
+ 0x57, 0x7a, 0xc8, 0xe1, 0x73, 0x48, 0x35, 0xfb, 0x22, 0x8b, 0x0a, 0xd5, 0x2b, 0xea, 0x25, 0xbe,
+ 0x83, 0x7c, 0x64, 0x9a, 0xf5, 0x86, 0x64, 0x55, 0x5a, 0x97, 0xdb, 0xeb, 0xff, 0x1d, 0x61, 0x4e,
+ 0xf3, 0x1c, 0x12, 0x3b, 0x65, 0xf5, 0x44, 0x63, 0xfc, 0xea, 0x01, 0xca, 0xa3, 0xb3, 0x6f, 0x7e,
+ 0x17, 0x53, 0x9c, 0xec, 0x25, 0xbe, 0x80, 0x6c, 0xcf, 0x3e, 0xdc, 0x3c, 0xba, 0xa0, 0xb3, 0x79,
+ 0x4c, 0xee, 0xd1, 0xe6, 0x1b, 0xc1, 0xf2, 0x6f, 0x9c, 0x47, 0x73, 0xfc, 0x00, 0x1b, 0x34, 0xbe,
+ 0x84, 0x13, 0x67, 0x84, 0x6e, 0x25, 0x8f, 0x9f, 0x73, 0x6f, 0x9f, 0x38, 0x5e, 0x43, 0x6e, 0x2c,
+ 0xb3, 0xce, 0x04, 0xe2, 0x82, 0x46, 0x87, 0x6f, 0x60, 0xa5, 0xc5, 0xa7, 0x13, 0xc6, 0xb6, 0x76,
+ 0x1a, 0x45, 0x00, 0x2c, 0x68, 0x19, 0x6f, 0x2f, 0xd3, 0x28, 0x7c, 0xa4, 0x1b, 0xfa, 0x9e, 0x29,
+ 0xde, 0x3a, 0x27, 0x39, 0xc9, 0xe6, 0x48, 0xbc, 0xbd, 0x3a, 0xc9, 0xdf, 0xf2, 0xc0, 0x7c, 0xfb,
+ 0x1b, 0x00, 0x00, 0xff, 0xff, 0x78, 0xb5, 0xce, 0x2a, 0xa5, 0x01, 0x00, 0x00,
+}
diff --git a/mdm/connect/internal/connectproto/connect.proto b/mdm/internal/connectproto/connect.proto
similarity index 89%
rename from mdm/connect/internal/connectproto/connect.proto
rename to mdm/internal/connectproto/connect.proto
index ca7555a4..5a2eddb5 100644
--- a/mdm/connect/internal/connectproto/connect.proto
+++ b/mdm/internal/connectproto/connect.proto
@@ -7,6 +7,7 @@ message Event {
int64 time = 2;
Response response = 3;
bytes raw = 4;
+ map params = 5;
}
message Response {
diff --git a/mdm/server.go b/mdm/server.go
new file mode 100644
index 00000000..7a7293d0
--- /dev/null
+++ b/mdm/server.go
@@ -0,0 +1,122 @@
+package mdm
+
+import (
+ "context"
+ "io/ioutil"
+ "net/http"
+
+ "github.com/go-kit/kit/endpoint"
+ "github.com/go-kit/kit/log"
+ httptransport "github.com/go-kit/kit/transport/http"
+ "github.com/gorilla/mux"
+ "github.com/pkg/errors"
+)
+
+type Endpoints struct {
+ CheckinEndpoint endpoint.Endpoint
+ AcknowledgeEndpoint endpoint.Endpoint
+}
+
+func MakeServerEndpoints(s Service) Endpoints {
+ return Endpoints{
+ CheckinEndpoint: MakeCheckinEndpoint(s),
+ AcknowledgeEndpoint: MakeAcknowledgeEndpoint(s),
+ }
+}
+
+func RegisterHTTPHandlers(r *mux.Router, e Endpoints, verifier SignatureVerifier, logger log.Logger) {
+ decoder := &requestDecoder{verifier: verifier}
+ options := []httptransport.ServerOption{
+ httptransport.ServerErrorEncoder(encodeError),
+ httptransport.ServerErrorLogger(logger),
+ httptransport.ServerBefore(httptransport.PopulateRequestContext),
+ }
+
+ r.Methods(http.MethodPut).Path("/mdm/checkin").Handler(httptransport.NewServer(
+ e.CheckinEndpoint,
+ decoder.decodeCheckinRequest,
+ encodeResponse,
+ options...,
+ ))
+
+ r.Methods(http.MethodPut).Path("/mdm/connect").Handler(httptransport.NewServer(
+ e.AcknowledgeEndpoint,
+ decoder.decodeAcknowledgeRequest,
+ encodeResponse,
+ options...,
+ ))
+}
+
+type SignatureVerifier interface {
+ VerifySignature(sig string, message []byte) error
+}
+
+type requestDecoder struct {
+ verifier SignatureVerifier
+}
+
+func (d *requestDecoder) readBody(r *http.Request) ([]byte, error) {
+ defer r.Body.Close()
+
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ return nil, errors.Wrap(err, "reading MDM Response HTTP Body")
+ }
+
+ if d.verifier != nil {
+ b64sig := r.Header.Get("Mdm-Signature")
+ if err := d.verifier.VerifySignature(b64sig, body); err != nil {
+ return nil, errors.Wrap(err, "verify signature")
+ }
+ }
+
+ return body, nil
+}
+
+// According to the MDM Check-in protocol, the server must respond with 200 OK
+// to successful Check-in requests.
+func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
+ type failer interface {
+ Failed() error
+ }
+
+ if e, ok := response.(failer); ok && e.Failed() != nil {
+ encodeError(ctx, e.Failed(), w)
+ return nil
+ }
+
+ w.WriteHeader(http.StatusOK)
+
+ type payloader interface {
+ Response() []byte
+ }
+
+ var err error
+ if r, ok := response.(payloader); ok {
+ _, err = w.Write(r.Response())
+ }
+ return errors.Wrap(err, "write acknowledge response")
+}
+
+func encodeError(ctx context.Context, err error, w http.ResponseWriter) {
+ err = errors.Cause(err)
+ type rejectUserAuthError interface {
+ error
+ UserAuthReject() bool
+ }
+ if e, ok := err.(rejectUserAuthError); ok && e.UserAuthReject() {
+ w.WriteHeader(http.StatusGone)
+ return
+ }
+
+ type checkoutErr interface {
+ error
+ Checkout() bool
+ }
+ if e, ok := err.(checkoutErr); ok && e.Checkout() {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ w.WriteHeader(http.StatusInternalServerError)
+}
diff --git a/mdm/service.go b/mdm/service.go
new file mode 100644
index 00000000..d71fa3c5
--- /dev/null
+++ b/mdm/service.go
@@ -0,0 +1,38 @@
+package mdm
+
+import (
+ "context"
+
+ "github.com/micromdm/micromdm/platform/pubsub"
+)
+
+type Service interface {
+ Checkin(ctx context.Context, event CheckinEvent) error
+ Acknowledge(ctx context.Context, event AcknowledgeEvent) (payload []byte, err error)
+}
+
+type Middleware func(Service) Service
+
+const (
+ ConnectTopic = "mdm.Connect"
+ AuthenticateTopic = "mdm.Authenticate"
+ TokenUpdateTopic = "mdm.TokenUpdate"
+ CheckoutTopic = "mdm.CheckOut"
+)
+
+// Queue is an MDM Command Queue.
+type Queue interface {
+ Next(context.Context, Response) ([]byte, error)
+}
+
+type MDMService struct {
+ pub pubsub.Publisher
+ queue Queue
+}
+
+func NewService(pub pubsub.Publisher, queue Queue) *MDMService {
+ return &MDMService{
+ pub: pub,
+ queue: queue,
+ }
+}
diff --git a/platform/apns/builtin/db.go b/platform/apns/builtin/db.go
index 4dfc705d..e5584b20 100644
--- a/platform/apns/builtin/db.go
+++ b/platform/apns/builtin/db.go
@@ -7,7 +7,7 @@ import (
"github.com/boltdb/bolt"
"github.com/pkg/errors"
- "github.com/micromdm/micromdm/mdm/checkin"
+ "github.com/micromdm/micromdm/mdm"
"github.com/micromdm/micromdm/platform/apns"
"github.com/micromdm/micromdm/platform/pubsub"
)
@@ -81,17 +81,17 @@ func (db *DB) Save(info *apns.PushInfo) error {
}
func (db *DB) pollCheckin(sub pubsub.Subscriber) error {
- tokenUpdateEvents, err := sub.Subscribe(context.TODO(), "push-info", checkin.TokenUpdateTopic)
+ tokenUpdateEvents, err := sub.Subscribe(context.TODO(), "push-info", mdm.TokenUpdateTopic)
if err != nil {
return errors.Wrapf(err,
- "subscribing push to %s topic", checkin.TokenUpdateTopic)
+ "subscribing push to %s topic", mdm.TokenUpdateTopic)
}
go func() {
for {
select {
case event := <-tokenUpdateEvents:
- var ev checkin.Event
- if err := checkin.UnmarshalEvent(event.Message, &ev); err != nil {
+ var ev mdm.CheckinEvent
+ if err := mdm.UnmarshalCheckinEvent(event.Message, &ev); err != nil {
fmt.Println(err)
continue
}
diff --git a/platform/blueprint/builtin/listener.go b/platform/blueprint/builtin/listener.go
index 6b0c0991..d7716888 100644
--- a/platform/blueprint/builtin/listener.go
+++ b/platform/blueprint/builtin/listener.go
@@ -6,7 +6,7 @@ import (
"github.com/pkg/errors"
- "github.com/micromdm/micromdm/mdm/checkin"
+ mdmsvc "github.com/micromdm/micromdm/mdm"
"github.com/micromdm/micromdm/mdm/mdm"
"github.com/micromdm/micromdm/platform/blueprint"
"github.com/micromdm/micromdm/platform/command"
@@ -99,8 +99,8 @@ func (db *DB) StartListener(sub pubsub.Subscriber, cmdSvc command.Service) error
for {
select {
case event := <-tokenUpdateEvents:
- var ev checkin.Event
- if err := checkin.UnmarshalEvent(event.Message, &ev); err != nil {
+ var ev mdmsvc.CheckinEvent
+ if err := mdmsvc.UnmarshalCheckinEvent(event.Message, &ev); err != nil {
fmt.Println(err)
continue
}
diff --git a/platform/device/builtin/db.go b/platform/device/builtin/db.go
index 8abc2b78..3e66fb80 100644
--- a/platform/device/builtin/db.go
+++ b/platform/device/builtin/db.go
@@ -10,8 +10,7 @@ import (
uuid "github.com/satori/go.uuid"
"github.com/micromdm/micromdm/dep/depsync"
- "github.com/micromdm/micromdm/mdm/checkin"
- "github.com/micromdm/micromdm/mdm/connect"
+ "github.com/micromdm/micromdm/mdm"
"github.com/micromdm/micromdm/platform/device"
"github.com/micromdm/micromdm/platform/pubsub"
)
@@ -175,37 +174,37 @@ func isNotFound(err error) bool {
}
func (db *DB) pollCheckin(pubsubSvc pubsub.PublishSubscriber) error {
- authenticateEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", checkin.AuthenticateTopic)
+ authenticateEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", mdm.AuthenticateTopic)
if err != nil {
return errors.Wrapf(err,
- "subscribing devices to %s topic", checkin.AuthenticateTopic)
+ "subscribing devices to %s topic", mdm.AuthenticateTopic)
}
- tokenUpdateEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", checkin.TokenUpdateTopic)
+ tokenUpdateEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", mdm.TokenUpdateTopic)
if err != nil {
return errors.Wrapf(err,
- "subscribing devices to %s topic", checkin.TokenUpdateTopic)
+ "subscribing devices to %s topic", mdm.TokenUpdateTopic)
}
- checkoutEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", checkin.CheckoutTopic)
+ checkoutEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", mdm.CheckoutTopic)
if err != nil {
return errors.Wrapf(err,
- "subscribing devices to %s topic", checkin.CheckoutTopic)
+ "subscribing devices to %s topic", mdm.CheckoutTopic)
}
depSyncEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", depsync.SyncTopic)
if err != nil {
return errors.Wrapf(err,
"subscribing devices to %s topic", depsync.SyncTopic)
}
- connectEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", connect.ConnectTopic)
+ connectEvents, err := pubsubSvc.Subscribe(context.TODO(), "devices", mdm.ConnectTopic)
if err != nil {
return errors.Wrapf(err,
- "subscribing devices to %s topic", connect.ConnectTopic)
+ "subscribing devices to %s topic", mdm.ConnectTopic)
}
go func() {
for {
select {
case event := <-authenticateEvents:
- var ev checkin.Event
- if err := checkin.UnmarshalEvent(event.Message, &ev); err != nil {
+ var ev mdm.CheckinEvent
+ if err := mdm.UnmarshalCheckinEvent(event.Message, &ev); err != nil {
fmt.Println(err)
continue
}
@@ -252,8 +251,8 @@ func (db *DB) pollCheckin(pubsubSvc pubsub.PublishSubscriber) error {
continue
}
case event := <-tokenUpdateEvents:
- var ev checkin.Event
- if err := checkin.UnmarshalEvent(event.Message, &ev); err != nil {
+ var ev mdm.CheckinEvent
+ if err := mdm.UnmarshalCheckinEvent(event.Message, &ev); err != nil {
fmt.Println(err)
continue
}
@@ -339,8 +338,8 @@ func (db *DB) pollCheckin(pubsubSvc pubsub.PublishSubscriber) error {
}
}
case event := <-connectEvents:
- var ev connect.Event
- if err := connect.UnmarshalEvent(event.Message, &ev); err != nil {
+ var ev mdm.AcknowledgeEvent
+ if err := mdm.UnmarshalAcknowledgeEvent(event.Message, &ev); err != nil {
fmt.Println(err)
continue
}
@@ -355,8 +354,8 @@ func (db *DB) pollCheckin(pubsubSvc pubsub.PublishSubscriber) error {
continue
}
case event := <-checkoutEvents:
- var ev checkin.Event
- if err := checkin.UnmarshalEvent(event.Message, &ev); err != nil {
+ var ev mdm.CheckinEvent
+ if err := mdm.UnmarshalCheckinEvent(event.Message, &ev); err != nil {
fmt.Println(err)
continue
}
diff --git a/platform/queue/queue.go b/platform/queue/queue.go
index 3341c555..49afdf40 100644
--- a/platform/queue/queue.go
+++ b/platform/queue/queue.go
@@ -9,7 +9,7 @@ import (
"github.com/groob/plist"
"github.com/pkg/errors"
- "github.com/micromdm/mdm"
+ "github.com/micromdm/micromdm/mdm"
"github.com/micromdm/micromdm/platform/command"
"github.com/micromdm/micromdm/platform/pubsub"
)
@@ -24,7 +24,18 @@ type Store struct {
*bolt.DB
}
-func (db *Store) Next(ctx context.Context, resp mdm.Response) (*Command, error) {
+func (db *Store) Next(ctx context.Context, resp mdm.Response) ([]byte, error) {
+ cmd, err := db.nextCommand(ctx, resp)
+ if err != nil {
+ return nil, err
+ }
+ if cmd == nil {
+ return nil, nil
+ }
+ return cmd.Payload, nil
+}
+
+func (db *Store) nextCommand(ctx context.Context, resp mdm.Response) (*Command, error) {
udid := resp.UDID
if resp.UserID != nil {
// use the user id for user level commands
diff --git a/platform/queue/queue_test.go b/platform/queue/queue_test.go
index 7f15f57e..1839cb1d 100644
--- a/platform/queue/queue_test.go
+++ b/platform/queue/queue_test.go
@@ -7,7 +7,7 @@ import (
"testing"
"github.com/boltdb/bolt"
- "github.com/micromdm/mdm"
+ "github.com/micromdm/micromdm/mdm"
)
func TestNext_Error(t *testing.T) {
@@ -29,7 +29,7 @@ func TestNext_Error(t *testing.T) {
Status: "Error",
}
for range dc.Commands {
- cmd, err := store.Next(ctx, resp)
+ cmd, err := store.nextCommand(ctx, resp)
if err != nil {
t.Fatalf("expected nil, but got err: %s", err)
}
@@ -57,16 +57,15 @@ func TestNext_NotNow(t *testing.T) {
ctx := context.Background()
tf := func(t *testing.T) {
-
resp := mdm.Response{
UDID: dc.DeviceUDID,
CommandUUID: "yCmd",
Status: "NotNow",
}
- cmd, err := store.Next(ctx, resp)
+ cmd, err := store.nextCommand(ctx, resp)
if err != nil {
- t.Fatalf("expected nil, but got err: %s", err)
+ t.Fatalf("expected nil, but got err: %s", err)
}
resp = mdm.Response{
@@ -75,7 +74,7 @@ func TestNext_NotNow(t *testing.T) {
Status: "NotNow",
}
- cmd, err = store.Next(ctx, resp)
+ cmd, err = store.nextCommand(ctx, resp)
if err != nil {
t.Fatalf("expected nil, but got err: %s", err)
}
@@ -111,7 +110,7 @@ func TestNext_Idle(t *testing.T) {
Status: "Idle",
}
for i, _ := range dc.Commands {
- cmd, err := store.Next(ctx, resp)
+ cmd, err := store.nextCommand(ctx, resp)
if err != nil {
t.Fatalf("expected nil, but got err: %s", err)
}
@@ -143,7 +142,7 @@ func TestNext_zeroCommands(t *testing.T) {
for _, s := range allStatuses {
t.Run(s, func(t *testing.T) {
resp := mdm.Response{CommandUUID: s, Status: s}
- cmd, err := store.Next(ctx, resp)
+ cmd, err := store.nextCommand(ctx, resp)
if err != nil {
t.Errorf("expected nil, but got err: %s", err)
}
diff --git a/platform/remove/remove.go b/platform/remove/remove.go
index ff36e6ca..b2b6e78a 100644
--- a/platform/remove/remove.go
+++ b/platform/remove/remove.go
@@ -6,7 +6,7 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/pkg/errors"
- "github.com/micromdm/micromdm/mdm/connect"
+ "github.com/micromdm/micromdm/mdm"
"github.com/micromdm/micromdm/platform/remove/internal/removeproto"
)
@@ -30,8 +30,8 @@ func UnmarshalDevice(data []byte, dev *Device) error {
return nil
}
-func RemoveMiddleware(store Store) connect.Middleware {
- return func(next connect.Service) connect.Service {
+func RemoveMiddleware(store Store) mdm.Middleware {
+ return func(next mdm.Service) mdm.Service {
return &removeMiddleware{
store: store,
next: next,
@@ -41,11 +41,11 @@ func RemoveMiddleware(store Store) connect.Middleware {
type removeMiddleware struct {
store Store
- next connect.Service
+ next mdm.Service
}
-func (mw removeMiddleware) Acknowledge(ctx context.Context, req connect.MDMConnectRequest) ([]byte, error) {
- udid := req.MDMResponse.UDID
+func (mw removeMiddleware) Acknowledge(ctx context.Context, req mdm.AcknowledgeEvent) ([]byte, error) {
+ udid := req.Response.UDID
_, err := mw.store.DeviceByUDID(udid)
if err != nil {
if !isNotFound(err) {
@@ -58,6 +58,10 @@ func (mw removeMiddleware) Acknowledge(ctx context.Context, req connect.MDMConne
return mw.next.Acknowledge(ctx, req)
}
+func (mw removeMiddleware) Checkin(ctx context.Context, req mdm.CheckinEvent) error {
+ return mw.next.Checkin(ctx, req)
+}
+
type checkoutErr struct{}
func (checkoutErr) Error() string {
diff --git a/platform/user/builtin/db.go b/platform/user/builtin/db.go
index 96cfbdbd..0999b35e 100644
--- a/platform/user/builtin/db.go
+++ b/platform/user/builtin/db.go
@@ -10,7 +10,7 @@ import (
"github.com/pkg/errors"
uuid "github.com/satori/go.uuid"
- "github.com/micromdm/micromdm/mdm/checkin"
+ "github.com/micromdm/micromdm/mdm"
"github.com/micromdm/micromdm/platform/pubsub"
"github.com/micromdm/micromdm/platform/user"
)
@@ -201,10 +201,10 @@ func (e *notFound) NotFound() bool {
}
func (db *DB) pollCheckin(pubsubSvc pubsub.PublishSubscriber) error {
- tokenUpdateEvents, err := pubsubSvc.Subscribe(context.TODO(), "users", checkin.TokenUpdateTopic)
+ tokenUpdateEvents, err := pubsubSvc.Subscribe(context.TODO(), "users", mdm.TokenUpdateTopic)
if err != nil {
return errors.Wrapf(err,
- "subscribing devices to %s topic", checkin.TokenUpdateTopic)
+ "subscribing devices to %s topic", mdm.TokenUpdateTopic)
}
go func() {
for {
@@ -252,10 +252,10 @@ func (db *DB) pollCheckin(pubsubSvc pubsub.PublishSubscriber) error {
return nil
}
-func unmarshalCheckin(event pubsub.Event) (checkin.Event, error) {
- var ev checkin.Event
- if err := checkin.UnmarshalEvent(event.Message, &ev); err != nil {
- return checkin.Event{}, err
+func unmarshalCheckin(event pubsub.Event) (mdm.CheckinEvent, error) {
+ var ev mdm.CheckinEvent
+ if err := mdm.UnmarshalCheckinEvent(event.Message, &ev); err != nil {
+ return mdm.CheckinEvent{}, err
}
return ev, nil
}
diff --git a/workflow/webhook/command.go b/workflow/webhook/command.go
index 849a4097..0aba772f 100644
--- a/workflow/webhook/command.go
+++ b/workflow/webhook/command.go
@@ -6,7 +6,7 @@ import (
"fmt"
"net/http"
- "github.com/micromdm/micromdm/mdm/connect"
+ "github.com/micromdm/micromdm/mdm"
"github.com/micromdm/micromdm/platform/pubsub"
"github.com/pkg/errors"
)
@@ -42,8 +42,8 @@ func (cw CommandWebhook) StartListener(sub pubsub.Subscriber) error {
for {
select {
case event := <-connectEvents:
- var ev connect.Event
- if err := connect.UnmarshalEvent(event.Message, &ev); err != nil {
+ var ev mdm.AcknowledgeEvent
+ if err := mdm.UnmarshalAcknowledgeEvent(event.Message, &ev); err != nil {
fmt.Println(err)
continue
}