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:
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.
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:
- In einer Entwicklungs-/Testumgebung erzwingen.
- Nur-Bericht-Modus in der Produktion aktivieren.
- 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.
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.
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
Im Beispiel:
- Die Berichterstellung ist deaktiviert.
- Die Modellgesteuerte Erzwingung ist aktiviert.
frame-ancestors
ist angepasst anhttps://www.foo.com
undhttps://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
Im Beispiel:
- Die Berichterstellung ist aktiviert.
- Berichterstellungsendpunkt ist auf
https://www.mysite.com/myreportingendpoint
festgelegt
- Berichterstellungsendpunkt ist auf
- Die Modellgesteuerte Erzwingung ist aktiviert.
frame-ancestors
wird als Standard beibehalten
- Canvas-Erzwingung ist deaktiviert.
frame-ancestors
ist angepasst anhttps://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, wennContentSecurityPolicyConfiguration
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 inscript-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.
- (Von MDN) Die frame-ancestors-Direktive von HTTP Content-Security-Policy (CSP) gibt gültige übergeordnete Elemente an, die eine Seite mit
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!')
}