內容安全性原則
內容安全性原則 (CSP) 目前在模型驅動和 canvas 中受支援 Power Apps。 管理員可以控制是否要傳送 CSP 標題,以及在一定程度上控制它包含的內容。 這些設置位於環境級別,這意味著一旦打開,它將應用於環境中的所有應用程式。
CSP 標題值的每個元件都會控制可以下載的資源,並將在Mozilla Developer Network (MDN) 上更詳細地描述。 預設值如下所示:
指示詞 | 預設值 | 可自訂 |
---|---|---|
腳本源 | * 'unsafe-inline' 'unsafe-eval' |
否 |
worker-src 的 | 'self' blob: |
否 |
樣式源 | * 'unsafe-inline' |
否 |
字體源 | * 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 應用和其他模型驅動應用,CSP 僅在在線環境和具有 Dynamics 365 Customer Engagement (內部部署) 版本 9.1 或更高版本的組織中可用。
正在設定 CSP
可透過 Power Platform 系統管理中心切換和設定 CSP。 請務必先 在開發/測試環境上啟用,因為如果違反策略,啟用 CSP 可能會開始阻止方案。 我們還支援「報告專用模式」,以便更輕鬆地加速生產。
若要設定 CSP,請瀏覽至 Power Platform 系統管理中心 - >環境 - >設定 - >隱私權 + 安全性。 下圖顯示設定的預設狀態:
回報
「啟用報告」切換會控制模型導向應用程式和畫布應用程式是否傳送違規報告。 若啟用它,則需要指定端點。 無論是否已強制執行 CSP,都會將違規報告傳送至此端點 (如果未強制執行 CSP,則使用報告專用模式)。 如需詳細資訊,請參閱報告文件。
實施
對於模型導向和畫布應用程式,強制執行 CSP 是獨立控制的,以提供提供精確的原則控制。 使用模型導向/畫布樞紐來修改預期的應用程式類型。
「強制執行內容安全性原則」開關可開啟指定應用程式類型強制執行的預設原則。 打開此切換開關將會變更此環境中應用程式的行為,以符合該原則。 因此,建議的啟用流程為:
- 在開發/測試環境上強制執行。
- 在生產中啟用報告專用模式。
- 只要沒有違規報告,就在生產中執行。
設定指示
本區段可讓您控制原則中的各個指示詞。 目前只有 frame-ancestors
可以自訂。
將預設指令保持開啟狀態,將使用本文先前顯示資料表中指定的預設值。 關閉切換功能可讓管理員指定指令的自訂值,並將其附加至預設值。 以下範例設定 frame-ancestors
的自訂值。 在此範例中,該指令會設為 frame-ancestors: 'self' https://*.powerapps.com https://www.foo.com https://www.bar.com
,表示應用程式可以託管在同一個來源 (https://*.powerapps.com
、https://www.foo.com
和 https://www.bar.com
) 中,而不是在其他來源中。 使用 [新增] 按鈕將項目新增至清單,並使用刪除圖示來移除它們。
一般設定
若要使用 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 設定範例:
範例 1
在範例中:
- 報告已關閉。
- 已啟用模型導向強制執行。
frame-ancestors
被自定義為https://www.foo.com
和https://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
在範例中:
- 報告已開啟。
- 報告端點設為
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 控制是否在模型驅動應用中發送 Content-Security-Policy 標頭。
ContentSecurityPolicyConfiguration 控制 frame-ancestors 部分的值 (如上所示,如果未設置,則設置為
'self'
ifContentSecurityPolicyConfiguration
)。 此設定是由具有下列結構的 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>
內嵌頁面的有效上層。
- (來自 MDN) HTTP 內容安全性原則 (CSP) frame-ancestor 指令指定可以使用
IsContentSecurityPolicyEnabledForCanvas 控制是否在畫布應用程式中發送 Content-Security-Policy 標頭。
ContentSecurityPolicyConfigurationForCanvas 使用上述相同的過程
ContentSecurityPolicyConfiguration
來控制 canvas 的策略。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!')
}