mirror of
https://github.com/fleetdm/fleet
synced 2026-04-25 23:47:25 +00:00
Changes: - Created a new database model: `MicrosoftComplianceTenant`. A model that stores information about complaince tenants - Added `/policies/is-cloud-customer`: a policy that blocks requests to microsoft proxy endpoints if a `MS API KEY` header is missing or does not match a new config variable (`sails.custom.config.cloudCustomerCompliancePartnerSharedSecret`) - Added `microsoft-proxy/create-compliance-partner-tenant`: an action that creates a database record for a new compliance tenant and generates an API key that is used to authenticate future requests to microsoft proxy endpoints for an entra tenant. - Added `microsoft-proxy/get-compliance-partner-settings`: an action that returns information about Fleet's complaince partner entra application and the entra tenant's admin consent status (whether or not a tenant's entra admin has granted permissions to Fleet's compliance partner application) - Added `microsoft-proxy/get-tenants-admin-consent-status`: an action that updates the admin consent status of a compliance tenant record. - Added `microsoft-proxy/setup-compliance-partner-tenant`: an action that provisions a compliance tenant, creates a complaince policy for macOS devices assigns the created policy to the built-in "All users" user group on the tenants entra instance. - Added `microsoft-proxy/update-one-devices-compliance-status`: an action that receives information about a device on a compliance tenant's Fleet instance, sends that information to their Entra instance, and returns the messsage ID returned by the asynchronus Entra API. - Added `microsoft-proxy/get-one-compliance-status-result`: an action that returns the result of a compliance status update from the Entra API. - Added `sails.helpers.microsoft-proxy.get-access-token-and-api-urls` A helper that gets an access token for a tenant's entra instance and the URLs of the API endpoints the microsoft proxy actions use for a tenant. - Added `scripts/send-entra-heartbeat-requests` A script that will run daily to keep all microsoft compliance integrations provisioned. - --------- Co-authored-by: Lucas Rodriguez <[email protected]>
111 lines
4.3 KiB
JavaScript
Vendored
111 lines
4.3 KiB
JavaScript
Vendored
module.exports = {
|
|
|
|
|
|
friendlyName: 'Get access token and api urls',
|
|
|
|
|
|
description: 'Retreives an access token and the URLS of API endpoints for a Microsoft compliance tenant',
|
|
|
|
|
|
inputs: {
|
|
complianceTenantRecordId: {
|
|
type: 'number',
|
|
required: true,
|
|
}
|
|
},
|
|
|
|
|
|
exits: {
|
|
|
|
success: {
|
|
outputFriendlyName: 'Access token and api urls',
|
|
},
|
|
|
|
},
|
|
|
|
|
|
fn: async function ({complianceTenantRecordId}) {
|
|
|
|
let informationAboutThisTenant = await MicrosoftComplianceTenant.findOne({id: complianceTenantRecordId});
|
|
if(!informationAboutThisTenant) {
|
|
return new Error(`No matching tenant record could be found with the specified ID. (${complianceTenantRecordId}`);
|
|
}
|
|
|
|
// Get a graph access token for this tenant
|
|
let graphAccessTokenResponse = await sails.helpers.http.sendHttpRequest.with({
|
|
method: 'POST',
|
|
url: `https://login.microsoftonline.com/${informationAboutThisTenant.entraTenantId}/oauth2/v2.0/token`,
|
|
enctype: 'application/x-www-form-urlencoded',
|
|
body: {
|
|
client_id: sails.config.custom.compliancePartnerClientId,// eslint-disable-line camelcase
|
|
scope: 'https://graph.microsoft.com/.default',
|
|
client_secret: sails.config.custom.compliancePartnerClientSecret,// eslint-disable-line camelcase
|
|
grant_type: 'client_credentials'// eslint-disable-line camelcase
|
|
}
|
|
});
|
|
// Get a management API access token for this tenant
|
|
let manageAccessTokenResponse = await sails.helpers.http.sendHttpRequest.with({
|
|
method: 'POST',
|
|
url: `https://login.microsoftonline.com/${informationAboutThisTenant.entraTenantId}/oauth2/v2.0/token`,
|
|
enctype: 'application/x-www-form-urlencoded',
|
|
body: {
|
|
client_id: sails.config.custom.compliancePartnerClientId,// eslint-disable-line camelcase
|
|
scope: 'https://api.manage.microsoft.com//.default',
|
|
client_secret: sails.config.custom.compliancePartnerClientSecret,// eslint-disable-line camelcase
|
|
grant_type: 'client_credentials'// eslint-disable-line camelcase
|
|
}
|
|
});
|
|
|
|
// Parse the json response body to get the access token.
|
|
let graphAccessToken;
|
|
let manageApiAccessToken;
|
|
try {
|
|
graphAccessToken = JSON.parse(graphAccessTokenResponse.body).access_token;
|
|
manageApiAccessToken = JSON.parse(manageAccessTokenResponse.body).access_token;
|
|
} catch(err){
|
|
throw new Error(`When sending a request to get an access token for a Microsoft compliance tenant, an error occured. full error: ${require('util').inspect(err)}`);
|
|
}
|
|
|
|
// [?]: https://learn.microsoft.com/en-us/graph/api/resources/serviceprincipal
|
|
let servicePrincipalResponse = await sails.helpers.http.get.with({
|
|
url: `https://graph.microsoft.com/v1.0/servicePrincipals?$filter=${encodeURIComponent(`appId eq '0000000a-0000-0000-c000-000000000000'`)}`,
|
|
headers: {
|
|
'Authorization': `Bearer ${graphAccessToken}`
|
|
}
|
|
});
|
|
|
|
let servicePrincipalObjectId = servicePrincipalResponse.value[0].id;
|
|
|
|
// [?]: https://learn.microsoft.com/en-us/graph/api/group-list-endpoints
|
|
let servicePrincipalEndpointResponse = await sails.helpers.http.get.with({
|
|
url: `https://graph.microsoft.com/v1.0/servicePrincipals/${servicePrincipalObjectId}/endPoints`,
|
|
headers: {
|
|
'Authorization': `Bearer ${graphAccessToken}`
|
|
},
|
|
});
|
|
|
|
let endpointsInResponse = servicePrincipalEndpointResponse.value;
|
|
|
|
let tenantDataSyncService = _.find(endpointsInResponse, {providerName: 'PartnerTenantDataSyncService'});
|
|
if(!tenantDataSyncService) {
|
|
throw new Error(`When sending a request to get the PartnerTenantDataSyncService service principal of a Microsoft compliance tenant, no PartnerTenantDataSyncService service principal was found.`);
|
|
}
|
|
let tenantDataSyncUrl = tenantDataSyncService.uri;
|
|
|
|
let deviceDataSyncService = _.find(endpointsInResponse, {providerName: 'PartnerDeviceDataSyncService'});
|
|
if(!deviceDataSyncService) {
|
|
throw new Error(`When sending a request to get the PartnerDeviceDataSyncService service principal of a Microsoft compliance tenant, no PartnerDeviceDataSyncService service principal was found.`);
|
|
}
|
|
let deviceDataSyncUrl = deviceDataSyncService.uri;
|
|
|
|
return {
|
|
manageApiAccessToken,
|
|
graphAccessToken,
|
|
tenantDataSyncUrl,
|
|
deviceDataSyncUrl,
|
|
};
|
|
}
|
|
|
|
|
|
};
|
|
|