Zasady zabezpieczeń zawartości

Zasady zabezpieczeń zawartości (CSP) są obecnie obsługiwane na podstawie modelu i kanwie Power Apps. Administratorzy mogą kontrolować, czy ma być wysyłany nagłówek CSP i, do pewnego stopnia, jego treści. To ustawienie jest na poziomie środowiska, co oznacza, że po włączeniu zostanie zastosowane do wszystkich aplikacji w środowisku.

Każdy składnik tej wartości nagłówka steruje zasobami, które można pobrać, i jest opisany bardziej szczegółowo w sieci Mozilla Developer Network (MDN). Wartości domyślne ukazano poniżej:

Dyrektywa Domyślna wartość Można dostosowywać
script-src * 'unsafe-inline' 'unsafe-eval' Nie
worker-src 'self' blob: Nie
style-src * 'unsafe-inline' Nie
font-src * data: Nie.
frame-ancestors 'self' https://*.powerapps.com Tak

W wyniku tego jest domyślnie domyślny script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com; W naszym harmonogramie jest dostępna możliwość modyfikowania nagłówków, które nie są obecnie dostępne do dostosowania.

Wymagania wstępne

  • W przypadku aplikacji Dynamics 365 Customer Engagement i innych aplikacji opartych na modelu CSP jest dostępne tylko w środowiskach online i organizacjach z Dynamics 365 Customer Engagement (on-premises) w wersji 9.1 lub nowszej.

Konfigurowanie CSP

Dostawcę CSP można przełączać i konfigurować za pośrednictwem centrum administracyjnego Power Platform. Ważne jest, aby najpierw włączyć środowisko projektowe/testowe, ponieważ włączenie programu CSP może rozpocząć blokowanie scenariuszy, jeśli zasady zostały naruszone. Planujemy w przyszłości obsługiwać „tryb tylko raportowania”, aby umożliwić łatwiejszy rozwój produkcji.

Aby skonfigurować program CSP, przejdź do centrum administracyjnego Power Platform ->Środowiska ->Ustawienia ->Prywatność + Bezpieczeństwo. Na poniższym obrazie przedstawiono domyślny stan ustawień:

Domyślne ustawienia zasad zabezpieczeń zawartości

Zgłaszanie

Przełączając funkcję "Włączanie raportowania", można określić, czy aplikacje oparte na modelach i kanwie wysyłają raporty o naruszeniech. Włączenie tej funkcji wymaga punkt końcowy danych. Do niniejszego raportu będą wysyłane raporty o naruszenie punkt końcowy niezależnie od tego, czy CSP jest wymuszany czy nie (jeśli nie jest wymuszany za pomocą trybu tylko do raportu). Aby uzyskać więcej informacji, zobacz dokumentację reportowania.

Włączanie punktu końcowego raportowania

Egzekwowanie

Wymuszanie CSP jest kontrolowane niezależnie w przypadku aplikacji opartych na modelach i kanw, aby zapewnić ziarnistą kontrolę nad zasadami. Użyj pivota na podstawie modelu/kanwy, aby zmodyfikować przeznaczony typ aplikacji.

Przełączenie "Wymuszaj stosowanie zasad zabezpieczeń zawartości" powoduje włączenie domyślnej zasady wymuszania dla danego typu aplikacji. Włączenie tego przełączania spowoduje zmianę zachowania aplikacji w tym środowisku w celu przestrzegania zasad. Dlatego sugerowany przepływ włączania powinien mieć:

  1. Wymuszanie w środowisku dewelopera/testowego.
  2. Włącz tryb tylko do raportu w środowisku produkcyjnym.
  3. Wymuszanie w środowisku produkcyjnym po tym, jak nie zgłaszane są żadne naruszenie.

Konfiguruj dyrektywy

Ostatnia sekcja to "Konfigurowanie konfiguracyjną". Ta sekcja umożliwia sterowanie poszczególnymi osobami w ramach zasad. Obecnie można dostosowywać frame-ancestors tylko te dostosowania.

Konfiguruj dyrektywy CSP

Pozostawienie domyślnej dyrektywy przełączania używa wartości domyślnej określonej w tabeli pokazanej wcześniej w tym artykule. Wyłączenie tego przełączania umożliwia administratorom określenie niestandardowych wartości dyrektywy i dołączenie ich do wartości domyślnej. W poniższym przykładzie przedstawiono niestandardowe wartości opcji frame-ancestors. W tym przykładzie ta dyrektywa powinna być ustawiona na wartość frame-ancestors: 'self' https://*.powerapps.com https://www.foo.com https://www.bar.com, czyli aplikacja może być hostowana w tym samym źródle, https://*.powerapps.com, https://www.foo.com i https://www.bar.com, ale nie w innych źródłach. Aby dodać pozycje do listy i usunąć ikony usuwania, użyj przycisku Dodaj.

Ustawianie niestandardowych dyrektyw CSP

Typowe konfiguracje

Dla integracji Microsoft Teams korzystającej z aplikacji Dynamics 365 dodaj następujące elementy do frame-ancestors:

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

Dla usługi Dynamics 365 App for Outlook należy też dodać stronę główną pochodzenia aplikacji Outlook w sieci Web do frame-ancestors.

Aby osadzić Power Apps w raportach Power BI, dodaj następujące elementy do frame-ancestors:

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

Ważne uwagi

Wyłączenie dyrektywy domyślnej i zapisanie pustej listy powoduje całkowite wyłączenie dyrektywy i nie jest wysyłana jako część nagłówka odpowiedzi CSP.

Przykłady

Zobaczmy kilka przykładów konfiguracji programu CSP:

Przykład 1

Przykład CSP 1

W powyższym przykładzie:

  • Raportowanie jest wyłączone.
  • Włączono funkcję wymuszania opartego na modelach.
    • frame-ancestors jest dostosowany do https://www.foo.com orazhttps://www.bar.com
  • Wykonanie kanw jest wyłączone.

Skuteczne nagłówki to:

  • Aplikacje oparte na modelu: 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;
  • Aplikacje kanw: nagłówek CSP nie jest wysyłany.

Przykład 2

Przykład CSP 2

W powyższym przykładzie:

  • Raportowanie jest włączone.
    • Punkt końcowy raportowania ustawiony na https://www.mysite.com/myreportingendpoint
  • Włączono funkcję wymuszania opartego na modelach.
    • frame-ancestors jest zachowywana jako domyślna
  • Wykonanie kanw jest wyłączone.
    • frame-ancestors jest dostosowany do https://www.baz.com

Efektywne wartości CSP byłyby następujące:

  • Aplikacje oparte na modelu: Content-Security-Policy: script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com; report-uri https://www.mysite.com/myreportingendpoint;
  • Aplikacje kanwy: 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;

Ustawienia organizacji

Program CSP można skonfigurować bez konieczności używania interfejsu użytkownika, modyfikując bezpośrednio następujące ustawienia organizacji:

  • IsContentSecurityPolicyEnabled określa, czy nagłówek zasad zabezpieczeń zawartości jest wysyłany na stronie aplikacji na modelu.

  • Kontrolka ContentSecurityPolicyConfiguration steruje wartością części elementów", na przykład 'self', jeśli nie ustawiono konfiguracji ContentSecurityPolicyConfiguration. To ustawienie jest reprezentowane przez obiekt JSON o następującej strukturze — { "Frame-Ancestor": { "sources": [ { "source": "foo" }, { "source": "bar" } ] } }. To miałoby przetłumaczyć na script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'foo' 'bar';

    • (Z MDN) Dyrektywa HTTP Content-Security-Policy (CSP) frame-ancestors określa prawidłowych rodziców, którzy mogą osadzić stronę za pomocą <frame>, <iframe>, <object>, <embed>, lub <applet>.
  • IsContentSecurityPolicyEnabledForCanvas określa, czy nagłówek zasad zabezpieczeń zawartości jest wysyłany na stronie aplikacji na kanwie.

  • ContentSecurityPolicyConfigurationForCanvas steruje zasadą dla kanw przy użyciu tego samego procesu opisanego powyżej ContentSecurityPolicyConfiguration.

  • Formant ContentSecurityPolicyReportUri określa, czy raportowanie ma być używane. To ustawienie jest używane zarówno przez aplikacje korzystające z modelu, jak i aplikacje z kanwą. Prawidłowy ciąg wyśle raporty naruszeń do określonego punktu końcowego przy użyciu trybu tylko raportów, jeśli opcja IsContentSecurityPolicyEnabled/IsContentSecurityPolicyEnabledForCanvas jest wyłączona. Pusty ciąg powoduje wyłączenie raportowania. Aby uzyskać więcej informacji, zobacz dokumentację reportowania.

Konfiguracja CSP bez interfejsu użytkownika

W szczególności w środowiskach Power Platform, które nie są dostępne w centrum administracyjnym, lokalny konfiguracji, administratorzy mogą chcieć skonfigurować program CSP za pomocą skryptów w celu bezpośredniej modyfikacji ustawień.

Włączanie programu CSP bez interfejsu użytkownika

Kroki:

  • Otwórz narzędzia do tworzenia przeglądarek, używając aplikacji korzystającej z modelu jako użytkownika z uprawnieniami do aktualizowania encji organizacji (rozwiązanie System Administrator jest dobrym rozwiązaniem).
  • Wklej i wykonaj poniższy skrypt do konsoli.
  • Aby włączyć CSP, należy przekazać konfigurację domyślną — enableFrameAncestors(["'self'"])
  • Przykład włączania dodatkowych pochodzenia do osadzenia aplikacji — 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!')
}

Wyłączanie programu CSP bez interfejsu użytkownika

Kroki:

  • Otwórz narzędzia do tworzenia przeglądarek, używając aplikacji korzystającej z modelu jako użytkownika z uprawnieniami do aktualizowania encji organizacji (rozwiązanie System Administrator jest dobrym rozwiązaniem).
  • Wklej i wykonaj poniższy skrypt do konsoli.
  • Aby wyłączyć CSP, wklej go do konsoli: 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!')
}