Directiva de seguridad de contenido
directiva de seguridad de contenido (CSP) actualmente es compatible con modelos controlados y lienzo Power Apps. Los administradores pueden controlar si se envía el encabezado CSP y, hasta cierto punto, qué contiene. La configuración está en el nivel ambiente, lo que significa que se aplicará a todas las aplicaciones en ambiente 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 |
---|---|---|
fuente del script | * 'unsafe-inline' 'unsafe-eval' |
No |
trabajador-origen | 'self' blob: |
No |
estilo-src | * 'unsafe-inline' |
No |
fuente-src | * data: |
No |
ancestros del marco | 'self' https://*.powerapps.com |
Sí |
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 de interacción con el cliente de Dynamics 365 y otras aplicaciones basadas en modelos, CSP solo está disponible en entornos en línea y en organizaciones con Dynamics 365 Customer Engagement (local), 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 ambiente en un entorno de desarrollo/prueba primero, ya que habilitar CSP podría comenzar a bloquear escenarios si se viola la política. 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:
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.
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:
- Aplicar en un entorno de desarrollo/prueba.
- Habilite el modo de solo informe en producción.
- Hacer cumplir en producción una vez que no se informen infracciones.
Configurar directivas
Esta sección le permite controlar directivas individuales dentro de la política. Actualmente, solo se puede personalizar frame-ancestors
.
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.
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://teams.cloud.microsoft/
https://msteamstabintegration.dynamics.com/
Para Dynamics 365 App for Outlook, agregue lo siguiente a frame-ancestors
:
- El origen de la página de inicio de Outlook Web App
https://outlook.office.com
https://outlook.office365.com
Para incrustar Power Apps en informes de Power BI, agregue lo siguiente a frame-ancestors
:
https://app.powerbi.com
https://ms-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
En el ejemplo:
- Los informes están desactivados.
- La aplicación basada en modelos está habilitada.
frame-ancestors
está personalizado parahttps://www.foo.com
yhttps://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
En el ejemplo:
- Los informes están activados.
- El extremo de informes está establecido en
https://www.mysite.com/myreportingendpoint
- El extremo de informes está establecido en
- La aplicación basada en modelos está habilitada.
frame-ancestors
se mantiene como predeterminado
- La aplicación de lienzo está deshabilitada.
frame-ancestors
está personalizado parahttps://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 modelos.
ContentSecurityPolicyConfiguration controla el valor de la parte de los ancestros del marco (como se ve arriba, se establece en
'self'
siContentSecurityPolicyConfiguration
no está 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 enscript-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>
.
- (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
IsContentSecurityPolicyEnabledForCanvas controla si el encabezado Content-Security-Policy se envía en aplicaciones de lienzo.
ContentSecurityPolicyConfigurationForCanvas controla la política para el lienzo utilizando el mismo proceso descrito
ContentSecurityPolicyConfiguration
arriba.ContentSecurityPolicyReportUri controla si se deben utilizar 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 CSP, pase la configuración predeterminada:
enableFrameAncestors(["'self'"])
- Como ejemplo de cómo permitir que otros orígenes integren 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!')
}