Share via


Stratégie de sécurité du contenu

La Stratégie de sécurité du contenu (CSP) est actuellement prise en charge dans les Power Apps canevas et pilotées par modèle. Les administrateurs peuvent contrôler si l’en-tête CSP est envoyé et, dans une certaine mesure, ce qu’il contient. Les paramètres sont au niveau de l’environnement, ce qui signifie qu’ils seraient appliqués à toutes les applications de l’environnement une fois activés.

Chaque composant de la valeur d’en-tête CSP contrôle les actifs pouvant être téléchargés et est décrit plus en détail sur le Mozilla Developer Network (MDN). Les valeurs par défaut sont les suivantes :

Instructions Valeur par défaut Personnalisable
script-src * 'unsafe-inline' 'unsafe-eval' Non
worker-src 'self' blob: Non
style-src * 'unsafe-inline' Non
font-src * data: Non
frame-ancestors 'self' https://*.powerapps.com Oui

Cela se traduit par une CSP par défaut de script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com;. Dans notre feuille de route, nous avons la possibilité de modifier les en-têtes actuellement non personnalisables.

Conditions préalables

  • Pour les applications Dynamics 365 Customer Engagement et les autres applications pilotées par modèle, CSP est uniquement disponible dans les environnements en ligne et dans les organisations équipées de Dynamics 365 Customer Engagement (on-premises), version 9.1 ou version ultérieure.

Configuration du fournisseur de solutions Cloud

La CSP peut être activée/désactivée et configurée dans le centre d’administration Power Platform. Il est important de l’activer d’abord dans un environnement de développement/test car l’activation de CSP pourrait commencer à bloquer les scénarios si la stratégie est violée. Nous prenons également en charge un « mode de rapport uniquement » pour permettre une montée en puissance plus facile de la production.

Pour configurer la CSP, accédez au Centre d’administration Power Platform ->Environnements ->Paramètres ->Confidentialité + Sécurité. L’image suivante montre l’état par défaut des paramètres :

Paramètres par défaut de la stratégie de sécurité du contenu

Signalement

Le bouton à bascule « Activer les rapports » contrôle si les applications pilotées par modèle et canevas envoient des rapports de violation. Son activation nécessite la spécification d’un point de terminaison. Les rapports de violation sont envoyés à ce point de terminaison, que la CSP soit appliquée ou non (en utilisant le mode rapport uniquement si la CSP n’est pas appliquée). Pour plus d’informations, consultez la documentation sur la génération de rapports.

Activation d’un point de terminaison de génération de rapports

Mise en application

L’application de la CSP est contrôlée indépendamment pour les applications pilotées par modèle et canevas afin de fournir un contrôle granulaire sur les stratégies. Utilisez le tableau croisé piloté par modèle/canevas pour modifier le type d’application souhaité.

Le bouton « Appliquer la stratégue de sécurité du contenu » active la stratégie d’application par défaut pour le type d’application donné. L’activation de ce bouton bascule modifie le comportement des applications dans cet environnement pour respecter la stratégie. Par conséquent, le flux d’activation suggéré serait :

  1. Appliquer dans un environnement de développement/test.
  2. Activer le mode rapport uniquement en production.
  3. Appliquer en production une fois qu’aucune violation n’est signalée.

Configuration des directives

La dernière section est « Configurer les directives ». Cette section vous permet de contrôler les directives individuelles au sein de la stratégie. Actuellement, seul frame-ancestors peut être personnalisé.

Configurer les directives CSP

Si vous laissez la directive par défaut activée, la valeur par défaut spécifiée dans le tableau affiché précédemment dans cet article est utilisée. La désactivation du bouton bascule permet aux administrateurs de spécifier des valeurs personnalisées pour la directive et de les ajouter à la valeur par défaut. L’exemple ci-dessous définit des valeurs personnalisées pour frame-ancestors. La directive serait définie sur frame-ancestors: 'self' https://*.powerapps.com https://www.foo.com https://www.bar.com dans cet exemple, ce qui signifie que l’application pourrait être hébergée dans la même origine, https://*.powerapps.com, https://www.foo.com et https://www.bar.com, mais pas dans d’autres origines. Utilisez le bouton Ajouter pour ajouter des entrées à la liste et l’icône de suppression pour en supprimer.

Définition de directives CSP personnalisées

Configurations courantes

Pour l’intégration de Microsoft Teams à l’aide de l’application Dynamics 365, ajoutez ce qui suit à frame-ancestors :

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

Pour Dynamics 365 App for Outlook, vous devez ajouter l’origine de votre page d’accueil Outlook Web App à frame-ancestors.

Pour l’intégration de Power Apps dans les rapports Power BI, ajoutez ce qui suit à frame-ancestors :

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

Remarques importantes

La désactivation de la directive par défaut et son enregistrement avec une liste vide désactive complètement la directive et ne l’envoie pas dans le cadre de l’en-tête de réponse CSP.

Examples

Jetons un coup d’œil à quelques exemples de configuration CSP :

Exemple 1

Exemple CSP 1

Dans l’exemple ci-dessus :

  • La génération de rapports est désactivée.
  • L’application pilotée par modèle est activée.
    • frame-ancestors est personnalisé pour https://www.foo.com et https://www.bar.com
  • L’application canevas est désactivée.

Les en-têtes effectifs seraient :

  • Applications pilotées par modèle : 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;
  • Applications canevas : l’en-tête CSP ne serait pas envoyé.

Exemple 2

Exemple CSP 2

Dans l’exemple ci-dessus :

  • La génération de rapports est activée.
    • Le point de terminaison de génération de rapports est défini sur https://www.mysite.com/myreportingendpoint
  • L’application pilotée par modèle est activée.
    • frame-ancestors est conservé par défaut
  • L’application canevas est désactivée.
    • frame-ancestors est personnalisé pour https://www.baz.com

Les valeurs CSP effectives seraient :

  • Applications pilotées par modèle : 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;
  • Applications canevas : 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;

Paramètres de l’organisation

La CSP peut être configurée sans utiliser l’interface utilisateur en modifiant directement les paramètres d’organisation suivants :

  • IsContentSecurityPolicyEnabled contrôle si l’en-tête Content-Security-Policy est envoyée dans les applications pilotées par modèle.

  • ContentSecurityPolicyConfiguration contrôle la valeur de la partie frame-ancestors (comme vu ci-dessus, elle est définie sur 'self' si ContentSecurityPolicyConfiguration n’est pas défini). Ce paramètre est représenté par un objet JSON avec la structure suivante - { "Frame-Ancestor": { "sources": [ { "source": "foo" }, { "source": "bar" } ] } }. Cela se traduirait par script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'foo' 'bar';

    • (À partir de MDN) La directive HTTP Content-Security-Policy (CSP) frame-ancestors spécifie des parents valides qui peuvent intégrer une page à l’aide de <frame>, <iframe>, <object>, <embed> ou <applet>.
  • IsContentSecurityPolicyEnabledForCanvas contrôle si l’en-tête Content-Security-Policy est envoyée dans les applications canevas.

  • ContentSecurityPolicyConfigurationForCanvas contrôle la stratégie pour les applications canevas en utilisant le même processus décrit dans ContentSecurityPolicyConfiguration ci-dessus.

  • ContentSecurityPolicyReportUri contrôle si la génération de rapports doit être utilisée. Ce paramètre est pris en charge à la fois dans les applications pilotées par modèle et les applications canevas. Une chaîne valide envoie les rapports de violation au point de terminaison spécifié, en utilisant le mode rapport uniquement si IsContentSecurityPolicyEnabled/IsContentSecurityPolicyEnabledForCanvas est désactivé. Une chaîne vide désactive la création de rapports. Pour plus d’informations, consultez la documentation sur la génération de rapports.

Configurer la CSP sans interface utilisateur

En particulier pour les environnements qui ne se trouvent pas dans le Centre d’administration de Power Platform, tels que les configurations locales, les administrateurs peuvent souhaiter configurer la CSP à l’aide de scripts pour modifier directement les paramètres.

Activation de la CSP sans interface utilisateur

Étapes :

  • Ouvrez les outils de développement du navigateur tout en utilisant l’application basée sur un modèle en tant qu’utilisateur disposant des privilèges de mise à jour de l’entité de l’organisation (Administrateur système est une bonne option).
  • Collez et exécutez le script ci-dessous dans la console.
  • Pour activer simplement la stratégie CSP, transmettez la configuration par défaut - enableFrameAncestors(["'self'"])
  • À titre d’exemple d’activation d’origines supplémentaires pour intégrer l’application - 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!')
}

Désactivation de la CSP sans interface utilisateur

Étapes :

  • Ouvrez les outils de développement du navigateur tout en utilisant l’application basée sur un modèle en tant qu’utilisateur disposant des privilèges de mise à jour de l’entité de l’organisation (Administrateur système est une bonne option).
  • Collez et exécutez le script ci-dessous dans la console.
  • Pour désactiver le fournisseur de solutions Cloud, collez dans la 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!')
}