Criteri di sicurezza dei contenuti

Criteri di sicurezza del contenuto (CSP) è attualmente supportato nelle Power Apps canvas e basate su modello. Gli amministratori possono controllare se l'intestazione CSP viene inviata e, in una certa misura, cosa contiene. Le impostazioni sono a livello di ambiente, il che significa che verranno applicate a tutte le app nell'ambiente una volta attivate.

Ciascun componente di questo valore di intestazione CSP controlla le risorse che possono essere scaricate ed è descritto in modo più dettagliato su Mozilla Developer Network (MDN). I valori predefiniti sono i seguenti:

Direttiva Valore predefinito Personalizzabile
script-src * 'unsafe-inline' 'unsafe-eval' No
worker-src 'self' blob: No
style-src * 'unsafe-inline' No
font-src * data: No
frame-ancestors 'self'

Ciò si traduce in un CSP predefinito di script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self';. Nella nostra tabella di marcia, abbiamo la possibilità di modificare le intestazioni attualmente non personalizzabili.

Prerequisiti

  • Per le app Dynamics 365 Customer Engagement e altre app basate su modello, CSP è disponibile solo negli ambienti online e nelle organizzazioni con Dynamics 365 Customer Engagement (on-premises), versione 9.1 o successiva.

Configurazione di CSP

CSP può essere attivato configurato tramite l'interfaccia di amministrazione di Power Platform. È importante abilitare prima un ambiente di sviluppo/test poiché l'abilitazione di CSP potrebbe iniziare a bloccare gli scenari se i criteri vengono bloccati. Supportiamo anche una "modalità solo report" per consentire un più facile avvio in produzione.

Per configurare CSP, accedi all'interfaccia di amministrazione di Power Platform ->Ambienti - >Impostazioni>Privacy + Sicurezza. L'immagine seguente mostra lo stato predefinito delle impostazioni:

Impostazioni predefinite dei criteri di sicurezza dei contenuti

Report

L'interruttore "Abilita creazione report" controlla se le app basate su modello e canvas inviano segnalazioni di violazione. Per abilitarlo è necessario specificare un endpoint. Le segnalazioni di violazione vengono inviate a questo endpoint indipendentemente dal fatto che CSP sia applicato o meno (utilizzando la modalità di solo segnalazione se CSP non è applicato). Per altre informazioni, vedi la documentazione sulla creazione di report.

Abilitazione dell'endpoint di creazione di report

Applicazione

L'applicazione del CSP è controllata in modo indipendente per le app basate su modello e canvas per fornire un controllo granulare sui criteri. Usa il pivot basato su modello/canvas per modificare il tipo di app previsto.

L'interruttore "Abilita criteri di sicurezza contenuto" attiva i criteri predefiniti per l'applicazione per il tipo di app specificato. L'attivazione di questo interruttore cambia il comportamento delle app in questo ambiente per aderire alle norme. Pertanto, il flusso di abilitazione suggerito sarebbe:

  1. Applica su un ambiente di sviluppo/test.
  2. Abilita la modalità solo report in produzione.
  3. Applica in produzione una volta che non vengono segnalate violazioni.

Configurazione delle direttive

La sezione finale è "Configura direttive". Questa sezione consente di controllare le singole direttive all'interno dei criteri. Attualmente, solo frame-ancestors può essere personalizzato.

Configura direttive CSP

Lasciando attivata la direttiva predefinita viene utilizzato il valore predefinito specificato nella tabella mostrata in precedenza in questo articolo. La disattivazione dell'interruttore consente agli amministratori di specificare valori personalizzati per la direttiva e di aggiungerli al valore predefinito. L'esempio seguente imposta valori personalizzati per frame-ancestors. La direttiva verrebbe impostata su frame-ancestors: 'self' https://www.foo.com https://www.bar.com in questo esempio, il che significa che l'app potrebbe essere ospitata nella stessa origine, https://www.foo.com e https://www.bar.com, ma non in altre origini. Utilizza il pulsante Aggiungi per aggiungere voci all'elenco e l'icona Elimina per rimuoverle.

Impostazione delle direttive CSP personalizzate

Configurazioni comuni

Per l'integrazione di Microsoft Teams tramite l' app Dynamics 365, aggiungi quanto segue a frame-ancestors:

  • https://teams.microsoft.com/
  • https://msteamstabintegration.dynamics.com/

Per Dynamics 365 App for Outlook, è necessario aggiungere l'origine della home page di Outlook Web App a frame-ancestors.

Per l'integrazione di Power Apps nei report Power BI, aggiungi quanto segue a frame-ancestors:

  • https://app.powerbi.com
  • https://msi-pbi.pbi.microsoft.com

Considerazioni importanti

La disattivazione della direttiva predefinita e il salvataggio con un elenco vuoto disattiva completamente la direttiva e non la invia come parte dell'intestazione della risposta CSP.

Esempi

Diamo un'occhiata a un paio di esempi di configurazione CSP:

Esempio 1

Esempio di CSP 1

Nell'esempio sopra:

  • La creazione di report è disattivata.
  • L'applicazione basata su modello è abilitata.
    • frame-ancestors è personalizzato per https://www.foo.com e https://www.bar.com
  • L'applicazione canvas è disabilitata.

Le intestazioni effettive sarebbero:

  • App basate su modello: Content-Security-Policy: script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors https://www.foo.com https://www.bar.com;
  • App canvas: l'intestazione CSP non verrebbe inviata.

Esempio 2

Esempio di CSP 2

Nell'esempio sopra:

  • La creazione di report è attivata.
    • L'endpoint di creazione di report è impostato su https://www.mysite.com/myreportingendpoint
  • L'applicazione basata su modello è abilitata.
    • frame-ancestors viene mantenuto come impostazione predefinita
  • L'applicazione canvas è disabilitata.
    • frame-ancestors è personalizzato per https://www.baz.com

I valori CSP effettivi sarebbero:

  • App basate su modello: Content-Security-Policy: script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self'; report-uri https://www.mysite.com/myreportingendpoint;
  • App canvas: Content-Security-Policy-Report-Only: script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors https://www.baz.com; report-uri https://www.mysite.com/myreportingendpoint;

Impostazioni dell'organizzazione

È possibile configurare CSP senza utilizzare l'interfaccia utente modificando direttamente le seguenti impostazioni dell'organizzazione:

  • IsContentSecurityPolicyEnabled controlla se l'intestazione Content-Security-Policy viene inviata nelle app basate su modello.

  • ContentSecurityPolicyConfiguration controlla il valore della parte frame-ancestors (come visto sopra, è impostato su 'self' se ContentSecurityPolicyConfiguration non è impostato). Questa impostazione è rappresentata da un oggetto JSON con la struttura seguente: { "Frame-Ancestor": { "sources": [ { "source": "foo" }, { "source": "bar" } ] } }. Questo si tradurrebbe in script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'foo' 'bar';

    • (Da MDN) La direttiva frame-ancestors HTTP Content-Security-Policy (CSP) specifica i genitori validi che possono incorporare una pagina utilizzando <frame>, <iframe>, <object>, <embed>, o <applet>.
  • IsContentSecurityPolicyEnabledForCanvas controlla se l'intestazione Content-Security-Policy viene inviata nelle app canvas.

  • ContentSecurityPolicyConfigurationForCanvas controlla i criteri per canvas tela utilizzando lo stesso processo descritto in ContentSecurityPolicyConfiguration sopra.

  • ContentSecurityPolicyReportUri controlla se la creazione di report deve essere utilizzata. Questa impostazione viene utilizzata sia dalle app basate su modello che da quelle canvas. Una stringa valida invia i report di violazione al endpoint specificato, utilizzando la modalità solo report se IsContentSecurityPolicyEnabled/IsContentSecurityPolicyEnabledForCanvas è disattivato. Una stringa vuota disabilita la creazione di report. Per altre informazioni, vedi la documentazione sulla creazione di report.

Configurazione di CSP senza interfaccia utente

Soprattutto per ambienti fuori dall'interfaccia utente di Power Platform come le configurazioni locali, gli amministratori potrebbero voler configurare CSP utilizzando gli script per modificare direttamente le impostazioni.

Abilitazione di CSP senza interfaccia utente

Passaggi:

  • Apri gli strumenti di sviluppo del browser mentre utilizzi l'app basata su modello come utente con privilegi di aggiornamento dell'entità dell'organizzazione (Amministratore di sistema è una buona opzione).
  • Incolla ed esegui lo script seguente nella console.
  • Per abilitare la funzionalità CSP, passa la configurazione predefinita - enableFrameAncestors(["'self'"])
  • Come esempio di abilitazione di origini aggiuntive per incorporare l'app - enableFrameAncestors(["*.powerapps.com", "'self'", "abcxyz"])
async function enableFrameAncestors(sources) {
    const baseUrl = Xrm.Utility.getGlobalContext().getClientUrl();

    if (!Array.isArray(sources) || sources.some(s => typeof s !== 'string')) {
        throw new Error('sources must be a string array');
    }

    const orgResponse = await fetch(`${baseUrl}/api/data/v9.1/organizations`);
    if (!orgResponse.ok) throw new Error('Failed to retrieve org info');
    const orgs = await orgResponse.json();
    const { organizationid, contentsecuritypolicyconfiguration, iscontentsecuritypolicyenabled } = orgs.value[0];

    console.log(`Organization Id: ${organizationid}`);
    console.log(`CSP Enabled?: ${iscontentsecuritypolicyenabled}`);
    console.log(`CSP Config: ${contentsecuritypolicyconfiguration}`);

    const orgProperty = prop => `${baseUrl}/api/data/v9.1/organizations(${organizationid})/${prop}`;

    console.log('Updating CSP configuration...')
    const config = {
        'Frame-Ancestor': {
            sources: sources.map(source => ({ source })),
        },
    };
    const cspConfigResponse = await fetch(orgProperty('contentsecuritypolicyconfiguration'), {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            value: JSON.stringify(config),
        }),
    });

    if (!cspConfigResponse.ok) {
        throw new Error('Failed to update csp configuration');
    }
    console.log('Successfully updated CSP configuration!')

    if (iscontentsecuritypolicyenabled) {
        console.log('CSP is already enabled! Skipping update.')
        return;
    }

    console.log('Enabling CSP...')
    const cspEnableResponse = await fetch(orgProperty('iscontentsecuritypolicyenabled'), {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            value: true,
        }),
    });

    if (!cspEnableResponse.ok) {
        throw new Error('Failed to enable csp');
    }
    console.log('Successfully enabled CSP!')
}

Disabilitazione di CSP senza interfaccia utente

Passaggi:

  • Apri gli strumenti di sviluppo del browser mentre utilizzi l'app basata su modello come utente con privilegi di aggiornamento dell'entità dell'organizzazione (Amministratore di sistema è una buona opzione).
  • Incolla ed esegui lo script seguente nella console.
  • Per disabilitare CSP, incolla nella console: disableCSP()
async function disableCSP() {
    const baseUrl = Xrm.Utility.getGlobalContext().getClientUrl();

    const orgResponse = await fetch(`${baseUrl}/api/data/v9.1/organizations`);
    if (!orgResponse.ok) throw new Error('Failed to retrieve org info');
    const orgs = await orgResponse.json();
    const { organizationid, iscontentsecuritypolicyenabled } = orgs.value[0];

    console.log(`Organization Id: ${organizationid}`);
    console.log(`CSP Enabled?: ${iscontentsecuritypolicyenabled}`);

    const orgProperty = prop => `${baseUrl}/api/data/v9.1/organizations(${organizationid})/${prop}`;

    if (!iscontentsecuritypolicyenabled) {
        console.log('CSP is already disabled! Skipping update.')
        return;
    }

    console.log('Disabling CSP...')
    const cspEnableResponse = await fetch(orgProperty('iscontentsecuritypolicyenabled'), {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            value: false,
        }),
    });

    if (!cspEnableResponse.ok) {
        throw new Error('Failed to disable csp');
    }
    console.log('Successfully disabled CSP!')
}