mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 00:49:03 +00:00
feat: return better errors when private key not configured (#19471)
> Related issue: #19464 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [x] Added/updated tests - [x] Manual QA for all new/changed functionality
This commit is contained in:
commit
aac7c0435f
6 changed files with 67 additions and 5 deletions
1
changes/19464-private-key-errors
Normal file
1
changes/19464-private-key-errors
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Adds clearer error messages when attempting to set up Apple MDM without a server private key configured.
|
||||
|
|
@ -32,7 +32,10 @@ const ApplePushCertSetup = ({
|
|||
onSetupSuccess();
|
||||
} catch (e) {
|
||||
const msg = getErrorReason(e);
|
||||
if (msg.toLowerCase().includes("invalid certificate")) {
|
||||
if (
|
||||
msg.toLowerCase().includes("invalid certificate") ||
|
||||
msg.toLowerCase().includes("required private key")
|
||||
) {
|
||||
renderFlash("error", msg);
|
||||
} else {
|
||||
renderFlash("error", "Couldn’t connect. Please try again.");
|
||||
|
|
@ -46,7 +49,10 @@ const ApplePushCertSetup = ({
|
|||
const onDownloadError = useCallback(
|
||||
(e: unknown) => {
|
||||
const msg = getErrorReason(e);
|
||||
if (msg.toLowerCase().includes("email address")) {
|
||||
if (
|
||||
msg.toLowerCase().includes("email address") ||
|
||||
msg.toLowerCase().includes("required private key")
|
||||
) {
|
||||
renderFlash("error", msg);
|
||||
} else {
|
||||
renderFlash("error", "Something’s gone wrong. Please try again.");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
import React, { FormEvent, useCallback, useMemo, useState } from "react";
|
||||
import React, {
|
||||
FormEvent,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useState,
|
||||
useContext,
|
||||
} from "react";
|
||||
|
||||
import mdmAppleBusinessManagerApi from "services/entities/mdm_apple_bm";
|
||||
import { NotificationContext } from "context/notification";
|
||||
import { getErrorReason } from "interfaces/errors";
|
||||
|
||||
import Icon from "components/Icon";
|
||||
import Button from "components/buttons/Button";
|
||||
|
|
@ -23,6 +31,7 @@ const useDownloadABMKey = ({
|
|||
onError,
|
||||
}: Omit<IDownloadABMKeyProps, "baseClass">) => {
|
||||
const [downloadState, setDownloadState] = useState<RequestState>(undefined);
|
||||
const { renderFlash } = useContext(NotificationContext);
|
||||
|
||||
const handleDownload = useCallback(
|
||||
async (evt: FormEvent) => {
|
||||
|
|
@ -34,6 +43,8 @@ const useDownloadABMKey = ({
|
|||
setDownloadState("success");
|
||||
onSuccess && onSuccess();
|
||||
} catch (e) {
|
||||
const msg = getErrorReason(e);
|
||||
renderFlash("error", msg);
|
||||
setDownloadState("error");
|
||||
onError && onError(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3592,6 +3592,16 @@ func (svc *Service) GenerateABMKeyPair(ctx context.Context) (*fleet.MDMAppleDEPK
|
|||
if err := svc.authz.Authorize(ctx, &fleet.AppleBM{}, fleet.ActionWrite); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
privateKey := svc.config.Server.PrivateKey
|
||||
if testSetEmptyPrivateKey {
|
||||
privateKey = ""
|
||||
}
|
||||
|
||||
if len(privateKey) == 0 {
|
||||
return nil, ctxerr.New(ctx, "Couldn't download public key. Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
|
||||
}
|
||||
|
||||
var publicKeyPEM, privateKeyPEM []byte
|
||||
assets, err := svc.ds.GetAllMDMConfigAssetsByName(ctx, []fleet.MDMAssetName{
|
||||
fleet.MDMAssetABMCert,
|
||||
|
|
|
|||
|
|
@ -936,6 +936,15 @@ func (s *integrationMDMTestSuite) TestGetMDMCSR() {
|
|||
t := s.T()
|
||||
ctx := context.Background()
|
||||
|
||||
// Validate errors if no private key is set
|
||||
testSetEmptyPrivateKey = true
|
||||
t.Cleanup(func() { testSetEmptyPrivateKey = false })
|
||||
s.uploadAPNSCert([]byte("-----BEGIN CERTIFICATE-----\nZm9vCg==\n-----END CERTIFICATE-----"), http.StatusInternalServerError, "Couldn't upload APNs certificate. Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
|
||||
|
||||
r := s.Do("GET", "/api/latest/fleet/mdm/apple/request_csr", getMDMAppleCSRRequest{}, http.StatusInternalServerError)
|
||||
require.Contains(t, extractServerErrorText(r.Body), "Couldn't download signed CSR. Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
|
||||
testSetEmptyPrivateKey = false
|
||||
|
||||
// ensure we leave everything in a clean state for other tests
|
||||
t.Cleanup(s.appleCoreCertsSetup)
|
||||
|
||||
|
|
@ -8674,6 +8683,14 @@ func (s *integrationMDMTestSuite) TestABMAssetManagement() {
|
|||
// ensure enable ABM again for other tests
|
||||
t.Cleanup(s.enableABM)
|
||||
|
||||
// Validate error when server private key not set
|
||||
testSetEmptyPrivateKey = true
|
||||
t.Cleanup(func() { testSetEmptyPrivateKey = false })
|
||||
|
||||
r := s.Do("GET", "/api/latest/fleet/mdm/apple/abm_public_key", generateABMKeyPairResponse{}, http.StatusInternalServerError)
|
||||
require.Contains(t, extractServerErrorText(r.Body), "Couldn't download public key. Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
|
||||
testSetEmptyPrivateKey = false
|
||||
|
||||
// grab the current public key
|
||||
var abmResp generateABMKeyPairResponse
|
||||
s.DoJSON("GET", "/api/latest/fleet/mdm/apple/abm_public_key", nil, http.StatusOK, &abmResp)
|
||||
|
|
|
|||
|
|
@ -2120,6 +2120,9 @@ func (svc *Service) ResendHostMDMProfile(ctx context.Context, hostID uint, profi
|
|||
// GET /mdm/apple/request_csr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Used for overriding the env var value in testing
|
||||
var testSetEmptyPrivateKey bool
|
||||
|
||||
type getMDMAppleCSRRequest struct{}
|
||||
|
||||
type getMDMAppleCSRResponse struct {
|
||||
|
|
@ -2143,8 +2146,13 @@ func (svc *Service) GetMDMAppleCSR(ctx context.Context) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if len(svc.config.Server.PrivateKey) == 0 {
|
||||
return nil, ctxerr.New(ctx, "no private key configured")
|
||||
privateKey := svc.config.Server.PrivateKey
|
||||
if testSetEmptyPrivateKey {
|
||||
privateKey = ""
|
||||
}
|
||||
|
||||
if len(privateKey) == 0 {
|
||||
return nil, ctxerr.New(ctx, "Couldn't download signed CSR. Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
|
||||
}
|
||||
|
||||
vc, ok := viewer.FromContext(ctx)
|
||||
|
|
@ -2298,6 +2306,15 @@ func (svc *Service) UploadMDMAppleAPNSCert(ctx context.Context, cert io.ReadSeek
|
|||
return err
|
||||
}
|
||||
|
||||
privateKey := svc.config.Server.PrivateKey
|
||||
if testSetEmptyPrivateKey {
|
||||
privateKey = ""
|
||||
}
|
||||
|
||||
if len(privateKey) == 0 {
|
||||
return ctxerr.New(ctx, "Couldn't upload APNs certificate. Missing required private key. Learn how to configure the private key here: https://fleetdm.com/learn-more-about/fleet-server-private-key")
|
||||
}
|
||||
|
||||
if cert == nil {
|
||||
return ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("certificate", "Invalid certificate. Please provide a valid certificate from Apple Push Certificate Portal."))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue