Sdílet prostřednictvím


Zásady zabezpečení obsahu

Zásady zabezpečení obsahu (CSP) jsou v současné době podporovány v aplikacích řízených modelem, plátnových a kódových aplikacích. Tento článek vysvětluje, jak nakonfigurovat CSP pro modelově řízené aplikace a aplikace typu plátno. Informace o programu CSP pro aplikace kódu najdete v dokumentaci k aplikacím kódu. Správci mohou řídit, zda se hlavička CSP odesílá a do určité míry i to, co obsahuje. Nastavení jsou na úrovni prostředí, což znamená, že se po zapnutí použijí pro všechny aplikace v prostředí.

Poznámka

Zásady zabezpečení obsahu se vztahují pouze na prostředí používající Dataverse.

Každá komponenta hodnoty hlavičky CSP řídí prostředky, které lze stáhnout. Mozilla Developer Network (MDN) poskytuje podrobnější popisy. Výchozí hodnoty jsou:

Direktiva Výchozí hodnota Přizpůsobitelné
skript-src * 'unsafe-inline' 'unsafe-eval' blob: Ne
worker-src 'self' blob: Ne
style-src * 'unsafe-inline' Ne
font-src * data: Ne
frame-ancestors 'self' https://*.powerapps.com Ano

Tato konfigurace má za následek výchozí CSP script-src * 'unsafe-inline' 'unsafe-eval' blob: ; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com;.

Striktní režim

Přepínač Strict CSP vytvoří CSP, která většinou neobsahuje zástupné znaky nebo nebezpečné směrnice, například unsafe-inline. Když zapnete Strict CSP, předchozí direktivy se stanou následujícími direktivy podrobnými v této části. Zápis <platform> znamená, že domény platformy jsou poskytovány podle požadavků produktu. Domény v této části se můžou v průběhu času měnit s růstem produktu.

Direktiva Výchozí hodnota (modelem řízená) Výchozí hodnota (plátno) Přizpůsobitelné
skript-src 'self' blob: <platform>' 'self' <platform>' Ano
worker-src 'self' blob: 'self' blob: Ne
style-src 'self' 'unsafe-inline' <platform> 'self' 'unsafe-inline' <platform> Ano
font-src 'self' data: <platform> 'self' data: <platform> Ano
frame-ancestors 'self' https://*.powerapps.com 'self' https://*.powerapps.com Ano
img-src 'self' blob: data: <platform> 'self' data: <platform> Ano
connect-src 'self' blob: data: wss: <platform> 'self' blob: <platform> Ano
frame-src 'self' blob: <platform> 'self' <platform> Ano
base-uri 'none' N/A Ne
form-action <platform> N/A Ano
default-src 'self' 'self' Ne

Požadavky

Pro aplikace Dynamics 365 Customer Engagement a další modelem řízené aplikace je CSP k dispozici pouze v online prostředích a v organizacích s Dynamics 365 Customer Engagement (on-premises) verze 9.1 nebo novější.

Konfigurace CSP

CSP můžete přepínat a konfigurovat prostřednictvím centra pro správu Power Platform. Je důležité nejprve povolit vývojové/testovací prostředí, protože povolení CSP by mohlo v případě porušení zásad začít blokovat scénáře. Centrum pro správu podporuje také režim pouze sestavy, aby umožnil snazší náběh výroby.

Ke konfiguraci CSP postupujte takto:

  1. Přihlaste se k centru pro správu Power Platform.
  2. V navigačním podokně vyberte Spravovat. V podokně Spravovat vyberte Prostředí.
  3. Na stránce Prostředí vyberte prostředí.
  4. Na panelu příkazů vyberte Nastavení.
  5. Rozbalte Produkt a vyberte Ochrana osobních údajů a zabezpečení.

Následující obrázek ukazuje výchozí stav nastavení.

Výchozí nastavení zásad zabezpečení obsahu.

Nahlašování

Přepínač Povolit vykazování řídí, zda modelem řízené aplikace a aplikace plátna odesílají hlášení o porušení. Pokud ho chcete povolit, zadejte koncový bod. Aplikace odesílá do tohoto koncového bodu sestavy porušení bez ohledu na to, zda je CSP vynuceno, nebo ne. Pokud není CSP vynucování, aplikace používá režim jen pro sestavy. Další informace získáte v dokumentaci k reportování.

Zapněte přepínač hlášení.

Vynucení

Vynucení CSP je řízeno nezávisle pro modelem řízené aplikace a aplikace plátna, aby bylo zajištěno podrobné ovládání zásad. K úpravě zamýšleného typu aplikace použijte pivot řízený modelem / plátna.

Přepínač Vynutit zásadu zabezpečení obsahu aktivuje výchozí zásady vynucení pro daný typ aplikace. Zapnutím tohoto přepínače změní chování aplikací v tomto prostředí tak, aby dodržovaly zásady. Proto postupujte podle tohoto navrhovaného toku povolení:

  1. Vynucujte zásady pro vývojové nebo testovací prostředí.
  2. Povolit režim pouze pro sestavy v produkci.
  3. Vynucujte zásadu v produkčním prostředí, jakmile se nenahlásí žádná porušení.

Konfigurace předpisů

Oddíl Konfigurovat direktivy umožňuje řídit jednotlivé direktivy v rámci zásad. V současné době můžete direktivu frame-ancestors přizpůsobit pouze.

Konfigurace zásad CSP.

Pokud ponecháte zapnutou výchozí direktivu, použijete výchozí hodnotu zadanou v tabulce. Pokud přepínač vypnete, můžete zadat vlastní hodnoty pro direktivu a připojit je k výchozí hodnotě. Následující příklad nastaví vlastní hodnoty pro frame-ancestors. Direktiva je v tomto příkladu nastavena frame-ancestors: 'self' https://*.powerapps.com https://www.foo.com https://www.bar.com . Toto nastavení znamená, že aplikace může být hostovaná ve stejném původu, https://*.powerapps.comhttps://www.foo.coma https://www.bar.com, ale ne v jiných zdrojích. Pomocí tlačítka Přidat přidáte položky do seznamu a pomocí ikony Odstranit je odstraníte.

Nastavení vlastních zásad CSP.

Běžné konfigurace

Při integraci Microsoft Teams pomocí aplikace Dynamics 365 přidejte následující do frame-ancestors:

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

Pro aplikaci Dynamics 365 App for Outlook přidejte následující do frame-ancestors:

  • Původ úvodní stránky webové aplikace Outlook
  • https://outlook.office.com
  • https://outlook.office365.com

Pro vložení Power Apps do sestav Power BI přidejte následující k frame-ancestors:

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

Důležitá poznámka

Vypnutí výchozí zásady a uložení s prázdným seznamem úplně vypne zásadu a neodesílá ji jako součást hlavičky odpovědi CSP.

Příklady konfigurace CSP

Tady je několik příkladů konfigurací CSP.

Příklad 1 – hlášení vypnuto

Příklad CSP 1, modelem řízený

CSP – příklad 1, plátno

V tomto příkladu:

  • Hlášení je vypnuto.
  • Modelem řízené vynucení je povoleno.
    • frame-ancestors je přizpůsoben na https://www.contoso.com a https://www.fabrikam.com.
  • Vynucení plátna je deaktivováno.

Efektivní hlavičky jsou:

  • Modelem řízené aplikace: Content-Security-Policy: script-src * 'unsafe-inline' 'unsafe-eval' blob: data:; worker-src 'self' blob: data:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors https://www.contoso.com https://www.fabrikam.com;
  • Canvas apps: Hlavička CSP se neodesílá.

Příklad 2 – hlášení zapnuto

Příklad CSP 2, modelem řízený

Příklad CSP 2, plátno

V tomto příkladu:

  • Hlášení je zapnuté.
    • Koncový bod pro vytváření sestav je nastaven na https://contoso.com/reporting-endpoint
  • Modelem řízené vynucení je povoleno.
    • frame-ancestors je zachováno jako výchozí
  • Vynucení plátna je deaktivováno.
    • frame-ancestors je přizpůsobeno na https://www.contoso.com

Platné hodnoty CSP jsou:

  • Modelem řízené aplikace: Content-Security-Policy: script-src * 'unsafe-inline' 'unsafe-eval' blob:; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com; report-uri https://contoso.com/reporting-endpoint;
  • Aplikace plátna: 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.contoso.com; report-uri https://contoso.com/reporting-endpoint;

Přímá úprava nastavení organizace

CSP můžete nakonfigurovat bez použití uživatelského rozhraní přímou úpravou těchto nastavení organizace:

  • IsContentSecurityPolicyEnabled řídí, zda se záhlaví Content-Security-Policy odesílá v modelem řízených aplikacích.

  • ContentSecurityPolicyConfiguration řídí hodnotu části frame-ancestors (jak je vidět výše, nastaví se na 'self' pokud ContentSecurityPolicyConfiguration není nastavena). Toto nastavení definujte pomocí objektu JSON s následující strukturou – { "Frame-Ancestor": { "sources": [ { "source": "foo" }, { "source": "bar" } ] } }. Tato konfigurace se promítá do script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'foo' 'bar';

    • (Z MDN) Direktiva HTTP Content-Security-Policy (CSP) frame-ancestors určuje platné nadřazené položky, které mohou vložit stránku pomocí <frame>, <iframe>, <object>, <embed>, nebo <applet>.
  • IsContentSecurityPolicyEnabledForCanvas řídí, zda se záhlaví Content-Security-Policy odesílá v aplikacích plátna.

  • Konfigurace ContentSecurityPolicyConfigurationForCanvas řídí zásady pro plátno pomocí stejného procesu popsaného v ContentSecurityPolicyConfiguration.

  • ContentSecurityPolicyReportUri řídí, zda by se mělo používat hlášení. Toto nastavení používají aplikace řízené modelem i aplikace plátna. Platný řetězec odesílá hlášení o porušení na zadaný koncový bod pomocí režimu pouze sestavy, pokud je IsContentSecurityPolicyEnabled/IsContentSecurityPolicyEnabledForCanvas vypnuté. Prázdný řetězec deaktivuje hlášení. Další informace získáte v dokumentaci k reportování.

Konfigurace CSP bez uživatelského rozhraní

Zejména pro prostředí, která nejsou v centru pro správu Power Platform, jako jsou místní konfigurace, mohou správci chtít nakonfigurovat CSP pomocí skriptů pro přímou úpravu nastavení.

Povolit CSP bez uživatelského rozhraní

Chcete-li povolit CSP bez uživatelského rozhraní, postupujte takto:

  • Otevřete vývojářské nástroje prohlížeče při používání modelem řízené aplikace jako uživatel s oprávněními pro aktualizaci organizační entity (Dobrou možností je správce systému).
  • Vložte a spusťte následující skript do konzoly.
  • Chcete-li povolit CSP, předejte výchozí konfiguraci - enableFrameAncestors(["'self'"])
  • Jako příklad povolení dalších zdrojů pro vložení aplikace - 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!')
}

Zakázat CSP bez uživatelského rozhraní

Chcete-li zakázat CSP bez uživatelského rozhraní, postupujte takto:

  • Otevřete vývojářské nástroje prohlížeče při používání modelem řízené aplikace jako uživatel s oprávněními pro aktualizaci organizační entity (Dobrou možností je správce systému).
  • Vložte a spusťte následující skript do konzoly.
  • Chcete-li CSP zakázat, vložte do konzoly: 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!')
}