Declarative Management hand-off (#882)

This commit is contained in:
Jesse Peterson
2023-05-02 08:54:04 -07:00
committed by GitHub
parent 4d0df77cbd
commit 1f01f70dba
10 changed files with 330 additions and 110 deletions

View File

@@ -125,6 +125,7 @@ func serve(args []string) error {
flValidateSCEPExpiration = flagset.Bool("validate-scep-expiration", env.Bool("MICROMDM_VALIDATE_SCEP_EXPIRATION", false), "validate that the SCEP certificate is still valid")
flPrintArgs = flagset.Bool("print-flags", false, "Print all flags and their values")
flQueue = flagset.String("queue", env.String("MICROMDM_QUEUE", "builtin"), "command queue type")
flDMURL = flagset.String("dm", env.String("DM", ""), "URL to send Declarative Management requests to")
)
flagset.Usage = usageFor(flagset, "micromdm serve [flags]")
if err := flagset.Parse(args); err != nil {
@@ -177,6 +178,7 @@ func serve(args []string) error {
SCEPClientValidity: *flSCEPClientValidity,
Queue: *flQueue,
DMURL: *flDMURL,
}
if !sm.UseDynSCEPChallenge {
// TODO: we have a static SCEP challenge password here to prevent

View File

@@ -2,6 +2,8 @@ package mdm
import (
"context"
stderrors "errors"
"fmt"
"net/http"
"time"
@@ -16,6 +18,10 @@ type BootstrapToken struct {
BootstrapToken []byte
}
type DeclarativeManagement interface {
DeclarativeManagement(ctx context.Context, id, endpoint string, data []byte) ([]byte, error)
}
func (svc *MDMService) Checkin(ctx context.Context, event CheckinEvent) ([]byte, error) {
// reject user settings at the loginwindow.
// https://github.com/micromdm/micromdm/pull/379
@@ -33,15 +39,14 @@ func (svc *MDMService) Checkin(ctx context.Context, event CheckinEvent) ([]byte,
return nil, errors.Wrap(err, "get checkin topic from message")
}
if topic == AuthenticateTopic {
var resp []byte
switch topic {
case AuthenticateTopic:
if err := svc.queue.Clear(ctx, event); err != nil {
return nil, errors.Wrap(err, "clearing queue on enrollment attempt")
}
}
var resp []byte
if topic == GetBootstrapTokenTopic {
case GetBootstrapTokenTopic:
udid := event.Command.UDID
btBytes, err := svc.dev.GetBootstrapToken(ctx, udid)
@@ -55,6 +60,23 @@ func (svc *MDMService) Checkin(ctx context.Context, event CheckinEvent) ([]byte,
if err != nil {
return nil, errors.Wrap(err, "marshal bootstrap token")
}
case DeclarativeManagementTopic:
if svc.dm == nil {
return nil, stderrors.New("no Declarative Management handler")
}
udid := event.Command.UDID
if event.Command.UserID != "" {
udid = event.Command.UserID
}
if event.Command.EnrollmentID != "" {
udid = event.Command.EnrollmentID
}
resp, err = svc.dm.DeclarativeManagement(ctx, udid, event.Command.Endpoint, event.Command.Data)
if err != nil {
return resp, fmt.Errorf("declarative management: %w", err)
}
}
err = svc.pub.Publish(ctx, topic, msg)
@@ -73,6 +95,8 @@ func topicFromMessage(messageType string) (string, error) {
return GetBootstrapTokenTopic, nil
case "SetBootstrapToken":
return SetBootstrapTokenTopic, nil
case "DeclarativeManagement":
return DeclarativeManagementTopic, nil
default:
return "", errors.Errorf("unknown checkin message type %s", messageType)
}

View File

@@ -30,6 +30,7 @@ type CheckinCommand struct {
update
getBootstrap
setBootstrap
declarativeManagementMessage
}
// Authenticate Message Type
@@ -74,6 +75,12 @@ type setBootstrap struct {
BootstrapToken []byte
}
// DeclarativeManagement Message Type
type declarativeManagementMessage struct {
Data []byte
Endpoint string
}
// data decodes to []byte,
// we can then attach a string method to the type
// Tokens are encoded as Hex Strings
@@ -125,6 +132,11 @@ func MarshalCheckinEvent(e *CheckinEvent) ([]byte, error) {
BootstrapToken: e.Command.BootstrapToken,
SetAwaitingConfiguration: e.Command.SetAwaitingConfiguration,
}
case "DeclarativeManagament":
command.DeclarativeManagement = &checkinproto.DeclarativeManagement{
Data: e.Command.Data,
Endpoint: e.Command.Endpoint,
}
}
return proto.Marshal(&checkinproto.Event{
Id: e.ID,
@@ -179,6 +191,9 @@ func UnmarshalCheckinEvent(data []byte, e *CheckinEvent) error {
case "SetBootstrapToken":
e.Command.BootstrapToken = pb.Command.SetBootstrapToken.BootstrapToken
e.Command.SetAwaitingConfiguration = pb.Command.SetBootstrapToken.SetAwaitingConfiguration
case "DeclarativeManagement":
e.Command.Data = pb.Command.DeclarativeManagement.Data
e.Command.Endpoint = pb.Command.DeclarativeManagement.Endpoint
}
e.Raw = pb.GetRaw()
e.Params = pb.GetParams()

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.0
// protoc v3.21.2
// protoc-gen-go v1.28.1
// protoc v3.20.2
// source: checkin.proto
package checkinproto
@@ -104,14 +104,15 @@ type Command struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MessageType string `protobuf:"bytes,1,opt,name=message_type,json=messageType,proto3" json:"message_type,omitempty"`
Topic string `protobuf:"bytes,2,opt,name=topic,proto3" json:"topic,omitempty"`
Udid string `protobuf:"bytes,3,opt,name=udid,proto3" json:"udid,omitempty"`
Authenticate *Authenticate `protobuf:"bytes,4,opt,name=authenticate,proto3" json:"authenticate,omitempty"`
TokenUpdate *TokenUpdate `protobuf:"bytes,5,opt,name=token_update,json=tokenUpdate,proto3" json:"token_update,omitempty"`
EnrollmentId string `protobuf:"bytes,6,opt,name=enrollment_id,json=enrollmentId,proto3" json:"enrollment_id,omitempty"`
GetBootstrapToken *GetBootstrapToken `protobuf:"bytes,7,opt,name=get_bootstrap_token,json=getBootstrapToken,proto3" json:"get_bootstrap_token,omitempty"`
SetBootstrapToken *SetBootstrapToken `protobuf:"bytes,8,opt,name=set_bootstrap_token,json=setBootstrapToken,proto3" json:"set_bootstrap_token,omitempty"`
MessageType string `protobuf:"bytes,1,opt,name=message_type,json=messageType,proto3" json:"message_type,omitempty"`
Topic string `protobuf:"bytes,2,opt,name=topic,proto3" json:"topic,omitempty"`
Udid string `protobuf:"bytes,3,opt,name=udid,proto3" json:"udid,omitempty"`
Authenticate *Authenticate `protobuf:"bytes,4,opt,name=authenticate,proto3" json:"authenticate,omitempty"`
TokenUpdate *TokenUpdate `protobuf:"bytes,5,opt,name=token_update,json=tokenUpdate,proto3" json:"token_update,omitempty"`
EnrollmentId string `protobuf:"bytes,6,opt,name=enrollment_id,json=enrollmentId,proto3" json:"enrollment_id,omitempty"`
GetBootstrapToken *GetBootstrapToken `protobuf:"bytes,7,opt,name=get_bootstrap_token,json=getBootstrapToken,proto3" json:"get_bootstrap_token,omitempty"`
SetBootstrapToken *SetBootstrapToken `protobuf:"bytes,8,opt,name=set_bootstrap_token,json=setBootstrapToken,proto3" json:"set_bootstrap_token,omitempty"`
DeclarativeManagement *DeclarativeManagement `protobuf:"bytes,9,opt,name=declarative_management,json=declarativeManagement,proto3" json:"declarative_management,omitempty"`
}
func (x *Command) Reset() {
@@ -202,6 +203,13 @@ func (x *Command) GetSetBootstrapToken() *SetBootstrapToken {
return nil
}
func (x *Command) GetDeclarativeManagement() *DeclarativeManagement {
if x != nil {
return x.DeclarativeManagement
}
return nil
}
type Authenticate struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -526,6 +534,61 @@ func (x *SetBootstrapToken) GetSetAwaitingConfiguration() bool {
return false
}
type DeclarativeManagement struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
Endpoint string `protobuf:"bytes,2,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
}
func (x *DeclarativeManagement) Reset() {
*x = DeclarativeManagement{}
if protoimpl.UnsafeEnabled {
mi := &file_checkin_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeclarativeManagement) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeclarativeManagement) ProtoMessage() {}
func (x *DeclarativeManagement) ProtoReflect() protoreflect.Message {
mi := &file_checkin_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeclarativeManagement.ProtoReflect.Descriptor instead.
func (*DeclarativeManagement) Descriptor() ([]byte, []int) {
return file_checkin_proto_rawDescGZIP(), []int{6}
}
func (x *DeclarativeManagement) GetData() []byte {
if x != nil {
return x.Data
}
return nil
}
func (x *DeclarativeManagement) GetEndpoint() string {
if x != nil {
return x.Endpoint
}
return ""
}
var File_checkin_proto protoreflect.FileDescriptor
var file_checkin_proto_rawDesc = []byte{
@@ -545,7 +608,7 @@ var file_checkin_proto_rawDesc = []byte{
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x22, 0x9b, 0x03, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x21,
0x38, 0x01, 0x22, 0xf7, 0x03, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x21,
0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70,
0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
@@ -571,62 +634,72 @@ var file_checkin_proto_rawDesc = []byte{
0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x74, 0x42,
0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x11, 0x73,
0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
0x22, 0xb6, 0x02, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x12, 0x23, 0x0a, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x65,
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f,
0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69,
0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0c, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a,
0x04, 0x69, 0x6d, 0x65, 0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x6d, 0x65,
0x69, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6d, 0x65, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69,
0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65,
0x6e, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c,
0x65, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x09, 0x20,
0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f,
0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xa9, 0x02, 0x0a, 0x0b, 0x54, 0x6f,
0x6b, 0x65, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12,
0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x73, 0x68, 0x4d, 0x61, 0x67, 0x69, 0x63, 0x12, 0x21,
0x0a, 0x0c, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65,
0x6e, 0x12, 0x35, 0x0a, 0x16, 0x61, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
0x08, 0x52, 0x15, 0x61, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72,
0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49,
0x64, 0x12, 0x24, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x4c,
0x6f, 0x6e, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x5f,
0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12,
0x24, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x5f, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c,
0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x6f, 0x74, 0x4f, 0x6e, 0x43, 0x6f,
0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x22, 0x51, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74,
0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x3c, 0x0a, 0x1a, 0x67, 0x65,
0x74, 0x5f, 0x61, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18,
0x67, 0x65, 0x74, 0x41, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7a, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x42,
0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x27, 0x0a,
0x0f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61,
0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x77,
0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x73, 0x65, 0x74, 0x41,
0x12, 0x5a, 0x0a, 0x16, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f,
0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x23, 0x2e, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67,
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x15, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69,
0x76, 0x65, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xb6, 0x02, 0x0a,
0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a,
0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x09, 0x6f, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d,
0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e,
0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x72,
0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6d, 0x65,
0x69, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x6d, 0x65, 0x69, 0x12, 0x12, 0x0a,
0x04, 0x6d, 0x65, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x69,
0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61,
0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18,
0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52,
0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x6f, 0x64, 0x65,
0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xa9, 0x02, 0x0a, 0x0b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x70,
0x75, 0x73, 0x68, 0x5f, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x09, 0x70, 0x75, 0x73, 0x68, 0x4d, 0x61, 0x67, 0x69, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e,
0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x0b, 0x75, 0x6e, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x35, 0x0a,
0x16, 0x61, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x61,
0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6d, 0x64, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72,
0x6f, 0x6d, 0x64, 0x6d, 0x2f, 0x6d, 0x64, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18,
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a,
0x0e, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x6e, 0x67, 0x4e,
0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x68, 0x6f, 0x72,
0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x75, 0x73,
0x65, 0x72, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e,
0x6f, 0x74, 0x5f, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x18, 0x08, 0x20,
0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x6f, 0x74, 0x4f, 0x6e, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c,
0x65, 0x22, 0x51, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61,
0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x3c, 0x0a, 0x1a, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x77,
0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x67, 0x65, 0x74, 0x41,
0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7a, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x42, 0x6f, 0x6f, 0x74, 0x73,
0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x6f, 0x6f,
0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x0e, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x54, 0x6f, 0x6b,
0x65, 0x6e, 0x12, 0x3c, 0x0a, 0x1a, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x77, 0x61, 0x69, 0x74, 0x69,
0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x73, 0x65, 0x74, 0x41, 0x77, 0x61, 0x69, 0x74,
0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x47, 0x0a, 0x15, 0x44, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4d,
0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74,
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a,
0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6d, 0x64, 0x6d,
0x2f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x6d, 0x64, 0x6d, 0x2f, 0x6d, 0x64, 0x6d, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -641,28 +714,30 @@ func file_checkin_proto_rawDescGZIP() []byte {
return file_checkin_proto_rawDescData
}
var file_checkin_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_checkin_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_checkin_proto_goTypes = []interface{}{
(*Event)(nil), // 0: checkinproto.Event
(*Command)(nil), // 1: checkinproto.Command
(*Authenticate)(nil), // 2: checkinproto.Authenticate
(*TokenUpdate)(nil), // 3: checkinproto.TokenUpdate
(*GetBootstrapToken)(nil), // 4: checkinproto.GetBootstrapToken
(*SetBootstrapToken)(nil), // 5: checkinproto.SetBootstrapToken
nil, // 6: checkinproto.Event.ParamsEntry
(*Event)(nil), // 0: checkinproto.Event
(*Command)(nil), // 1: checkinproto.Command
(*Authenticate)(nil), // 2: checkinproto.Authenticate
(*TokenUpdate)(nil), // 3: checkinproto.TokenUpdate
(*GetBootstrapToken)(nil), // 4: checkinproto.GetBootstrapToken
(*SetBootstrapToken)(nil), // 5: checkinproto.SetBootstrapToken
(*DeclarativeManagement)(nil), // 6: checkinproto.DeclarativeManagement
nil, // 7: checkinproto.Event.ParamsEntry
}
var file_checkin_proto_depIdxs = []int32{
1, // 0: checkinproto.Event.command:type_name -> checkinproto.Command
6, // 1: checkinproto.Event.params:type_name -> checkinproto.Event.ParamsEntry
7, // 1: checkinproto.Event.params:type_name -> checkinproto.Event.ParamsEntry
2, // 2: checkinproto.Command.authenticate:type_name -> checkinproto.Authenticate
3, // 3: checkinproto.Command.token_update:type_name -> checkinproto.TokenUpdate
4, // 4: checkinproto.Command.get_bootstrap_token:type_name -> checkinproto.GetBootstrapToken
5, // 5: checkinproto.Command.set_bootstrap_token:type_name -> checkinproto.SetBootstrapToken
6, // [6:6] is the sub-list for method output_type
6, // [6:6] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
6, // 6: checkinproto.Command.declarative_management:type_name -> checkinproto.DeclarativeManagement
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_checkin_proto_init() }
@@ -743,6 +818,18 @@ func file_checkin_proto_init() {
return nil
}
}
file_checkin_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeclarativeManagement); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -750,7 +837,7 @@ func file_checkin_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_checkin_proto_rawDesc,
NumEnums: 0,
NumMessages: 7,
NumMessages: 8,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -21,6 +21,7 @@ message Command {
string enrollment_id = 6;
GetBootstrapToken get_bootstrap_token = 7;
SetBootstrapToken set_bootstrap_token = 8;
DeclarativeManagement declarative_management = 9;
}
message Authenticate {
@@ -55,3 +56,8 @@ message SetBootstrapToken {
bytes bootstrap_token = 1;
bool set_awaiting_configuration = 2;
}
message DeclarativeManagement {
bytes data = 1;
string endpoint = 2;
}

View File

@@ -21,12 +21,13 @@ type Service interface {
type Middleware func(Service) Service
const (
ConnectTopic = "mdm.Connect"
AuthenticateTopic = "mdm.Authenticate"
TokenUpdateTopic = "mdm.TokenUpdate"
CheckoutTopic = "mdm.CheckOut"
GetBootstrapTokenTopic = "mdm.GetBootstrapToken"
SetBootstrapTokenTopic = "mdm.SetBootstrapToken"
ConnectTopic = "mdm.Connect"
AuthenticateTopic = "mdm.Authenticate"
TokenUpdateTopic = "mdm.TokenUpdate"
CheckoutTopic = "mdm.CheckOut"
GetBootstrapTokenTopic = "mdm.GetBootstrapToken"
SetBootstrapTokenTopic = "mdm.SetBootstrapToken"
DeclarativeManagementTopic = "mdm.DeclarativeManagement"
)
// BootBootstrapTokenRetriever retrieves BootStrap Tokens for devices
@@ -45,12 +46,14 @@ type MDMService struct {
dev BootstrapTokenRetriever
pub pubsub.Publisher
queue Queue
dm DeclarativeManagement
}
func NewService(pub pubsub.Publisher, queue Queue, dev BootstrapTokenRetriever) *MDMService {
func NewService(pub pubsub.Publisher, queue Queue, dev BootstrapTokenRetriever, dm DeclarativeManagement) *MDMService {
return &MDMService{
dev: dev,
pub: pub,
queue: queue,
dm: dm,
}
}

View File

@@ -30,8 +30,8 @@ func RegisterHTTPHandlers(r *mux.Router, e Endpoints, options ...httptransport.S
options...,
))
// POST /v1/commands/udid Add new MDM Command with raw plist to device queue.
r.Methods("POST").Path("/v1/commands/{udid}").Handler(httptransport.NewServer(
// POST,PUT /v1/commands/udid Add new MDM Command with raw plist to device queue.
r.Methods("POST", "PUT").Path("/v1/commands/{udid}").Handler(httptransport.NewServer(
e.NewRawCommandEndpoint,
decodeNewRawCommandRequest,
httputil.EncodeJSONResponse,

View File

@@ -94,23 +94,19 @@ func (mw *udidCertAuthMiddleware) Checkin(ctx context.Context, req mdm.CheckinEv
if err != nil {
return nil, errors.Wrap(err, "error retrieving device certificate")
}
switch req.Command.MessageType {
case "Authenticate":
if req.Command.MessageType == "Authenticate" {
// unconditionally save the cert hash on Authenticate message
if err := mw.store.SaveUDIDCertHash([]byte(req.Command.UDID), hashCertRaw(devcert.Raw)); err != nil {
return nil, err
}
return mw.next.Checkin(ctx, req)
case "TokenUpdate", "CheckOut", "GetBootstrapToken", "SetBootstrapToken":
matched, err := mw.validateUDIDCertAuth([]byte(req.Command.UDID), hashCertRaw(devcert.Raw))
if err != nil {
return nil, err
}
if !matched && !mw.warnOnly {
return nil, errors.New("device certifcate UDID mismatch")
}
return mw.next.Checkin(ctx, req)
default:
return nil, errors.Errorf("unknown checkin message type %s", req.Command.MessageType)
}
matched, err := mw.validateUDIDCertAuth([]byte(req.Command.UDID), hashCertRaw(devcert.Raw))
if err != nil {
return nil, err
}
if !matched && !mw.warnOnly {
return nil, errors.New("device certifcate UDID mismatch")
}
return mw.next.Checkin(ctx, req)
}

78
server/dm.go Normal file
View File

@@ -0,0 +1,78 @@
package server
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/http"
"net/url"
)
const enrollmentIDHeader = "X-Enrollment-ID"
type DeclarativeManagementHTTPCaller struct {
url *url.URL
client *http.Client
}
// NewDeclarativeManagementHTTPCaller creates a new DeclarativeManagementHTTPCaller
func NewDeclarativeManagementHTTPCaller(urlPrefix string, client *http.Client) (*DeclarativeManagementHTTPCaller, error) {
url, err := url.Parse(urlPrefix)
return &DeclarativeManagementHTTPCaller{url: url, client: client}, err
}
type HTTPStatusError struct {
Err error
Status int
}
func (e HTTPStatusError) Error() string {
return e.Err.Error()
}
func (e HTTPStatusError) StatusCode() int {
return e.Status
}
// DeclarativeManagement calls out to an HTTP URL to handle the actual Declarative Management protocol
func (c *DeclarativeManagementHTTPCaller) DeclarativeManagement(ctx context.Context, id, endpoint string, data []byte) ([]byte, error) {
if c.url == nil {
return nil, errors.New("missing URL")
}
endpointURL, err := url.Parse(endpoint)
if err != nil {
return nil, fmt.Errorf("parsing endpoint URL: %w", err)
}
u := c.url.ResolveReference(endpointURL)
method := http.MethodGet
if len(data) > 0 {
method = http.MethodPut
}
req, err := http.NewRequestWithContext(ctx, method, u.String(), bytes.NewBuffer(data))
if err != nil {
return nil, err
}
req.Header.Set(enrollmentIDHeader, id)
if len(data) > 0 {
req.Header.Set("Content-Type", "application/json")
}
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
// return the same HTTP status with a Go-kit StatusCoder
return bodyBytes, HTTPStatusError{
Err: fmt.Errorf("unexpected HTTP status: %d", resp.StatusCode),
Status: resp.StatusCode,
}
}
return bodyBytes, nil
}

View File

@@ -66,6 +66,7 @@ type Server struct {
ValidateSCEPExpiration bool
UDIDCertAuthWarnOnly bool
Queue string
DMURL string
APNSPushService apns.Service
CommandService command.Service
@@ -202,7 +203,15 @@ func (c *Server) setupCommandQueue(logger log.Logger) error {
var mdmService mdm.Service
{
svc := mdm.NewService(c.PubClient, q, devDB)
var dm mdm.DeclarativeManagement
if c.DMURL != "" {
dm, err = NewDeclarativeManagementHTTPCaller(c.DMURL, http.DefaultClient)
if err != nil {
return fmt.Errorf("setting up declarative management: %w", err)
}
}
svc := mdm.NewService(c.PubClient, q, devDB, dm)
mdmService = svc
mdmService = block.RemoveMiddleware(c.RemoveDB)(mdmService)