feat: upload apns cert

This commit is contained in:
Jahziel Villasana-Espinoza 2024-05-24 09:44:15 -04:00
parent b26bf4f57d
commit f4f247ef06
3 changed files with 78 additions and 3 deletions

View file

@ -694,6 +694,8 @@ type Service interface {
// write these to the DB. On subsequent calls, it will use the saved APNS key for generating the CSR.
GetMDMAppleCSR(ctx context.Context) ([]byte, error)
UploadMDMAppleAPNSCert(ctx context.Context, cert io.ReadSeeker) error
// GetHostDEPAssignment retrieves the host DEP assignment for the specified host.
GetHostDEPAssignment(ctx context.Context, host *Host) (*HostDEPAssignment, error)

View file

@ -495,8 +495,6 @@ func attachFleetAPIRoutes(r *mux.Router, svc fleet.Service, config config.FleetC
// Generative AI
ue.POST("/api/_version_/fleet/autofill/policy", autofillPoliciesEndpoint, autofillPoliciesRequest{})
ue.GET("/api/_version_/fleet/mdm/apple/request_csr", getMDMAppleCSREndpoint, getMDMAppleCSRRequest{})
// Only Fleet MDM specific endpoints should be within the root /mdm/ path.
// NOTE: remember to update
// `service.mdmConfigurationRequiredEndpoints` when you add an
@ -714,6 +712,9 @@ func attachFleetAPIRoutes(r *mux.Router, svc fleet.Service, config config.FleetC
ue.POST("/api/_version_/fleet/mdm/apple/request_csr", requestMDMAppleCSREndpoint, requestMDMAppleCSRRequest{})
ue.POST("/api/_version_/fleet/mdm/apple/dep/key_pair", newMDMAppleDEPKeyPairEndpoint, nil)
ue.GET("/api/_version_/fleet/mdm/apple/request_csr", getMDMAppleCSREndpoint, getMDMAppleCSRRequest{})
ue.POST("/api/_version_/fleet/mdm/apple/apns_certificate", uploadMDMAppleAPNSCertEndpoint, uploadMDMAppleAPNSCertRequest{})
// Deprecated: GET /mdm/apple_bm is now deprecated, replaced by the
// GET /abm endpoint.
ue.GET("/api/_version_/fleet/mdm/apple_bm", getAppleBMEndpoint, nil)

View file

@ -2221,6 +2221,78 @@ func (svc *Service) GetMDMAppleCSR(ctx context.Context) ([]byte, error) {
return nil, ctxerr.Wrap(ctx, err, "get signed CSR")
}
// Return signed CSR; these bytes are already base64 encoded
// Return signed CSR
return signedCSRB64, nil
}
type uploadMDMAppleAPNSCertRequest struct {
File *multipart.FileHeader
}
func (uploadMDMAppleAPNSCertRequest) DecodeRequest(ctx context.Context, r *http.Request) (interface{}, error) {
decoded := uploadSoftwareInstallerRequest{}
err := r.ParseMultipartForm(512 * units.MiB)
if err != nil {
return nil, &fleet.BadRequestError{
Message: "failed to parse multipart form",
InternalErr: err,
}
}
if r.MultipartForm.File["certificate"] == nil || len(r.MultipartForm.File["certificate"]) == 0 {
return nil, &fleet.BadRequestError{
Message: "certificate multipart field is required",
InternalErr: err,
}
}
decoded.File = r.MultipartForm.File["certificate"][0]
return &decoded, nil
}
type uploadMDMAppleAPNSCertResponse struct {
Err error `json:"error,omitempty"`
}
func (r uploadMDMAppleAPNSCertResponse) error() error {
return r.Err
}
func (r uploadMDMAppleAPNSCertResponse) Status() int { return http.StatusAccepted }
func uploadMDMAppleAPNSCertEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (errorer, error) {
req := request.(*uploadSoftwareInstallerRequest)
file, err := req.File.Open()
if err != nil {
return uploadMDMAppleAPNSCertResponse{Err: err}, nil
}
defer file.Close()
if err := svc.UploadMDMAppleAPNSCert(ctx, file); err != nil {
return &uploadMDMAppleAPNSCertResponse{Err: err}, nil
}
return &uploadMDMAppleAPNSCertResponse{}, nil
}
func (svc *Service) UploadMDMAppleAPNSCert(ctx context.Context, cert io.ReadSeeker) error {
if err := svc.authz.Authorize(ctx, &fleet.AppleCSR{}, fleet.ActionWrite); err != nil {
return ctxerr.Wrap(ctx, err)
}
// Get cert file bytes
certBytes, err := io.ReadAll(cert)
if err != nil {
return ctxerr.Wrap(ctx, err, "reading apns certificate")
}
// Save to DB
if err := svc.ds.InsertMDMConfigAssets(ctx, []fleet.MDMConfigAsset{
{Name: fleet.MDMAssetAPNSCert, Value: certBytes},
}); err != nil {
return ctxerr.Wrap(ctx, err, "writing apns cert to db")
}
return nil
}