httpapi

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 18 Imported by: 0

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

Index

Constants

View Source
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

func CertFromHeader(name string) func(http.Handler) http.Handler

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

func CertFromMdmSignature(o cms.VerifyOptions, maxBytes int64) func(http.Handler) http.Handler

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

func CertFromTLS(next http.Handler) http.Handler

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

func CheckinHandler(cfg Config) http.Handler

CheckinHandler serves the check-in URL.

func ConnectHandler

func ConnectHandler(cfg Config) http.Handler

ConnectHandler serves the server URL (command channel).

func Handler

func Handler(cfg Config) http.Handler

Handler routes by content type so both URLs can point at one path, as NanoMDM and MicroMDM deployments commonly do.

func IsCertMissing

func IsCertMissing(err error) bool

IsCertMissing reports whether err came from a missing certificate.

func WithCert

func WithCert(ctx context.Context, cert *x509.Certificate) context.Context

WithCert stores the device certificate in the context.

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.

type Connecter

type Connecter interface {
	Connect(ctx context.Context, r *mdm.Request, resp *mdm.Response) (*mdm.Command, error)
}

Connecter is the command half of the service.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL