このガイドでは、アプリケーションリスク交換モジュール内で提供される機能を活用して、顧客リスクエコシステムから最大限の価値を引き出すための新しいアプリケーションリスク交換プラグインの作成方法について説明します。このガイドに従えば、開発者は技術的な問題なく、独自に新しいプラグインを作成できるようになるはずです。
前提条件
- Python 3.xのプログラミング経験(中級レベル)。
- Netskope Cloud Exchangeプラットフォームへのアクセス。
- プラグインを作成する必要のある製品またはソリューションへのAPIまたはPython SDKへのアクセス。
- 製品に対する最低限の権限を持つアカウント。
アプリケーションリスク交換モジュール
Cloud Exchangeプラットフォームとその Application Risk Exchange モジュールには、高度なカスタマイズを可能にする豊富な機能セットが付属しているため、以下に示すプラットフォームのさまざまな側面についてよく理解しておくことをお勧めします。 このモジュールは、Netskopeからサードパーティツールへのデータ共有をサポートします。
Netskopeの概念と用語
- コア:CEコアエンジンは、サードパーティ製プラグインとそのライフサイクルメソッドを管理します。プラットフォームと対話してさまざまなタスクを実行するための API エンドポイントがあります。
- モジュール:機能的なコードは、さまざまなワークフローを実行するためにモジュール固有のプラグインを呼び出すものです。Application Risk Exchangeは、Cloud Exchangeで動作するモジュールの1つです。
- プラグイン:プラグインは、サードパーティの脅威インテリジェンスシステムからユーザーとリスクスコアを取得するロジックを備えたPythonパッケージであり、取得されたデータはアプリケーションリスクエクスチェンジに保存されます。また、動作を実行することもできます。
- プラグイン構成:プラグイン構成とは、必要なパラメータで構成され、ユーザーとスコアを取得するためにCloud Exchangeコアエンジンによってスケジュールされるプラグインクラスオブジェクトのことです。
- アプリケーション(アプリケーションイベント):Netskopeテナントのアプリケーションイベントから取得したアプリケーションの詳細。これらの情報は、Application Risk Exchangeで構成された他のプラグインと共有されます。
開発ガイドライン
- すべての Python コードのパッケージ ディレクトリ構造を使用します。
- プラグインパッケージに同梱されているすべてのサードパーティライブラリについて、既知の脆弱性がないか確認してください。
- 標準的なPythonのコーディング規約を必ず守ってください。(https://peps.python.org/pep-0008/)
- flake8 lint チェックを実行し、docstring チェックを有効にした状態で合格することを確認してください。1 行の最大長は 80 文字である必要があります。
- タイムスタンプ値を人間が読みやすい形式に変換します(エポックからDateTimeオブジェクトへ)。UIに表示される時刻が、現地のタイムゾーンであることを確認してください。
- 可能であれば、プラグインで設定パラメータを追加する際に、デフォルト値を追加してください。
- Pythonで記述されたスクリプトや統合機能については、必ず単体テストを作成してください。下記の「単体テスト」のセクションを参照してください。
- プラグインアーキテクチャでは状態の保存は可能ですが、状態管理のために巨大なオブジェクトを保存することは避けてください。
- Pythonコードに脆弱性がないか確認してください。
- プラグインのアイコンは10KB未満でなければなりません。必ず会社のロゴ(製品のロゴではなく)を透明なバックグランドで使用してください。 ロゴの推奨サイズは300×50ピクセル、またはそれに近いアスペクト比です。
- 必ず アプリケーションの詳細をサードパーティ製品に送信する際は、アプリケーションデータモデルで使用可能なすべてのフィールドを確認してください。
- プラグインディレクトリ構造に従ってください。
- デスクトップリプションにリンクが含まれている場合は、プレーンテキストではなくハイパーリンクにする必要があります。
- validateメソッドに渡されるパラメータを適切に検証し、すべてのパラメータに対して適切なヘルプテキストを提供します。
- 障害や重大な状況(レート制限、ペイロードサイズの超過など)が発生した場合に通知を発生させ、プラグインの状態をユーザーに通知するための通知オブジェクト。
- Cloud Exchangeプラットフォームによって渡されるロガー オブジェクトを使用して、適切なログ メカニズムを実装してください。 運用チームがトラブルシューティングを行う際に役立つよう、十分なログ記録が行われるようにしてください。通知に機密データが記録されたり、漏洩したりしないようにしてください。
- ロガーメッセージとトーストメッセージには、APIトークンとパスワードタイプのフィールド値を含めてはいけません。
- プラグインの機能開発においては、ページネーションを常に考慮に入れるべきです。
- ステータスコード429に対する再試行メカニズムを必ず追加してください。
- 障害や重大な状況(レート制限、ペイロードサイズの超過など)が発生した場合に通知を発生させ、プラグインの状態をユーザーに通知するための通知オブジェクト。
- Cloud Exchangeプラットフォームによって渡されるロガー オブジェクトを使用して、適切なログ メカニズムを実装してください。 運用チームがトラブルシューティングを行う際に役立つよう、十分なログ記録が行われるようにしてください。通知に機密データが記録されたり、漏洩したりしないようにしてください。
- すべてのパラメータに対して適切なヘルプテキスト(ツールチップ)を提供してください。可能であれば、ツールチップでそのパラメータの重要性を説明するようにしてください。
- プラグイン設定パラメータには必ず意味のある名前とデスクリプションを指定してください。
- パラメータには、適切な設定タイプ(テキスト、数値、パスワード、選択式、複数選択式)を指定してください。
- アウトバウンドリクエスト (API/SDK) を行う際に、 Cloud Exchangeプラットフォームによって渡されるプロキシ構成辞書と SSL 証明書検証フラグを必ず使用してください。
- 必須ではないパラメーターの値を取得するようにしてください .get() メソッドを作成し、 .get() を使用するときにデフォルト値を提供します 方法。
- API トークンとパスワード フィールドでは、strip() を使用しないでください。
- The log messages should start with “<module> <app name> Plugin [configuration_name]: “. Example: “ARE Bitsight Plugin [Bitsight Configuration Name]: <log_message>“. [This is a suggestion, we can avoid configuration name]. (logger.info(“<module> <plugin_name> Plugin: <message>”))
- エラーログを記録する際には、可能であれば例外のトレースバックも追加すべきです。使う: s elf.logger.error(error, 詳細=traceback.format_exc()) 。
- The Toast message should not contain the <app_name> <module> Plugin: in the message.
- API呼び出し中および呼び出し後に、適切な例外とステータスコードを捕捉するようにしてください。可能であれば、開発者はリクエストを行うためのヘルパーメソッドを作成し、必要に応じて適切なパラメータを指定してこのメソッドを呼び出すことができます。
- CHANGELOG.md ファイルには、追加、変更、修正などの適切なタグと、ユーザーにとって分かりやすいメッセージを追加して更新する必要があります。ファイル名がCHANGELOG.mdと完全に一致していることを確認してください。
- プラグインディレクトリ名(sample_plugin)がmanifest.jsonと一致していることを確認してください。IDフィールド。
- API呼び出しを行う際には、ユーザーエージェントをヘッダーに追加する必要があります。ユーザーエージェントのフォーマット: Netskope -ce- <ce_version>-<module>-<plugin_name>-<plugin_version> 。注: プラグインバージョンは動的に取得する必要があり、 Netskope -ce- <version>文字列を取得するには コアで定義されたメソッドを使用します。
- プラグインの機能開発においては、ページネーションを常に考慮に入れるべきです。
- ロガーステートメントはすべて、次の形式に従う必要があります。
logger.info(“<module> <plugin_name> Plugin: <message>”)
プラグインの作成
このセクションでは、プラグインをゼロから作成するプロセスについて説明します。
サンプルプラグインは NetskopeOSSの公開Githubリポジトリ またはCloud Exchangeナレッジベース(こちら)からダウンロードできます: https://support.netskope.com/hc/en-us/articles/360052128734-Cloud-Threat-Exchange。
開発環境のセットアップ
Python
当システムはPython3(バージョン3.7以降)を使用しています。開発環境にPython3がインストールされていることを確認してください。Pytest は単体テストを実行するために使います。
含まれるPythonライブラリ
Netskope Cloud Exchangeプラットフォームには、次の Python ライブラリが含まれています。
| 図書館名 | バージョン |
|---|---|
| aiofiles | 22.1.0 |
| amqp | 5.1.1 |
| anyio | 3.6.2 |
| asgiref | 3.6.0 |
| attrs | 22.2.0 |
| azure-core | 1.26.2 |
| azure-storage-blob | 12.14.1 |
| bcrypt | 4.0.1 |
| boto3 | 1.26.51 |
| botocore | 1.29.51 |
| billiard | 3.6.4.0 |
| celery | 5.2.7 |
| cabby | 0.1.23 |
| cachetools | 5.2.1 |
| celerybeat-mongo | 0.2.0 |
| certifi | 2022.12.7 |
| cffi | 1.15.1 |
| chardet | 5.1.0 |
| charset-normalizer | 3.0.1 |
| click | 8.1.3 |
| click-didyoumean | 0.3.0 |
| click-plugins | 1.1.1 |
| click-repl | 0.2.0 |
| colorama | 0.4.6 |
| colorlog | 6.7.0 |
| cryptography | 39.0.0 |
| cybox | 2.1.0.21 |
| defusedxml | 0.7.1 |
| dnspython | 2.3.0 |
| docker | 6.0.1 |
| fastapi | 0.89.1 |
| furl | 2.1.3 |
| google-api-core | 2.11.0 |
| google-auth | 2.16.0 |
| google-cloud-core | 2.3.2 |
| google-cloud-pubsub | 2.13.12 |
| google-cloud-pubsublite | 1.6.0 |
| google-cloud-storage | 2.7.0 |
| google-crc32c | 1.5.0 |
| google-resumable-media | 2.4.0 |
| googleapis-common-protos | 1.58.0 |
| grpc-google-iam-v1 | 0.12.6 |
| grpcio | 1.51.1 |
| grpcio-status | 1.51.1 |
| gunicorn | 20.1.0 |
| h11 | 0.14.0 |
| idna | 3.4 |
| importlib-metadata | 6.0.0 |
| isodate | 0.6.1 |
| jmespath | 1.0.1 |
| jsonpath | 0.82 |
| jsonschema | 4.17.3 |
| kombu | 5.2.4 |
| libcst | 0.3.21 |
| libtaxii | 1.1.119 |
| lxml | 4.9.2 |
| mongoengine | 0.25.0 |
| more-itertools | 9.0.0 |
| MarkupSafe | 2.1.2 |
| memory-profiler | 0.61.0 |
| mixbox | 1.0.5 |
| mongoquery | 1.4.2 |
| msrest | 0.7.1 |
| multidict | 6.0.4 |
| mypy-extensions | 0.4.3 |
| netskopesdk | 0.0.25 |
| numpy | 1.23.5 |
| oauthlib | 3.2.2 |
| onelogin | 3.1.0 |
| ordered-set | 4.1.0 |
| orderedmultidict | 1.0.1 |
| overrides | 6.5.0 |
| pandas | 1.5.0 |
| packaging | 23.0 |
| passlib | 1.7.4 |
| pycparser | 2.21 |
| prompt-toolkit | 3.0.36 |
| proto-plus | 1.22.2 |
| protobuf | 4.21.12 |
| psutil | 5.9.4 |
| pydantic | 1.10.4 |
| pyasn1 | 0.4.8 |
| pyasn1-modules | 0.2.8 |
| PyJWT | 2.6.0 |
| pymongo | 4.3.3 |
| pyparsing | 3.0.9 |
| python-dateutil | 2.8.2 |
| pyrsistent | 0.19.3 |
| python-multipart | 0.0.5 |
| python3-saml | 1.15.0 |
| pytz | 2022.7.1 |
| PyYAML | 6.0 |
| requests | 2.28.2 |
| requests-oauthlib | 1.3.1 |
| rsa | 4.9 |
| six | 1.16.0 |
| starlette | 0.22.0 |
| sniffio | 1.3.0 |
| s3transfer | 0.6.0 |
| stix | 1.2.0.11 |
| taxii2-client | 2.3.0 |
| typing-inspect | 0.8.0 |
| typing-utils | 0.1.0 |
| typing_extensions | 4.4.0 |
| urllib3 | 1.26.14 |
| uvicorn | 0.20.0 |
| vine | 5.0.0 |
| wcwidth | 0.2.6 |
| weakrefmethod | 1.0.3 |
| websocket-client | 1.4.2 |
| Werkzeug | 2.2.2 |
| xmlsec | 1.3.11 |
| zipp | 3.11.0 |
| requests-mock | 1.7.0 |
カスタムプラグインライブラリを含む
Netskopeは、プラグインが必要とするサードパーティ製のPythonライブラリはすべて、プラグインパッケージ自体に同梱することを推奨しています。pipインストーラーは、このバンドルを実現するために使用します。ディレクトリを入力として受け取るスイッチが用意されています。 ディレクトリが指定されている場合、pipはそのディレクトリにパッケージをインストールします。
For example, the command shown below will install the cowsay package into the directory lib.
> pip install cowsay --target ./lib
これに関する公式ドキュメントについては、 https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-tを参照してください。
上記のlibフォルダからモジュールをインポートする際は、 絶対インポートではなく相対インポートを使用する必要があります。
IDE
推奨されるIDEはPyCharmまたはVisual Studio Codeです。
プラグインディレクトリ構造
このセクションでは、アプリケーションリスク交換プラグインにおける一般的なディレクトリ構造について説明します。
/sample_plugin/ ├── __init__.py ├── Changelog.md ├── icon.png ├── main.py └── manifest.json
- __init__.py:Application Risk Exchangeのコードでは、すべてのプラグインパッケージはPythonモジュールとみなされます。すべてのプラグインパッケージに空の「__init__.py」が含まれていることを確認してください。ファイル。
- CHANGELOG.md:このファイルにはプラグインの更新に関する詳細が含まれており、追加、変更、修正などの適切なタグと、ユーザーにとって分かりやすいメッセージを追加して更新する必要があります。
- icon.png: プラグインのアイコンロゴ。これは、UI 上のプラグインのチクレットと設定カードに表示されます。ロゴには、推奨サイズ 300*50 ピクセルまたは同様のアスペクト比の透明なバックグランドが必要です。
- main.py:このPythonファイルには、push、validate、およびget_target_fieldsメソッドの具体的な実装を含むPluginクラスが含まれています。
- manifest.json:プラグインパッケージのマニフェストファイル。設定可能なすべてのパラメータとそのデータ型に関する情報が含まれています。このファイルには、プラグインの統合に関する詳細情報も記載されています。
ここに記載されているファイルは、プラグインの統合に必須ですが、開発者は特定の統合要件に基づいて他のファイルを追加することもできます。
注記
プラグインディレクトリ名(sample_plugin)がmanifest.jsonと一致していることを確認してください。IDフィールド。
CHANGELOG.md
これはプラグインの更新に関する詳細情報を含むファイルであり、追加、変更、修正などの適切なタグと、ユーザーにとって分かりやすい適切なメッセージで更新する必要があります。
- 追加: 新しい機能が追加されたときに使う。
- 修正済み: バグ/エラーが修正されたときに使用します。
- 変更済み: プラグインの既存の実装に変更があった場合。
# 1.0.1 ## Fixed - Fixed pagination when there are more than 10k Logs. # 1.0.0 ## Added - Initial release.
Manifest.json
これは、プラグインに関連するメタ情報を格納する JSON ファイルです。このファイルは、Application Risk Exchange モジュールによって読み込まれ、UI にプラグインを表示するとともに、Application Risk Exchange モジュールがプラグインに関する詳細情報(必要な構成パラメータ、プラグイン ID、プラグイン名など)を把握できるようにします。
- すべてのプラグインには、Application Risk Exchangeがプラグインオブジェクトを適切にインスタンス化できるように、必要な情報を含むこのファイルが含まれている必要があります。
- マニフェスト.json の一般的なパラメーターには次のものがあります。
- name: (文字列) プラグインの名前。(必須)
- デスクリプション: (文字列) プラグインのデスクリプション。 プラグインの機能と使用手順について説明した詳細なデスクリプションを提供します。 グループ内のユーザーとユーザースコアを取得し、メンバーに対してアクションを実行します。このデスク リプションは、プラグイン設定カードに表示されます。 (必須)
- ID: (文字列) プラグインパッケージのID。Cloud Exchangeにインストールされているすべてのプラグインで、一意であることを確認してください。IDはプラグインパッケージのディレクトリ名と一致する必要があります。(必須
- version: (文字列) プラグインのバージョン。MAJOR.MINOR.PATCH の使用 (例:1.0.1)バージョン管理方式を推奨しますが、特に制限はありません。(必須)
- 設定: (配列) プラグインに必要なすべてのパラメーターに関する情報 (名前、タイプ、ID など) を含む JSON オブジェクトの配列。ネストされた JSON オブジェクトによくあるパラメーターについては、以下で説明します。
- ラベル:パラメータの名前。これはプラグインの設定ページに表示されます。(必須)
- key: プラグイン設定が使用される Python dict オブジェクト内のキーとして使用される一意のパラメーター キー。 (必須)
- type: パラメータの値の型。使用可能な値は、「text」、「password」、「number」、「choice」、「multichoice」です。(必須)詳細については、下記のプラグイン設定パラメータの種類を参照してください。
- default: このパラメータのデフォルト値。この値は、ARE UI のプラグイン設定ページに表示されます。サポートされているデータ型は、「テキスト」、「数値」、「リスト」(複数選択型の場合)です。(必須)
- mandatory: このパラメータが必須かどうかを示すブール値。パラメータが必須の場合、ARE UI ではパラメータに空の値を指定することはできません。許容される値は「true」と「false」です。(必須)
- デスクリプション: パラメータと期待値に関する詳細を提供する、パラメータのヘルプ テキスト レベルのデスクリプション。 この文字列は、プラグインの設定ページにヘルプテキストとして表示されます。(必須)
- 選択肢:キーと値をJSONキーとして含むJSONオブジェクトのリスト。このパラメータは‘type’: ‘choice and multichoice`のみでサポートされています。
Plugin Configuration Parameter Types
プラグインのmanifest.jsonファイルのconfigurationセクションに、必要なプラグイン設定パラメータがすべて記載されていることを確認してください。
Password Parameter
このパラメータは、API エンドポイントでの認証のためのシークレット/パスワードを保存するために使用されます。 パスワードを型とするパラメータは、プラグイン設定ページにパスワード入力欄が表示され、プラットフォームによって難読化および暗号化されます。
サンプルJSON
"configuration": [
{
"label": "API Token",
"key": "api_token",
"type": "password"
},
]
プラグイン設定画面:

Text Parameter
このパラメータは、ベースURL、ユーザー名などの文字列情報を格納します。 このパラメータは、プラグイン設定ページに通常のテキスト入力欄として表示されます。
サンプルJSON
"configuration": [
{
"label": "Tenant Name",
"key": "user_name",
"type": "text"
},
]
プラグイン設定ビュー

Number Parameter
このパラメータは数値/浮動小数点値を保存するために使用されます。 このパラメータは、プラグイン設定ページに数値入力ボックスとして表示されます。(ハッシュリストは脅威交換モジュールにあります。)
サンプルJSON
"configuration": [
{
"label": "Maximum File hash list size in MB.",
"key": "max_size",
"type": "number"
},
]
プラグイン設定ビュー

Choice Parameter
このパラメータは、列挙パラメータの値を格納するために使用されます。 このパラメータは、プラグイン設定ページにドロップダウンボックスとして表示されます。
サンプルJSON
"configuration": [
{
"label": "Base URL",
"key": "base_url",
"type": "choice",
"choices": [
{
"key": "Commercial cloud (api.crowdstrike.com)",
"value": "https://api.crowdstrike.com"
},
{
"key": "US 2 (api.us-2.crowdstrike.com)",
"value": "https://api.us-2.crowdstrike.com"
},
{
"key": "Falcon on GovCloud (api.laggar.gcw.crowdstrike.com)",
"value": "https://api.laggar.gcw.crowdstrike.com"
},
{
"key": "EU cloud (api.eu-1.crowdstrike.com)",
"value": "https://api.eu-1.crowdstrike.com"
}
],
"default": "https://api.crowdstrike.com",
"mandatory": true,
"description": "API Base URL."
},
プラグイン設定ビュー
入力を選択した後:

Multichoice Parameter
このパラメータは、複数の選択肢の値を保存するために使用します。 このパラメータは、プラグイン設定ページにドロップダウンボックスとして表示され、複数の値を選択できるようになります。(重要度は脅威交換モジュールにあります。)
サンプルJSON
"configuration": [
{
"label": "Severity",
"key": "severity",
"type": "multichoice",
"choices": [
{
"key": "Unknown",
"value": "unknown"
},
{
"key": "Low",
"value": "low"
},
{
"key": "Medium",
"value": "medium"
},
{
"key": "High",
"value": "high"
},
{
"key": "Critical",
"value": "critical"
}
],
"default": [
"critical",
"high",
"medium",
"low",
"unknown"
],
"mandatory": false,
"description": "Only indicators with matching severity will be saved."
}
]
プラグイン設定ビュー

Toggle Parameter
このパラメータはブール値を格納します。トグル有効はTrue、トグル無効はFalseです。
システム プロキシ ('proxy'):
Use system proxy configured in Settings.(Default: False)
プラグイン設定ビュー

注記
このパラメータはCoreによって提供されるものであり、プラグインのmanifest.jsonファイルから追加することはできません。
main.py
このPythonファイルには、プラグインのコア実装が含まれています。
標準輸入品
from netskope.integrations.grc.plugin_base import (
PluginBase,
ValidationResult,
PushResult,
)
from netskope.integrations.grc.models.configuration import (
TargetMappingFields,
MappingType,
)
PluginBase 変数
PluginBase は、プラグインのライフサイクル中に使用できる変数へのアクセスを提供します。 メソッド。 以下は変数の一覧です。
| 変数名 | Usage | デスクリプション |
|---|---|---|
| self.logger | self.logger.error(“メッセージ”) self.logger.warn(“メッセージ”) self.logger.info(“メッセージ”) | コアによって提供されるロガーハンドル。このオブジェクトを使用して重要なイベントを記録します。 ログはCloud Exchangeの監査ログに表示されます。ロガーオブジェクトのドキュメントを参照してください。 |
| self.configuration | self.configuration.get()<attribute-key-name> | プラグインインスタンスの設定オブジェクトをJSON形式で表現したもの。これを使用して、認証クレデンシャル、サーバーの詳細などの構成属性にアクセスします。manifest.json に記載されている属性のキー名を使用します。 |
| self.last_run_at | self.last_run_at: の場合self.last_run_at.timestamp() この形式は、最後の実行時間をエポック形式に変換するためのものです。 | プラグインのプルメソッドが最後に正常に実行された時刻のタイムスタンプを提供します。Cloud Exchange コアは、pull() の実行が成功するたびにチェックポイント時刻を保持します。初回実行時の値はNoneになります。オブジェクトのデータ型はdatetimeです。 |
| self.storage | Cloud Exchangeは、プラグインが状態を維持するためのメカニズムを提供する。このオブジェクトは、後続の呼び出しで必要となる状態を保持します。 このオブジェクトのデータ型はPythonの辞書型です。 | |
| self.notifier | self.notifier.info(“message”) self.notifier.warn(“message”) self.notifier.error(“message”) | このオブジェクトは、Cloud Exchangeコアの通知機能のハンドルを提供します。このオブジェクトを使用して、プラットフォームに通知をプッシュします。 通知はアプリケーションリスク交換UIに表示されます。ユーザーが読んで必要な行動を取れるよう、メッセージ は要約された情報が含まれていることを確認してください。 Netskopeプラグインの通知機能。push()メソッドが製品の8MB制限を超えた場合に通知します。 |
| self.proxy | requests.get(url=url,プロキシ=self.proxy) | システムのプロキシ設定が設定されている場合はそのハンドル、設定されていない場合は {}。 |
| self.ssl_validation | requests.get(url=url,verify=self.ssl_validation) | REST API呼び出しに対してSSL検証を強制するかどうかを示すブール値。 |
プラグインクラス
- PluginクラスはPluginBaseクラスを継承する必要があります。PluginBase クラスはNetskope .integrations.grc.plugin_baseで定義されています。
- Plugin クラスが、validate、get_target_fields、および push メソッドの実装を提供していることを確認してください。
- プラグインクラスには、サードパーティAPIとの接続と認証を確立するために必要なすべてのパラメータが含まれます。
"""Sample plugin implementation.
This is a sample implementation of base PluginBase class. Which explains the concrete implementation
of the base class.
"""
from netskope.integrations.grc.plugin_base import (
PluginBase,
ValidationResult,
PushResult,
)
from netskope.common.utils import add_user_agent
from netskope.integrations.grc.models.configuration import (
TargetMappingFields,
MappingType,
)
from typing import List
from datetime import datetime
import requests
PLUGIN_NAME = “<module> <plugin_name> Plugin”
class SamplePlugin(PluginBase):
"""SamplePlugin class having concrete implementation for fetching information and performing actions.
This class is responsible for implementing pull, perform actions and validate methods with proper return types, so that its lifecycle execution can be scheduled by the ARE core engine.
"""
def get_target_fields()
これはPluginBaseクラスの抽象メソッドです。
- このメソッドは、ドロップダウンリストからターゲットが選択されたときにUIに表示されるフィールドのリストを返す必要があります。
- このメソッドは、ユーザーがプラグインの設定時に設定パラメータを正常に検証し、マッピング情報を選択した後に呼び出す必要があります。
def get_target_fields(self, plugin_id, plugin_parameters):
"""Get available Target fields."""
return [
TargetMappingFields(
label="Company Name",
type=MappingType.STRING,
value="name",
),
TargetMappingFields(
label="Company Legal Name",
type=MappingType.STRING,
value="company_legal_name",
),
]
def validate()
これはPluginBaseクラスの抽象メソッドです。
- このメソッドは、プラグイン構成を作成する際に渡されたプラグイン構成および認証パラメータを検証します。
- このメソッドは、新しい設定が作成または更新された場合にのみ呼び出されます。
- 渡されたすべての必須パラメータが適切なデータ型であるかどうかを検証します。
- 認証パラメータと API エンドポイントを検証して、プラグインのライフサイクルがスムーズに実行されるようにします。
- 検証の成功または失敗を示す成功フラグと、検証失敗の理由を含む検証メッセージを含むValidationResultオブジェクト(ValidationResultデータモデルを参照)を返します。
def validate(self, data):
""Validate the Plugin configuration parameters.
Validation for all the parameters mentioned in the manifest.json for the existence and
data type. Method returns the netskope.integrations.grc.plugin_base.ValidationResult object with success = True in the case of successful validation and success = False and an error message in the case of failure.
Args:
data (dict): Dict object having all the Plugin configuration parameters.
Returns:
netskope.integrations.grc.plugin_base.ValidateResult: ValidateResult object with success flag and message.
"""
self.logger.info(f”PLUGIN_NAME}: Executing validate method for Sample plugin")
if (
"secret_field_id1" not in data
or not data["secret_field_id1"]
or type(data["secret_field_id1"]) != str
):
self.logger.error(
f"{PLUGIN_NAME}: Validation error occurred Error: Secret Field1 is required with type string."
)
return ValidationResult(
success=False, message="Invalid Secret Field 1 provided.",
防御プッシュ
- このメソッドは、アプリケーションの詳細を製品 API エンドポイントまたはソケット接続にプッシュするロジックを実装します。
- すべてのデータを受信してから送信します。データをプッシュするには、あらゆる種類の戦略を使用できます。 ソケット接続であれ、REST APIであれ。
- このメソッドは、 Cloud Exchangeプラットフォームがアプリケーション データを受信したときに呼び出されます。
- APIエンドポイントがサポートする最大ペイロードサイズを超えた場合は必ず対処してください。 このケースに対処する方法は複数考えられます。
- API エンドポイントがペイロード サイズが固定された複数のリクエストをサポートしている場合は、データをチャンクで送信します。
- API エンドポイントが複数のリクエストをサポートしていない場合 (つまり、 (1回のAPI呼び出しでのみプッシュできます)プラグインは残りのログをスキップして、共有フィルターを調整するようにユーザーに通知するか、ペイロードサイズ超過のエラーで失敗することができます。
- 接続と HTTP レスポンス コードを含むすべての例外を処理し、エラーが発生した場合は、ロガーとともにエラー メッセージを含む例外を発生させます。
- API呼び出しを行う際には、ユーザーエージェントをヘッダーに追加する必要があります。ユーザーエージェントのフォーマット: Netskope -ce- <ce_version>-<module>-<plugin_name>-<plugin_version> 。
- このメソッドでは、「システム プロキシを使う」トグルの「プロキシ」変数は、API 呼び出し中に使用する必要があります。
- PushResultオブジェクト(PushResultデータモデルを参照)を、プッシュ操作が成功したかどうかを示す成功フラグとともに返します。
データモデル
このセクションでは、データモデルとその特性を一覧表示します。
アプリケーションモデル
- このモデルには、applicationId、applicationName、vendor、cci、ccl、categoryName、deepLink、users、customTags、discoveryDomains、steeringDomains、createdTime、updatedTime、firstSeen、lastSeen の 15 個のフィールドが含まれています。
- アプリケーションの詳細情報を第三者に送信する際に、プッシュメソッド内でモデルとやり取りすることになります。
データモデルの特性
| 名前 | タイプ | デスクリプション |
|---|---|---|
| applicationId | int | 固有のアプリケーションID。 |
| applicationName | String | アプリケーション名。 |
| vendor | String | フィールドの価値。 |
| cci | int | 任意の正の整数値を指定できます。 |
| ccl | String | 以下の値のいずれかになります[劣悪、低、中、高、優良、不明]。 |
| categoryName | String | カテゴリ名。 |
| deepLink | String | 共有されたアプリケーションの詳細を確認できる第三者ページのリンクです。 |
| users | Listr[string] | ユーザー一覧。 |
| customTags | Listr[string] | List of custom tags. |
| discoveryDomains | Listr[string] | 発見ドメインの一覧。 |
| steeringDomains | Listr[string] | ステアリングドメインの一覧。 |
| createdTime | datetime | 作成日時。 |
| updatedTime | datetime | 更新日時 |
| firstSeen | datetime | 初めて目撃された日時。 |
| lastSeen | datetime | 最後に目撃された日時。 |
TargetMappingFieldsモデル
- このモデルには、ラベル、タイプ、値の3つのフィールドが含まれています。
- get_target_fields メソッドでは、Target のリストを返す際にモデルとやり取りします。フィールズ
データモデルの特性
| 名前 | タイプ | デスクリプション |
|---|---|---|
| label | string | UIに表示されるフィールドのラベル。 |
| タイプ | MappingType | フィールドのデータ型。 |
| value | string | フィールドの価値。 |
from netskope.integrations.grc.models import Application
Application(
applicationId=0,
applicationName="string",
vendor="string",
cci=100,
ccl="poor",
categoryName="string",
deepLink="",
source="string",
createdTime="2023-03-20T06:02:15.893Z",
updatedTime="2023-03-20T06:02:15.893Z",
users=[],
customTags=[],
discoveryDomains=[],
steeringDomains=[],
firstSeen="2023-03-20T06:02:15.893Z",
lastSeen="2023-03-20T06:02:15.893Z",
)
MappingType
これは、リスト、文字列、整数の3つの値で構成される列挙型です。
データモデルの特性
| 名前 | タイプ | デスクリプション |
|---|---|---|
| list | List | 文字列または整数のリストを指定できます。 |
| string | string | 文字列でも構いません。 |
| integer | Integer | 正の整数で構いません。 |
PushResultクラス
- このクラスには、製品 API エンドポイントへのアプリケーション詳細の Push 操作の結果が含まれます。
- 成功フラグはプッシュ操作の結果を示し、メッセージフラグは失敗した場合に適切なエラーメッセージを示す必要があります。 (成功の場合は、成功フラグがTrueのシンプルな成功メッセージが返されます。)
データモデルの特性
| 名前 | タイプ | デスクリプション |
|---|---|---|
| success | bool | 成功フラグは、プッシュ操作が成功したか失敗したか、その結果を示します。 |
| message | string | メッセージフィールドは失敗の場合のエラーを示します。 成功の場合には、シンプルな成功メッセージでも構いません。 |
from netskope.integrations.grc.plugin_base import PushResult
PushResult(
success=True,
message="Successfully pushed data to 3rd party."
)
ValidationResultクラス
- このクラスには、プラグインの新しい設定を作成する際にPluginオブジェクトに渡されるプラグイン設定パラメータに対する検証プロセスの結果が含まれています。
- validate メソッドに渡されるすべてのパラメータが、データ型と値に対して検証されていることを確認してください。
- Validate メソッドは、検証操作の結果を示す成功フラグと、検証が失敗した場合に適切なエラーメッセージを含むメッセージフィールドを持つ、このクラスのオブジェクトを返します。 (成功した場合は、成功フラグがTrueの単純な成功メッセージを返す必要があります。)
- Validate Action もこのクラスのオブジェクトを返すことに注意してください。
データモデルの特性
| 名前 | タイプ | デスクリプション |
|---|---|---|
| success | bool | 成功フラグは、検証操作の結果(成功したか失敗したか)を示します。 |
| message | string | メッセージフィールドは失敗の場合のエラーを示します。 成功の場合には、シンプルな成功メッセージで十分です。 |
from netskope.integrations.cre.plugin_base import ValidationResult
ValidationResult(
success=True,
message="Validation Successful for Sample plugin"
)
ログ記録
Application Risk Exchangeは、ログ記録用のロガーオブジェクトのハンドルを提供します。
- コード内でprint文を使用することは避けてください。
- このオブジェクトは、タイムスタンプフィールドを使用して中央のCloud Exchangeデータベースにログを記録します。 サポートされているログレベルは、情報、警告、エラーです。
- API認証情報やその他の機密情報がログメッセージに漏洩しないようにしてください。
- Cloud Exchangeプラットフォームによって渡されるロガー オブジェクトを使用して、適切なログ メカニズムを実装してください。
- 運用チームがトラブルシューティングを行う際に役立つよう、十分なログ記録が行われるようにしてください。
- 通知やログに機密データが記録されたり、漏洩したりしないようにしてください。
self.logger.error(
f"{PLUGIN_NAME}: Error log-message goes here."
)
self.logger.warn(
f"{PLUGIN_NAME}: Warning log-message goes here."
)
self.logger.info(
f"{PLUGIN_NAME}: Info log-message goes here."
)
通知
Application Risk Exchange は通知オブジェクトのハンドルを提供します。このハンドルは Application Risk Exchange UI で通知を生成するために使用できます。
- このオブジェクトは、 Cloud Exchangeプラットフォームから Plugin オブジェクトに渡されます。 すべてのプラグイン統合は ユーザーに即座に通知する必要のある障害が発生した場合はいつでもこのオブジェクトを使用できます。 通知のタイムスタンプは、 Cloud Exchangeプラットフォームによって管理されます。
- このオブジェクトは、障害の深刻度に応じて色分けされた通知をUI上に表示します。サポートされている通知の重要度は、情報、警告、エラーです。
- 通知メッセージに、API認証情報やその他の機密情報が含まれていないことを確認してください。
- 障害や重大な状況(レート制限、ペイロードサイズの超過など)が発生した場合に通知を発生させ、プラグインの状態をユーザーに通知するための通知オブジェクト。
self.notifier.info(
f"{PLUGIN_NAME}: Info notification-message goes here."
)
self.notifier.error(
f"{PLUGIN_NAME}: Error notification-message goes here."
)
self.notifier.warn(
f"{PLUGIN_NAME}: Warning notification-message goes here."
)
Testing
Linting
ビルドプロセスの一環として、いくつかのリンターを実行して、 プログラミングエラー、スタイルエラー、および潜在的なセキュリティ問題を検出します。
Flake8
これは基本的なリンターです。必要な依存関係がすべて揃っていなくても実行でき、不要なエラーを検出します。 また このリンターを使用して、標準的な Python PEP8 フォーマットスタイルを強制します。 まれに、このリンターから返されるエラーや警告を無効にする必要が生じる場合があります。エラーを無効にしたい行に、次のようなインラインコメントを追加することでこれを実現します。
# noqa: <error-id>
例:
example = lambda: 'example' # noqa: E731
インラインコメントを追加する場合は、必ず無効にするエラーコードも含めます。そうすれば、同じ行に他のエラーがあった場合、それらが報告されます。
詳細については、次のURLをご覧ください: https://flake8.pycqa.org/en/latest/user/violations.html#in-line-ignoring-errors
Flake8リンターでは、PEP8スタイルのドキュメント文字列チェックも有効になっています。したがって、すべての関数/モジュールに適切なドキュメンテーション文字列が追加されていることを確認してください。
単体テスト
単体テストを実施し、コードの小さな単位を隔離された状態で、かつ決定論的にテストするようにしてください。単体テストでは、外部 API との通信や モックの使用を避けるようにしてください。 単体テストによってコードカバレッジが70%以上であることを確認してください。
環境設定
単体テストを行うには、統合または自動化スクリプトをプラグインディレクトリ構造で開発する必要があります。 セットアップを実行するために必要なすべてのPythonモジュール依存関係をインストールするには、PIPを使用します。 テストを実行する前に、Application Risk Exchange コアリポジトリの requirements.txt に記載されている必要な依存関係をすべてインストールしてください。
ユニットテストを作成する
ユニットテストは、 <your_plugin_name> _test.py という名前の別の Python ファイルに記述してください。単体テストファイル内では、各単体テスト関数は test_ という名前を付ける必要があります。<your test case>単体テストの書き方やフォーマットに関する詳細は、 PyTest ドキュメントをご覧ください。
Mocking
モックにはpytest-mockを使います。 pytest-mockはデフォルトで有効になっており、上記の基本環境にインストールされています。モッカーオブジェクトを使うには、テスト関数のパラメータとしてパスするだけです。モッカーは プラグインクラスオブジェクトと外部APIの両方をモックできます。
例:
ef test_netskope_push(mocker):
mocker.patch("grc.plugins.sample.main.SamplePlugin")
Push_return_result = PushResult(
success=True,
message="Successfully pushed data to third_party.",
)
samplePlugin.push.return_value = Push_return_result
sp = samplePlugin(None, None, None, logger)
application = [Application(objectId="64116b18969c9579c080c5ac",
applicationId=0,
applicationName="Postman",
vendor="Nexus Venture Partners",
cci=100,
ccl="poor",
categoryName="Desktop",
deepLink="",
createdTime="2023-03-15T06:52:08.374000",
updatedTime="2023-03-15T06:52:08.374000",
source="netskope",
users=[],
customTags=[],
discoveryDomains=[],
steeringDomains=[],
firstSeen="2023-03-15T06:52:08.374000",
lastSeen="2023-03-15T06:52:08.374000"
)]
mappings = {
"jsonQuery": {
"and": [
{
"==": [
{
"var": "name"
},
"applicationName"
]
}
]
},
"query": "name == \"applicationName\""
}
actual_push = sp.push(application,mappings)
assert push_return_result == actual_push
API呼び出しのリクエストモジュールのレスポンスをモックするため(requests_mock Pytestプラグインはすべての依存関係とともにインストールされています)。
def test_fetch_users(requests_mock):
endpoint_url = "https://example-api.com"
mock_response_json = {
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#directoryObjects",
"value": [
{
"@odata.type": "#microsoft.graph.user",
"id": "48a97c4b-65af-4cb7-90f9-c7835d5ecd8b",
"userPrincipalName": "adaml@xyz.com"
}
]
}
requests_mock.get(endpoint_url, json=mock_response_json)
config_dict = {
"tenant_name": "ecre-ccec-jpvasq",
"client_id": "ue4y-3id8-mnx87q",
"client_secret": "d9oe-ple7-nfi34w",
"api_token": "token",
}
sp = SamplePlugin(config_dict, None, None, logger)
actual_users_lists = sp.fetch_users(
endpoint_url,
config_dict['api_token']
)
users_mock = [
Record(uid="a@def.com", type=Record.user, score=400),
Record(uid="b@pqr.com", type=Record.user, score=300),
Record(uid="c@xyz.com", type=Record.user, score=750),
]
assert len(actual_users_lists) == len(users_mock)
for i in range(len(actual_users_lists)):
assert actual_ind_lists[i].value == users_mock[i].value
ユニットテストを実行する
$ PYTHONPATH=. pytest
Cloud Exchangeへのプラグイン展開
プラグインをパッケージ化する
Cloud Exchangeは、開発されたプラグインをzipおよびtar.gz形式で提供することを想定しています。
パッケージを圧縮するには、次のコマンドを実行してください。
zip -r sample_plugin.zip sample_plugin
tar.gzパッケージを生成するには、以下のコマンドを実行してください。
tar -zcvf sample_plugin.tar.gz sample_plugin
プラグインをアップロードする
この zip または tar.gz をCloud Exchangeにデプロイするには、次の手順に従います。
- Cloud Exchangeプラットフォームにログインします。
- Settings > Plugin .
へ移動してください。
- Add New Plugin .
をクリックしてください
- Browseをクリックしてください。
- zipファイルまたはtar.gzファイルをSelect 。

- Uploadをクリックしてください。
Add a Repo
Cloud Exchangeプラットフォームにプラグインをデプロイするには、次の手順に従ってCloud Exchangeプラットフォームにリポジトリを追加します。
- Cloud Exchangeプラットフォームにログインします。
- Settings > Plugin Repository .
へ移動してください。
- Configure New Repository .
をクリックしてください
- リポジトリ名、リポジトリURL、ユーザー名、および個人アクセストークンを入力してください。
- Saveをクリックしてください。

- Settings > Pluginsへ移動してください。
- リポジトリのドロップダウンリストからリポジトリ名Select 。

Deliverables
Plugin Guide
- プラグインガイドは、リリースごとに必ず更新してください。
- プラグインガイドには以下の内容を含める必要があります。
- Compatibility
- リリースノート
- デスクリプション
- 前提条件
- 権限
- 製品の承認
- Netskope Application Risk Exchangeプラグインの設定
- 当社が開発したサードパーティ製アプリケーションリスク交換プラグインの設定。
- ビジネスルールの設定
- 共有設定の追加設定
- Validation
デモビデオ
Application Risk Exchangeプラグインの開発が成功したら、デモビデオを作成し、プラグインのエンドツーエンドのワークフローを示してください。

