Share via


Directiva de seguridad de contenido

Política de seguridad de contenido (CSP) actualmente es compatible con Power Apps basadas en modelo y de lienzo. Los administradores pueden controlar si se envía el encabezado CSP y, hasta cierto punto, qué contiene. La configuración se encuentra en el nivel del entorno, lo que significa que se aplicaría a todas las aplicaciones del entorno una vez activadas.

Cada componente del valor de encabezado CSP controla los activos que se pueden descargar y se describe con más detalle en Red para desarrolladores de Mozilla (MDN). Los valores predeterminados son los siguientes:

Directiva Valor predeterminado Personalizable
script-src * 'unsafe-inline' 'unsafe-eval' No
worker-src 'self' blob: No
style-src * 'unsafe-inline' No
font-src * data: No
frame-ancestors 'self' https://*.powerapps.com

Esto da como resultado un CSP predeterminado de script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com;. En nuestra hoja de ruta, tenemos la capacidad de modificar encabezados actualmente no personalizables.

Requisitos previos

  • Para las aplicaciones Dynamics 365 Customer Engagement y otras aplicaciones basadas en modelos, CSP solo está disponible en entornos en línea y en organizaciones con Dynamics 365 Customer Engagement (on-premises), versión 9.1 o posterior.

Configurando CSP

CSP se puede cambiar y configurar mediante el centro de administración de Power Platform. Es importante habilitar primero en un entorno de desarrollo/prueba ya que si habilita el CSP podría comenzar a bloquear escenarios si se infringe la directiva. También admitimos un "modo de solo informe" para permitir un aumento más fácil en producción.

Para configurar CSP, vaya al Centro de administración de Power Platform ->Entornos ->Ajustes ->Privacidad + Seguridad. La siguiente imagen muestra el estado predeterminado de la configuración:

Configuración predeterminada de la política de seguridad de contenido

Denunciando

La opción "Habilitar informes" controla si las aplicaciones basadas en modelos y de lienzo envían informes de infracciones. Habilitarlo requiere que se especifique un punto de conexión. Los informes de infracciones se envían a este punto de conexión independientemente de si CSP se aplica o no (usando el modo de solo informe si CSP no se aplica). Para obtener más información, consulte la documentación de informes.

Habilitar el extremo de informes

Aplicación

La aplicación de CSP se controla de forma independiente para aplicaciones de lienzo y basadas en modelos para proporcionar un control granular sobre las políticas. Use el pivote basado en modelo/lienzo para modificar el tipo de aplicación previsto.

La opción de alternancia "Habilitar directiva de seguridad de contenido" activa la directiva predeterminada de aplicación para el tipo de aplicación determinado. Activar esta opción cambia el comportamiento de las aplicaciones en este entorno para cumplir con la política. Por lo tanto, el flujo de habilitación sugerido sería:

  1. Aplicar en un entorno de desarrollo/prueba.
  2. Habilite el modo de solo informe en producción.
  3. Hacer cumplir en producción una vez que no se informen infracciones.

Configurar directivas

La sección final es "Configurar directivas". Esta sección le permite controlar directivas individuales dentro de la política. Actualmente, solo se puede personalizar frame-ancestors.

Configurar directivas CSP

Al dejar activada la directiva predeterminada se utiliza el valor predeterminado especificado en la tabla que se muestra anteriormente en este artículo. Desactivar la opción de alternancia permite a los administradores especificar valores personalizados para la directiva y anexarlos al valor predeterminado. El siguiente ejemplo establece valores personalizados para frame-ancestors. La directiva se establecería en frame-ancestors: 'self' https://*.powerapps.com https://www.foo.com https://www.bar.com en este ejemplo, lo que significa que la aplicación podría hospedarse en el mismo origen, https://*.powerapps.com, https://www.foo.com y https://www.bar.com pero no en otros orígenes. Utilice el botón Agregar para agregar entradas a la lista y el icono de eliminar para eliminarlas.

Configuración de directivas CSP personalizadas

Opciones de configuración comunes

Para la integración de Microsoft Teams mediante la aplicación Dynamics 365, agregue lo siguiente a frame-ancestors:

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

Para Dynamics 365 App for Outlook, debe agregar el origen de la página de inicio de Outlook Web App en frame-ancestors.

Para incrustar Power Apps en informes de Power BI, agregue lo siguiente a frame-ancestors:

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

Consideraciones importantes

Desactivar la directiva predeterminada y guardar con una lista vacía apaga la directiva por completo y no lo envía como parte del encabezado de respuesta de CSP.

Ejemplos

Echemos un vistazo a un par de ejemplos de configuración de CSP:

Ejemplo 1

Ejemplo 1 de CSP

En el ejemplo anterior:

  • Los informes están desactivados.
  • La aplicación basada en modelos está habilitada.
    • frame-ancestors está personalizado para https://www.foo.com y https://www.bar.com
  • La aplicación de lienzo está deshabilitada.

Los encabezados efectivos serían:

  • Aplicaciones basadas en modelos: 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;
  • Aplicaciones de lienzo: no se enviaría el encabezado CSP.

Ejemplo 2

Ejemplo 2 de CSP

En el ejemplo anterior:

  • Los informes están activados.
    • El extremo de informes está establecido en https://www.mysite.com/myreportingendpoint
  • La aplicación basada en modelos está habilitada.
    • frame-ancestors se mantiene por defecto
  • La aplicación de lienzo está deshabilitada.
    • frame-ancestors está personalizado a https://www.baz.com

Los valores CSP efectivos serían:

  • Aplicaciones basadas en modelos: 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;
  • Aplicaciones de lienzo: 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;

Configuración de organización

CSP se puede configurar sin usar la interfaz de usuario modificando directamente la siguiente configuración de la organización:

  • IsContentSecurityPolicyEnabled controla si el encabezado Content-Security-Policy se envía en aplicaciones basadas en modelo.

  • ContentSecurityPolicyConfiguration controla el valor de la parte frame-ancestors (como se ha visto, está establecida en 'self' si ContentSecurityPolicyConfiguration no se ha establecido). Esta configuración está representada por un objeto JSON con la siguiente estructura: { "Frame-Ancestor": { "sources": [ { "source": "foo" }, { "source": "bar" } ] } }. Esto se traduciría en script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'foo' 'bar';

    • (De MDN) La directiva HTTP Content-Security-Policy (CSP) frame-ancestors (CSP) especifica elementos primarios válidos que pueden incrustarse en una página usando <frame>, <iframe>, <object>, <embed> o <applet>.
  • IsContentSecurityPolicyEnabledForCanvas controla si el encabezado Content-Security-Policy se envía en aplicaciones basadas en modelo.

  • ContentSecurityPolicyConfigurationForCanvas controla la política de lienzo utilizando el mismo proceso descrito en ContentSecurityPolicyConfiguration arriba.

  • ContentSecurityPolicyReportUri controla si se deben utilizar los informes. Esta configuración se usa tanto en las aplicaciones basadas en modelos como en las de lienzo. Una cadena válida envía informes de infracción al punto de conexión especificado, utilizando el modo de solo informe si IsContentSecurityPolicyEnabled/IsContentSecurityPolicyEnabledForCanvas esta desactivado. Una cadena vacía deshabilita los informes. Para obtener más información, consulte la documentación de informes.

Configurar CSP sin IU

Especialmente para entornos que no están en el centro de administración de Power Platform, como configuraciones local, es posible que los administradores deseen configurar CSP mediante scripts para modificar directamente la configuración.

Habilitación de CSP sin interfaz de usuario

Pasos:

  • Abra las herramientas de desarrollo del navegador mientras usa la aplicación basada en modelos como un usuario con privilegios de actualización de entidades de la organización (administrador del sistema es una buena opción).
  • Pegue y ejecute el siguiente script en la consola.
  • Para habilitar simplemente CSP, pase la configuración predeterminada: enableFrameAncestors(["'self'"])
  • Un ejemplo de habilitar orígenes adicionales para incrustar en la aplicación: 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!')
}

Deshabilitación de CSP sin interfaz de usuario

Pasos:

  • Abra las herramientas de desarrollo del navegador mientras usa la aplicación basada en modelos como un usuario con privilegios de actualización de entidades de la organización (administrador del sistema es una buena opción).
  • Pegue y ejecute el siguiente script en la consola.
  • Para deshabilitar CSP, pegue en la consola: 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!')
}