コンテンツ セキュリティ ポリシー (CSP) は現在、モデル駆動型アプリとキャンバス アプリでサポートされています。 管理者は、CSP ヘッダーを送信するかどうか、およびその内容をある程度制御できます。 設定は環境レベルです。つまり、オンにすると、環境内のすべてのアプリに適用されます。
メモ
コンテンツ セキュリティ ポリシーは、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 |
あり |
この構成では、既定の CSP は 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; になります。
厳格モード
Strict CSP トグルは、ワイルドカードや安全でないディレクティブ ( unsafe-inlineなど) をほとんど含まないコンテンツ セキュリティ ポリシーを作成します。 Strict CSP がオンの場合、前の表で詳しく説明したディレクティブは、次の表で詳しく説明されているディレクティブに変わります。
<platform>表記は、プラットフォーム ドメインが製品の必要に応じて提供されることを意味します。 このセクションのドメインは、製品の成長に合わせて時間の経過と同時に変化する可能性があります。
メモ
厳密な 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> |
あり |
| base-uri | 'none' |
いいえ |
| form-action | <platform> |
あり |
| default-src | 'self' |
いいえ |
前提条件
Dynamics 365 Customer Engagement アプリやその他のモデル駆動型アプリでは、CSP はオンライン環境でのみ利用可能であり、Dynamics 365 Customer Engagement (on-premises) バージョン 9.1 以降がインストールされている組織でのみ利用可能です。
CSP の構成
CSP の切り替えと構成は、Power Platform 管理センターで行うことができます。 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.comhttps://outlook.office365.com
Power BI レポートの埋め込み Power Apps の場合、以下を frame-ancestorsに追加します。
https://app.powerbi.comhttps://ms-pbi.pbi.microsoft.com
重要な考慮事項
既定ののディレクティブをオフにし、空のリストで保存すると、ディレクティブが完全にオフになり、CSP 応答ヘッダの一部として送信されなくなります。
CSP 構成の例
CSP 構成の例をいくつか見てみましょう。
例 1 - レポートがオフになっている
例:
- レポートはオフになっています。
- モデル駆動型の適用が有効になっています。
-
frame-ancestorsはhttps://www.foo.comとhttps://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: 有効化されたレポート
例:
- レポートはオンになっています。
- レポート エンドポイントは、
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に設定されます)。 この設定は、{ "Frame-Ancestor": { "sources": [ { "source": "foo" }, { "source": "bar" } ] } }の構造を持つ JSON オブジェクトを使用して定義されます。 この構成は、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-ancestors ディレクティブは、
<frame>、<iframe>、<object>、<embed>、<applet>を使用してページを埋め込むことができる有効な親を指定します。
- (MDN から) HTTP コンテンツ セキュリティー ポリシー (CSP) の frame-ancestors ディレクティブは、
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!')
}