コンテンツセキュリティポリシー(CSP)

コンテンツセキュリティポリシー(CSP)は、クロスサイトスクリプティング(XSS)やデータインジェクション攻撃などの、特定の種類の攻撃を検知して軽減するための追加セキュリティレイヤーです。CSPで問題が発生している場合は、Pendoが完全に機能するように調整する必要がある場合があります。

この記事では、Pendoが完全に機能するために最低限必要なディレクティブの概要と、厳密なCSPを持つアプリケーションのための互換性ガイドコンテンツの例を紹介します。

Feedbackをご利用の方は、フィードバックのコンテンツに関するセキュリティポリシーをご覧ください。

ガイド配信の設定

厳密なCSPを使用するアプリケーションでは、[ガイド配信設定(Guide Delivery Settings)]がXHRに設定されていることを確認する必要があります。

[ガイド配信設定]にアクセスするには、[アプリの詳細(App Details)]ページに移動し、[エージェント設定(Agent Settings)]タブをクリックして、[本番設定管理(Manage Production Settings)]をクリックします。

XHRのラジオボタンが選択されていることを確認してください。

guideDisplay.png

CSP(CNAMEなし)

以下のコードブロック例におけるディレクティブとエントリの説明については、ディレクティブとエントリの用語集を参照してください。

注:以下のfoo.example.comの部分をすべて、適切なホスト名に置き換えてください。SUB_IDをお客様のサブスクリプションIDに置き換えてください。サブスクリプションIDは、PendoにログインしているときにページのURLに表示されます。フォーマットはhttps://app.pendo.io/s/[SUB_ID]/です。/s/ の直後にサブスクリプションIDが表示されますが、Pendo内を移動する際にURLパスの最後に表示されるガイドやレポートの一意のIDを誤って取得しないようにしてください。

必要に応じて、ホスト名の前にhttps://を加えてください。

最低限必要なCSPディレクティブ(EU以外の米国/各国のお客様)

デザイナーを含めた全ての機能で有効です。

script-src foo.example.com 'unsafe-inline' 'unsafe-eval' app.pendo.io pendo-io-static.storage.googleapis.com cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io;
style-src foo.example.com 'unsafe-inline' app.pendo.io cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com;
img-src foo.example.com cdn.pendo.io app.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io;
connect-src app.pendo.io data.pendo.iopendo-static-SUB_ID.storage.googleapis.com;
frame-ancestors app.pendo.io;
frame-src app.pendo.io; child-src app.pendo.io;
完全なエージェント機能と本番環境でのガイドの表示:
(デザイナーおよびインラインのガイドスタイル、もしくはスクリプトは含まれません)。
script-src foo.example.com pendo-io-static.storage.googleapis.com cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io;
style-src foo.example.com app.pendo.io cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com;
img-src foo.example.com cdn.pendo.io app.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io;
connect-src app.pendo.io data.pendo.io pendo-static-SUB_ID.storage.googleapis.com;frame-ancestors app.pendo.io;
ステージングにおけるガイド表示:
script-src foo.example.com app.pendo.io pendo-io-static.storage.googleapis.com cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io;
style-src foo.example.com app.pendo.io cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com;
img-src foo.example.com cdn.pendo.io app.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io;
connect-src app.pendo.io data.pendo.io pendo-static-SUB_ID.storage.googleapis.com;frame-ancestors app.pendo.io;

最低限必要なCSPディレクティブ(EUのお客様)

デザイナーを含めた全ての機能で有効です。

script-src foo.example.com 'unsafe-inline' 'unsafe-eval' app.eu.pendo.io pendo-eu-static.storage.googleapis.com cdn.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com data.eu.pendo.io;
style-src foo.example.com 'unsafe-inline' app.eu.pendo.io cdn.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com;
img-src foo.example.com cdn.eu.pendo.io app.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com data.eu.pendo.io;
connect-src app.eu.pendo.io data.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com;
frame-ancestors app.eu.pendo.io;
frame-src app.eu.pendo.io; child-src app.eu.pendo.io;
完全なエージェント機能と本番環境でのガイドの表示:
(デザイナーおよびインラインのガイドスタイル、もしくはスクリプトは含まれません)。
script-src foo.example.com pendo-eu-static.storage.googleapis.com cdn.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com data.eu.pendo.io;
style-src foo.example.com app.eu.pendo.io cdn.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com;
img-src foo.example.com cdn.eu.pendo.io app.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com data.eu.pendo.io;
connect-src app.eu.pendo.io data.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com;frame-ancestors app.eu.pendo.io;

ステージングにおけるガイド表示:

script-src foo.example.com app.eu.pendo.io pendo-eu-static.storage.googleapis.com cdn.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com data.eu.pendo.io;
style-src foo.example.com app.eu.pendo.io cdn.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com;
img-src foo.example.com cdn.eu.pendo.io app.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com data.eu.pendo.io;
connect-src app.eu.pendo.io data.eu.pendo.io pendo-eu-static-SUB-ID.storage.googleapis.com;frame-ancestors app.eu.pendo.io;

CNAMEがあるCSP

以下のコードブロック例におけるディレクティブとエントリの説明については、ディレクティブとエントリの用語集を参照してください。これらの一部は、CNAMEでCSPを使用すると置き換えられます。詳細については、CNAMEを使用する場合のディレクティブとエントリを参照してください。

CNAMEがあるCSPを使用している場合、ホスト名の変更時にCSPがPendoサービスを中断することなくCNAMEを適切に設定するには、いくつかの手順を経る必要があります。PendoのサポートチームとCNAMEを設定するときに、移行コードを使用するようにCSPディレクティブを更新します。CNAMEの設定が完了した後、CNAMEのみのコードを使用して、CNAMEを使用するPendoリソースのみを許可します。

注:以下のfoo.example.comの部分(content.data.の後の部分)をすべて自分のホスト名に置き換えてください。

CSPディレクティブのCNAMEへの移行

デザイナーを含めた全ての機能で有効です。
script-src foo.example.com 'unsafe-inline' 'unsafe-eval' app.pendo.io pendo-io-static.storage.googleapis.com cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io content.pendo.example.com data.pendo.example.com;
style-src foo.example.com 'unsafe-inline' app.pendo.io cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com content.pendo.example.com data.pendo.example.com;
img-src foo.example.com cdn.pendo.io app.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io content.pendo.example.com data.pendo.example.com;
connect-src app.pendo.io data.pendo.io pendo-static-SUB_ID.storage.googleapis.com content.pendo.example.com data.pendo.example.com;
frame-ancestors app.pendo.io data.pendo.example.com;
frame-src app.pendo.io data.pendo.example.com;
child-src app.pendo.io data.pendo.example.com;
完全なエージェント機能と本番環境でのガイドの表示:
script-src foo.example.com pendo-io-static.storage.googleapis.com cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io content.pendo.example.com data.pendo.example.com;
style-src foo.example.com app.pendo.io cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com content.pendo.example.com data.pendo.example.com;
img-src foo.example.com cdn.pendo.io app.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io content.pendo.example.com data.pendo.example.com;
connect-src app.pendo.io data.pendo.io pendo-static-SUB_ID.storage.googleapis.com content.pendo.example.com data.pendo.example.com;
ステージングにおけるガイド表示:
script-src foo.example.com app.pendo.io pendo-io-static.storage.googleapis.com cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io content.pendo.example.com data.pendo.example.com;
style-src foo.example.com app.pendo.io cdn.pendo.io pendo-static-SUB_ID.storage.googleapis.com content.pendo.example.com data.pendo.example.com;
img-src foo.example.com cdn.pendo.io app.pendo.io pendo-static-SUB_ID.storage.googleapis.com data.pendo.io content.pendo.example.com data.pendo.example.com;
connect-src app.pendo.io data.pendo.io pendo-static-SUB_ID.storage.googleapis.com content.pendo.example.com data.pendo.example.com;
frame-ancestors app.pendo.io data.pendo.example.com;

CNAMEのみを使用するCSPディレクティブ

デザイナーを含めた全ての機能で有効です。
script-src foo.example.com 'unsafe-inline' 'unsafe-eval' content.pendo.example.com data.pendo.example.com;
style-src foo.example.com 'unsafe-inline' content.pendo.example.com data.pendo.example.com;
img-src foo.example.com content.pendo.example.com data.pendo.example.com;
connect-src content.pendo.example.com data.pendo.example.com;
frame-ancestors data.pendo.example.com;
frame-src data.pendo.example.com;
child-src data.pendo.example.com;app.pendo.io;
完全なエージェント機能と本番環境でのガイドの表示:
script-src foo.example.com content.pendo.example.com data.pendo.example.com;
style-src foo.example.com content.pendo.example.com data.pendo.example.com;
img-src foo.example.com content.pendo.example.com data.pendo.example.com;
connect-src content.pendo.example.com data.pendo.example.com;
frame-ancestors data.pendo.example.com;app.pendo.io;
ステージングにおけるガイド表示:
script-src foo.example.com content.pendo.example.com data.pendo.example.com;
style-src foo.example.com content.pendo.example.com data.pendo.example.com;
img-src foo.example.com content.pendo.example.com data.pendo.example.com;
connect-src content.pendo.example.com data.pendo.example.com;
frame-ancestors data.pendo.example.com;app.pendo.io;

対応ガイドコンテンツ

Pendoは厳密なCSPディレクティブに対応していますが、ガイドコンテンツがお客様のCSP制限に対応しているかどうかは、お客様の責任でご確認ください。

style-srcおよびscript-srcディレクティブ内にunsafe-inlineが存在しない場合、ガイドのHTMLタブ内のインラインCSSおよびJavaScriptは正しく機能しません。予期しないガイドの表示を防ぐには、すべてのインラインスタイルとスクリプトをガイドコードブロックまたはテンプレートのCSSタブとJSタブに移動する必要があります。

最小限のCSPディレクティブ(インラインディレクティブなし)を適切に設定すれば、Pendoデザイナーでフィーチャーの表示やタグ付けができるようになります。X-Frame-Optionsプラグインにより、厳密なCSPを使用したガイド編集モードでデザイナーを使用できるようになります。デザイナーの外部で、X-Frame-Optionsプラグインをオフにしてガイドコンテンツをテストすることが重要です。

厳密なCSP対応コンテンツの例

基本的なコンセプトは、「unsafe-inline」のスタイル設定とJavaScriptをすべて削除することです。

たとえば、このHTMLボタン内のすべてのインラインスタイル設定とJavaScriptは次のようになります:

<button class="_pendo-guide-next_" style="color:blue;" onclick="pendo.onGuideAdvanced()">Next</button>

これで、ガイドのHTML、CSS、JSのそれぞれのタブに分散して表示されます。以下の例は、ガイドコンテンツの要素を分解する方法を示しています。お客様やお客様のチームの開発者は、別の、あるいはもっと良いアプローチを取っているかもしれません:

HTML

<button class="_pendo-guide-next_ blue-button">Next</button>

CSS

.bluebutton { color: blue; }

JavaScript

(function wireGuideAdvanceButton (step) { step && step.attachEvent(step.guideElement[0],'click', function (e) { var advanceButton = pendo.dom(e.target|| e.srcElement).closest('._pendo-guide-next_'); if (advanceButton.length){ pendo.onGuideAdvanced(); } }); })(step,guide);

ディレクティブとエントリの用語集

ディレクティブ:script-src

これらのエントリ(ホスト)により、Pendoのスクリプトをダウンロードして実行できます。

ホスト 説明
cdn.pendo.io

インストールスクリプト(「snippet」)で参照されるPendoエージェントの場所。これは、デフォルトでPendoエージェントがダウンロードされる場所です。

pendo-io-static.storage.googleapis.com

ステージングドメイン用にダウンロードされたPendoエージェントの場所。

pendo-static-{{ SUB_ID }}.storage.googleapis.com

すべてのガイドコンテンツの場所。

data.pendo.io

訪問者が利用できるガイドのリストをダウンロードするために使用されます。これは、JSONP配信メソッドにのみ必要です。

app.pendo.io

デザイナーを使用する場合にのみ必要です。

'unsafe-inline'

デザイナーでカスタムコードブロックまたはクラシックガイドを使用する場合にのみ必要です。

'unsafe-eval'

デザイナーでカスタムコードブロックまたはクラシックガイドを使用する場合に必要です。

 

ディレクティブ:style-src

これらのエントリ(ホスト)により、貴社のサイトでPendoのスタイルを使用できるようになります。

ホスト 説明
pendo-io-static.storage.googleapis.com

クラシックガイドが有効になっている場合にのみ必要です。このURLからデフォルトのガイドCSSが読み込まれます。

pendo-static-{{ SUB_ID }}.storage.googleapis.com

ガイドスタイルとグローバルCSS。

'unsafe-inline'

ガイドの擬似スタイル(ホバー、リソースセンターのキャレット、数値スケール)およびデザイナー起動時のスタイルに使用されます。

app.pendo.io

デザイナーを使用する場合にのみ必要です。

 

ディレクティブ:img-src

これらのエントリにより、Pendoがホストする画像をサイトに表示できます。

ホスト 説明
cdn.pendo.io

デフォルトのクラシックガイドのバッジに使用されます。

data.pendo.io

イベントは、画像srcを使用してこのURLに送信されます。

pendo-static-{{ SUB_ID }}.storage.googleapis.com

ガイド画像はこちらのURLからダウンロードされます。

app.pendo.io

デザイナーを使用する場合にのみ必要です。

data:

デフォルトのバッジ画像。バッジにカスタム画像を使用する場合、これは必要ありません。

 

ディレクティブ:connect-src

これらのエントリにより、ページ上のスクリプトがPendoと通信できるようになります。

ホスト 説明
data.pendo.io イベント通信に必要です。
pendo-static-{{ SUB_ID }}.storage.googleapis.com

ここにガイド構造ファイルを読み込みます。

app.pendo.io

デザイナーを使用する場合にのみ必要です。

 

ディレクティブ:frame-ancestors

このエントリは、Pendoがサイトのページを<frame>内に読み込むようにするためのものです。クラシックデザイナーを使用している場合のみ必要です。

ホスト 説明
app.pendo.io

クラシックデザイナーがアプリケーションを読み込むPendoホスト。

 

ディレクティブ:rame-src

このエントリにより、Pendoはサイトの<frame>内にデザイナーを読み込むことができます。

ホスト 説明
app.pendo.io

ビジュアルデザインスタジオ(Visual Design Studio)は、このURLから読み込まれます。ガイドの設計にのみ必要です。

 

CNAMEを使用する場合のディレクティブとエントリ

CNAMEを使用する場合、上記のディレクティブとエントリの用語集の下に記載されているいくつかのエントリが置き換えられます。

ダウンタイムを防ぐために、CNAMEを設定するプロセスで、上記のURLと、その新しいコンテンツとデータホストの両方を含めるようにします。それを以下に示します。

ホスト 説明
cdn.pendo.io

content.pendo.example.comのように、どこでもコンテンツホストに置き換えられます。

pendo-io-static.storage.googleapis.com

content.pendo.example.comのように、どこでもコンテンツホストに置き換えられます。

pendo-static-{{ SUB_ID }}.storage.googleapis.com

content.pendo.example.comのように、どこでもコンテンツホストに置き換えられます。

data.pendo.io

data.pendo.example.comのように、どこでもデータホストに置き換えられます。

app.pendo.io

デザイナーを使用するには引き続き必要です。

'unsafe-inline'

デザイナーでカスタムコードブロックまたはクラシックガイドを使用する場合は引き続き必要です。

'unsafe-eval'

デザイナーでカスタムコードブロックまたはクラシックガイドを使用する場合は引き続き必要です。

data:

前述のルールに従う場合は、引き続き必要です。

 

よくある質問

Visual Design StudioとClassic Designerではディレクティブが違いますか?

はい。Visual Design Studioではframe-srcが使用され、Classic Designerではframe-ancestorsが使用されます。サブスクリプションでClassic Designerを使用してVisual Design Studioリリース以前に作成されたガイドを管理しない場合は、frame-ancestorsディレクティブは必要ありません。すべてのアプリケーションで、Visual Design Studioのコンテンツを許可する必要があります。これはページやフィーチャーのタグ付けや、最新のフィーチャーを使ったガイドの構築が可能な唯一のツールです。

unsafe-inlineおよびunsafe-evalディレクティブは本当に必要でしょうか?

はい。unsafe-evalディレクティブは、クラシックデザイナーの全機能を利用するために必要であり、 unsafe-inlineディレクティブは、公開されているガイドやビジュアルデザインスタジオの全機能を利用するために必要です。

その他のリソース