mirror of
https://github.com/micromdm/micromdm/
synced 2026-08-10 19:46:07 +08:00
committed by
Victor Vrantchan
parent
fe50027f15
commit
4b867f1d04
@@ -53,7 +53,7 @@ func loadConfig() (*Config, error) {
|
||||
// APNS config. Can be either two files or a combined .p12 (like the one exported from keychain access")
|
||||
flPushCert = flag.String("push-cert", envString("MICROMDM_PUSH_CERT", ""), "path to push certificate")
|
||||
flPushPass = flag.String("push-password", envString("MICROMDM_PUSH_PASSWORD", ""), "push certificate password")
|
||||
flPushKey = flag.String("push-key", envString("MICROMDM_PUSH_KEY", ""), "path to push certificate private key(if not using a single .p12 file)")
|
||||
flPushKey = flag.String("push-key", envString("MICROMDM_PUSH_KEY", ""), "path to push certificate private key (if not using a single .p12 file)")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
|
||||
pushcertificate "github.com/RobotsAndPencils/buford/certificate"
|
||||
@@ -20,6 +25,8 @@ import (
|
||||
"github.com/micromdm/micromdm/enroll"
|
||||
"github.com/micromdm/micromdm/management"
|
||||
"github.com/micromdm/micromdm/workflow"
|
||||
|
||||
"golang.org/x/crypto/pkcs12"
|
||||
)
|
||||
|
||||
// setupServices uses the values from the config to set up the various components
|
||||
@@ -33,6 +40,7 @@ func setupServices(config *Config, logger log.Logger) (*serviceManager, error) {
|
||||
sm.setupWorkflowDatastore()
|
||||
sm.setupCertificateDatastore()
|
||||
|
||||
sm.loadPushCerts()
|
||||
sm.setupPushService()
|
||||
|
||||
sm.setupCommandService()
|
||||
@@ -55,6 +63,7 @@ type serviceManager struct {
|
||||
ApplicationDatastore application.Datastore
|
||||
|
||||
PushService *push.Service
|
||||
pushServiceCert
|
||||
|
||||
CommandService command.Service
|
||||
ManagementService management.Service
|
||||
@@ -68,15 +77,80 @@ type serviceManager struct {
|
||||
err error
|
||||
}
|
||||
|
||||
type pushServiceCert struct {
|
||||
*x509.Certificate
|
||||
PrivateKey interface{}
|
||||
}
|
||||
|
||||
func (s *serviceManager) loadPushCerts() {
|
||||
if s.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if s.APNS.PrivateKeyPath == "" {
|
||||
var pkcs12Data []byte
|
||||
pkcs12Data, s.err = ioutil.ReadFile(s.APNS.CertificatePath)
|
||||
if s.err != nil {
|
||||
return
|
||||
}
|
||||
s.pushServiceCert.PrivateKey, s.pushServiceCert.Certificate, s.err = pkcs12.Decode(pkcs12Data, s.APNS.PrivateKeyPass)
|
||||
return
|
||||
}
|
||||
|
||||
var pemData []byte
|
||||
pemData, s.err = ioutil.ReadFile(s.APNS.CertificatePath)
|
||||
if s.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pemBlock, _ := pem.Decode(pemData)
|
||||
if pemBlock == nil {
|
||||
s.err = errors.New("invalid PEM data for cert")
|
||||
return
|
||||
}
|
||||
s.pushServiceCert.Certificate, s.err = x509.ParseCertificate(pemBlock.Bytes)
|
||||
if s.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pemData, s.err = ioutil.ReadFile(s.APNS.PrivateKeyPath)
|
||||
if s.err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pemBlock, _ = pem.Decode(pemData)
|
||||
if pemBlock == nil {
|
||||
s.err = errors.New("invalid PEM data for privkey")
|
||||
return
|
||||
}
|
||||
s.pushServiceCert.PrivateKey, s.err = x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
|
||||
}
|
||||
|
||||
var oidASN1UserID = asn1.ObjectIdentifier{0, 9, 2342, 19200300, 100, 1, 1}
|
||||
|
||||
func topicFromCert(cert *x509.Certificate) (string, error) {
|
||||
for _, v := range cert.Subject.Names {
|
||||
if v.Type.Equal(oidASN1UserID) {
|
||||
return v.Value.(string), nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("Could not find Push Topic (UserID OID) in certificate")
|
||||
}
|
||||
|
||||
func (s *serviceManager) setupEnrollmentService() {
|
||||
if s.err != nil {
|
||||
return
|
||||
}
|
||||
pushTopic, err := topicFromCert(s.pushServiceCert.Certificate)
|
||||
if err != nil {
|
||||
s.err = err
|
||||
return
|
||||
}
|
||||
// TODO: clean up order of inputs. Maybe pass *SCEPConfig as an arg?
|
||||
// but if you do, the packages are coupled, better not.
|
||||
s.EnrollmentService, s.err = enroll.NewService(
|
||||
s.APNS.CertificatePath,
|
||||
s.APNS.PrivateKeyPass,
|
||||
pushTopic,
|
||||
s.Enrollment.CACertPath,
|
||||
s.SCEP.RemoteURL,
|
||||
s.SCEP.Challenge,
|
||||
@@ -155,15 +229,10 @@ func (s *serviceManager) setupPushService() {
|
||||
if s.err != nil {
|
||||
return
|
||||
}
|
||||
cert, key, err := pushcertificate.Load(
|
||||
s.APNS.CertificatePath,
|
||||
s.APNS.PrivateKeyPass,
|
||||
)
|
||||
if err != nil {
|
||||
s.err = err
|
||||
return
|
||||
}
|
||||
client, err := push.NewClient(pushcertificate.TLS(cert, key))
|
||||
client, err := push.NewClient(pushcertificate.TLS(
|
||||
s.pushServiceCert.Certificate,
|
||||
s.pushServiceCert.PrivateKey.(*rsa.PrivateKey),
|
||||
))
|
||||
if err != nil {
|
||||
s.err = err
|
||||
return
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package enroll
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"golang.org/x/crypto/pkcs12"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
const PushTopicASN1 string = "0.9.2342.19200300.100.1.1"
|
||||
|
||||
func GetPushTopicFromPKCS12(certPath string, certPass string) (string, error) {
|
||||
certData, err := ioutil.ReadFile(certPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
_, cert, err := pkcs12.Decode(certData, certPass)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, v := range cert.Subject.Names {
|
||||
if v.Type.String() == PushTopicASN1 {
|
||||
return v.Value.(string), nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("Could not find Push Topic in the provided pkcs12 bundle.")
|
||||
}
|
||||
@@ -10,13 +10,9 @@ type Service interface {
|
||||
Enroll(ctx context.Context) (Profile, error)
|
||||
}
|
||||
|
||||
func NewService(pushCertPath, pushCertPass, caCertPath, scepURL, scepChallenge, url, tlsCertPath, scepSubject string) (Service, error) {
|
||||
pushTopic, err := GetPushTopicFromPKCS12(pushCertPath, pushCertPass)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func NewService(pushTopic, caCertPath, scepURL, scepChallenge, url, tlsCertPath, scepSubject string) (Service, error) {
|
||||
var caCert, tlsCert []byte
|
||||
var err error
|
||||
|
||||
if caCertPath != "" {
|
||||
caCert, err = ioutil.ReadFile(caCertPath)
|
||||
|
||||
Reference in New Issue
Block a user