Documentation
¶
Overview ¶
Package httpapi exposes the service layer over HTTP the way Apple devices expect: a check-in URL and a server URL that accept PUT requests carrying plists, identified by content type, plus the middlewares that extract the device identity certificate from TLS, a proxy header, or the Mdm-Signature header.
Why ¶
Apple devices speak a narrow HTTP dialect: PUT, a plist body, an identity proven by a client certificate or a detached CMS signature, and a small set of status codes with fixed meanings. Phase 2 of the plan of record needs handlers that map that dialect onto the typed service interfaces without leaking transport concerns into them. Handler routes by content type so both URLs can point at one path, as NanoMDM and MicroMDM deployments commonly do, and the certificate middlewares put the verified identity in the request context for the service to pin.
The handlers never return 401: some Apple clients treat it as a reason to unenroll (decision record 0006). Unknown enrollments get 403, with Apple's ErrorUnrecognizedDevice body only when the deployment opts in. Enrollment profile delivery and the OTA profile service live in enroll, the DDM endpoints in the ddm/adapter packages, and the reference server wiring in phase 8.
References ¶
- Decision record 0004: docs/research/decisions/0004-checkin-and-command-core.md
- Decision record 0006: docs/research/decisions/0006-mdm-signature-verification.md
- Plan of record: docs/research/implementation_plan.md (phase 2)
- Threat model: docs/security/threat-model.md (/checkin and /connect rows)
- End-to-end scenarios: docs/testing/e2e-scenarios.md (E2E-001 to E2E-005)
- Apple: https://developer.apple.com/documentation/devicemanagement/check-in
- Apple: https://developer.apple.com/documentation/devicemanagement/managing-connections
- Schema: third_party/device-management/mdm/checkin/*.yaml
- Schema: third_party/device-management/mdm/errors/*.yaml
Index ¶
- Constants
- func CertFromContext(ctx context.Context) *x509.Certificate
- func CertFromHeader(name string) func(http.Handler) http.Handler
- func CertFromMdmSignature(o cms.VerifyOptions, maxBytes int64) func(http.Handler) http.Handler
- func CertFromTLS(next http.Handler) http.Handler
- func CheckinHandler(cfg Config) http.Handler
- func ConnectHandler(cfg Config) http.Handler
- func Handler(cfg Config) http.Handler
- func IsCertMissing(err error) bool
- func WithCert(ctx context.Context, cert *x509.Certificate) context.Context
- type Checkiner
- type Config
- type Connecter
Constants ¶
const ( ContentTypeCheckin = "application/x-apple-aspen-mdm-checkin" ContentTypeConnect = "application/x-apple-aspen-mdm" )
Content types Apple devices send.
Variables ¶
This section is empty.
Functions ¶
func CertFromContext ¶
func CertFromContext(ctx context.Context) *x509.Certificate
CertFromContext returns the device certificate stored by a middleware, or nil.
func CertFromHeader ¶
CertFromHeader takes the device certificate from a header set by a TLS terminating proxy. Two encodings are accepted: RFC 9440 (":<base64 DER>:") and URL-escaped PEM, as nginx and Apache produce. A malformed header is rejected with 400; an absent header passes through.
func CertFromMdmSignature ¶
CertFromMdmSignature verifies the Mdm-Signature header over the request body and takes the signer as the device certificate. The body is read (bounded by maxBytes, 0 for the plist default) and handed on to the next handler. A missing header passes through; an invalid signature is 400.
func CertFromTLS ¶
CertFromTLS takes the device certificate from the TLS peer certificates (mutual TLS terminated by this process). Requests without one pass through unchanged; the service decides whether that is acceptable.
func CheckinHandler ¶
CheckinHandler serves the check-in URL.
func ConnectHandler ¶
ConnectHandler serves the server URL (command channel).
func Handler ¶
Handler routes by content type so both URLs can point at one path, as NanoMDM and MicroMDM deployments commonly do.
func IsCertMissing ¶
IsCertMissing reports whether err came from a missing certificate.
Types ¶
type Checkiner ¶
type Checkiner interface {
Checkin(ctx context.Context, r *mdm.Request, ck *mdm.Checkin) (*service.CheckinResult, error)
}
Checkiner is the check-in half of the service.
type Config ¶
type Config struct {
Checkin Checkiner
Connect Connecter
// Logger defaults to slog.Default.
Logger *slog.Logger
// Decoder sets plist limits; zero means the defaults.
Decoder plist.Decoder
// UnenrollUnknown answers unknown enrollments with Apple's
// ErrorUnrecognizedDevice body, which makes the device unenroll. Off
// by default because it is irreversible for the device.
UnenrollUnknown bool
// Now defaults to time.Now.
Now func() time.Time
}
Config builds handlers.