共用方式為


內容安全性原則

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

Note

內容安全性原則僅適用於使用 Dataverse 的環境。

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

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

此設定會產生 script-src * 'unsafe-inline' 'unsafe-eval' blob: data:; worker-src 'self' blob: data:; style-src * 'unsafe-inline'; font-src * data:; frame-ancestors 'self' https://*.powerapps.com; 的預設 CSP。

嚴格模式

嚴格 CSP 切換會建立內容安全性原則,其中大部分不包含萬用字元或不安全的指示詞,例如 unsafe-inline。 當 Strict CSP 開啟時,上表中詳述的指示詞會變成下表中詳述的指示詞。 此 <platform> 表示法表示平台網域是依產品需求提供。 隨著產品的成長,本節中的網域可能會隨著時間而變更。

Note

嚴格 CSP 目前僅適用於模型導向應用程式。

指示詞 預設值 (模型驅動) 可自訂
script-src 'self' blob: data: <platform>' .是
worker-src 'self' blob: data:
style-src 'self' 'unsafe-inline' <platform> .是
font-src 'self' data: <platform> .是
frame-ancestors 'self' https://*.powerapps.com .是
img-src 'self' blob: data: <platform> .是
connect-src 'self' blob: data: wss: <platform> .是
frame-src 'self' blob: <platform> .是
基本 uri 'none'
表單動作 <platform> .是
預設來源 'self'

先決條件

對於 Dynamics 365 客戶互動應用程式和其他模型導向應用程式,CSP 僅在線上環境和具有 Dynamics 365 Customer Engagement (on-premises) 版本 9.1 或更高版本的組織中可用。

設定 CSP

您可以透過 Power Platform 系統管理中心切換並設定 CSP。 務必先啟用開發/測試環境,因為如果違反策略,啟用 CSP 可能會開始封鎖案例。 我們還支援報告專用模式,以便更輕鬆地加速生產。

若要設定 CSP:

  1. 登入 Power Platform 系統管理中心
  2. 在瀏覽窗格中,選取管理,然後在管理窗格中選取環境
  3. 環境頁面上,選取一個環境。
  4. 在命令列中,選取設定
  5. 展開產品,然後選取隱私權 + 安全性

下圖顯示設定的預設狀態:

內容安全性原則預設設定。

回報

啟用報告切換會控制模型導向應用程式和畫布應用程式是否傳送違規報告。 您需要指定端點才能啟用此功能。 無論是否已強制執行 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://teams.cloud.microsoft/
  • https://msteamstabintegration.dynamics.com/

對於 Dynamics 365 App for Outlook,將下列項目新增至 frame-ancestors

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

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

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

重要考量

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

CSP 範例設定

讓我們查看幾個 CSP 設定範例。

範例 1 - 報告已關閉

CSP 範例 1。

在範例中:

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

有效的標頭將是:

  • 模型導向應用程式:Content-Security-Policy: script-src * 'unsafe-inline' 'unsafe-eval' blob: data:; worker-src 'self' blob: data:; 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' blob: data:; worker-src 'self' blob: data:; 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 控制是否要在模型導向應用程式中傳送 Content-Security-Policy 標頭。

  • ContentSecurityPolicyConfiguration 控制 frame-ancestors 部分的值 (如上所示,如果未設定 'self',則設定為 ContentSecurityPolicyConfiguration)。 此設定是使用具有以下結構的 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 控制是否要在畫布應用程式中傳送 Content-Security-Policy 標頭。

  • ContentSecurityPolicyConfigurationForCanvas 使用 ContentSecurityPolicyConfiguration 中所述的相同程序控制畫布的原則。

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

在沒有 UI 的情況下設定 CSP

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

啟用沒有 UI 的 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

執行以下步驟以停用沒有 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!')
}