diff --git a/frontend/pages/admin/IntegrationsPage/cards/Mdm/Mdm.tsx b/frontend/pages/admin/IntegrationsPage/cards/Mdm/Mdm.tsx index 02e47179af..26d31e7fc4 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/Mdm/Mdm.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/Mdm/Mdm.tsx @@ -20,21 +20,21 @@ import { readableDate } from "utilities/helpers"; import RequestCSRModal from "./components/RequestCSRModal"; import EditTeamModal from "./components/EditTeamModal"; -// MDM TODO: key validation? -// import { isValidKeys } from "../../.."; +interface IABMKeys { + decodedPublic: string; + decodedPrivate: string; +} const baseClass = "mdm-integrations"; const Mdm = (): JSX.Element => { - const { isPremiumTier } = useContext(AppContext); + const { isPremiumTier, config } = useContext(AppContext); const { renderFlash } = useContext(NotificationContext); const [showRequestCSRModal, setShowRequestCSRModal] = useState(false); const [showEditTeamModal, setShowEditTeamModal] = useState(false); const [defaultTeamName, setDefaultTeamName] = useState("No team"); - const [showCSRFlag, setShowCSRFlag] = useState(true); - const { data: appleAPNInfo, isLoading: isLoadingMdmApple, @@ -43,7 +43,7 @@ const Mdm = (): JSX.Element => { ["appleAPNInfo"], () => mdmAppleAPI.getAppleAPNInfo(), { - enabled: isPremiumTier, + enabled: isPremiumTier && config?.mdm.enabled_and_configured, staleTime: 5000, } ); @@ -56,7 +56,7 @@ const Mdm = (): JSX.Element => { ["mdmAppleBmAPI"], () => mdmAppleBmAPI.getAppleBMInfo(), { - enabled: isPremiumTier, + enabled: isPremiumTier && config?.mdm.enabled_and_configured, staleTime: 5000, onSuccess: (appleBmData) => { setDefaultTeamName(appleBmData.default_team ?? "No team"); @@ -64,12 +64,11 @@ const Mdm = (): JSX.Element => { } ); - // MDM TODO: Test manually after backend is merged const { data: keys, error: fetchKeysError, isFetching: isFetchingKeys, - } = useQuery(["keys"], () => mdmAppleBmAPI.loadKeys(), { + } = useQuery(["keys"], () => mdmAppleBmAPI.loadKeys(), { enabled: isPremiumTier, refetchOnWindowFocus: false, }); @@ -95,14 +94,26 @@ const Mdm = (): JSX.Element => { } if (keys) { - // MDM TODO: Validate keys like we validate certificates? - // if (keys && isValidKeys(keys)) { - const filename = "fleet.pem"; - const file = new global.window.File([keys], filename, { - type: "application/x-pem-file", - }); + const publicFilename = "fleet-apple-mdm-bm-public-key.crt"; + const publicFile = new global.window.File( + [keys.decodedPublic], + publicFilename, + { + type: "application/x-pem-file", + } + ); - FileSaver.saveAs(file); + const privateFilename = "fleet-apple-mdm-bm-private.key"; + const privateFile = new global.window.File( + [keys.decodedPublic], + privateFilename, + { + type: "application/x-pem-file", + } + ); + + FileSaver.saveAs(publicFile); + FileSaver.saveAs(privateFile); } else { renderFlash( "error", diff --git a/frontend/services/entities/mdm_apple_bm.ts b/frontend/services/entities/mdm_apple_bm.ts index 38b54cdde0..0331661339 100644 --- a/frontend/services/entities/mdm_apple_bm.ts +++ b/frontend/services/entities/mdm_apple_bm.ts @@ -3,8 +3,6 @@ import sendRequest from "services"; import endpoints from "utilities/endpoints"; export default { - // TODO: set up full MDM testing environment, including all keys/credentials/tokens, to be able to - // get proper data from this API as opposed to the mock backend above getAppleBMInfo: () => { const { MDM_APPLE_BM } = endpoints; const path = MDM_APPLE_BM; @@ -14,19 +12,20 @@ export default { const { MDM_APPLE_BM_KEYS } = endpoints; const path = MDM_APPLE_BM_KEYS; - // MDM TODO: Originally written for certificate_chain for certificate, refactor for keys when backend is merged - return sendRequest("GET", path).then(({ certificate_chain }) => { - let decodedKeys; + return sendRequest("POST", path).then(({ private_key, public_key }) => { + let decodedPublic; + let decodedPrivate; try { - decodedKeys = global.window.atob(certificate_chain); + decodedPublic = global.window.atob(public_key); + decodedPrivate = global.window.atob(private_key); } catch (err) { return Promise.reject(`Unable to decode keys: ${err}`); } - if (!decodedKeys) { + if (!decodedPrivate || !decodedPublic) { return Promise.reject("Missing or undefined keys."); } - return Promise.resolve(decodedKeys); + return Promise.resolve({ decodedPublic, decodedPrivate }); }); }, }; diff --git a/frontend/utilities/endpoints.ts b/frontend/utilities/endpoints.ts index 8fd7087849..677030b783 100644 --- a/frontend/utilities/endpoints.ts +++ b/frontend/utilities/endpoints.ts @@ -37,7 +37,7 @@ export default { // TODO: Clean up MDM endpoints to be consistent and up to date MDM_APPLE: `/${API_VERSION}/fleet/mdm/apple`, MDM_APPLE_BM: `/${API_VERSION}/fleet/mdm/apple_bm`, - MDM_APPLE_BM_KEYS: `/${API_VERSION}/fleet/mdm/apple_bm/keys`, + MDM_APPLE_BM_KEYS: `/${API_VERSION}/fleet/mdm/apple/dep/key_pair`, MDM_SUMMARY: `/${API_VERSION}/fleet/hosts/summary/mdm`, MDM_REQUEST_CSR: `/${API_VERSION}/fleet/mdm/apple/request_csr`, // Should below 2 endpoints be consistent? diff --git a/server/service/handler.go b/server/service/handler.go index 305bdd87cf..c330921e56 100644 --- a/server/service/handler.go +++ b/server/service/handler.go @@ -437,11 +437,11 @@ func attachFleetAPIRoutes(r *mux.Router, svc fleet.Service, config config.FleetC ue.GET("/api/_version_/fleet/mdm/apple/installers", listMDMAppleInstallersEndpoint, listMDMAppleInstallersRequest{}) ue.GET("/api/_version_/fleet/mdm/apple/devices", listMDMAppleDevicesEndpoint, listMDMAppleDevicesRequest{}) ue.GET("/api/_version_/fleet/mdm/apple/dep/devices", listMDMAppleDEPDevicesEndpoint, listMDMAppleDEPDevicesRequest{}) - ue.POST("/api/_version_/fleet/mdm/apple/dep/key_pair", newMDMAppleDEPKeyPairEndpoint, nil) // host-specific mdm commands ue.PATCH("/api/_version_/fleet/mdm/hosts/{id:[0-9]+}/unenroll", mdmAppleCommandRemoveEnrollmentProfileEndpoint, mdmAppleCommandRemoveEnrollmentProfileRequest{}) } + ue.POST("/api/_version_/fleet/mdm/apple/dep/key_pair", newMDMAppleDEPKeyPairEndpoint, nil) ue.GET("/api/_version_/fleet/mdm/apple", getAppleMDMEndpoint, nil) ue.GET("/api/_version_/fleet/mdm/apple_bm", getAppleBMEndpoint, nil) // this endpoint must always be accessible (even if MDM is not configured) as