mirror of
https://github.com/micromdm/micromdm/
synced 2026-08-05 00:45:50 +08:00
organize essential APIs into platform, workflow and pkg folders (#337)
Add more logic to the way code is organized. /pkg -- library code not directly connected to micromdm /mdm -- packages meant for the services devices interract with. The MDM protocol. /dep -- DEP API and related packages. /platform -- Core APIs the server provides. Commands API, Devices API, queue, pubsub etc. /workflow -- Packages/API that build on top of platform. Today that's the webhook package. Depending on what ends up here, the workflow folder might become its own repository.
This commit is contained in:
84
platform/command/command.go
Normal file
84
platform/command/command.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package command
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
// CommandBucket is the *bolt.DB bucket where commands are archived.
|
||||
CommandBucket = "mdm.Command.ARCHIVE"
|
||||
|
||||
// CommandTopic is a PubSub topic that events are published to.
|
||||
CommandTopic = "mdm.Command"
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
db *bolt.DB
|
||||
publisher pubsub.Publisher
|
||||
archiveFn func(int64, []byte) error
|
||||
}
|
||||
|
||||
func New(db *bolt.DB, pub pubsub.Publisher) (*Command, error) {
|
||||
err := db.Update(func(tx *bolt.Tx) error {
|
||||
_, err := tx.CreateBucketIfNotExists([]byte(CommandBucket))
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "creating %s bucket", CommandBucket)
|
||||
}
|
||||
svc := Command{
|
||||
db: db,
|
||||
publisher: pub,
|
||||
}
|
||||
svc.archiveFn = svc.archive
|
||||
return &svc, nil
|
||||
}
|
||||
|
||||
func (svc *Command) NewCommand(ctx context.Context, request *mdm.CommandRequest) (*mdm.Payload, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("empty CommandRequest")
|
||||
}
|
||||
payload, err := mdm.NewPayload(request)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "creating mdm payload")
|
||||
}
|
||||
event := NewEvent(*payload, request.UDID)
|
||||
msg, err := MarshalEvent(event)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "marshalling mdm command event")
|
||||
}
|
||||
if err := svc.archive(event.Time.UnixNano(), msg); err != nil {
|
||||
return nil, errors.Wrap(err, "archive mdm command")
|
||||
}
|
||||
if err := svc.publisher.Publish(context.TODO(), CommandTopic, msg); err != nil {
|
||||
return nil, errors.Wrapf(err, "publish mdm command on topic: %s", CommandTopic)
|
||||
}
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// archive events to BoltDB bucket using timestamp as key to preserve order.
|
||||
func (svc *Command) 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(CommandBucket))
|
||||
if bkt == nil {
|
||||
return fmt.Errorf("bucket %q not found!", CommandBucket)
|
||||
}
|
||||
key := []byte(fmt.Sprintf("%d", nano))
|
||||
if err := bkt.Put(key, msg); err != nil {
|
||||
return errors.Wrap(err, "put command event to boltdb")
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
103
platform/command/command_test.go
Normal file
103
platform/command/command_test.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/micromdm/mdm"
|
||||
)
|
||||
|
||||
func TestService_NewCommand(t *testing.T) {
|
||||
svc := setupDB(t)
|
||||
mock := &mockPublisher{}
|
||||
svc.publisher = mock
|
||||
passPublisher := func(string, []byte) error { return nil }
|
||||
failPublisher := func(string, []byte) error {
|
||||
return errors.New("failed")
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
publisher func(string, []byte) error
|
||||
request *mdm.CommandRequest
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
wantErr: false,
|
||||
publisher: passPublisher,
|
||||
request: &mdm.CommandRequest{
|
||||
UDID: "foobarbaz",
|
||||
Command: mdm.Command{
|
||||
RequestType: "DeviceInformation",
|
||||
DeviceInformation: mdm.DeviceInformation{
|
||||
Queries: []string{"foo", "bar", "baz"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "publish fail",
|
||||
wantErr: true,
|
||||
publisher: failPublisher,
|
||||
request: &mdm.CommandRequest{
|
||||
Command: mdm.Command{
|
||||
RequestType: "DeviceInformation",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty request",
|
||||
wantErr: true,
|
||||
publisher: passPublisher,
|
||||
},
|
||||
{
|
||||
name: "bad payload",
|
||||
wantErr: true,
|
||||
publisher: passPublisher,
|
||||
request: &mdm.CommandRequest{
|
||||
UDID: "foobarbaz",
|
||||
Command: mdm.Command{
|
||||
RequestType: "DevicePropaganda",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
mock.PublishFn = tt.publisher
|
||||
_, err := svc.NewCommand(context.Background(), tt.request)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("%q. CommandService.NewCommand() error = %v, wantErr %v",
|
||||
tt.name, err, tt.wantErr)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type mockPublisher struct {
|
||||
PublishFn func(string, []byte) error
|
||||
}
|
||||
|
||||
func (m *mockPublisher) Publish(ctx context.Context, s string, b []byte) error {
|
||||
return m.PublishFn(s, b)
|
||||
}
|
||||
|
||||
func setupDB(t *testing.T) *Command {
|
||||
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
|
||||
}
|
||||
78
platform/command/endpoint.go
Normal file
78
platform/command/endpoint.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/metrics"
|
||||
"github.com/micromdm/mdm"
|
||||
)
|
||||
|
||||
var errEmptyRequest = errors.New("request must contain UDID of the device")
|
||||
|
||||
type Endpoints struct {
|
||||
NewCommandEndpoint endpoint.Endpoint
|
||||
}
|
||||
|
||||
// MakeNewCommandEndpoint creates an endpoint which creates new MDM Commands.
|
||||
func MakeNewCommandEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(newCommandRequest)
|
||||
if req.UDID == "" || req.RequestType == "" {
|
||||
return newCommandResponse{Err: errEmptyRequest}, nil
|
||||
}
|
||||
payload, err := svc.NewCommand(ctx, &req.CommandRequest)
|
||||
if err != nil {
|
||||
return newCommandResponse{Err: err}, nil
|
||||
}
|
||||
return newCommandResponse{Payload: payload}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// EndpointInstrumentingMiddleware returns an endpoint middleware that records
|
||||
// the duration of each invocation to the passed histogram. The middleware adds
|
||||
// a single field: "success", which is "true" if no error is returned, and
|
||||
// "false" otherwise.
|
||||
func EndpointInstrumentingMiddleware(duration metrics.Histogram) endpoint.Middleware {
|
||||
return func(next endpoint.Endpoint) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
defer func(begin time.Time) {
|
||||
duration.With("success", fmt.Sprint(err == nil)).Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return next(ctx, request)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// EndpointLoggingMiddleware returns an endpoint middleware that logs the
|
||||
// duration of each invocation, and the resulting error, if any.
|
||||
func EndpointLoggingMiddleware(logger log.Logger) endpoint.Middleware {
|
||||
return func(next endpoint.Endpoint) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
|
||||
defer func(begin time.Time) {
|
||||
logger.Log("error", err, "took", time.Since(begin))
|
||||
}(time.Now())
|
||||
return next(ctx, request)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type newCommandRequest struct {
|
||||
mdm.CommandRequest
|
||||
}
|
||||
|
||||
type newCommandResponse struct {
|
||||
Payload *mdm.Payload `json:"payload,omitempty"`
|
||||
Err error `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func (r newCommandResponse) error() error { return r.Err }
|
||||
func (r newCommandResponse) status() int { return http.StatusCreated }
|
||||
260
platform/command/event.go
Normal file
260
platform/command/event.go
Normal file
@@ -0,0 +1,260 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/micromdm/mdm"
|
||||
"github.com/pkg/errors"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/command/internal/commandproto"
|
||||
)
|
||||
|
||||
type Event struct {
|
||||
ID string
|
||||
Time time.Time
|
||||
Payload mdm.Payload
|
||||
DeviceUDID string
|
||||
}
|
||||
|
||||
// NewEvent returns an Event with a unique ID and the current time.
|
||||
func NewEvent(cmd mdm.Payload, udid string) *Event {
|
||||
event := Event{
|
||||
ID: uuid.NewV4().String(),
|
||||
Time: time.Now().UTC(),
|
||||
Payload: cmd,
|
||||
DeviceUDID: udid,
|
||||
}
|
||||
return &event
|
||||
}
|
||||
|
||||
// MarshalEvent serializes an event to a protocol buffer wire format.
|
||||
func MarshalEvent(e *Event) ([]byte, error) {
|
||||
payload := &commandproto.Payload{
|
||||
CommandUuid: e.Payload.CommandUUID,
|
||||
}
|
||||
if e.Payload.Command != nil {
|
||||
payload.Command = &commandproto.Command{
|
||||
RequestType: e.Payload.Command.RequestType,
|
||||
}
|
||||
}
|
||||
switch e.Payload.Command.RequestType {
|
||||
case "DeviceLock":
|
||||
payload.Command.DeviceLock = &commandproto.DeviceLock{
|
||||
Pin: e.Payload.Command.DeviceLock.PIN,
|
||||
Message: e.Payload.Command.DeviceLock.Message,
|
||||
PhoneNumber: e.Payload.Command.DeviceLock.PhoneNumber,
|
||||
}
|
||||
case "EraseDevice":
|
||||
payload.Command.EraseDevice = &commandproto.EraseDevice{
|
||||
Pin: e.Payload.Command.EraseDevice.PIN,
|
||||
}
|
||||
case "DeleteUser":
|
||||
payload.Command.DeleteUser = &commandproto.DeleteUser{
|
||||
Username: e.Payload.Command.DeleteUser.UserName,
|
||||
ForceDeletion: e.Payload.Command.DeleteUser.ForceDeletion,
|
||||
}
|
||||
case "ScheduleOSUpdateScan":
|
||||
payload.Command.ScheduleOsUpdateScan = &commandproto.ScheduleOSUpdateScan{
|
||||
Force: e.Payload.Command.ScheduleOSUpdateScan.Force,
|
||||
}
|
||||
case "ScheduleOSUpdate":
|
||||
p := e.Payload.Command.ScheduleOSUpdate
|
||||
var updates []*commandproto.OSUpdate
|
||||
for _, update := range p.Updates {
|
||||
updates = append(updates, &commandproto.OSUpdate{
|
||||
ProductKey: update.ProductKey,
|
||||
InstallAction: update.InstallAction,
|
||||
})
|
||||
}
|
||||
payload.Command.ScheduleOsUpdate = &commandproto.ScheduleOSUpdate{
|
||||
Updates: updates,
|
||||
}
|
||||
case "AccountConfiguration":
|
||||
p := e.Payload.Command.AccountConfiguration
|
||||
payload.Command.AccountConfiguration = &commandproto.AccountConfiguration{
|
||||
SkipPrimarySetupAccountCreation: p.SkipPrimarySetupAccountCreation,
|
||||
SetPrimarySetupAccountAsRegularUser: p.SetPrimarySetupAccountAsRegularUser,
|
||||
}
|
||||
for _, account := range p.AutoSetupAdminAccounts {
|
||||
payload.Command.AccountConfiguration.AutoSetupAdminAccounts = append(
|
||||
payload.Command.AccountConfiguration.AutoSetupAdminAccounts, &commandproto.AutoSetupAdminAccounts{
|
||||
ShortName: account.ShortName,
|
||||
FullName: account.FullName,
|
||||
PasswordHash: account.PasswordHash,
|
||||
Hidden: account.Hidden,
|
||||
})
|
||||
}
|
||||
case "DeviceInformation":
|
||||
payload.Command.DeviceInformation = &commandproto.DeviceInformation{
|
||||
Queries: e.Payload.Command.DeviceInformation.Queries,
|
||||
}
|
||||
case "InstallProfile":
|
||||
payload.Command.InstallProfile = &commandproto.InstallProfile{
|
||||
Payload: e.Payload.Command.InstallProfile.Payload,
|
||||
}
|
||||
case "RemoveProfile":
|
||||
payload.Command.RemoveProfile = &commandproto.RemoveProfile{
|
||||
Identifier: e.Payload.Command.RemoveProfile.Identifier,
|
||||
}
|
||||
case "InstallApplication":
|
||||
cmd := e.Payload.Command.InstallApplication
|
||||
payload.Command.InstallApplication = &commandproto.InstallApplication{
|
||||
ItunesStoreId: int64(cmd.ITunesStoreID),
|
||||
Identifier: cmd.Identifier,
|
||||
ManifestUrl: cmd.ManifestURL,
|
||||
ManagementFlags: int64(cmd.ManagementFlags),
|
||||
NotManaged: cmd.NotManaged,
|
||||
ChangeManagementState: cmd.ChangeManagementState,
|
||||
}
|
||||
case "Settings":
|
||||
cmd := e.Payload.Command.Settings
|
||||
var settings []*commandproto.Setting
|
||||
for _, s := range cmd.Settings {
|
||||
protoSetting := &commandproto.Setting{
|
||||
Item: s.Item,
|
||||
}
|
||||
if s.DeviceName != nil {
|
||||
protoSetting.DeviceName = &commandproto.DeviceNameSetting{
|
||||
DeviceName: *s.DeviceName,
|
||||
}
|
||||
}
|
||||
|
||||
if s.HostName != nil {
|
||||
protoSetting.Hostname = &commandproto.HostnameSetting{
|
||||
Hostname: *s.HostName,
|
||||
}
|
||||
}
|
||||
settings = append(settings, protoSetting)
|
||||
}
|
||||
payload.Command.Settings = &commandproto.Settings{Settings: settings}
|
||||
}
|
||||
return proto.Marshal(&commandproto.Event{
|
||||
Id: e.ID,
|
||||
Time: e.Time.UnixNano(),
|
||||
Payload: payload,
|
||||
DeviceUdid: e.DeviceUDID,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// UnmarshalEvent parses a protocol buffer representation of data into
|
||||
// the Event.
|
||||
func UnmarshalEvent(data []byte, e *Event) error {
|
||||
var pb commandproto.Event
|
||||
if err := proto.Unmarshal(data, &pb); err != nil {
|
||||
return errors.Wrap(err, "unmarshal pb Event")
|
||||
}
|
||||
e.ID = pb.Id
|
||||
e.DeviceUDID = pb.DeviceUdid
|
||||
e.Time = time.Unix(0, pb.Time).UTC()
|
||||
if pb.Payload == nil {
|
||||
return nil
|
||||
}
|
||||
e.Payload = mdm.Payload{
|
||||
CommandUUID: pb.Payload.CommandUuid,
|
||||
}
|
||||
if pb.Payload.Command == nil {
|
||||
return nil
|
||||
}
|
||||
e.Payload.Command = &mdm.Command{
|
||||
RequestType: pb.Payload.Command.RequestType,
|
||||
}
|
||||
switch pb.Payload.Command.RequestType {
|
||||
case "DeviceLock":
|
||||
cmd := pb.Payload.Command.GetDeviceLock()
|
||||
e.Payload.Command.DeviceLock = mdm.DeviceLock{
|
||||
PIN: cmd.GetPin(),
|
||||
Message: cmd.GetMessage(),
|
||||
PhoneNumber: cmd.GetPhoneNumber(),
|
||||
}
|
||||
case "EraseDevice":
|
||||
cmd := pb.Payload.Command.GetEraseDevice()
|
||||
e.Payload.Command.EraseDevice = mdm.EraseDevice{
|
||||
PIN: cmd.GetPin(),
|
||||
}
|
||||
case "DeleteUser":
|
||||
cmd := pb.Payload.Command.GetDeleteUser()
|
||||
e.Payload.Command.DeleteUser = mdm.DeleteUser{
|
||||
UserName: cmd.GetUsername(),
|
||||
ForceDeletion: cmd.GetForceDeletion(),
|
||||
}
|
||||
case "ScheduleOSUpdateScan":
|
||||
cmd := pb.Payload.Command.GetScheduleOsUpdateScan()
|
||||
e.Payload.Command.ScheduleOSUpdateScan = mdm.ScheduleOSUpdateScan{
|
||||
Force: cmd.GetForce(),
|
||||
}
|
||||
case "ScheduleOSUpdate":
|
||||
cmd := pb.Payload.Command.GetScheduleOsUpdate()
|
||||
var updates []mdm.OSUpdate
|
||||
for _, update := range cmd.GetUpdates() {
|
||||
updates = append(updates, mdm.OSUpdate{
|
||||
ProductKey: update.GetProductKey(),
|
||||
InstallAction: update.GetInstallAction(),
|
||||
})
|
||||
}
|
||||
e.Payload.Command.ScheduleOSUpdate = mdm.ScheduleOSUpdate{
|
||||
Updates: updates,
|
||||
}
|
||||
case "AccountConfiguration":
|
||||
cmd := pb.Payload.Command.GetAccountConfiguration()
|
||||
e.Payload.Command.AccountConfiguration = mdm.AccountConfiguration{
|
||||
SkipPrimarySetupAccountCreation: cmd.GetSkipPrimarySetupAccountCreation(),
|
||||
SetPrimarySetupAccountAsRegularUser: cmd.GetSetPrimarySetupAccountAsRegularUser(),
|
||||
}
|
||||
for _, account := range cmd.GetAutoSetupAdminAccounts() {
|
||||
e.Payload.Command.AccountConfiguration.AutoSetupAdminAccounts = append(e.Payload.Command.AutoSetupAdminAccounts, mdm.AdminAccount{
|
||||
ShortName: account.GetShortName(),
|
||||
FullName: account.GetFullName(),
|
||||
PasswordHash: account.GetPasswordHash(),
|
||||
Hidden: account.GetHidden(),
|
||||
})
|
||||
}
|
||||
case "DeviceInformation":
|
||||
e.Payload.Command.DeviceInformation = mdm.DeviceInformation{
|
||||
Queries: pb.Payload.Command.DeviceInformation.Queries,
|
||||
}
|
||||
case "InstallProfile":
|
||||
e.Payload.Command.InstallProfile = mdm.InstallProfile{
|
||||
Payload: pb.Payload.Command.InstallProfile.Payload,
|
||||
}
|
||||
case "RemoveProfile":
|
||||
e.Payload.Command.RemoveProfile = mdm.RemoveProfile{
|
||||
Identifier: pb.Payload.Command.RemoveProfile.Identifier,
|
||||
}
|
||||
case "InstallApplication":
|
||||
cmd := pb.Payload.Command.GetInstallApplication()
|
||||
e.Payload.Command.InstallApplication = mdm.InstallApplication{
|
||||
ITunesStoreID: int(cmd.GetItunesStoreId()),
|
||||
Identifier: cmd.GetIdentifier(),
|
||||
ManifestURL: cmd.GetManifestUrl(),
|
||||
ManagementFlags: int(cmd.GetManagementFlags()),
|
||||
ChangeManagementState: cmd.GetChangeManagementState(),
|
||||
}
|
||||
case "Settings":
|
||||
cmd := pb.Payload.Command.GetSettings()
|
||||
var settings []mdm.Setting
|
||||
for _, s := range cmd.GetSettings() {
|
||||
mdmSetting := mdm.Setting{
|
||||
Item: s.GetItem(),
|
||||
}
|
||||
|
||||
if s.GetDeviceName() != nil {
|
||||
mdmSetting.DeviceName = stringPtr(s.GetDeviceName().GetDeviceName())
|
||||
}
|
||||
|
||||
if s.GetHostname() != nil {
|
||||
mdmSetting.HostName = stringPtr(s.GetHostname().GetHostname())
|
||||
}
|
||||
|
||||
settings = append(settings, mdmSetting)
|
||||
}
|
||||
e.Payload.Command.Settings = mdm.Settings{Settings: settings}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
83
platform/command/event_test.go
Normal file
83
platform/command/event_test.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package command_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/groob/plist"
|
||||
"github.com/micromdm/mdm"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/command"
|
||||
)
|
||||
|
||||
var marshalTests = []string{
|
||||
"DeviceInformation",
|
||||
"DeviceInformation_empty_queries",
|
||||
"InstallProfile",
|
||||
"Settings_hostname_devicename",
|
||||
}
|
||||
|
||||
func TestMarshalEvent(t *testing.T) {
|
||||
for _, tt := range marshalTests {
|
||||
name := tt
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
v := command.NewEvent(mustLoadPayload(t, name), name)
|
||||
var other command.Event
|
||||
if buf, err := command.MarshalEvent(v); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if err := command.UnmarshalEvent(buf, &other); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(v, &other) {
|
||||
t.Logf("\nwant: %#v\n, \nhave: %#v\n", v.Payload.Command, other.Payload.Command)
|
||||
t.Fatalf("\nwant: %#v\n \nhave: %#v\n", v, other)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalProto(b *testing.B) {
|
||||
for _, tt := range marshalTests {
|
||||
v := command.NewEvent(mustLoadPayload(&testing.T{}, tt), tt)
|
||||
for n := 0; n < b.N; n++ {
|
||||
var other command.Event
|
||||
if buf, err := command.MarshalEvent(v); err != nil {
|
||||
b.Fatal(err)
|
||||
} else if err := command.UnmarshalEvent(buf, &other); err != nil {
|
||||
b.Fatal(err)
|
||||
} else if !reflect.DeepEqual(v, &other) {
|
||||
b.Fatalf("\nwant: %#v\n \nhave: %#v\n", v, other)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMarshalJSON(b *testing.B) {
|
||||
for _, tt := range marshalTests {
|
||||
v := command.NewEvent(mustLoadPayload(&testing.T{}, tt), tt)
|
||||
for n := 0; n < b.N; n++ {
|
||||
var other command.Event
|
||||
if buf, err := json.Marshal(&v); err != nil {
|
||||
b.Fatal(err)
|
||||
} else if err := json.Unmarshal(buf, &other); err != nil {
|
||||
b.Fatal(err)
|
||||
} else if !reflect.DeepEqual(v, &other) {
|
||||
b.Fatalf("\nwant: %#v\n \nhave: %#v\n", v, other)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustLoadPayload(t *testing.T, name string) mdm.Payload {
|
||||
var payload mdm.Payload
|
||||
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
|
||||
}
|
||||
3
platform/command/internal/commandproto/command.go
Normal file
3
platform/command/internal/commandproto/command.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package commandproto
|
||||
|
||||
//go:generate protoc --go_out=. command.proto
|
||||
706
platform/command/internal/commandproto/command.pb.go
Normal file
706
platform/command/internal/commandproto/command.pb.go
Normal file
@@ -0,0 +1,706 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: command.proto
|
||||
|
||||
/*
|
||||
Package commandproto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
command.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Event
|
||||
Payload
|
||||
Command
|
||||
ScheduleOSUpdate
|
||||
OSUpdate
|
||||
ScheduleOSUpdateScan
|
||||
AccountConfiguration
|
||||
AutoSetupAdminAccounts
|
||||
DeviceInformation
|
||||
InstallProfile
|
||||
RemoveProfile
|
||||
DeleteUser
|
||||
InstallApplication
|
||||
EraseDevice
|
||||
DeviceLock
|
||||
Settings
|
||||
Setting
|
||||
DeviceNameSetting
|
||||
HostnameSetting
|
||||
*/
|
||||
package commandproto
|
||||
|
||||
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"`
|
||||
Payload *Payload `protobuf:"bytes,3,opt,name=payload" json:"payload,omitempty"`
|
||||
DeviceUdid string `protobuf:"bytes,4,opt,name=device_udid,json=deviceUdid" json:"device_udid,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) GetPayload() *Payload {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Event) GetDeviceUdid() string {
|
||||
if m != nil {
|
||||
return m.DeviceUdid
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Payload struct {
|
||||
CommandUuid string `protobuf:"bytes,1,opt,name=command_uuid,json=commandUuid" json:"command_uuid,omitempty"`
|
||||
Command *Command `protobuf:"bytes,2,opt,name=command" json:"command,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Payload) Reset() { *m = Payload{} }
|
||||
func (m *Payload) String() string { return proto.CompactTextString(m) }
|
||||
func (*Payload) ProtoMessage() {}
|
||||
func (*Payload) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *Payload) GetCommandUuid() string {
|
||||
if m != nil {
|
||||
return m.CommandUuid
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Payload) GetCommand() *Command {
|
||||
if m != nil {
|
||||
return m.Command
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
RequestType string `protobuf:"bytes,1,opt,name=request_type,json=requestType" json:"request_type,omitempty"`
|
||||
DeviceInformation *DeviceInformation `protobuf:"bytes,2,opt,name=device_information,json=deviceInformation" json:"device_information,omitempty"`
|
||||
InstallProfile *InstallProfile `protobuf:"bytes,3,opt,name=install_profile,json=installProfile" json:"install_profile,omitempty"`
|
||||
InstallApplication *InstallApplication `protobuf:"bytes,4,opt,name=install_application,json=installApplication" json:"install_application,omitempty"`
|
||||
AccountConfiguration *AccountConfiguration `protobuf:"bytes,5,opt,name=account_configuration,json=accountConfiguration" json:"account_configuration,omitempty"`
|
||||
ScheduleOsUpdate *ScheduleOSUpdate `protobuf:"bytes,6,opt,name=schedule_os_update,json=scheduleOsUpdate" json:"schedule_os_update,omitempty"`
|
||||
ScheduleOsUpdateScan *ScheduleOSUpdateScan `protobuf:"bytes,7,opt,name=schedule_os_update_scan,json=scheduleOsUpdateScan" json:"schedule_os_update_scan,omitempty"`
|
||||
RemoveProfile *RemoveProfile `protobuf:"bytes,8,opt,name=remove_profile,json=removeProfile" json:"remove_profile,omitempty"`
|
||||
DeleteUser *DeleteUser `protobuf:"bytes,9,opt,name=delete_user,json=deleteUser" json:"delete_user,omitempty"`
|
||||
Settings *Settings `protobuf:"bytes,10,opt,name=settings" json:"settings,omitempty"`
|
||||
EraseDevice *EraseDevice `protobuf:"bytes,11,opt,name=erase_device,json=eraseDevice" json:"erase_device,omitempty"`
|
||||
DeviceLock *DeviceLock `protobuf:"bytes,12,opt,name=device_lock,json=deviceLock" json:"device_lock,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{2} }
|
||||
|
||||
func (m *Command) GetRequestType() string {
|
||||
if m != nil {
|
||||
return m.RequestType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Command) GetDeviceInformation() *DeviceInformation {
|
||||
if m != nil {
|
||||
return m.DeviceInformation
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetInstallProfile() *InstallProfile {
|
||||
if m != nil {
|
||||
return m.InstallProfile
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetInstallApplication() *InstallApplication {
|
||||
if m != nil {
|
||||
return m.InstallApplication
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetAccountConfiguration() *AccountConfiguration {
|
||||
if m != nil {
|
||||
return m.AccountConfiguration
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetScheduleOsUpdate() *ScheduleOSUpdate {
|
||||
if m != nil {
|
||||
return m.ScheduleOsUpdate
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetScheduleOsUpdateScan() *ScheduleOSUpdateScan {
|
||||
if m != nil {
|
||||
return m.ScheduleOsUpdateScan
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetRemoveProfile() *RemoveProfile {
|
||||
if m != nil {
|
||||
return m.RemoveProfile
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetDeleteUser() *DeleteUser {
|
||||
if m != nil {
|
||||
return m.DeleteUser
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetSettings() *Settings {
|
||||
if m != nil {
|
||||
return m.Settings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetEraseDevice() *EraseDevice {
|
||||
if m != nil {
|
||||
return m.EraseDevice
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Command) GetDeviceLock() *DeviceLock {
|
||||
if m != nil {
|
||||
return m.DeviceLock
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ScheduleOSUpdate struct {
|
||||
Updates []*OSUpdate `protobuf:"bytes,1,rep,name=updates" json:"updates,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ScheduleOSUpdate) Reset() { *m = ScheduleOSUpdate{} }
|
||||
func (m *ScheduleOSUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*ScheduleOSUpdate) ProtoMessage() {}
|
||||
func (*ScheduleOSUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func (m *ScheduleOSUpdate) GetUpdates() []*OSUpdate {
|
||||
if m != nil {
|
||||
return m.Updates
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type OSUpdate struct {
|
||||
ProductKey string `protobuf:"bytes,1,opt,name=product_key,json=productKey" json:"product_key,omitempty"`
|
||||
InstallAction string `protobuf:"bytes,2,opt,name=install_action,json=installAction" json:"install_action,omitempty"`
|
||||
}
|
||||
|
||||
func (m *OSUpdate) Reset() { *m = OSUpdate{} }
|
||||
func (m *OSUpdate) String() string { return proto.CompactTextString(m) }
|
||||
func (*OSUpdate) ProtoMessage() {}
|
||||
func (*OSUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
|
||||
func (m *OSUpdate) GetProductKey() string {
|
||||
if m != nil {
|
||||
return m.ProductKey
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *OSUpdate) GetInstallAction() string {
|
||||
if m != nil {
|
||||
return m.InstallAction
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ScheduleOSUpdateScan struct {
|
||||
Force bool `protobuf:"varint,1,opt,name=force" json:"force,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ScheduleOSUpdateScan) Reset() { *m = ScheduleOSUpdateScan{} }
|
||||
func (m *ScheduleOSUpdateScan) String() string { return proto.CompactTextString(m) }
|
||||
func (*ScheduleOSUpdateScan) ProtoMessage() {}
|
||||
func (*ScheduleOSUpdateScan) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||
|
||||
func (m *ScheduleOSUpdateScan) GetForce() bool {
|
||||
if m != nil {
|
||||
return m.Force
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type AccountConfiguration struct {
|
||||
SkipPrimarySetupAccountCreation bool `protobuf:"varint,1,opt,name=skip_primary_setup_account_creation,json=skipPrimarySetupAccountCreation" json:"skip_primary_setup_account_creation,omitempty"`
|
||||
SetPrimarySetupAccountAsRegularUser bool `protobuf:"varint,2,opt,name=set_primary_setup_account_as_regular_user,json=setPrimarySetupAccountAsRegularUser" json:"set_primary_setup_account_as_regular_user,omitempty"`
|
||||
AutoSetupAdminAccounts []*AutoSetupAdminAccounts `protobuf:"bytes,3,rep,name=auto_setup_admin_accounts,json=autoSetupAdminAccounts" json:"auto_setup_admin_accounts,omitempty"`
|
||||
}
|
||||
|
||||
func (m *AccountConfiguration) Reset() { *m = AccountConfiguration{} }
|
||||
func (m *AccountConfiguration) String() string { return proto.CompactTextString(m) }
|
||||
func (*AccountConfiguration) ProtoMessage() {}
|
||||
func (*AccountConfiguration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
||||
|
||||
func (m *AccountConfiguration) GetSkipPrimarySetupAccountCreation() bool {
|
||||
if m != nil {
|
||||
return m.SkipPrimarySetupAccountCreation
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *AccountConfiguration) GetSetPrimarySetupAccountAsRegularUser() bool {
|
||||
if m != nil {
|
||||
return m.SetPrimarySetupAccountAsRegularUser
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *AccountConfiguration) GetAutoSetupAdminAccounts() []*AutoSetupAdminAccounts {
|
||||
if m != nil {
|
||||
return m.AutoSetupAdminAccounts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AutoSetupAdminAccounts struct {
|
||||
ShortName string `protobuf:"bytes,1,opt,name=short_name,json=shortName" json:"short_name,omitempty"`
|
||||
FullName string `protobuf:"bytes,2,opt,name=full_name,json=fullName" json:"full_name,omitempty"`
|
||||
PasswordHash []byte `protobuf:"bytes,3,opt,name=password_hash,json=passwordHash,proto3" json:"password_hash,omitempty"`
|
||||
Hidden bool `protobuf:"varint,4,opt,name=hidden" json:"hidden,omitempty"`
|
||||
}
|
||||
|
||||
func (m *AutoSetupAdminAccounts) Reset() { *m = AutoSetupAdminAccounts{} }
|
||||
func (m *AutoSetupAdminAccounts) String() string { return proto.CompactTextString(m) }
|
||||
func (*AutoSetupAdminAccounts) ProtoMessage() {}
|
||||
func (*AutoSetupAdminAccounts) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
||||
|
||||
func (m *AutoSetupAdminAccounts) GetShortName() string {
|
||||
if m != nil {
|
||||
return m.ShortName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *AutoSetupAdminAccounts) GetFullName() string {
|
||||
if m != nil {
|
||||
return m.FullName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *AutoSetupAdminAccounts) GetPasswordHash() []byte {
|
||||
if m != nil {
|
||||
return m.PasswordHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AutoSetupAdminAccounts) GetHidden() bool {
|
||||
if m != nil {
|
||||
return m.Hidden
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type DeviceInformation struct {
|
||||
Queries []string `protobuf:"bytes,1,rep,name=queries" json:"queries,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DeviceInformation) Reset() { *m = DeviceInformation{} }
|
||||
func (m *DeviceInformation) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeviceInformation) ProtoMessage() {}
|
||||
func (*DeviceInformation) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
|
||||
|
||||
func (m *DeviceInformation) GetQueries() []string {
|
||||
if m != nil {
|
||||
return m.Queries
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type InstallProfile struct {
|
||||
Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
|
||||
}
|
||||
|
||||
func (m *InstallProfile) Reset() { *m = InstallProfile{} }
|
||||
func (m *InstallProfile) String() string { return proto.CompactTextString(m) }
|
||||
func (*InstallProfile) ProtoMessage() {}
|
||||
func (*InstallProfile) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
|
||||
|
||||
func (m *InstallProfile) GetPayload() []byte {
|
||||
if m != nil {
|
||||
return m.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RemoveProfile struct {
|
||||
Identifier string `protobuf:"bytes,1,opt,name=identifier" json:"identifier,omitempty"`
|
||||
}
|
||||
|
||||
func (m *RemoveProfile) Reset() { *m = RemoveProfile{} }
|
||||
func (m *RemoveProfile) String() string { return proto.CompactTextString(m) }
|
||||
func (*RemoveProfile) ProtoMessage() {}
|
||||
func (*RemoveProfile) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
|
||||
|
||||
func (m *RemoveProfile) GetIdentifier() string {
|
||||
if m != nil {
|
||||
return m.Identifier
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type DeleteUser struct {
|
||||
Username string `protobuf:"bytes,1,opt,name=username" json:"username,omitempty"`
|
||||
ForceDeletion bool `protobuf:"varint,2,opt,name=force_deletion,json=forceDeletion" json:"force_deletion,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DeleteUser) Reset() { *m = DeleteUser{} }
|
||||
func (m *DeleteUser) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeleteUser) ProtoMessage() {}
|
||||
func (*DeleteUser) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
|
||||
|
||||
func (m *DeleteUser) GetUsername() string {
|
||||
if m != nil {
|
||||
return m.Username
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *DeleteUser) GetForceDeletion() bool {
|
||||
if m != nil {
|
||||
return m.ForceDeletion
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type InstallApplication struct {
|
||||
ItunesStoreId int64 `protobuf:"varint,1,opt,name=itunes_store_id,json=itunesStoreId" json:"itunes_store_id,omitempty"`
|
||||
Identifier string `protobuf:"bytes,2,opt,name=identifier" json:"identifier,omitempty"`
|
||||
ManifestUrl string `protobuf:"bytes,3,opt,name=manifest_url,json=manifestUrl" json:"manifest_url,omitempty"`
|
||||
ManagementFlags int64 `protobuf:"varint,4,opt,name=management_flags,json=managementFlags" json:"management_flags,omitempty"`
|
||||
NotManaged bool `protobuf:"varint,5,opt,name=not_managed,json=notManaged" json:"not_managed,omitempty"`
|
||||
ChangeManagementState string `protobuf:"bytes,6,opt,name=change_management_state,json=changeManagementState" json:"change_management_state,omitempty"`
|
||||
}
|
||||
|
||||
func (m *InstallApplication) Reset() { *m = InstallApplication{} }
|
||||
func (m *InstallApplication) String() string { return proto.CompactTextString(m) }
|
||||
func (*InstallApplication) ProtoMessage() {}
|
||||
func (*InstallApplication) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
|
||||
|
||||
func (m *InstallApplication) GetItunesStoreId() int64 {
|
||||
if m != nil {
|
||||
return m.ItunesStoreId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *InstallApplication) GetIdentifier() string {
|
||||
if m != nil {
|
||||
return m.Identifier
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *InstallApplication) GetManifestUrl() string {
|
||||
if m != nil {
|
||||
return m.ManifestUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *InstallApplication) GetManagementFlags() int64 {
|
||||
if m != nil {
|
||||
return m.ManagementFlags
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *InstallApplication) GetNotManaged() bool {
|
||||
if m != nil {
|
||||
return m.NotManaged
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *InstallApplication) GetChangeManagementState() string {
|
||||
if m != nil {
|
||||
return m.ChangeManagementState
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EraseDevice struct {
|
||||
Pin string `protobuf:"bytes,1,opt,name=pin" json:"pin,omitempty"`
|
||||
PreserveDataPlan bool `protobuf:"varint,2,opt,name=preserve_data_plan,json=preserveDataPlan" json:"preserve_data_plan,omitempty"`
|
||||
}
|
||||
|
||||
func (m *EraseDevice) Reset() { *m = EraseDevice{} }
|
||||
func (m *EraseDevice) String() string { return proto.CompactTextString(m) }
|
||||
func (*EraseDevice) ProtoMessage() {}
|
||||
func (*EraseDevice) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
|
||||
|
||||
func (m *EraseDevice) GetPin() string {
|
||||
if m != nil {
|
||||
return m.Pin
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *EraseDevice) GetPreserveDataPlan() bool {
|
||||
if m != nil {
|
||||
return m.PreserveDataPlan
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type DeviceLock struct {
|
||||
Pin string `protobuf:"bytes,1,opt,name=pin" json:"pin,omitempty"`
|
||||
Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
|
||||
PhoneNumber string `protobuf:"bytes,3,opt,name=phone_number,json=phoneNumber" json:"phone_number,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DeviceLock) Reset() { *m = DeviceLock{} }
|
||||
func (m *DeviceLock) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeviceLock) ProtoMessage() {}
|
||||
func (*DeviceLock) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
|
||||
|
||||
func (m *DeviceLock) GetPin() string {
|
||||
if m != nil {
|
||||
return m.Pin
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *DeviceLock) GetMessage() string {
|
||||
if m != nil {
|
||||
return m.Message
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *DeviceLock) GetPhoneNumber() string {
|
||||
if m != nil {
|
||||
return m.PhoneNumber
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Settings struct {
|
||||
Settings []*Setting `protobuf:"bytes,1,rep,name=settings" json:"settings,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Settings) Reset() { *m = Settings{} }
|
||||
func (m *Settings) String() string { return proto.CompactTextString(m) }
|
||||
func (*Settings) ProtoMessage() {}
|
||||
func (*Settings) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
|
||||
|
||||
func (m *Settings) GetSettings() []*Setting {
|
||||
if m != nil {
|
||||
return m.Settings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Setting struct {
|
||||
Item string `protobuf:"bytes,1,opt,name=item" json:"item,omitempty"`
|
||||
DeviceName *DeviceNameSetting `protobuf:"bytes,2,opt,name=device_name,json=deviceName" json:"device_name,omitempty"`
|
||||
Hostname *HostnameSetting `protobuf:"bytes,3,opt,name=hostname" json:"hostname,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Setting) Reset() { *m = Setting{} }
|
||||
func (m *Setting) String() string { return proto.CompactTextString(m) }
|
||||
func (*Setting) ProtoMessage() {}
|
||||
func (*Setting) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
|
||||
|
||||
func (m *Setting) GetItem() string {
|
||||
if m != nil {
|
||||
return m.Item
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Setting) GetDeviceName() *DeviceNameSetting {
|
||||
if m != nil {
|
||||
return m.DeviceName
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Setting) GetHostname() *HostnameSetting {
|
||||
if m != nil {
|
||||
return m.Hostname
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceNameSetting struct {
|
||||
DeviceName string `protobuf:"bytes,1,opt,name=device_name,json=deviceName" json:"device_name,omitempty"`
|
||||
}
|
||||
|
||||
func (m *DeviceNameSetting) Reset() { *m = DeviceNameSetting{} }
|
||||
func (m *DeviceNameSetting) String() string { return proto.CompactTextString(m) }
|
||||
func (*DeviceNameSetting) ProtoMessage() {}
|
||||
func (*DeviceNameSetting) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
|
||||
|
||||
func (m *DeviceNameSetting) GetDeviceName() string {
|
||||
if m != nil {
|
||||
return m.DeviceName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type HostnameSetting struct {
|
||||
Hostname string `protobuf:"bytes,1,opt,name=hostname" json:"hostname,omitempty"`
|
||||
}
|
||||
|
||||
func (m *HostnameSetting) Reset() { *m = HostnameSetting{} }
|
||||
func (m *HostnameSetting) String() string { return proto.CompactTextString(m) }
|
||||
func (*HostnameSetting) ProtoMessage() {}
|
||||
func (*HostnameSetting) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
|
||||
|
||||
func (m *HostnameSetting) GetHostname() string {
|
||||
if m != nil {
|
||||
return m.Hostname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Event)(nil), "commandproto.Event")
|
||||
proto.RegisterType((*Payload)(nil), "commandproto.Payload")
|
||||
proto.RegisterType((*Command)(nil), "commandproto.Command")
|
||||
proto.RegisterType((*ScheduleOSUpdate)(nil), "commandproto.ScheduleOSUpdate")
|
||||
proto.RegisterType((*OSUpdate)(nil), "commandproto.OSUpdate")
|
||||
proto.RegisterType((*ScheduleOSUpdateScan)(nil), "commandproto.ScheduleOSUpdateScan")
|
||||
proto.RegisterType((*AccountConfiguration)(nil), "commandproto.AccountConfiguration")
|
||||
proto.RegisterType((*AutoSetupAdminAccounts)(nil), "commandproto.AutoSetupAdminAccounts")
|
||||
proto.RegisterType((*DeviceInformation)(nil), "commandproto.DeviceInformation")
|
||||
proto.RegisterType((*InstallProfile)(nil), "commandproto.InstallProfile")
|
||||
proto.RegisterType((*RemoveProfile)(nil), "commandproto.RemoveProfile")
|
||||
proto.RegisterType((*DeleteUser)(nil), "commandproto.DeleteUser")
|
||||
proto.RegisterType((*InstallApplication)(nil), "commandproto.InstallApplication")
|
||||
proto.RegisterType((*EraseDevice)(nil), "commandproto.EraseDevice")
|
||||
proto.RegisterType((*DeviceLock)(nil), "commandproto.DeviceLock")
|
||||
proto.RegisterType((*Settings)(nil), "commandproto.Settings")
|
||||
proto.RegisterType((*Setting)(nil), "commandproto.Setting")
|
||||
proto.RegisterType((*DeviceNameSetting)(nil), "commandproto.DeviceNameSetting")
|
||||
proto.RegisterType((*HostnameSetting)(nil), "commandproto.HostnameSetting")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("command.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 1139 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x56, 0x5b, 0x6f, 0x1c, 0x35,
|
||||
0x14, 0xd6, 0xee, 0xb6, 0xd9, 0xdd, 0xb3, 0xd9, 0x24, 0x35, 0x49, 0x3a, 0xa5, 0xb4, 0x09, 0x53,
|
||||
0x40, 0x2d, 0xea, 0x05, 0x0a, 0x42, 0xaa, 0x04, 0x12, 0xa1, 0x29, 0x6a, 0x45, 0xdb, 0x04, 0x87,
|
||||
0x80, 0x10, 0x42, 0x96, 0x3b, 0xe3, 0xdd, 0xb5, 0x32, 0x63, 0x4f, 0x6d, 0x4f, 0xd0, 0x3e, 0xf0,
|
||||
0xc4, 0x2f, 0xe0, 0x15, 0x89, 0x7f, 0xc3, 0x0f, 0x43, 0xbe, 0xcd, 0x5e, 0xfb, 0xe6, 0xf3, 0xf9,
|
||||
0x3b, 0x9f, 0xcf, 0xf8, 0x5c, 0x3c, 0x30, 0xcc, 0x64, 0x59, 0x52, 0x91, 0x3f, 0xac, 0x94, 0x34,
|
||||
0x12, 0x6d, 0x06, 0xd3, 0x59, 0xe9, 0x9f, 0x70, 0xf5, 0xd9, 0x25, 0x13, 0x06, 0x6d, 0x41, 0x9b,
|
||||
0xe7, 0x49, 0xeb, 0xb0, 0x75, 0xb7, 0x8f, 0xdb, 0x3c, 0x47, 0x08, 0xae, 0x18, 0x5e, 0xb2, 0xa4,
|
||||
0x7d, 0xd8, 0xba, 0xdb, 0xc1, 0x6e, 0x8d, 0x1e, 0x41, 0xb7, 0xa2, 0xd3, 0x42, 0xd2, 0x3c, 0xe9,
|
||||
0x1c, 0xb6, 0xee, 0x0e, 0x1e, 0xef, 0x3d, 0x9c, 0x17, 0x7b, 0x78, 0xea, 0x37, 0x71, 0x64, 0xa1,
|
||||
0x03, 0x18, 0xe4, 0xec, 0x92, 0x67, 0x8c, 0xd4, 0x39, 0xcf, 0x93, 0x2b, 0x4e, 0x1d, 0x3c, 0x74,
|
||||
0x9e, 0xf3, 0x3c, 0xfd, 0x1d, 0xba, 0xc1, 0x09, 0x7d, 0x08, 0x31, 0x32, 0x52, 0xd7, 0x4d, 0x28,
|
||||
0x83, 0x80, 0x9d, 0xd7, 0x3c, 0xb7, 0xe7, 0x07, 0xd3, 0x85, 0xb5, 0x72, 0xfe, 0x53, 0x6f, 0xe0,
|
||||
0xc8, 0x4a, 0xff, 0xdb, 0x80, 0x6e, 0x00, 0xad, 0xbe, 0x62, 0x6f, 0x6b, 0xa6, 0x0d, 0x31, 0xd3,
|
||||
0x8a, 0x45, 0xfd, 0x80, 0xfd, 0x34, 0xad, 0x18, 0x7a, 0x0d, 0x28, 0x84, 0xcb, 0xc5, 0x48, 0xaa,
|
||||
0x92, 0x1a, 0x2e, 0x45, 0x38, 0xea, 0x60, 0xf1, 0xa8, 0x63, 0xc7, 0x7b, 0x31, 0xa3, 0xe1, 0x6b,
|
||||
0xf9, 0x32, 0x84, 0x9e, 0xc1, 0x36, 0x17, 0xda, 0xd0, 0xa2, 0x20, 0x95, 0x92, 0x23, 0x5e, 0xb0,
|
||||
0x70, 0x6f, 0x1f, 0x2c, 0x8a, 0xbd, 0xf0, 0xa4, 0x53, 0xcf, 0xc1, 0x5b, 0x7c, 0xc1, 0x46, 0x3f,
|
||||
0xc2, 0x7b, 0x51, 0x86, 0x56, 0x55, 0xc1, 0x33, 0x1f, 0xd7, 0x15, 0x27, 0x75, 0xb8, 0x56, 0xea,
|
||||
0x68, 0xc6, 0xc3, 0x88, 0xaf, 0x60, 0xe8, 0x17, 0xd8, 0xa3, 0x59, 0x26, 0x6b, 0x61, 0x48, 0x26,
|
||||
0xc5, 0x88, 0x8f, 0x6b, 0xe5, 0x45, 0xaf, 0x3a, 0xd1, 0x74, 0x51, 0xf4, 0xc8, 0x53, 0x9f, 0xce,
|
||||
0x33, 0xf1, 0x2e, 0x5d, 0x83, 0xa2, 0x97, 0x80, 0x74, 0x36, 0x61, 0x79, 0x5d, 0x30, 0x22, 0x35,
|
||||
0xa9, 0xab, 0x9c, 0x1a, 0x96, 0x6c, 0x38, 0xd5, 0xdb, 0x8b, 0xaa, 0x67, 0x81, 0x77, 0x72, 0x76,
|
||||
0xee, 0x58, 0x78, 0x27, 0x7a, 0x9e, 0x68, 0x8f, 0xa0, 0x5f, 0xe1, 0xfa, 0xaa, 0x1a, 0xd1, 0x19,
|
||||
0x15, 0x49, 0x77, 0x5d, 0xa0, 0xcb, 0x92, 0x67, 0x19, 0x15, 0x78, 0x77, 0x59, 0xd6, 0xa2, 0xe8,
|
||||
0x3b, 0xd8, 0x52, 0xac, 0x94, 0x97, 0xac, 0x49, 0x4d, 0xcf, 0x29, 0xde, 0x5c, 0x54, 0xc4, 0x8e,
|
||||
0x13, 0x33, 0x33, 0x54, 0xf3, 0x26, 0x7a, 0x62, 0xcb, 0xbb, 0x60, 0x86, 0x91, 0x5a, 0x33, 0x95,
|
||||
0xf4, 0x9d, 0x40, 0xb2, 0x5c, 0x28, 0x96, 0x70, 0xae, 0x99, 0xb2, 0x85, 0x1f, 0xd7, 0xe8, 0x31,
|
||||
0xf4, 0x34, 0x33, 0x86, 0x8b, 0xb1, 0x4e, 0xc0, 0xf9, 0xed, 0x2f, 0x7d, 0x4a, 0xd8, 0xc5, 0x0d,
|
||||
0x0f, 0x7d, 0x0d, 0x9b, 0x4c, 0x51, 0xcd, 0x88, 0xaf, 0xb4, 0x64, 0xe0, 0xfc, 0x6e, 0x2c, 0xfa,
|
||||
0x3d, 0xb3, 0x0c, 0x5f, 0x9d, 0x78, 0xc0, 0x66, 0x86, 0x0f, 0xd6, 0x15, 0x77, 0x21, 0xb3, 0x8b,
|
||||
0x64, 0x73, 0x7d, 0xb0, 0x96, 0xf0, 0x52, 0x66, 0x17, 0xb1, 0x4b, 0xed, 0x3a, 0x3d, 0x86, 0x9d,
|
||||
0xe5, 0x9b, 0x45, 0x9f, 0x41, 0xd7, 0xa7, 0x43, 0x27, 0xad, 0xc3, 0xce, 0x6a, 0xfc, 0x4d, 0x56,
|
||||
0x23, 0x2d, 0xc5, 0xd0, 0x6b, 0xbc, 0x0f, 0x60, 0x50, 0x29, 0x99, 0xd7, 0x99, 0x21, 0x17, 0x6c,
|
||||
0x1a, 0x7a, 0x11, 0x02, 0xf4, 0x03, 0x9b, 0xa2, 0x8f, 0x61, 0xab, 0xa9, 0xf9, 0xac, 0x69, 0xc3,
|
||||
0x3e, 0x1e, 0xc6, 0x62, 0x76, 0x60, 0x7a, 0x1f, 0x76, 0xd7, 0xe5, 0x1c, 0xed, 0xc2, 0xd5, 0x91,
|
||||
0x54, 0x99, 0xef, 0xf2, 0x1e, 0xf6, 0x46, 0xfa, 0x6f, 0x1b, 0x76, 0x8f, 0xd6, 0x57, 0xed, 0x1d,
|
||||
0x7d, 0xc1, 0x2b, 0x52, 0x29, 0x5e, 0x52, 0x35, 0x25, 0x9a, 0x99, 0xba, 0x22, 0x4d, 0x87, 0x28,
|
||||
0xe6, 0x9b, 0xc3, 0x8b, 0x1d, 0x58, 0xea, 0xa9, 0x67, 0x9e, 0x59, 0x62, 0x94, 0x0c, 0x34, 0xf4,
|
||||
0x33, 0xdc, 0xd3, 0xcc, 0xbc, 0x43, 0x8c, 0x6a, 0xa2, 0xd8, 0xb8, 0x2e, 0xa8, 0xf2, 0x45, 0xd3,
|
||||
0x76, 0x9a, 0x77, 0x34, 0x33, 0x6b, 0x24, 0x8f, 0x34, 0xf6, 0x5c, 0x57, 0x33, 0x04, 0x6e, 0xd0,
|
||||
0xda, 0xc8, 0x28, 0x98, 0x97, 0x5c, 0x44, 0x59, 0x9d, 0x74, 0x5c, 0x12, 0x3e, 0x5a, 0x6a, 0xdc,
|
||||
0xda, 0x48, 0xaf, 0x67, 0xc9, 0x41, 0x54, 0xe3, 0x7d, 0xba, 0x16, 0x4f, 0xff, 0x6e, 0xc1, 0xfe,
|
||||
0x7a, 0x17, 0x74, 0x0b, 0x40, 0x4f, 0xa4, 0x32, 0x44, 0xd0, 0x32, 0xce, 0xce, 0xbe, 0x43, 0x5e,
|
||||
0xd3, 0x92, 0xa1, 0x9b, 0xd0, 0x1f, 0xd5, 0x45, 0xe1, 0x77, 0x7d, 0xa6, 0x7a, 0x16, 0x70, 0x9b,
|
||||
0x77, 0x60, 0x58, 0x51, 0xad, 0xff, 0x90, 0x2a, 0x27, 0x13, 0xaa, 0x27, 0x6e, 0x08, 0x6e, 0xe2,
|
||||
0xcd, 0x08, 0x3e, 0xa7, 0x7a, 0x82, 0xf6, 0x61, 0x63, 0xc2, 0xf3, 0x9c, 0xf9, 0xb9, 0xd6, 0xc3,
|
||||
0xc1, 0x4a, 0x1f, 0xc0, 0xb5, 0x95, 0x59, 0x8b, 0x12, 0xe8, 0xbe, 0xad, 0x99, 0xe2, 0xa1, 0xf8,
|
||||
0xfa, 0x38, 0x9a, 0xe9, 0xa7, 0xb0, 0xb5, 0x38, 0x4d, 0x2d, 0x37, 0x3e, 0x5a, 0x2d, 0x77, 0x6e,
|
||||
0x34, 0xd3, 0x47, 0x30, 0x5c, 0x68, 0x6f, 0x74, 0x1b, 0x80, 0xe7, 0x4c, 0x18, 0x3e, 0xe2, 0x4c,
|
||||
0xc5, 0xa2, 0x9c, 0x21, 0xe9, 0x09, 0xc0, 0xac, 0x9d, 0xd1, 0xfb, 0xd0, 0xb3, 0x19, 0x9c, 0xbb,
|
||||
0x90, 0xc6, 0xb6, 0xe5, 0xeb, 0x4a, 0x8e, 0xb8, 0x96, 0x8f, 0xe5, 0xdb, 0xc3, 0x43, 0x87, 0x1e,
|
||||
0x07, 0x30, 0xfd, 0xab, 0x0d, 0x68, 0x75, 0x62, 0xa3, 0x4f, 0x60, 0x9b, 0x9b, 0x5a, 0x30, 0x4d,
|
||||
0xb4, 0x91, 0x8a, 0x91, 0xf0, 0x1a, 0x76, 0xf0, 0xd0, 0xc3, 0x67, 0x16, 0x7d, 0x91, 0x2f, 0xc5,
|
||||
0xdb, 0x5e, 0x8e, 0xd7, 0x3e, 0x79, 0x25, 0x15, 0x7c, 0x64, 0xdf, 0xbc, 0x5a, 0x15, 0xee, 0xde,
|
||||
0xfb, 0x78, 0x10, 0xb1, 0x73, 0x55, 0xa0, 0x7b, 0xb0, 0x53, 0x52, 0x41, 0xc7, 0xac, 0x64, 0xc2,
|
||||
0x90, 0x51, 0x41, 0xc7, 0xda, 0x25, 0xa0, 0x83, 0xb7, 0x67, 0xf8, 0xf7, 0x16, 0xb6, 0x3d, 0x2b,
|
||||
0xa4, 0x21, 0x1e, 0xce, 0xdd, 0x4b, 0xd1, 0xc3, 0x20, 0xa4, 0x79, 0xe5, 0x11, 0xf4, 0x15, 0x5c,
|
||||
0xcf, 0x26, 0x54, 0x8c, 0x19, 0x99, 0x93, 0xd4, 0x26, 0x3e, 0x00, 0x7d, 0xbc, 0xe7, 0xb7, 0x5f,
|
||||
0x35, 0xbb, 0x67, 0x76, 0x33, 0x7d, 0x05, 0x83, 0xb9, 0xa9, 0x85, 0x76, 0xa0, 0x53, 0x71, 0x11,
|
||||
0xae, 0xd4, 0x2e, 0xd1, 0x7d, 0x40, 0x95, 0x62, 0x9a, 0xa9, 0x4b, 0x46, 0x72, 0x6a, 0x28, 0xa9,
|
||||
0x0a, 0x1a, 0x6f, 0x74, 0x27, 0xee, 0x1c, 0x53, 0x43, 0x4f, 0x0b, 0x2a, 0xd2, 0xdf, 0x6c, 0x96,
|
||||
0xe2, 0xec, 0x5a, 0xa3, 0x96, 0x40, 0xb7, 0x64, 0x5a, 0xd3, 0x71, 0xac, 0xd4, 0x68, 0xda, 0xfb,
|
||||
0xaa, 0x26, 0x52, 0x30, 0x22, 0xea, 0xf2, 0x0d, 0x53, 0xf1, 0xbe, 0x1c, 0xf6, 0xda, 0x41, 0xe9,
|
||||
0x37, 0xd0, 0x8b, 0x93, 0x19, 0x7d, 0x3e, 0x37, 0xc3, 0xfd, 0x0c, 0xdc, 0x5b, 0x3b, 0xc3, 0x67,
|
||||
0x23, 0x3c, 0xfd, 0xa7, 0x05, 0xdd, 0x80, 0xda, 0x3f, 0x2c, 0x6e, 0x58, 0x19, 0x42, 0x73, 0x6b,
|
||||
0xf4, 0x6d, 0x33, 0xa4, 0x9b, 0x4e, 0x7a, 0xc7, 0xaf, 0x87, 0xed, 0xac, 0xa8, 0x1f, 0x66, 0xb5,
|
||||
0x6b, 0xb6, 0x27, 0xd0, 0x9b, 0x48, 0x6d, 0x9c, 0xbb, 0xff, 0xd9, 0xb8, 0xb5, 0xe8, 0xfe, 0x3c,
|
||||
0xec, 0x36, 0xc1, 0x45, 0x7a, 0xfa, 0x65, 0x6c, 0xb5, 0x39, 0xed, 0xb9, 0x5f, 0xb8, 0xb9, 0x42,
|
||||
0x9f, 0x3b, 0x30, 0x7d, 0x00, 0xdb, 0x4b, 0x92, 0xb6, 0x33, 0x9a, 0x18, 0x42, 0x67, 0x44, 0xfb,
|
||||
0xcd, 0x86, 0x8b, 0xe2, 0x8b, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x4e, 0x4b, 0x47, 0x7e, 0x96,
|
||||
0x0a, 0x00, 0x00,
|
||||
}
|
||||
112
platform/command/internal/commandproto/command.proto
Normal file
112
platform/command/internal/commandproto/command.proto
Normal file
@@ -0,0 +1,112 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package commandproto;
|
||||
|
||||
message Event {
|
||||
string id = 1;
|
||||
int64 time = 2;
|
||||
Payload payload = 3;
|
||||
string device_udid = 4;
|
||||
}
|
||||
|
||||
message Payload {
|
||||
string command_uuid = 1;
|
||||
Command command = 2;
|
||||
}
|
||||
|
||||
message Command {
|
||||
string request_type = 1;
|
||||
DeviceInformation device_information = 2;
|
||||
InstallProfile install_profile = 3;
|
||||
InstallApplication install_application = 4;
|
||||
AccountConfiguration account_configuration = 5;
|
||||
ScheduleOSUpdate schedule_os_update = 6;
|
||||
ScheduleOSUpdateScan schedule_os_update_scan = 7;
|
||||
RemoveProfile remove_profile = 8;
|
||||
DeleteUser delete_user = 9;
|
||||
Settings settings = 10;
|
||||
EraseDevice erase_device = 11;
|
||||
DeviceLock device_lock = 12;
|
||||
}
|
||||
|
||||
message ScheduleOSUpdate {
|
||||
repeated OSUpdate updates = 1;
|
||||
}
|
||||
|
||||
message OSUpdate {
|
||||
string product_key = 1;
|
||||
string install_action = 2;
|
||||
}
|
||||
|
||||
message ScheduleOSUpdateScan {
|
||||
bool force = 1;
|
||||
}
|
||||
|
||||
message AccountConfiguration {
|
||||
bool skip_primary_setup_account_creation = 1;
|
||||
bool set_primary_setup_account_as_regular_user = 2;
|
||||
repeated AutoSetupAdminAccounts auto_setup_admin_accounts = 3;
|
||||
}
|
||||
|
||||
message AutoSetupAdminAccounts {
|
||||
string short_name = 1;
|
||||
string full_name = 2;
|
||||
bytes password_hash = 3;
|
||||
bool hidden = 4;
|
||||
}
|
||||
|
||||
message DeviceInformation {
|
||||
repeated string queries = 1;
|
||||
}
|
||||
|
||||
message InstallProfile {
|
||||
bytes payload = 1;
|
||||
}
|
||||
|
||||
message RemoveProfile {
|
||||
string identifier = 1;
|
||||
}
|
||||
|
||||
message DeleteUser {
|
||||
string username = 1;
|
||||
bool force_deletion = 2;
|
||||
}
|
||||
|
||||
message InstallApplication {
|
||||
int64 itunes_store_id = 1;
|
||||
string identifier = 2;
|
||||
string manifest_url = 3;
|
||||
int64 management_flags = 4;
|
||||
bool not_managed = 5;
|
||||
string change_management_state = 6;
|
||||
}
|
||||
|
||||
message EraseDevice {
|
||||
string pin = 1;
|
||||
bool preserve_data_plan = 2;
|
||||
}
|
||||
|
||||
message DeviceLock {
|
||||
string pin = 1;
|
||||
string message = 2;
|
||||
string phone_number = 3;
|
||||
}
|
||||
|
||||
message Settings {
|
||||
repeated Setting settings = 1;
|
||||
}
|
||||
|
||||
message Setting {
|
||||
string item = 1;
|
||||
DeviceNameSetting device_name = 2;
|
||||
HostnameSetting hostname = 3;
|
||||
}
|
||||
|
||||
message DeviceNameSetting {
|
||||
string device_name = 1;
|
||||
}
|
||||
|
||||
|
||||
message HostnameSetting {
|
||||
string hostname = 1;
|
||||
}
|
||||
67
platform/command/service.go
Normal file
67
platform/command/service.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Package command provides utilities for creating MDM Payloads.
|
||||
package command
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/metrics"
|
||||
"github.com/micromdm/mdm"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
NewCommand(context.Context, *mdm.CommandRequest) (*mdm.Payload, error)
|
||||
}
|
||||
|
||||
// Middleware describes a service (as opposed to endpoint) middleware.
|
||||
type Middleware func(Service) Service
|
||||
|
||||
// ServiceLoggingMiddleware returns a service middleware that logs the
|
||||
// parameters and result of each method invocation.
|
||||
func ServiceLoggingMiddleware(logger log.Logger) Middleware {
|
||||
return func(next Service) Service {
|
||||
return serviceLoggingMiddleware{
|
||||
logger: logger,
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (mw serviceLoggingMiddleware) NewCommand(ctx context.Context, req *mdm.CommandRequest) (p *mdm.Payload, err error) {
|
||||
defer func(begin time.Time) {
|
||||
mw.logger.Log(
|
||||
"method", "NewCommand",
|
||||
"error", err,
|
||||
"took", time.Since(begin),
|
||||
)
|
||||
}(time.Now())
|
||||
return mw.next.NewCommand(ctx, req)
|
||||
}
|
||||
|
||||
type serviceLoggingMiddleware struct {
|
||||
logger log.Logger
|
||||
next Service
|
||||
}
|
||||
|
||||
// ServiceInstrumentingMiddleware returns a service middleware that tracks the
|
||||
// number of payloads created by the service.
|
||||
func ServiceInstrumentingMiddleware(p metrics.Counter) Middleware {
|
||||
return func(next Service) Service {
|
||||
return serviceInstrumentingMiddleware{
|
||||
payloads: p,
|
||||
next: next,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type serviceInstrumentingMiddleware struct {
|
||||
payloads metrics.Counter
|
||||
next Service
|
||||
}
|
||||
|
||||
func (mw serviceInstrumentingMiddleware) NewCommand(ctx context.Context, req *mdm.CommandRequest) (*mdm.Payload, error) {
|
||||
p, err := mw.next.NewCommand(ctx, req)
|
||||
mw.payloads.Add(1)
|
||||
return p, err
|
||||
}
|
||||
3
platform/command/testdata/DeviceInformation.plist
vendored
Executable file
3
platform/command/testdata/DeviceInformation.plist
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0"><dict><key>Command</key><dict><key>Queries</key><array><string>foo</string><string>bar</string></array><key>RequestType</key><string>DeviceInformation</string></dict><key>CommandUUID</key><string>7564fecc-f1b5-4d2d-af17-986fdd68a252</string></dict></plist>
|
||||
3
platform/command/testdata/DeviceInformation_empty_queries.plist
vendored
Executable file
3
platform/command/testdata/DeviceInformation_empty_queries.plist
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0"><dict><key>Command</key><dict><key>RequestType</key><string>DeviceInformation</string></dict><key>CommandUUID</key><string>1ad24ed8-0405-47e5-a230-6966207b6e14</string></dict></plist>
|
||||
3
platform/command/testdata/InstallProfile.plist
vendored
Executable file
3
platform/command/testdata/InstallProfile.plist
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0"><dict><key>Command</key><dict><key>Payload</key><data>Zm9vYmFyYmF6</data><key>RequestType</key><string>InstallProfile</string></dict><key>CommandUUID</key><string>7e761ec5-9e20-42d1-9072-3d5a611e3ac5</string></dict></plist>
|
||||
28
platform/command/testdata/Settings_hostname_devicename.plist
vendored
Normal file
28
platform/command/testdata/Settings_hostname_devicename.plist
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Command</key>
|
||||
<dict>
|
||||
<key>RequestType</key>
|
||||
<string>Settings</string>
|
||||
<key>Settings</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>DeviceName</key>
|
||||
<string>foo</string>
|
||||
<key>Item</key>
|
||||
<string>DeviceName</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>HostName</key>
|
||||
<string>foo-bar</string>
|
||||
<key>Item</key>
|
||||
<string>HostName</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>CommandUUID</key>
|
||||
<string>19a68ea7-eb45-4ced-a7e6-5aa0b0eb71bc</string>
|
||||
</dict>
|
||||
</plist>
|
||||
68
platform/command/transport_http.go
Normal file
68
platform/command/transport_http.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
)
|
||||
|
||||
type HTTPHandlers struct {
|
||||
NewCommandHandler http.Handler
|
||||
}
|
||||
|
||||
func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
|
||||
h := HTTPHandlers{
|
||||
NewCommandHandler: httptransport.NewServer(
|
||||
endpoints.NewCommandEndpoint,
|
||||
decodeRequest,
|
||||
encodeResponse,
|
||||
opts...,
|
||||
),
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
type errorer interface {
|
||||
error() error
|
||||
}
|
||||
|
||||
type statuser interface {
|
||||
status() int
|
||||
}
|
||||
|
||||
// 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 with JSON.
|
||||
func EncodeError(ctx context.Context, err error, w http.ResponseWriter) {
|
||||
enc := json.NewEncoder(w)
|
||||
enc.SetIndent("", " ")
|
||||
|
||||
enc.Encode(map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
func decodeRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var req newCommandRequest
|
||||
err := json.NewDecoder(io.LimitReader(r.Body, 10000)).Decode(&req)
|
||||
return req, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if s, ok := response.(statuser); ok {
|
||||
w.WriteHeader(s.status())
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
enc.SetIndent("", " ")
|
||||
return enc.Encode(response)
|
||||
}
|
||||
35
platform/command/transport_http_test.go
Normal file
35
platform/command/transport_http_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDecodeRequest(t *testing.T) {
|
||||
requestData := `
|
||||
{
|
||||
"request_type": "InstallApplication",
|
||||
"udid" : "564D38A0-4C3B-AD69-803B-DAC58A298191",
|
||||
"manifest_url" : "https://mdm.acme.co/repo/munkitools-3.0.0.3298.plist",
|
||||
"management_flags" : 1
|
||||
}
|
||||
`
|
||||
req := httptest.NewRequest("POST", "https://mdm.acme.co/v1/commands", strings.NewReader(requestData))
|
||||
request, err := decodeRequest(context.Background(), req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
decoded := request.(newCommandRequest)
|
||||
|
||||
if have, want := decoded.RequestType, "InstallApplication"; have != want {
|
||||
t.Errorf("have %s, want %s", have, want)
|
||||
}
|
||||
|
||||
if have, want := decoded.CommandRequest.InstallApplication.ManifestURL,
|
||||
"https://mdm.acme.co/repo/munkitools-3.0.0.3298.plist"; have != want {
|
||||
t.Errorf("have %s, want %s", have, want)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user