mirror of
https://github.com/micromdm/micromdm/
synced 2026-08-08 02:25:34 +08:00
Switch to using jessepeterson/cfgprofiles for profile generation (#827)
* Switch to using jessepeterson/cfgprofiles for profile generation
This commit is contained in:
3
go.mod
3
go.mod
@@ -5,11 +5,12 @@ require (
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17
|
||||
github.com/go-kit/kit v0.7.0
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/gorilla/mux v1.6.2
|
||||
github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda
|
||||
github.com/groob/plist v0.0.0-20220217120414-63fa881b19a5
|
||||
github.com/jessepeterson/cfgprofiles v0.2.0
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0
|
||||
github.com/kolide/kit v0.0.0-20180912215818-0c28f72eb2b0
|
||||
github.com/korylprince/go-macos-pkg v1.3.5
|
||||
|
||||
13
go.sum
13
go.sum
@@ -24,8 +24,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
@@ -36,20 +36,17 @@ github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda h1:5ikpG9mYCMFiZX0nkxoV6aU2IpCHPdws3gCNgdZeEV0=
|
||||
github.com/groob/finalizer v0.0.0-20170707115354-4c2ed49aabda/go.mod h1:MyndkAZd5rUMdNogn35MWXBX1UiBigrU8eTj8DoAC2c=
|
||||
github.com/groob/plist v0.0.0-20180203051248-dd56909aee38 h1:afbUddvIjPRC7XHHgeSTRfzZtIxEsSl4VCxumLBGDJU=
|
||||
github.com/groob/plist v0.0.0-20180203051248-dd56909aee38/go.mod h1:qg2Nek0ND/hIr+nY8H1oVqEW2cLzVVNaAQ0QexOyjyc=
|
||||
github.com/groob/plist v0.0.0-20190114192801-a99fbe489d03/go.mod h1:qg2Nek0ND/hIr+nY8H1oVqEW2cLzVVNaAQ0QexOyjyc=
|
||||
github.com/groob/plist v0.0.0-20220217120414-63fa881b19a5 h1:saaSiB25B1wgaxrshQhurfPKUGJ4It3OxNJUy0rdOjU=
|
||||
github.com/groob/plist v0.0.0-20220217120414-63fa881b19a5/go.mod h1:itkABA+w2cw7x5nYUS/pLRef6ludkZKOigbROmCTaFw=
|
||||
github.com/jessepeterson/cfgprofiles v0.2.0 h1:yuAWfY5X0MZfWA1yGppnqIJr5zXziHSlutDKv5ST/wg=
|
||||
github.com/jessepeterson/cfgprofiles v0.2.0/go.mod h1:bdPSaKnOBjiToJhSVaF2+0N3iSMvugICiC7kguXkD14=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+uGHxWtRt4C0Wjc6kJKo5XYx8xE=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
|
||||
github.com/kolide/kit v0.0.0-20180912215818-0c28f72eb2b0 h1:8UB0NJBoB/lN2O9zG9+U2klyYE0UhvN2Zrn7HBjhwNY=
|
||||
github.com/kolide/kit v0.0.0-20180912215818-0c28f72eb2b0/go.mod h1:N3Yv8okDVC/5qZhPA9uxVYRfkp4mD2vrlQiSCWlNCpg=
|
||||
github.com/korylprince/go-cpio-odc v0.9.3 h1:MGpo1PcJN2ajysEoAhF34zR/Peevo4N+T+OmhDLIUvk=
|
||||
github.com/korylprince/go-cpio-odc v0.9.3/go.mod h1:1iHsjUXO64Hui0YsubGp0Tm/Uf04Iow2iy+1LJIarMw=
|
||||
github.com/korylprince/go-cpio-odc v0.9.4 h1:N0Afrp7Z5qCZF8cbpzF5CvyiC/KHK5IcLJwqm5MWpNU=
|
||||
github.com/korylprince/go-cpio-odc v0.9.4/go.mod h1:1iHsjUXO64Hui0YsubGp0Tm/Uf04Iow2iy+1LJIarMw=
|
||||
github.com/korylprince/go-macos-pkg v1.3.4 h1:6McQ9bj3p/k/FeqFBHhdvXVvi+ftNcWXj4EWAEuEiz0=
|
||||
github.com/korylprince/go-macos-pkg v1.3.4/go.mod h1:eLXotCZDK3vBt6AfDg62Fl20lCjrIm5e8V/8Q9YLHIo=
|
||||
github.com/korylprince/go-macos-pkg v1.3.5 h1:jwwefLR1yRKQPNu51QTwk2B4abIjjISj/BHipcvKKGs=
|
||||
github.com/korylprince/go-macos-pkg v1.3.5/go.mod h1:jlPGliXXjjCMpISR30/fL60hXKrCJ2LNQSptdx+WQkc=
|
||||
github.com/korylprince/goxar v0.0.0-20211111233330-e9f257bcdf25 h1:XVf+U+WekiGPPD27w7qI+0Pe8NehaTWPqRuO3BddefY=
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
package enroll
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Payload struct {
|
||||
PayloadType string `json:"type" db:"type"`
|
||||
PayloadVersion int `json:"version" db:"version"`
|
||||
PayloadIdentifier string `json:"identifier" db:"identifier"`
|
||||
PayloadUUID string `json:"uuid" db:"uuid"`
|
||||
PayloadDisplayName string `json:"displayname" db:"displayname"`
|
||||
PayloadDescription string `json:"description,omitempty" db:"description"`
|
||||
PayloadOrganization string `json:"organization,omitempty" db:"organization"`
|
||||
PayloadScope string `json:"scope" db:"scope" plist:",omitempty"`
|
||||
PayloadContent interface{} `json:"content,omitempty" plist:"PayloadContent,omitempty"`
|
||||
}
|
||||
|
||||
type Profile struct {
|
||||
PayloadContent []interface{} `json:"content,omitempty" db:"content"`
|
||||
PayloadDescription string `json:"description,omitempty" db:"description"`
|
||||
PayloadDisplayName string `json:"displayname,omitempty" db:"displayname"`
|
||||
PayloadExpirationDate *time.Time `json:"expiration_date,omitempty" db:"expiration_date" plist:",omitempty"`
|
||||
PayloadIdentifier string `json:"identifier" db:"identifier"`
|
||||
PayloadOrganization string `json:"organization,omitempty" db:"organization"`
|
||||
PayloadUUID string `json:"uuid" db:"uuid"`
|
||||
PayloadRemovalDisallowed bool `json:"removal_disallowed" db:"removal_disallowed" plist:",omitempty"`
|
||||
PayloadType string `json:"type" db:"type"`
|
||||
PayloadVersion int `json:"version" db:"version"`
|
||||
PayloadScope string `json:"scope" db:"scope" plist:",omitempty"`
|
||||
RemovalDate *time.Time `json:"removal_date" db:"removal_date" plist:"-" plist:",omitempty"`
|
||||
DurationUntilRemoval float32 `json:"duration_until_removal" db:"duration_until_removal" plist:",omitempty"`
|
||||
ConsentText map[string]string `json:"consent_text" db:"consent_text" plist:",omitempty"`
|
||||
}
|
||||
|
||||
func NewProfile() *Profile {
|
||||
payloadUuid := uuid.New()
|
||||
|
||||
return &Profile{
|
||||
PayloadVersion: 1,
|
||||
PayloadType: "Configuration",
|
||||
PayloadUUID: payloadUuid.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func NewPayload(payloadType string) *Payload {
|
||||
payloadUuid := uuid.New()
|
||||
|
||||
return &Payload{
|
||||
PayloadVersion: 1,
|
||||
PayloadType: payloadType,
|
||||
PayloadUUID: payloadUuid.String(),
|
||||
}
|
||||
}
|
||||
|
||||
type SCEPPayloadContent struct {
|
||||
CAFingerprint []byte `plist:"CAFingerprint,omitempty"` // NSData
|
||||
Challenge string `plist:"Challenge,omitempty"`
|
||||
Keysize int
|
||||
KeyType string `plist:"Key Type"`
|
||||
KeyUsage int `plist:"Key Usage"`
|
||||
Name string
|
||||
Subject [][][]string `plist:"Subject,omitempty"`
|
||||
URL string
|
||||
}
|
||||
|
||||
// AccessRights define the management rights of the MDM server over the device.
|
||||
// May not be zero. If 2 is specified, 1 must also be specified. If 128 is specified, 64 must also be specified.
|
||||
type AccessRights int
|
||||
|
||||
const (
|
||||
// Allow inspection of installed configuration profiles.
|
||||
ProfileInspection AccessRights = 1 << iota
|
||||
|
||||
// Allow installation and removal of configuration profiles.
|
||||
ProfileInstallAndRemoval
|
||||
|
||||
// Allow device lock and passcode removal.
|
||||
DeviceLock
|
||||
|
||||
// Allow device erase.
|
||||
DeviceErase
|
||||
|
||||
// Allow query of Device Information (device capacity, serial number).
|
||||
DeviceInformationQuery
|
||||
|
||||
// Allow query of Network Information (phone/SIM numbers, MAC addresses).
|
||||
NetworkInformationQuery
|
||||
|
||||
// Allow inspection of installed provisioning profiles.
|
||||
ProvisioningProfileInspection
|
||||
|
||||
// Allow installation and removal of provisioning profiles.
|
||||
ProvisioningProfileInstallAndRemoval
|
||||
|
||||
// Allow inspection of installed applications.
|
||||
ApplicationInspection
|
||||
|
||||
// Allow restriction-related queries.
|
||||
RestrictionQuery
|
||||
|
||||
// Allow security-related queries.
|
||||
SecurityQuery
|
||||
|
||||
// Allow manipulation of settings.
|
||||
// Availability: Available in iOS 5.0 and later. Available in macOS 10.9 for certain commands.
|
||||
SettingsManipulation
|
||||
|
||||
// Allow app management.
|
||||
// Availability: Available in iOS 5.0 and later. Available in macOS 10.9 for certain commands.
|
||||
AppManagement
|
||||
)
|
||||
|
||||
func allRights() AccessRights {
|
||||
return ProfileInspection |
|
||||
ProfileInstallAndRemoval |
|
||||
DeviceLock |
|
||||
DeviceErase |
|
||||
DeviceInformationQuery |
|
||||
NetworkInformationQuery |
|
||||
ProvisioningProfileInspection |
|
||||
ProvisioningProfileInstallAndRemoval |
|
||||
ApplicationInspection |
|
||||
RestrictionQuery |
|
||||
SecurityQuery |
|
||||
SettingsManipulation |
|
||||
AppManagement
|
||||
}
|
||||
|
||||
// TODO: Actually this is one of those non-nested payloads that doesnt respect the PayloadContent key.
|
||||
type MDMPayloadContent struct {
|
||||
Payload
|
||||
AccessRights AccessRights
|
||||
CheckInURL string
|
||||
CheckOutWhenRemoved bool
|
||||
IdentityCertificateUUID string
|
||||
ServerCapabilities []string `plist:"ServerCapabilities,omitempty"`
|
||||
SignMessage bool `plist:"SignMessage,omitempty"`
|
||||
ServerURL string
|
||||
Topic string
|
||||
}
|
||||
|
||||
type ProfileServicePayload struct {
|
||||
URL string
|
||||
Challenge string `plist:",omitempty"`
|
||||
DeviceAttributes []string
|
||||
}
|
||||
@@ -11,14 +11,13 @@ func TestEnrollProfile(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var payloadContent MDMPayloadContent
|
||||
for _, payload := range profile.PayloadContent {
|
||||
if c, ok := payload.(MDMPayloadContent); ok {
|
||||
payloadContent = c
|
||||
}
|
||||
mdmPayloads := profile.MDMPayloads()
|
||||
if len(mdmPayloads) != 1 {
|
||||
t.Fatal("number of MDM payloads is not 1")
|
||||
}
|
||||
payloadContent := mdmPayloads[0]
|
||||
|
||||
if have, want := payloadContent.AccessRights, AccessRights(8191); have != want {
|
||||
if have, want := payloadContent.AccessRights, 8191; have != want {
|
||||
t.Errorf("have %d, want %d", have, want)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/micromdm/scep/v2/challenge"
|
||||
|
||||
"github.com/groob/plist"
|
||||
"github.com/jessepeterson/cfgprofiles"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@@ -21,6 +22,17 @@ import (
|
||||
const (
|
||||
EnrollmentProfileId string = "com.github.micromdm.micromdm.enroll"
|
||||
OTAProfileId string = "com.github.micromdm.micromdm.ota"
|
||||
|
||||
profilePayloadOrganization = "MicroMDM"
|
||||
profilePayloadDisplayName = "Enrollment Profile"
|
||||
profilePayloadDescription = "The server may alter your settings"
|
||||
|
||||
mdmPayloadDescription = "Enrolls with the MDM server"
|
||||
mdmPayloadServerEndpoint = "/mdm/connect"
|
||||
mdmPayloadCheckInEndpoint = "/mdm/checkin"
|
||||
|
||||
scepPayloadDescription = "Configures SCEP"
|
||||
scepPayloadDisplayName = "SCEP"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
@@ -126,17 +138,20 @@ type TopicProvider interface {
|
||||
}
|
||||
|
||||
func profileOrPayloadFromFunc(f interface{}) (interface{}, error) {
|
||||
fPayload, ok := f.(func() (Payload, error))
|
||||
fProfile, ok := f.(func() (*cfgprofiles.Profile, error))
|
||||
if !ok {
|
||||
fProfile := f.(func() (Profile, error))
|
||||
return fProfile()
|
||||
fPayload := f.(func() (*ProfileServicePayload, error))
|
||||
return fPayload()
|
||||
}
|
||||
return fPayload()
|
||||
return fProfile()
|
||||
}
|
||||
|
||||
func profileOrPayloadToMobileconfig(in interface{}) (profile.Mobileconfig, error) {
|
||||
if _, ok := in.(Payload); !ok {
|
||||
_ = in.(Profile)
|
||||
switch in.(type) {
|
||||
case *ProfileServicePayload, *cfgprofiles.Profile:
|
||||
break
|
||||
default:
|
||||
return nil, errors.New("invalid profile type")
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
enc := plist.NewEncoder(buf)
|
||||
@@ -164,88 +179,78 @@ func (svc *service) Enroll(ctx context.Context) (profile.Mobileconfig, error) {
|
||||
return svc.findOrMakeMobileconfig(ctx, EnrollmentProfileId, svc.MakeEnrollmentProfile)
|
||||
}
|
||||
|
||||
func (svc *service) scepChallenge() (challenge string, err error) {
|
||||
if svc.SCEPChallengeStore != nil {
|
||||
challenge, err = svc.SCEPChallengeStore.SCEPChallenge()
|
||||
} else if svc.SCEPChallenge != "" {
|
||||
challenge = svc.SCEPChallenge
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const perUserConnections = "com.apple.mdm.per-user-connections"
|
||||
const bootstrapToken = "com.apple.mdm.bootstraptoken"
|
||||
|
||||
func (svc *service) MakeEnrollmentProfile() (Profile, error) {
|
||||
profile := NewProfile()
|
||||
profile.PayloadIdentifier = EnrollmentProfileId
|
||||
profile.PayloadOrganization = "MicroMDM"
|
||||
profile.PayloadDisplayName = "Enrollment Profile"
|
||||
profile.PayloadDescription = "The server may alter your settings"
|
||||
func (svc *service) MakeEnrollmentProfile() (*cfgprofiles.Profile, error) {
|
||||
profile := cfgprofiles.NewProfile(EnrollmentProfileId)
|
||||
profile.PayloadScope = "System"
|
||||
profile.PayloadOrganization = profilePayloadOrganization
|
||||
profile.PayloadDisplayName = profilePayloadDisplayName
|
||||
profile.PayloadDescription = profilePayloadDescription
|
||||
|
||||
mdmPayload := NewPayload("com.apple.mdm")
|
||||
mdmPayload.PayloadDescription = "Enrolls with the MDM server"
|
||||
mdmPayload.PayloadOrganization = "MicroMDM"
|
||||
mdmPayload.PayloadIdentifier = EnrollmentProfileId + ".mdm"
|
||||
mdmPayload.PayloadScope = "System"
|
||||
mdmPayload := cfgprofiles.NewMDMPayload(EnrollmentProfileId + ".mdm")
|
||||
mdmPayload.PayloadOrganization = profilePayloadOrganization
|
||||
mdmPayload.PayloadDescription = mdmPayloadDescription
|
||||
|
||||
mdmPayload.ServerURL = svc.URL + mdmPayloadServerEndpoint
|
||||
mdmPayload.CheckInURL = svc.URL + mdmPayloadCheckInEndpoint
|
||||
mdmPayload.CheckOutWhenRemoved = true
|
||||
mdmPayload.AccessRights = 8191
|
||||
|
||||
svc.mu.Lock()
|
||||
topic := svc.Topic
|
||||
mdmPayload.Topic = svc.Topic
|
||||
svc.mu.Unlock()
|
||||
|
||||
mdmPayloadContent := MDMPayloadContent{
|
||||
Payload: *mdmPayload,
|
||||
AccessRights: allRights(),
|
||||
CheckInURL: svc.URL + "/mdm/checkin",
|
||||
CheckOutWhenRemoved: true,
|
||||
ServerURL: svc.URL + "/mdm/connect",
|
||||
Topic: topic,
|
||||
SignMessage: true,
|
||||
ServerCapabilities: []string{perUserConnections, bootstrapToken},
|
||||
}
|
||||
|
||||
payloadContent := []interface{}{}
|
||||
mdmPayload.SignMessage = true
|
||||
mdmPayload.ServerCapabilities = []string{perUserConnections, bootstrapToken}
|
||||
|
||||
if svc.SCEPURL != "" {
|
||||
scepContent := SCEPPayloadContent{
|
||||
scepPayload := cfgprofiles.NewSCEPPayload(EnrollmentProfileId + ".scep")
|
||||
scepPayload.PayloadDescription = scepPayloadDescription
|
||||
scepPayload.PayloadDisplayName = scepPayloadDisplayName
|
||||
scepPayload.PayloadOrganization = profilePayloadOrganization
|
||||
|
||||
scepPayload.PayloadContent = cfgprofiles.SCEPPayloadContent{
|
||||
URL: svc.SCEPURL,
|
||||
Keysize: 2048,
|
||||
KeySize: 2048,
|
||||
KeyType: "RSA",
|
||||
KeyUsage: int(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment),
|
||||
Name: "Device Management Identity Certificate",
|
||||
Subject: svc.SCEPSubject,
|
||||
}
|
||||
|
||||
if svc.SCEPChallengeStore != nil {
|
||||
challenge, err := svc.SCEPChallengeStore.SCEPChallenge()
|
||||
if err != nil {
|
||||
return *profile, err
|
||||
}
|
||||
scepContent.Challenge = challenge
|
||||
} else if svc.SCEPChallenge != "" {
|
||||
scepContent.Challenge = svc.SCEPChallenge
|
||||
var err error
|
||||
scepPayload.PayloadContent.Challenge, err = svc.scepChallenge()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scepPayload := NewPayload("com.apple.security.scep")
|
||||
scepPayload.PayloadDescription = "Configures SCEP"
|
||||
scepPayload.PayloadDisplayName = "SCEP"
|
||||
scepPayload.PayloadIdentifier = EnrollmentProfileId + ".scep"
|
||||
scepPayload.PayloadOrganization = "MicroMDM"
|
||||
scepPayload.PayloadContent = scepContent
|
||||
scepPayload.PayloadScope = "System"
|
||||
|
||||
payloadContent = append(payloadContent, *scepPayload)
|
||||
mdmPayloadContent.IdentityCertificateUUID = scepPayload.PayloadUUID
|
||||
profile.AddPayload(scepPayload)
|
||||
mdmPayload.IdentityCertificateUUID = scepPayload.PayloadUUID
|
||||
}
|
||||
|
||||
payloadContent = append(payloadContent, mdmPayloadContent)
|
||||
profile.AddPayload(mdmPayload)
|
||||
|
||||
// Client needs to trust us at this point if we are using a self signed certificate.
|
||||
if len(svc.TLSCert) > 0 {
|
||||
tlsPayload := NewPayload("com.apple.security.pem")
|
||||
tlsPayload := cfgprofiles.NewCertificatePKCS1Payload(EnrollmentProfileId + ".cert.selfsigned")
|
||||
tlsPayload.PayloadDisplayName = "Self-signed TLS certificate for MicroMDM"
|
||||
tlsPayload.PayloadDescription = "Installs the TLS certificate for MicroMDM"
|
||||
tlsPayload.PayloadIdentifier = EnrollmentProfileId + ".cert.selfsigned"
|
||||
tlsPayload.PayloadContent = svc.TLSCert
|
||||
|
||||
payloadContent = append(payloadContent, *tlsPayload)
|
||||
profile.AddPayload(tlsPayload)
|
||||
}
|
||||
|
||||
profile.PayloadContent = payloadContent
|
||||
|
||||
return *profile, nil
|
||||
return profile, nil
|
||||
}
|
||||
|
||||
// OTAEnroll returns an Over-the-Air "Profile Service" Payload for enrollment.
|
||||
@@ -253,20 +258,32 @@ func (svc *service) OTAEnroll(ctx context.Context) (profile.Mobileconfig, error)
|
||||
return svc.findOrMakeMobileconfig(ctx, OTAProfileId, svc.MakeOTAEnrollPayload)
|
||||
}
|
||||
|
||||
func (svc *service) MakeOTAEnrollPayload() (Payload, error) {
|
||||
payload := NewPayload("Profile Service")
|
||||
payload.PayloadIdentifier = OTAProfileId
|
||||
payload.PayloadDisplayName = "MicroMDM Profile Service"
|
||||
payload.PayloadDescription = "Profile Service enrollment"
|
||||
payload.PayloadOrganization = "MicroMDM"
|
||||
payload.PayloadContent = ProfileServicePayload{
|
||||
URL: svc.URL + "/ota/phase23",
|
||||
Challenge: "",
|
||||
DeviceAttributes: []string{"UDID", "VERSION", "PRODUCT", "SERIAL", "MEID", "IMEI"},
|
||||
type ProfileServicePayloadContent struct {
|
||||
URL string
|
||||
Challenge string `plist:",omitempty"`
|
||||
DeviceAttributes []string
|
||||
}
|
||||
|
||||
type ProfileServicePayload struct {
|
||||
*cfgprofiles.Payload
|
||||
PayloadContent ProfileServicePayloadContent
|
||||
}
|
||||
|
||||
func (svc *service) MakeOTAEnrollPayload() (*ProfileServicePayload, error) {
|
||||
payload := &ProfileServicePayload{
|
||||
Payload: cfgprofiles.NewPayload("Profile Service", OTAProfileId),
|
||||
PayloadContent: ProfileServicePayloadContent{
|
||||
URL: svc.URL + "/ota/phase23",
|
||||
Challenge: "",
|
||||
DeviceAttributes: []string{"UDID", "VERSION", "PRODUCT", "SERIAL", "MEID", "IMEI"},
|
||||
},
|
||||
}
|
||||
payload.PayloadOrganization = profilePayloadOrganization
|
||||
payload.PayloadDescription = "Profile Service enrollment"
|
||||
payload.PayloadDisplayName = "MicroMDM Profile Service"
|
||||
|
||||
// yes, this is a bare Payload, not a Profile
|
||||
return *payload, nil
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// OTAPhase2 returns a SCEP Profile for use in phase 2 of Over-the-Air enrollment.
|
||||
@@ -274,38 +291,36 @@ func (svc *service) OTAPhase2(ctx context.Context) (profile.Mobileconfig, error)
|
||||
return svc.findOrMakeMobileconfig(ctx, OTAProfileId+".phase2", svc.MakeOTAPhase2Profile)
|
||||
}
|
||||
|
||||
func (svc *service) MakeOTAPhase2Profile() (Profile, error) {
|
||||
profile := NewProfile()
|
||||
profile.PayloadIdentifier = OTAProfileId + ".phase2"
|
||||
profile.PayloadOrganization = "MicroMDM"
|
||||
func (svc *service) MakeOTAPhase2Profile() (*cfgprofiles.Profile, error) {
|
||||
profile := cfgprofiles.NewProfile(OTAProfileId + ".phase2")
|
||||
profile.PayloadOrganization = profilePayloadOrganization
|
||||
profile.PayloadDisplayName = "OTA Phase 2"
|
||||
profile.PayloadDescription = "The server may alter your settings"
|
||||
profile.PayloadDescription = profilePayloadDescription
|
||||
profile.PayloadScope = "System"
|
||||
|
||||
scepContent := SCEPPayloadContent{
|
||||
scepPayload := cfgprofiles.NewSCEPPayload(OTAProfileId + ".phase2.scep")
|
||||
scepPayload.PayloadDescription = scepPayloadDescription
|
||||
scepPayload.PayloadDisplayName = scepPayloadDisplayName
|
||||
scepPayload.PayloadOrganization = profilePayloadOrganization
|
||||
|
||||
scepPayload.PayloadContent = cfgprofiles.SCEPPayloadContent{
|
||||
URL: svc.SCEPURL,
|
||||
Keysize: 2048, // NOTE: OTA docs recommend 1024
|
||||
KeySize: 2048, // NOTE: OTA docs recommend 1024
|
||||
KeyType: "RSA",
|
||||
KeyUsage: int(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment),
|
||||
Name: "OTA Phase 2 Certificate",
|
||||
Subject: svc.SCEPSubject,
|
||||
}
|
||||
|
||||
if svc.SCEPChallenge != "" {
|
||||
scepContent.Challenge = svc.SCEPChallenge
|
||||
var err error
|
||||
scepPayload.PayloadContent.Challenge, err = svc.scepChallenge()
|
||||
if err != nil {
|
||||
return profile, err
|
||||
}
|
||||
|
||||
scepPayload := NewPayload("com.apple.security.scep")
|
||||
scepPayload.PayloadDescription = "Configures SCEP"
|
||||
scepPayload.PayloadDisplayName = "SCEP"
|
||||
scepPayload.PayloadIdentifier = OTAProfileId + ".phase2.scep"
|
||||
scepPayload.PayloadOrganization = "MicroMDM"
|
||||
scepPayload.PayloadContent = scepContent
|
||||
scepPayload.PayloadScope = "System"
|
||||
profile.AddPayload(scepPayload)
|
||||
|
||||
profile.PayloadContent = append(profile.PayloadContent, *scepPayload)
|
||||
|
||||
return *profile, nil
|
||||
return profile, nil
|
||||
}
|
||||
|
||||
// OTAPhase3 returns a Profile for use in phase 3 of Over-the-Air profile enrollment.
|
||||
|
||||
Reference in New Issue
Block a user