httpapi

package
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package httpapi exposes MDM check-in and command handlers and identity-certificate middleware.

Design

Handler dispatches PUT plist requests by content type, allowing check-in and server URLs to share a route. Certificate middleware extracts identity from Mdm-Signature, TLS or a configured proxy header for service authorization. Trust roots and proxy access controls must be configured; a header alone does not prove key possession.

Traditional MDM errors avoid 401. Recognized account-driven sessions can return Apple's typed reauthentication challenge so the device can retry. Unknown enrollments can receive the configured unrecognized-device response. Enrollment profile delivery belongs to mdmprotocol/enroll and server/internal/app.

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, opts ...HeaderOption) 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, or one that fails WithHeaderRoots, is rejected with 400; an absent header passes through.

Both WithHeaderRoots and WithHeaderPeers are required to accept an assertion.

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 CheckInURL and ServerURL can share a path.

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.

type HeaderOption

type HeaderOption func(*headerConfig)

HeaderOption configures CertFromHeader.

func WithHeaderPeers

func WithHeaderPeers(peers ...netip.Prefix) HeaderOption

WithHeaderPeers permits assertions only from these socket peer networks. X-Forwarded-For and similar headers do not establish proxy trust.

func WithHeaderRoots

func WithHeaderRoots(roots *x509.CertPool) HeaderOption

WithHeaderRoots verifies the header certificate chains to roots before it becomes the device identity.

A header carries no proof of possession, so on its own it is a statement by whatever sent the request. A device certificate is not secret: it travels to this server on every check-in and appears in the SCEP CertRep, so anyone who reaches the listener past the proxy can present another device's. Checking the chain narrows that to holders of a certificate the enrollment CA issued, and does not replace the proxy's responsibility to prove possession.

Jump to

Keyboard shortcuts

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