分享方式:


內容安全性原則

目前模型導向和畫布 Power Apps 支援內容安全性原則 (CSP)。 管理員可以控制是否要傳送 CSP 標題,以及在一定程度上控制它包含的內容。 這些設定位於環境層級,這代表一旦開啟,其就會套用至環境中的所有應用程式。

CSP 標題值的每個元件都會控制可以下載的資源,並將在Mozilla Developer Network (MDN) 上更詳細地描述。 預設值如下所示:

指示詞 預設值 可自訂
script-src * 'unsafe-inline' 'unsafe-eval'
worker-src 'self' blob:
style-src * 'unsafe-inline'
font-src * data:
frame-ancestors 'self' https://*.powerapps.com .是

這會產生 script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com; 的預設 CSP。 在我們的藍圖中,我們能夠修改目前不可自訂的標題。

先決條件

  • 對於 Dynamics 365 Customer Engagement 應用程式和其他模型導向應用程式,雲端解決方案提供者只能在線上環境或者擁有 Dynamics 365 Customer Engagement (on-premises) 9.1 版或更新版本的組織中使用。

正在設定 CSP

可透過 Power Platform 系統管理中心切換和設定 CSP。 先在開發/測試環境中啟用非常重要,因為如果違反原則,啟用 CSP 可能會開始封鎖場景。 我們還支援「報告專用模式」,以便更輕鬆地加速生產。

若要設定 CSP,請瀏覽至 Power Platform 系統管理中心 - >環境 - >設定 - >隱私權 + 安全性。 下圖顯示設定的預設狀態:

內容安全性原則預設設定

回報

「啟用報告」切換會控制模型導向應用程式和畫布應用程式是否傳送違規報告。 若啟用它,則需要指定端點。 無論是否已強制執行 CSP,都會將違規報告傳送至此端點 (如果未強制執行 CSP,則使用報告專用模式)。 如需詳細資訊,請參閱報告文件

啟用報告端點

實施

對於模型導向和畫布應用程式,強制執行 CSP 是獨立控制的,以提供提供精確的原則控制。 使用模型導向/畫布樞紐來修改預期的應用程式類型。

「強制執行內容安全性原則」開關可開啟指定應用程式類型強制執行的預設原則。 打開此切換開關將會變更此環境中應用程式的行為,以符合該原則。 因此,建議的啟用流程為:

  1. 在開發/測試環境上強制執行。
  2. 在生產中啟用報告專用模式。
  3. 只要沒有違規報告,就在生產中執行。

設定指示詞

最後一個區段為「設定指示詞」。 本區段可讓您控制原則中的各個指示詞。 目前只有 frame-ancestors 可以自訂。

設定 CSP 指示詞

將預設指令保持開啟狀態,將使用本文先前顯示資料表中指定的預設值。 關閉切換功能可讓管理員指定指令的自訂值,並將其附加至預設值。 以下範例設定 frame-ancestors 的自訂值。 在此範例中,該指令會設為 frame-ancestors: 'self' https://*.powerapps.com https://www.foo.com https://www.bar.com,表示應用程式可以託管在同一個來源 (https://*.powerapps.comhttps://www.foo.comhttps://www.bar.com) 中,而不是在其他來源中。 使用 [新增] 按鈕將項目新增至清單,並使用刪除圖示來移除它們。

設定自訂 CSP 指示詞

一般設定

若要使用 Dynamics 365 應用程式進行 Microsoft Teams 整合,請將下列項目新增至 frame-ancestors

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

對於 Dynamics 365 App for Outlook,將以下內容新增至 frame-ancestors

  • 您的 Outlook Web App 首頁來源
  • https://outlook.office.com

若要在 Power BI 報表中嵌入 Power Apps,請將下列內容新增至 frame-ancestors

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

重要考量

關閉預設指令並使用空白清單儲存完全關閉指示詞,且不會將其做為 CSP 回覆標題中的一部分傳送。

範例

讓我們看幾個 CSP 設定範例:

範例 1

CSP 範例 1

在上述範例中:

  • 報告已關閉。
  • 已啟用模型導向強制執行。
    • frame-ancestors 自訂為 https://www.foo.comhttps://www.bar.com
  • 已停用畫布強制執行。

有效的標頭將是:

  • 模型導向應用程式: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;
  • 畫布應用程式:不會傳送 CSP 標題。

範例 2

CSP 範例 2

在上述範例中:

  • 報告已開啟。
    • 報告端點設為 https://www.mysite.com/myreportingendpoint
  • 已啟用模型導向強制執行。
    • frame-ancestors 保留為預設值
  • 已停用畫布強制執行。
    • frame-ancestors 自訂為 https://www.baz.com

有效的 CSP 值將是:

  • 模型導向應用程式: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;
  • 畫布應用程式: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;

組織設定

您可以直接修改下列組織設定,以在不使用 UI 的情況下設定 CSP:

  • IsContentSecurityPolicyEnabled 控制是否要在模型導向應用程式中傳送內容安全性原則標題。

  • ContentSecurityPolicyConfiguration 控制 frame-ancestors 部分的值 (如上所示,如果未設定 ContentSecurityPolicyConfiguration,則將其設為 'self')。 此設定是由具有下列結構的 JSON 物件所表示 – { "Frame-Ancestor": { "sources": [ { "source": "foo" }, { "source": "bar" } ] } }。 這會將翻譯為 script-src * 'unsafe-inline' 'unsafe-eval'; worker-src 'self' blob:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'foo' 'bar';

    • (來自 MDN) HTTP 內容安全性原則 (CSP) frame-ancestor 指令指定可以使用 <frame><iframe><object><embed><applet> 內嵌頁面的有效上層。
  • IsContentSecurityPolicyEnabledForCanvas 控制是否要在畫布應用程式中傳送內容安全性原則標題。

  • ContentSecurityPolicyConfigurationForCanvas 會使用上述 ContentSecurityPolicyConfiguration 中描述的相同流程來控制畫布的原則。

  • ContentSecurityPolicyReportUri 控制是否應使用報告。 模型導向和畫布應用程式都使用此設定。 如果 IsContentSecurityPolicyEnabled/IsContentSecurityPolicyEnabledForCanvas 已關閉,則有效字串將使用報告專用模式將違規報告傳送到指定端點。 空字串會停用報告。 如需詳細資訊,請參閱報告文件

在沒有 UI 的情況下設定 CSP

特別是對於不在 Power Platform 系統管理中心的環境,例如內部部署設定,管理員可能希望使用指令碼設定 CSP 以直接修改設定。

在沒有 UI 的情況下啟用 CSP

步驟:

  • 以具有組織實體更新權限的使用者身分使用模型導向應用程式時,打開瀏覽器開發工具 (系統管理員會是不錯的選擇)。
  • 將以下指令碼貼上至主控台並執行。
  • 若只要啟用 CSP,請傳遞預設設定 - enableFrameAncestors(["'self'"])
  • 啟用其他來源內嵌應用程式的範例 - 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!')
}

在沒有 UI 的情況下停用 CSP

步驟:

  • 以具有組織實體更新權限的使用者身分使用模型導向應用程式時,打開瀏覽器開發工具 (系統管理員會是不錯的選擇)。
  • 將以下指令碼貼上至主控台並執行。
  • 若要停用 CSP,請將其貼上到主控台: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!')
}