Freigeben über


Inhaltssicherheitsrichtlinie

Richtlinie für Inhaltssicherheit (CSP) wird derzeit modellgesteuert und Canvas unterstützt Power Apps. Administratoren können steuern, ob der CSP-Header gesendet wird, und in gewissem Umfang, was er enthält. Die Einstellungen befinden sich auf der Ebene Umgebung, was bedeutet, dass sie nach dem Aktivieren auf Alle Apps in Umgebung angewendet werden.

Jede Komponente des CSP-Header-Werts steuert die Objekte, die heruntergeladen werden können, und wird im Mozilla Developer Network (MDN) ausführlicher beschrieben. Die Standardwerte sind wie folgt:

Richtlinie Standardwert Anpassbar
Skript-Quelle * 'unsafe-inline' 'unsafe-eval' Nein
Arbeiter-Quelle 'self' blob: Nein
Stil-Quelle * 'unsafe-inline' Nein
Schriftart-Quelle * data: Nein
Rahmen-Vorfahren 'self' https://*.powerapps.com Ja

Dies führt zu einem Standard-CSP von script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com;. In unserer Roadmap haben wir die Möglichkeit, derzeit nicht anpassbare Header zu ändern.

Anforderungen

  • Für Dynamics 365 Customer Engagement-Apps und andere modellgesteuerte Apps ist CSP nur in Onlineumgebungen und in Organisationen mit Dynamics 365 Customer Engagement (lokal), Version 9.1 oder höher, verfügbar.

CSP konfigurieren

CSP kann über das Power Platform Admin Center umgeschaltet und konfiguriert werden. Es ist wichtig, Umgebung zuerst bei einem Dev/Test zu aktivieren , da die Aktivierung von CSP bei einem Verstoß gegen die Richtlinie zu einer Blockierung von Szenarien führen könnte. Wir unterstützen außerdem einen „Nur-Bericht-Modus“, um einen einfacheren Produktionsstart zu ermöglichen.

Um CSP zu konfigurieren, navigieren Sie zum Power Platform Admin Center ->Umgebungen ->Einstellungen ->Sicherheit und Datenschutz. Das folgende Bild zeigt den Standardstatus der Einstellungen:

Standardeinstellungen der Inhaltssicherheitsrichtlinie

Berichterstellung

Der Schalter „Berichterstellung aktivieren“ steuert, ob Modellgesteuerte und Canvas-Apps Verstoßberichte senden. Um es zu aktivieren, muss ein Endpunkt angegeben werden. Berichte über Verstöße werden an diesen Endpunkt gesendet, unabhängig davon, ob CSP erzwungen wird oder nicht (unter Verwendung des Nur-Bericht-Modus, wenn CSP nicht erzwungen wird). Weitere Informationen finden Sie in der Dokumentation zur Berichterstellung.

Aktivieren des Berichterstellungsendpunkts

Durchsetzung

Die Durchsetzung von CSP wird für Modellgesteuerte und Canvas-Apps unabhängig gesteuert, um eine granulare Kontrolle über Richtlinien zu ermöglichen. Verwenden Sie die Modellgesteuerte/Canvas-Navigationssteuerung, um den beabsichtigten App-Typ zu ändern.

Der Schalter „Richtlinie für Inhaltssicherheit erzwingen“ aktiviert die Standardrichtlinie für die Durchsetzung für den angegebenen App-Typ. Durch Aktivieren dieses Schalters wird das Verhalten von Apps in dieser Umgebung geändert, um die Richtlinie einzuhalten. Daher wäre der vorgeschlagene Aktivierungsflow:

  1. In einer Entwicklungs-/Testumgebung erzwingen.
  2. Nur-Bericht-Modus in der Produktion aktivieren.
  3. In der Produktion erzwingen, sobald keine Verstöße gemeldet werden.

Richtlinien konfigurieren

In diesem Abschnitt können Sie einzelne Anweisungen innerhalb der Richtlinie steuern. Aktuell kann nur frame-ancestors angepasst werden.

CSP-Richtlinien konfigurieren

Wenn Sie die Standardanweisung aktiviert lassen, wird der Standardwert verwendet, der in der Tabelle weiter oben in diesem Artikel angegeben ist. Durch Deaktivieren des Schalters können Administratoren benutzerdefinierte Werte für die Direktive angeben und diese an den Standardwert anhängen. Im folgenden Beispiel werden benutzerdefinierte Werte für frame-ancestors festgelegt. Die Direktive wäre in diesem Beispiel auf frame-ancestors: 'self' https://*.powerapps.com https://www.foo.com https://www.bar.com gesetzt, was bedeutet, dass die App im selben Ursprung, https://*.powerapps.com, https://www.foo.com und https://www.bar.com, gehostet werden könnte, jedoch nicht in einem anderen Ursprung. Verwenden Sie die Schaltfläche „Hinzufügen“, um Einträge zur Liste hinzuzufügen, und das Symbol „Löschen“, um sie zu entfernen.

Festlegen benutzerdefinierter CSP-Richtlinien

Häufige Konfigurationen

Für die Microsoft Teams Integration mit der Dynamics 365-App fügen Sie Folgendes zu frame-ancestors hinzu:

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

Fügen Sie bei Dynamics 365 App for Outlook zu frame-ancestors Folgendes hinzu:

  • Der Ursprung Ihrer Outlook Web App-Startseite
  • https://outlook.office.com
  • https://outlook.office365.com

Um Power Apps in Power BI-Berichte einzubetten, fügen Sie Folgendes zu frame-ancestors hinzu:

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

Wichtige Überlegungen

Deaktivieren der Standarddirektive und Speichern mit einer leeren Liste deaktiviert die Direktive komplett und sendet sie nicht als Teil des CSP-Antwortheaders.

Beispiele

Werfen wir einen Blick auf ein paar Beispiele für die CSP-Konfiguration:

Beispiel 1

CSP-Beispiel 1

Im Beispiel:

  • Die Berichterstellung ist deaktiviert.
  • Die Modellgesteuerte Erzwingung ist aktiviert.
    • frame-ancestors ist angepasst an https://www.foo.com und https://www.bar.com
  • Canvas-Erzwingung ist deaktiviert.

Die effektiven Header wären:

  • Modellgesteuerte Apps: 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;
  • Canvas-Apps: CSP-Header würde nicht gesendet.

Beispiel 2

CSP-Beispiel 2

Im Beispiel:

  • Die Berichterstellung ist aktiviert.
    • Berichterstellungsendpunkt ist auf https://www.mysite.com/myreportingendpoint festgelegt
  • Die Modellgesteuerte Erzwingung ist aktiviert.
    • frame-ancestors wird als Standard beibehalten
  • Canvas-Erzwingung ist deaktiviert.
    • frame-ancestors ist angepasst an https://www.baz.com

Die effektiven CSP-Header wären:

  • Modellgesteuerte Apps: 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;
  • Canvas Apps: 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;

Organisationseinstellungen

CSP kann ohne Verwendung der Benutzeroberfläche konfiguriert werden, indem die folgenden Organisationseinstellungen direkt geändert werden:

  • IsContentSecurityPolicyEnabled steuert, ob der Content-Security-Policy-Header in modellgesteuerten Apps gesendet wird.

  • ContentSecurityPolicyConfiguration steuert den Wert des Frame-Ancestors-Abschnitts (wie oben zu sehen ist, wird es auf 'self' gesetzt, wenn ContentSecurityPolicyConfiguration nicht gesetzt ist). Diese Einstellung wird durch ein JSON-Objekt mit der folgenden Struktur dargestellt – { "Frame-Ancestor": { "sources": [ { "source": "foo" }, { "source": "bar" } ] } }. Dies würde übersetzt werden in script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'foo' 'bar';

    • (Von MDN) Die frame-ancestors-Direktive von HTTP Content-Security-Policy (CSP) gibt gültige übergeordnete Elemente an, die eine Seite mit <frame>, <iframe>, <object>, <embed> oder <applet> einbetten können.
  • IsContentSecurityPolicyEnabledForCanvas steuert, ob der Content-Security-Policy-Header in Canvas-Apps gesendet wird.

  • ContentSecurityPolicyConfigurationForCanvas steuert die Richtlinie für Canvas mit dem gleichen Prozess, der oben ContentSecurityPolicyConfiguration beschrieben ist.

  • ContentSecurityPolicyReportUri steuert, ob die Berichterstellung verwendet werden soll. Diese Einstellung wird sowohl von Modellgesteuerten Apps als auch von Canvas-Apps verwendet. Eine gültige Zeichenfolge sendet Verstoßberichte an den angegebenen Endpunkt, wobei der Nur-Bericht-Modus verwendet wird, wenn IsContentSecurityPolicyEnabled/IsContentSecurityPolicyEnabledForCanvas deaktiviert ist. Eine leere Zeichenfolge deaktiviert die Berichterstellung. Weitere Informationen finden Sie in der Dokumentation zur Berichterstellung.

Konfigurieren von CSP ohne Benutzeroberfläche

Besonders für Umgebungen, die nicht im Power Platform Admin Center sind, wie lokale Konfigurationen, möchten Administratoren möglicherweise CSP mithilfe von Skripts konfigurieren, um Einstellungen direkt zu ändern.

Aktivieren von CSP ohne Benutzeroberfläche

Schritte:

  • Öffnen Sie Browser-Entwicklertools, während Sie die Modellgesteuerte App als Benutzer mit Aktualisierungsberechtigungen für Organisationsentitäten verwenden (Systemadministrator ist eine gute Option).
  • Fügen Sie das folgende Skript in die Konsole ein, und führen Sie es aus.
  • Um CSP zu aktivieren, übergeben Sie die Standardkonfiguration - enableFrameAncestors(["'self'"])
  • Ein Beispiel für die Möglichkeit, die App anderen Ursprüngen zu ermöglichen - 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!')
}

Deaktivieren von CSP ohne Benutzeroberfläche

Schritte:

  • Öffnen Sie Browser-Entwicklertools, während Sie die Modellgesteuerte App als Benutzer mit Aktualisierungsberechtigungen für Organisationsentitäten verwenden (Systemadministrator ist eine gute Option).
  • Fügen Sie das folgende Skript in die Konsole ein und führen Sie es aus.
  • Um CSP zu deaktivieren, fügen Sie in die Konsole ein: 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!')
}