DAST API アナライザ

DAST API analyzerはGitLab 15.6でオンデマンドDAST APIスキャンのデフォルトアナライザーとなりました。

ウェブAPIの動的アプリケーションセキュリティテスト(DAST) を実行することで、他のQAプロセスが見逃す可能性のあるバグや潜在的なセキュリティ問題を発見することができます。他のGitLab Secureセキュリティスキャナや独自のテストプロセスに加えて、DAST API テストを使用してください。DAST API テストは、CI/CD ワークフローの一部として、またはオンデマンドで、あるいはその両方で実行することができます。

caution
本番サーバーに対して DAST API テストを実行しないでください。APIが実行できる_あらゆる_機能を実行できるだけでなく、APIのバグを誘発する可能性があります。これには、データの変更や削除などのアクションが含まれます。DAST API はテストサーバーに対してのみ実行してください。

DAST API は、以下の Web API タイプをテストすることができます:

  • REST API
  • SOAP
  • GraphQL
  • フォームボディ、JSON、またはXML

DAST APIスキャン実行時

CI/CD パイプラインで実行する場合、DAST API スキャンはdast デフォルトでステージで dast実行されます。dast DAST API スキャンが最新のコードを検査するようにするには、CI/CD パイプラインがステージの前にステージのテスト環境に変更をデプロイ dastするようにしてください。

パイプラインが各実行で同じ Web サーバーにデプロイされるように設定されている場合、別のパイプラインがまだ実行されている間にパイプラインを実行すると、あるパイプラインが別のパイプラインのコードを上書きするという競合状態が発生する可能性があります。スキャン対象のAPIは、DAST APIスキャンの間、変更から除外する必要があります。API に対する変更は、DAST API スキャナによるものだけにしてください。スキャン中に API に加えられた変更(ユーザー、スケジュールされたタスク、データベースの変更、コードの変更、他のパイプライン、他のスキャナなど)は、不正確な結果を引き起こす可能性があります。

DAST APIスキャンの設定例

以下のプロジェクトは、DAST API スキャンを実演しています:

DASTスキャンのためのターゲットAPI

を使ってスキャンしたい API を指定します:

OpenAPIの仕様

  • YAMLフォーマットによるOpenAPI仕様のサポートがGitLab 14.0から導入されました。
  • メディアタイプapplication/xml の生成サポートが GitLab 14.8 で導入されました。
  • メディアタイプのサポートが GitLab 14.10 で導入されました。

OpenAPI仕様(旧Swagger仕様)は、REST API用のAPI記述フォーマットです。このセクションでは、テスト対象のAPIに関する情報を提供するOpenAPI仕様書を使用してDAST APIスキャンを設定する方法を説明します。OpenAPI 仕様書は、ファイルシステムのリソースまたは URL として提供されます。JSON と YAML の両方の OpenAPI フォーマットに対応しています。

DAST API は、リクエストボディを生成するために OpenAPI ドキュメントを使用します。リクエストボディが必要な場合、ボディの生成はこれらのボディタイプに限定されます:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • application/xml

OpenAPI およびメディアタイプ

メディアタイプ (以前は MIME タイプとして知られていました) は、ファイルフォーマットと送信されるフォーマットコンテンツの識別子です。OpenAPI ドキュメントでは、あるオペレーションが異なるメディアタイプを受け付けることを指定できます。たとえば、PUT /user ユーザーデータを更新するオペレーションでは、XML (メディアタイプapplication/xml) または JSON (メディアタイプapplication/json) 形式のデータを受け取ることができます。OpenAPI 2.x では、受け入れられるメディアタイプをグローバルまたはオペレーションごとに指定することができ、OpenAPI 3.x では、受け入れられるメディアタイプをオペレーションごとに指定することができます。DAST APIは、リストされたメディアタイプをチェックし、サポートされている各メディアタイプのサンプルデータを作成しようとします。

  • GitLab 14.10以降では、デフォルトの動作として、サポートされているメディアタイプの中から1つを選択して使用します。最初にサポートされたメディアタイプがリストから選ばれます。この動作は設定可能です。
  • GitLab 14.9以前では、デフォルトの動作はサポートされている全てのメディアタイプを使ってテストを実行します。つまり、2つのメディアタイプがリストされている場合(例えば、application/jsonapplication/xml)、テストはJSONを使って行われ、次にXMLを使って同じテストが行われます。

異なるメディアタイプ(例えば、application/jsonapplication/xml)を使って、同じオペレーション(例えば、POST /user)をテストすることは、必ずしも望ましいことではありません。例えば、ターゲットアプリケーショ ンがリクエストのコンテントタイプに関係なく同じコードを実行する場合、テストセッションを終了するのに時間がかかり、ターゲッ トアプリによってはリクエストボディに関連する脆弱性を重複して報告するかもしれません。

環境DAST_API_OPENAPI_ALL_MEDIA_TYPES 変数によって、与えられたオペレーションに対するリクエストを生成するときに、1つのメディアタイプではなく、サポートされているすべてのメディアタイプを使うかどうかを指定 DAST_API_OPENAPI_ALL_MEDIA_TYPESできます。DAST_API_OPENAPI_ALL_MEDIA_TYPES 環境変数が DAST_API_OPENAPI_ALL_MEDIA_TYPES任意の値に設定されている場合、DAST API は指定されたオペレーションにおいて、1つのメディアタイプではなく、サポートされているすべてのメディアタイプのリクエストを生成しようとします。この場合、提供されたメディアタイプごとにテストが繰り返されるため、テストに時間がかかります。

別の方法として、このDAST_API_OPENAPI_MEDIA_TYPES 変数を使ってテストするメディアタイプの一覧を指定 DAST_API_OPENAPI_MEDIA_TYPESします。DAST_API_OPENAPI_MEDIA_TYPES 複数のメディアタイプを提供すると、選択されたメディアタイプごとにテストが実行されるため、テストに時間がかかります。環境変数が DAST_API_OPENAPI_MEDIA_TYPESメディアタイプのリストに設定されているときは、 リクエストを作成するときにリストされたメディアタイプだけが含まれます。

DAST_API_OPENAPI_MEDIA_TYPES 、複数のメディアタイプはコロン(:)で区切られます。たとえば、リクエスト生成をメディアタイプapplication/x-www-form-urlencodedmultipart/form-data に制限するには、環境変数DAST_API_OPENAPI_MEDIA_TYPESapplication/x-www-form-urlencoded:multipart/form-dataに設定します。このリストでサポートされているメディアタイプだけがリクエスト作成時に 含まれますが、サポートされていないメディアタイプは常にスキップされます。メディアタイプのテキストは異なるセクションを含むかもしれません。例えば、application/vnd.api+json; charset=UTF-8type "/" [tree "."] subtype ["+" suffix]* [";" parameter]の複合です。 リクエスト生成時にメディアタイプのフィルタリングを実行するとき、 パラメータは考慮されません。

環境変数DAST_API_OPENAPI_ALL_MEDIA_TYPESDAST_API_OPENAPI_MEDIA_TYPES でメディアタイプの扱い方を決めることができます。これらの設定は互いに排他的です。両方が有効な場合、DAST API はエラーを報告します。

OpenAPI 仕様による DAST API の設定

OpenAPI 仕様で DAST API スキャンを設定するには、以下の手順に従います:

  1. .gitlab-ci.yml ファイルにDAST-API.gitlab-ci.yml テンプレート含めます

  2. 設定ファイルには、異なるチェックを有効にした複数のテストプロファイルが定義されています。Quick プロファイルから始めることを推奨します。このプロファイルを使ったテストはより速く完了し、設定の検証がより簡単になります。.gitlab-ci.yml ファイルにDAST_API_PROFILE CI/CD 変数を追加してプロファイルを指定します。

  3. OpenAPI Specification の場所をファイルか URL で指定します。DAST_API_OPENAPI 変数を追加して場所を指定します。

  4. ターゲットAPIインスタンスのベースURLも必要です。DAST_API_TARGET_URL 変数かenvironment_url.txt ファイルを使って指定してください。

    プロジェクトのルートにあるenvironment_url.txt ファイルに URL を追加すると、動的環境でのテストに最適です。GitLab CI/CDパイプライン中に動的に作成されたアプリに対してDAST APIを実行するには、アプリにそのURLをenvironment_url.txt ファイルに保持させます。DAST APIは自動的にそのファイルを解析してスキャン対象を見つけます。この例はAuto DevOps CI YAMLで見ることができます。

OpenAPI 仕様を使用する完全な設定例:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/

これはDAST APIの最小設定です。ここから以下のことができます:

HTTPアーカイブ(HAR)

HTTP Archive フォーマット(HAR)はHTTPトランザクションを記録するためのアーカイブファイルフォーマットです。GitLab DAST APIスキャナで使用する場合、HARファイルにはテストするWeb APIを呼び出した記録が含まれていなければなりません。DAST API スキャナは全てのリクエストを抽出し、テストの実行に使用します。

HARファイルを生成するには様々なツールを使うことができます:

caution
HAR ファイルには、認証トークン、API キー、セッションクッキーなどの機密情報が含まれている場合があります。リポジトリに追加する前に、HAR ファイルの内容をレビューすることをお勧めします。

HAR ファイルを使用した DAST API スキャン

テスト対象の API に関する情報を提供する HAR ファイルを使用するように DAST API を設定します:

  1. .gitlab-ci.yml ファイルにDAST-API.gitlab-ci.yml テンプレート含めます

  2. 設定ファイルには、異なるチェックを有効にした複数のテストプロファイルが定義されています。Quick プロファイルから始めることを推奨します。このプロファイルでのテストはより速く完了し、設定の検証がより簡単になります。

    .gitlab-ci.yml ファイルにDAST_API_PROFILE CI/CD 変数を追加してプロファイルを指定します。

  3. HARファイルの場所を指定します。場所はファイルパスかURLで指定できます。URL サポートはGitLab 13.10 以降で導入されました。DAST_API_HAR 変数を追加して場所を指定してください。

  4. ターゲットAPIインスタンスのベースURLも必要です。DAST_API_TARGET_URL 変数かenvironment_url.txt ファイルを使って指定してください。

    プロジェクトのルートにあるenvironment_url.txt ファイルに URL を追加すると、動的環境でのテストに最適です。GitLab CI/CDパイプライン中に動的に作成されたアプリに対してDAST APIを実行するには、アプリにそのURLをenvironment_url.txt ファイルに保持させます。DAST APIは自動的にそのファイルを解析してスキャン対象を見つけます。この例はAuto DevOps CI YAMLで見ることができます。

HARファイルを使用する完全な設定例:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_HAR: test-api-recording.har
  DAST_API_TARGET_URL: http://test-deployment/

この例は、DAST APIの最小限の設定です。ここから以下のことができます:

GraphQL スキーマ

GraphQL SchemaのサポートはGitLab 15.4で導入されました。

GraphQLはAPIのクエリ言語であり、REST APIに代わるものです。DAST APIは複数の方法でGraphQLエンドポイントのテストをサポートしています:

  • GraphQL Schemaを使ったテスト。GitLab 15.4で導入されました
  • GraphQLクエリの記録(HAR) 。
  • GraphQLクエリを含むPostmanコレクションを使用してテストします。

このセクションでは、GraphQL スキーマを使用したテスト方法を説明します。DAST API の GraphQL スキーマサポートは、イントロスペクションをサポートするエンドポイントからスキーマをクエリできます。GraphiQL のようなツールが動作するように、イントロスペクションはデフォルトで有効になっています。イントロスペクションを有効にする方法の詳細については、GraphQL フレームワークのドキュメントを参照してください。

GraphQL エンドポイント URL による DAST API スキャン

DAST API の GraphQL サポートは、スキーマの GraphQL エンドポイントをクエリできます。

note
このメソッドが正しく動作するためには、GraphQLエンドポイントがイントロスペクションクエリをサポートしている必要があります。

テスト対象の API に関する情報を提供する GraphQL エンドポイント URL を使用するように DAST API を設定するには、以下の手順に従います:

  1. .gitlab-ci.yml ファイルにDAST-API.gitlab-ci.yml テンプレート含めます

  2. 例えば/api/graphql のように、GraphQL エンドポイントへのパスを指定します。DAST_API_GRAPHQL 変数を追加して場所を指定します。

  3. ターゲットAPIインスタンスのベースURLも必要です。DAST_API_TARGET_URL 変数かenvironment_url.txt ファイルを使って指定してください。

    プロジェクトのルートにあるenvironment_url.txt ファイルに URL を追加すると、動的環境でのテストに最適です。詳細については、ドキュメントの動的環境ソリューションのセクションを参照してください。

GraphQL エンドポイント パスを使用する完全な設定例:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

dast_api:
  variables:
    DAST_API_GRAPHQL: /api/graphql
    DAST_API_TARGET_URL: http://test-deployment/

この例は、DAST APIの最小限の設定です。ここから以下のことができます:

GraphQL スキーマファイルによる DAST API スキャン

DAST API は GraphQL スキーマファイルを使用して、イントロスペクションが無効になっている GraphQL エンドポイントを理解し、テストすることができます。GraphQL スキーマファイルを使用するには、introspection JSON 形式である必要があります。GraphQL スキーマは、オンラインのサードパーティツール(https://transform.tools/graphql-to-introspection-json)を使用して introspection JSON フォーマットに変換できます。

テスト対象の API に関する情報を提供する GraphQL スキーマファイルを使用するように DAST API を設定するには、以下の手順に従います:

  1. .gitlab-ci.yml ファイルにDAST-API.gitlab-ci.yml テンプレート含めます

  2. 例えば/api/graphql のように、GraphQL エンドポイントのパスを指定します。DAST_API_GRAPHQL 変数を追加してパスを指定します。

  3. GraphQLスキーマファイルの場所を指定します。ファイルのパスまたは URL として場所を指定できます。DAST_API_GRAPHQL_SCHEMA 変数を追加して場所を指定します。

  4. ターゲットAPIインスタンスのベースURLも必要です。DAST_API_TARGET_URL 変数かenvironment_url.txt ファイルを使って指定してください。

    プロジェクトのルートにあるenvironment_url.txt ファイルに URL を追加すると、動的環境でのテストに最適です。詳細については、ドキュメントの動的環境ソリューションのセクションを参照してください。

GraphQLスキーマファイルを使用する完全な設定例:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

dast_api:
  variables:
    DAST_API_GRAPHQL: /api/graphql
    DAST_API_GRAPHQL_SCHEMA: test-api-graphql.schema
    DAST_API_TARGET_URL: http://test-deployment/

GraphQLスキーマファイルのURLを使用する設定の完全な例:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

dast_api:
  variables:
    DAST_API_GRAPHQL: /api/graphql
    DAST_API_GRAPHQL_SCHEMA: http://file-store/files/test-api-graphql.schema
    DAST_API_TARGET_URL: http://test-deployment/

この例は、DAST APIの最小限の設定です。ここから以下のことができます:

ポストマンコレクション

Postman API Clientは、開発者やテスターが様々なタイプのAPIを呼び出すために使用する一般的なツールです。API 定義は、DAST API で使用するためにPostman Collection ファイルとしてエクスポートすることができます。エクスポートする際は、サポートされているPostman Collectionのバージョン(v2.0またはv2.1)を選択してください。

GitLab DAST APIスキャナで使用する場合、Postman Collectionには有効なデータでテストするWeb APIの定義が含まれている必要があります。DAST APIスキャナは全てのAPI定義を抽出し、テストを実行するために使用します。

caution
Postman Collectionファイルには、認証トークン、APIキー、セッションクッキーなどの機密情報が含まれている可能性があります。リポジトリに追加する前に、Postman Collectionファイルの内容をレビューすることをお勧めします。

Postman コレクションファイルによる DAST API スキャン

テスト対象の API に関する情報を提供する Postman Collection ファイルを使用するように DAST API を設定します:

  1. DAST-API.gitlab-ci.yml テンプレート含めます

  2. 設定ファイルには、異なるチェックを有効にした複数のテストプロファイルが定義されています。Quick プロファイルから始めることを推奨します。このプロファイルでのテストはより速く完了し、設定の検証がより簡単になります。

    .gitlab-ci.yml ファイルにDAST_API_PROFILE CI/CD 変数を追加してプロファイルを指定します。

  3. Postman Collection ファイルの場所をファイルまたは URL で指定します。DAST_API_POSTMAN_COLLECTION 変数を追加して場所を指定します。

  4. ターゲットAPIインスタンスのベースURLも必要です。DAST_API_TARGET_URL 変数かenvironment_url.txt ファイルを使って指定してください。

    プロジェクトのルートにあるenvironment_url.txt ファイルに URL を追加すると、動的環境でのテストに最適です。GitLab CI/CDパイプライン中に動的に作成されたアプリに対してDAST APIを実行するには、アプリにそのURLをenvironment_url.txt ファイルに保持させます。DAST APIは自動的にそのファイルを解析してスキャン対象を見つけます。この例はAuto DevOps CI YAMLで見ることができます。

Postman コレクションを使用する完全な設定例です:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_POSTMAN_COLLECTION: postman-collection_serviceA.json
  DAST_API_TARGET_URL: http://test-deployment/

これはDAST APIの最小設定です。ここから以下のことができます:

Postman の変数

  • GitLab15.1でPostman環境ファイルフォーマットのサポートが導入されました。
  • GitLab 15.1で複数の変数ファイルのサポートが導入されました。
  • Postman変数スコープをサポートしました:Global と Environment が GitLab 15.1 で導入されました。
Postman クライアントの変数

Postman では開発者がリクエストの様々な部分で使えるプレースホルダを定義できます。変数の使い方で説明したように、これらのプレースホルダは変数と呼ばれます。変数を使ってリクエストやスクリプトに値を保存したり再利用したりできます。たとえば、コレクションを編集してドキュメントに変数を追加できます:

Edit collection variable tab View

あるいは、環境変数を追加することもできます:

Edit environment variables View

URLやヘッダーなどのセクションで変数を使うことができます:

Edit request using variables View

Postmanは素敵なUXを体験できる基本的なクライアントツールから、スクリプトでAPIをテストしたり、二次リクエストをトリガーする複雑なコレクションを作成したり、途中で変数を設定したりできる、より複雑なエコシステムに成長しました。Postmanエコシステムのすべての機能がサポートされているわけではありません。例えば、スクリプトはサポートされていません。Postmanサポートの主な焦点は、Postmanクライアントで使用されるPostmanコレクション定義と、ワークスペース、環境、コレクション自体で定義された関連変数を取り込むことです。

Postmanは異なるスコープで変数を作成できます。それぞれのスコープは、Postmanツールでの可視性のレベルが異なります。例えば、すべてのオペレーション定義とワークスペースから見える_グローバル環境_スコープに変数を作成できます。また、特定の_環境_スコープに変数を作成し、その特定の環境が選択されているときのみ表示・使用されるようにすることもできます。例えば Postman エコシステムでは、Postman クライアントでリクエストを作成することができます。

Postman の変数スコープは難しいトピックで、誰もが知っているわけではありません。先に進む前に Postman ドキュメントの変数スコープを読むことを強くお勧めします。

上述したように、変数スコープには様々なものがあり、それぞれに目的があり、Postmanドキュメントに柔軟性を持たせるために使用することができます。Postmanのドキュメントにあるように、変数の値がどのように計算されるかについて重要な注意があります:

同じ名前の変数が2つの異なるスコープで宣言されている場合、最も狭いスコープの変数に格納されている値が使用されます。例えば、グローバル変数username 名とローカル変数名が usernameある場合、リクエストが実行されるときにはローカル変数の値が使われます。

Postman クライアントと DAST API がサポートする変数のスコープを以下にまとめます:

  • グローバル環境 (Global) スコープは、ワークスペース全体で利用可能な、あらかじめ定義された特別な環境です。_グローバル環境_スコープを_グローバル_スコープと呼ぶこともあります。Postman Client ではグローバル環境を JSON ファイルにエクスポートでき、DAST API で使用できます。
  • 環境スコープとは、ユーザーが Postman Client で作成した、名前付きの変数グループです。Postman Client はグローバル環境とともに、1つのアクティブ環境をサポートします。ユーザーが作成したアクティブ環境で定義された変数は、グローバル環境で定義された変数よりも優先されます。Postman クライアントでは、DAST API で使用できる JSON ファイルに環境をエクスポートできます。
  • コレクションスコープとは、あるコレクションで宣言された変数のグループのことです。コレクション変数は宣言されたコレクションと、ネストされたリクエストやコレクションで使用できます。コレクションスコープで定義された変数は_グローバル環境_スコープや_環境_スコープよりも優先されます。この JSON ファイルには選択されたコレクション、リクエスト、コレクション変数が含まれます。
  • DAST API スコープはDAST API によって追加された新しいスコープで、ユーザーが追加の変数を提供したり、他のサポートされているスコープで定義された変数を上書きしたりすることができます。このスコープは Postman ではサポートされていません。_DAST API スコープの_変数は、カスタム JSON ファイル形式で提供されます。
    • 環境またはコレクションで定義された値をオーバーライドします。
    • スクリプトからの変数の定義
    • サポートされていない_データ・スコープから_1行のデータを定義
  • データスコープとは、JSON や CSV ファイルの名前と値を持つ変数のグループです。NewmanPostman Collection Runnerのような Postman コレクションランナーは、JSON や CSV ファイルがある回数だけコレクション内のリクエストを実行します。これらの変数の良い使用例は、Postman のスクリプトを使ってテストを自動化することです。DAST API は CSV や JSON ファイルからの読み込みをサポートしていません
  • ローカルスコープはPostman スクリプト内で定義される変数です。DAST API は Postman スクリプトをサポートしておらず、スクリプト内で定義された変数もサポートしていません。スクリプトで定義された変数は、サポートされているスコープ、またはカスタム JSON フォーマットのいずれかで定義することで、値を提供することができます。

すべてのスコープが DAST API でサポートされているわけではなく、スクリプトで定義された変数はサポートされていません。以下の表は、最も広いスコープから最も狭いスコープにソートされています。

スコープポストマンDAST APIコメント
グローバル環境はいはい特別な事前定義環境
環境はいはい指定環境
コレクションはいはいpostmanコレクションで定義
DAST API スコープなしはいDAST APIによって追加されたカスタムスコープ
データはいなしCSVまたはJSON形式の外部ファイル
ローカルはいなしスクリプトで定義された変数

異なるスコープで変数を定義し、変数をエクスポートする方法の詳細については、以下を参照してください:

Postman クライアントからのエクスポート

Postman Client では様々なファイル形式でエクスポートできます。例えば、Postman コレクションや Postman 環境をエクスポートできます。エクスポートする環境はグローバル環境(常に利用可能)でも、以前に作成したカスタム環境でもかまいません。Postman コレクションをエクスポートする場合、コレクションと _ローカル_スコープ変数の宣言のみを含むことができます。

_環境_スコープ変数の宣言を得るには、その時点で指定された環境をエクスポートする必要があります。エクスポートされたファイルには、選択した環境の変数のみが含まれます。

サポートされるスコープが異なる変数のエクスポートの詳細については、こちらを参照してください:

DAST API スコープ、カスタム JSON ファイル形式

カスタムJSONファイルフォーマットは、各オブジェクトプロパティが変数名を表し、プロパティ値が変数値を表すJSONオブジェクトです。このファイルはお好みのテキストエディタを使用して作成することもできますし、パイプライン内の以前のジョブで作成することもできます。

この例では、DAST API スコープで 2 つの変数base_urltoken を定義しています:

{
  "base_url": "http://127.0.0.1/",
  "token": "Token 84816165151"
}
DAST API でのスコープの使用

GitLab15.1以降ではglobalenvironmentcollection、_GitLab DAST APIの_スコープがサポートされています。GitLab 15.0以前では、_collectionと_GitLab D_AST APIの_スコープのみをサポートしています。

以下の表は、スコープファイル/URLを DAST API 設定変数にマッピングするためのクイックリファレンスです:

スコープ提供方法
グローバル環境dast_api_postman_collection_variables
環境dast_api_postman_collection_variables
コレクションdast_api_postman_collection
DAST API スコープdast_api_postman_collection_variables
データ未対応
ローカル未対応

Postman Collection ドキュメントには、_コレクションに_スコープされた変数が自動的に含まれます。Postman Collection は設定変数DAST_API_POSTMAN_COLLECTION で提供されます。この変数はエクスポートされた1つのPostmanコレクションに設定できます。

他のスコープの変数はDAST_API_POSTMAN_COLLECTION_VARIABLES 設定変数を通して提供されます。この設定変数は、GitLab 15.1以降ではカンマ(,)区切りのファイルリストをサポートしています。GitLab 15.0とそれ以前では、単一のファイルのみをサポートしています。ファイルが必要なスコープ情報を提供するので、提供されるファイルの順番は重要ではありません。

設定変数DAST_API_POSTMAN_COLLECTION_VARIABLES

未定義のPostman変数

Postman コレクションファイルが使用しているすべての変数参照を、DAST API エンジンが見つけられない可能性があります。以下のようなケースが考えられます:

  • _データ_または_ローカル_スコープ変数を使用しており、前述のようにこれらのスコープは DAST API でサポートされていません。したがって、これらの変数の値がDAST API スコープを通して提供されていないと仮定すると、_データ_変数と_ローカル_スコープ変数の値は未定義です。
  • 変数名の入力に誤りがあり、定義されている変数と名前が一致しません。
  • Postman クライアントが、DAST API ではサポートされていない新しい動的変数をサポートしました。

可能な限り、DAST API は未定義の変数を扱う際に Postman Client と同じ動作をします。変数参照のテキストはそのままで、テキストの置換は行われません。サポートされていない動的変数についても同じ動作が適用されます。

例えば、Postman コレクションのリクエスト定義が変数を{{full_url}} 参照していて、その変数が見つから なかった場合、その変数は変更されずに . {{full_url}}

動的な Postman 変数

ユーザーが様々なスコープレベルで定義できる変数に加えて、Postman には_動的_変数と呼ばれる定義済みの変数があります。動的変数はすでに定義されており、その名前の先頭にはドル記号 ($) が付きます。インスタンスでは$guidとなります。_動的_変数は他の変数と同じように使うことができ、Postmanクライアントではリクエスト/コレクションの実行中にランダムな値を生成します。

DAST API と Postman の重要な違いは、DAST API は同じ動的変数を使用するたびに同じ値を返すことです。これは、同じ動的変数を使用するたびにランダムな値を返す Postman Client の動作とは異なります。言い換えると、DAST API は動的変数に静的な値を使用するのに対し、Postman はランダムな値を使用します。

スキャン処理中にサポートされる動的変数は以下の通りです:

変数
$guid611c2e81-2ccb-42d8-9ddc-2d0bfa65c1b4
$isoTimestamp2020-06-09T21:10:36.177Z
$randomAbbreviationPCI
$randomAbstractImagehttp://no-a-valid-host/640/480/abstract
$randomAdjectiveauxiliary
$randomAlphaNumerica
$randomAnimalsImagehttp://no-a-valid-host/640/480/animals
$randomAvatarImagehttps://no-a-valid-host/path/to/some/image.jpg
$randomBankAccount09454073
$randomBankAccountBicEZIAUGJ1
$randomBankAccountIbanMU20ZPUN3039684000618086155TKZ
$randomBankAccountNameHome Loan Account
$randomBitcoin3VB8JGT7Y4Z63U68KGGKDXMLLH5
$randomBooleantrue
$randomBskiller leverage schemas
$randomBsAdjectiveviral
$randomBsBuzzrepurpose
$randomBsNounmarkets
$randomBusinessImagehttp://no-a-valid-host/640/480/business
$randomCatchPhraseFuture-proofed heuristic open architecture
$randomCatchPhraseAdjectiveBusiness-focused
$randomCatchPhraseDescriptorbandwidth-monitored
$randomCatchPhraseNounsuperstructure
$randomCatsImagehttp://no-a-valid-host/640/480/cats
$randomCitySpinkahaven
$randomCityImagehttp://no-a-valid-host/640/480/city
$randomColorfuchsia
$randomCommonFileExtwav
$randomCommonFileNamewell_modulated.mpg4
$randomCommonFileTypeaudio
$randomCompanyNameGrady LLC
$randomCompanySuffixInc
$randomCountryKazakhstan
$randomCountryCodeMD
$randomCreditCardMask3622
$randomCurrencyCodeZMK
$randomCurrencyNamePound Sterling
$randomCurrencySymbol£
$randomDatabaseCollationutf8_general_ci
$randomDatabaseColumnupdatedAt
$randomDatabaseEngineMemory
$randomDatabaseTypetext
$randomDateFutureTue Mar 17 2020 13:11:50 GMT+0530 (India Standard Time)
$randomDatePastSat Mar 02 2019 09:09:26 GMT+0530 (India Standard Time)
$randomDateRecentTue Jul 09 2019 23:12:37 GMT+0530 (India Standard Time)
$randomDepartmentElectronics
$randomDirectoryPath/usr/local/bin
$randomDomainNametrevor.info
$randomDomainSuffixorg
$randomDomainWordjaden
$randomEmailIva.Kovacek61@no-a-valid-host.com
$randomExampleEmailnon-a-valid-user@example.net
$randomFashionImagehttp://no-a-valid-host/640/480/fashion
$randomFileExtwar
$randomFileNameneural_sri_lanka_rupee_gloves.gdoc
$randomFilePath/home/programming_chicken.cpio
$randomFileTypeapplication
$randomFirstNameChandler
$randomFoodImagehttp://no-a-valid-host/640/480/food
$randomFullNameConnie Runolfsdottir
$randomHexColor#47594a
$randomImageDataUridata:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20baseProfile%3D%22full%22%20width%3D%22undefined%22%20height%3D%22undefined%22%3E%20%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22grey%22%2F%3E%20%20%3Ctext%20x%3D%220%22%20y%3D%2220%22%20font-size%3D%2220%22%20text-anchor%3D%22start%22%20fill%3D%22white%22%3Eundefinedxundefined%3C%2Ftext%3E%20%3C%2Fsvg%3E
$randomImageUrlhttp://no-a-valid-host/640/480
$randomIngverbnavigating
$randomInt494
$randomIP241.102.234.100
$randomIPV6dbe2:7ae6:119b:c161:1560:6dda:3a9b:90a9
$randomJobAreaMobility
$randomJobDescriptorSenior
$randomJobTitleInternational Creative Liaison
$randomJobTypeSupervisor
$randomLastNameSchneider
$randomLatitude55.2099
$randomLocaleny
$randomLongitude40.6609
$randomLoremLinesDucimus in ut mollitia.\nA itaque non.\nHarum temporibus nihil voluptas.\nIste in sed et nesciunt in quaerat sed.
$randomLoremParagraphAb aliquid odio iste quo voluptas voluptatem dignissimos velit. Recusandae facilis qui commodi ea magnam enim nostrum quia quis. Nihil est suscipit assumenda ut voluptatem sed. Esse ab voluptas odit qui molestiae. Rem est nesciunt est quis ipsam expedita consequuntur.
$randomLoremParagraphsVoluptatem rem magnam aliquam ab id aut quaerat. Placeat provident possimus voluptatibus dicta velit non aut quasi. Mollitia et aliquam expedita sunt dolores nam consequuntur. Nam dolorum delectus ipsam repudiandae et ipsam ut voluptatum totam. Nobis labore labore recusandae ipsam quo.
$randomLoremSentenceMolestias consequuntur nisi non quod.
$randomLoremSentencesEt sint voluptas similique iure amet perspiciatis vero sequi atque. Ut porro sit et hic. Neque aspernatur vitae fugiat ut dolore et veritatis. Ab iusto ex delectus animi. Voluptates nisi iusto. Impedit quod quae voluptate qui.
$randomLoremSlugeos-aperiam-accusamus, beatae-id-molestiae, qui-est-repellat
$randomLoremTextQuisquam asperiores exercitationem ut ipsum. Aut eius nesciunt. Et reiciendis aut alias eaque. Nihil amet laboriosam pariatur eligendi. Sunt ullam ut sint natus ducimus. Voluptas harum aspernatur soluta rem nam.
$randomLoremWordest
$randomLoremWordsvel repellat nobis
$randomMACAddress33:d4:68:5f:b4:c7
$randomMimeTypeaudio/vnd.vmx.cvsd
$randomMonthFebruary
$randomNamePrefixDr.
$randomNameSuffixMD
$randomNatureImagehttp://no-a-valid-host/640/480/nature
$randomNightlifeImagehttp://no-a-valid-host/640/480/nightlife
$randomNounbus
$randomPasswordt9iXe7COoDKv8k3
$randomPeopleImagehttp://no-a-valid-host/640/480/people
$randomPhoneNumber700-008-5275
$randomPhoneNumberExt27-199-983-3864
$randomPhraseYou can't program the monitor without navigating the mobile XML program!
$randomPrice531.55
$randomProductPizza
$randomProductAdjectiveUnbranded
$randomProductMaterialSteel
$randomProductNameHandmade Concrete Tuna
$randomProtocolhttps
$randomSemver7.0.5
$randomSportsImagehttp://no-a-valid-host/640/480/sports
$randomStreetAddress5742 Harvey Streets
$randomStreetNameKuhic Island
$randomTransactionTypepayment
$randomTransportImagehttp://no-a-valid-host/640/480/transport
$randomUrlhttps://no-a-valid-host.net
$randomUserAgentMozilla/5.0 (Macintosh; U; Intel Mac OS X 10.9.8; rv:15.6) Gecko/20100101 Firefox/15.6.6
$randomUserNameJarrell.Gutkowski
$randomUUID6929bb52-3ab2-448a-9796-d6480ecad36b
$randomVerbnavigate
$randomWeekdayThursday
$randomWordwithdrawal
$randomWordsSamoa Synergistic sticky copying Grocery
$timestamp1562757107
例グローバルスコープ

この例では、_グローバル_スコープはPostman Client からglobal-scope.json としてエクスポートされ、DAST_API_POSTMAN_COLLECTION_VARIABLES 設定変数を通して DAST API に提供されます。

DAST_API_POSTMAN_COLLECTION_VARIABLESを使う例です:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_POSTMAN_COLLECTION: postman-collection.json
  DAST_API_POSTMAN_COLLECTION_VARIABLES: global-scope.json
  DAST_API_TARGET_URL: http://test-deployment/
例環境スコープ

この例では、_環境_スコープはPostman クライアントからenvironment-scope.json としてエクスポートされ、DAST_API_POSTMAN_COLLECTION_VARIABLES 設定変数を通して DAST API に提供されます。

DAST_API_POSTMAN_COLLECTION_VARIABLESを使う例です:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_POSTMAN_COLLECTION: postman-collection.json
  DAST_API_POSTMAN_COLLECTION_VARIABLES: environment-scope.json
  DAST_API_TARGET_URL: http://test-deployment/
例コレクション・スコープ

_コレクション_スコープ変数はエクスポートされた Postman Collection ファイルに含まれ、DAST_API_POSTMAN_COLLECTION 設定変数を通して提供されます。

DAST_API_POSTMAN_COLLECTIONを使う例です:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_POSTMAN_COLLECTION: postman-collection.json
  DAST_API_TARGET_URL: http://test-deployment/
例DAST API スコープ

DAST API スコープは、_DAST_API でサポートされていないデータや_ローカル_スコープの変数を定義することと、別のスコープで定義された既存の変数の値を変更することです。DAST API スコープはDAST_API_POSTMAN_COLLECTION_VARIABLES 設定変数を通じて提供されます。

DAST_API_POSTMAN_COLLECTION_VARIABLESを使う例です:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_POSTMAN_COLLECTION: postman-collection.json
  DAST_API_POSTMAN_COLLECTION_VARIABLES: dast-api-scope.json
  DAST_API_TARGET_URL: http://test-deployment/

ファイルdast-api-scope.json は、私たちのカスタムJSONファイル形式を使用しています。このJSONは、プロパティにキーと値のペアを持つオブジェクトです。キーは変数の名前で、値は変数の値です。例えば

{
  "base_url": "http://127.0.0.1/",
  "token": "Token 84816165151"
}
例複数のスコープ

この例では、_グローバル_スコープ、_環境_スコープ、_コレクション_スコープを設定します。まず最初に、さまざまなスコープをエクスポートします。

  • _グローバル_スコープを global-scope.json
  • として_環境_スコープをエクスポートします。environment-scope.json
  • _コレクション_スコープを含む Postman Collection を次のようにエクスポートします。postman-collection.json

Postman Collection はDAST_API_POSTMAN_COLLECTION 変数を使用して提供され、他のスコープはDAST_API_POSTMAN_COLLECTION_VARIABLES を使用して提供されます。 DAST API は、各ファイルで提供されるデータを使用して、提供されたファイルがどのスコープに一致するかを識別できます。

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_POSTMAN_COLLECTION: postman-collection.json
  DAST_API_POSTMAN_COLLECTION_VARIABLES: global-scope.json,environment-scope.json
  DAST_API_TARGET_URL: http://test-deployment/
例変数の値の変更

Exporter されたスコープを使用する場合、変数の値を DAST API で使用するために変更しなければならないことがよくあります。たとえば、_コレクション_スコープの変数にapi_version という名前の変数があり、その値がv2 であるのに対し、テストではv1 という値が必要です。これは、_DAST API_スコープが他のすべてのスコープよりも優先されるためです。

_コレクション_スコープ変数はエクスポートされた Postman Collection ファイルに含まれ、DAST_API_POSTMAN_COLLECTION 設定変数を通して提供されます。

DAST API スコープはDAST_API_POSTMAN_COLLECTION_VARIABLES 設定変数を通して提供されますが、まずファイルを作成する必要があります。ファイルdast-api-scope.json は、カスタムJSONファイル形式を使用しています。このJSONは、プロパティにキーと値のペアを持つオブジェクトです。キーは変数の名前で、値は変数の値です。例えば

{
  "api_version": "v1"
}

私たちのCI定義:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_POSTMAN_COLLECTION: postman-collection.json
  DAST_API_POSTMAN_COLLECTION_VARIABLES: dast-api-scope.json
  DAST_API_TARGET_URL: http://test-deployment/
例複数のスコープで変数の値を変更する例

Exporter スコープを使用する場合、DAST API で使用するために変数の値を変更しなければならないことがよくあります。たとえば、_環境_スコープにapi_version という変数があり、その値がv2 であるのに対し、テストではv1 という値が必要です。これは、_DAST API_スコープが他のすべてのスコープよりも優先されるためです。

この例では、_グローバル_スコープ、_環境_スコープ、_コレクション_スコープ、_DAST API_スコープを設定しています。まず最初に、さまざまなスコープをエクスポートして作成します。

  • _グローバル_スコープを global-scope.json
  • として_環境_スコープをエクスポートします。environment-scope.json
  • _コレクション_スコープを含む Postman Collection を次のようにエクスポートします。postman-collection.json

DAST APIスコープは、カスタムJSONファイルフォーマットを使用してファイルdast-api-scope.json を作成することで使用されます。このJSONは、プロパティのキーと値のペアを持つオブジェクトです。キーは変数名で、値は変数の値です。例えば

{
  "api_version": "v1"
}

Postman Collection はDAST_API_POSTMAN_COLLECTION 変数を使用して提供され、他のスコープはDAST_API_POSTMAN_COLLECTION_VARIABLES を使用して提供されます。 DAST API は、各ファイルで提供されるデータを使用して、提供されたファイルがどのスコープに一致するかを識別できます。

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_POSTMAN_COLLECTION: postman-collection.json
  DAST_API_POSTMAN_COLLECTION_VARIABLES: global-scope.json,environment-scope.json,dast-api-scope.json
  DAST_API_TARGET_URL: http://test-deployment/

認証

認証は、認証トークンをヘッダまたはクッキーとして提供することで処理されます。認証フローを実行したりトークンを計算したりするスクリプトを提供することができます。

HTTP ベーシック認証

HTTPベーシック認証は、HTTPプロトコルに組み込まれた認証方式で、トランスポートレイヤーセキュリティ(TLS)と組み合わせて使用されます。

パスワード用のCI/CD変数(例えば、TEST_API_PASSWORD )を作成し、それをマスクするように設定することをお勧めします。CI/CD変数は、GitLabプロジェクトのページのSettings > CI/CDのVariablesセクションから作成できます。マスクされた変数には制限があるため、パスワードを変数として追加する前にBase64エンコードする必要があります。

最後に、.gitlab-ci.yml ファイルに CI/CD 変数を2つ追加します:

  • DAST_API_HTTP_USERNAME:認証用のユーザー名。
  • DAST_API_HTTP_PASSWORD_BASE64:認証用の Base64 エンコードされたパスワード。
stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_HAR: test-api-recording.har
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_HTTP_USERNAME: testuser
  DAST_API_HTTP_PASSWORD_BASE64: $TEST_API_PASSWORD

生のパスワード

パスワードをBase64エンコードしたくない場合(あるいはGitLab 15.3以前を使っている場合)、DAST_API_HTTP_PASSWORD_BASE64 を使う代わりに生のパスワードDAST_API_HTTP_PASSWORD を指定することができます。

ベアラートークン

ベアラートークンは、OAuth2 や JSON Web Tokens(JWT)など、さまざまな認証メカニズムで使用されます。Bearer トークンはAuthorization HTTP ヘッダを使用して送信されます。DAST API で Bearer トークンを使用するには、以下のいずれかが必要です:

  • 有効期限がないトークン
  • テスト期間中有効なトークンを生成する方法。
  • DAST API がトークンを生成するために呼び出す Python スクリプト。

トークンの有効期限はありません

Bearer トークンに有効期限がない場合は、DAST_API_OVERRIDES_ENV 変数を使用してください。この変数の内容は、DAST API の送信 HTTP リクエストに追加するヘッダーとクッキーを提供する JSON スニペットです。

以下の手順に従って、DAST_API_OVERRIDES_ENVでベアラートークンを提供してください:

  1. CI/CD 変数、例えばTEST_API_BEARERAUTH作成し、その値を{"headers":{"Authorization":"Bearer dXNlcm5hbWU6cGFzc3dvcmQ="}} とします(トークンを代入してください)。CI/CD変数はGitLabプロジェクトページのSettings > CI/CDの Variablesセクションから作成できます。変数のフォーマット上、TEST_API_BEARERAUTH 変数をマスク TEST_API_BEARERAUTHすることはできません。TEST_API_BEARERAUTH トークンの値をマスクするには、トークンの値で2つ目の変数を作成し、その TEST_API_BEARERAUTH値を{"headers":{"Authorization":"Bearer $MASKED_VARIABLE"}}

  2. .gitlab-ci.yml ファイルで、DAST_API_OVERRIDES_ENV に先ほど作成した変数を設定します:

    stages:
      - dast
       
    include:
      - template: DAST-API.gitlab-ci.yml
       
    variables:
      DAST_API_PROFILE: Quick
      DAST_API_OPENAPI: test-api-specification.json
      DAST_API_TARGET_URL: http://test-deployment/
      DAST_API_OVERRIDES_ENV: $TEST_API_BEARERAUTH
    
  3. 認証が機能していることを確認するには、DAST API テストを実行し、ジョブログとテスト API のアプリケーションログをレビューします。

テスト実行時に生成されるトークン

ベアラ トークンを生成する必要があり、テスト中に期限切れにならない場合は、トークンを含むファイルを DAST API に提供できます。前のステージとジョブ、または DAST API ジョブの一部が、このファイルを生成できます。

DAST API は、以下の構造を持つ JSON ファイルを受け取ることを想定しています:

{
  "headers" : {
    "Authorization" : "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

このファイルは前のステージで生成され、DAST_API_OVERRIDES_FILE CI/CD 変数を通して DAST API に提供されます。

.gitlab-ci.yml ファイルにDAST_API_OVERRIDES_FILE を設定してください:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json

認証が機能していることを確認するには、DAST API テストを実行し、ジョブログとテスト API のアプリケーションログをレビューします。

トークンの有効期限が短い

Bearer トークンを生成する必要があり、スキャンが完了する前に有効期限が切れる場合は、DAST API スキャナにプログラムまたはスクリプトを提供して、指定した間隔で実行させることができます。提供されたスクリプトは、Python 3 と Bash がインストールされた Alpine Linux コンテナで実行されます。Python スクリプトに追加パッケージが必要な場合は、それを検出して実行時にパッケージをインストールする必要があります。

スクリプトは、ベアラ・トークンを特定の形式で含むJSONファイルを作成する必要があります:

{
  "headers" : {
    "Authorization" : "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

3つのCI/CD変数を提供する必要があり、それぞれ正しくオペレーションできるように設定されています:

  • DAST_API_OVERRIDES_FILE:コマンドが生成するJSONファイル。
  • DAST_API_OVERRIDES_CMD:JSONファイルを生成するコマンド。
  • DAST_API_OVERRIDES_INTERVAL:コマンドを実行する間隔(秒)。

使用例:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json
  DAST_API_OVERRIDES_CMD: renew_token.py
  DAST_API_OVERRIDES_INTERVAL: 300

認証が機能していることを確認するには、DAST API テストを実行し、ジョブ・ログとテスト API のアプリ ケーション・ログをレビューします。オーバーライド・コマンドの詳細については、「オーバーライド」のセクションを参照してください。

設定ファイル

すぐに始められるように、GitLab は設定ファイルgitlab-dast-api-config.ymlを用意しています。このファイルには、さまざまな数のテストを実行するいくつかのテストプロファイルがあります。各プロファイルの実行時間は、テストの数が増えるにつれて長くなります。設定ファイルを使うには、リポジトリのルートに.gitlab/gitlab-dast-api-config.ymlのように追加します。

プロファイル

以下のプロファイルは、デフォルト設定ファイルにあらかじめ定義されています。カスタム設定を作成することで、プロファイルを追加、削除、変更できます。

受動的

  • アプリケーション情報チェック
  • クリアテキスト認証チェック
  • JSONハイジャック・チェック
  • 機密情報チェック
  • セッションクッキーチェック

クイック

  • アプリケーション情報チェック
  • クリアテキスト認証チェック
  • フレームワークデバッグモードチェック
  • HTMLインジェクションチェック
  • 安全でない Http メソッドのチェック
  • JSONハイジャック・チェック
  • JSONインジェクション検査
  • 機密情報チェック
  • セッションクッキーチェック
  • SQLインジェクション検査
  • トークンのチェック
  • XMLインジェクション検査

フル

  • アプリケーション情報チェック
  • クリアテキスト認証チェック
  • CORSチェック
  • DNSリバインディングチェック
  • フレームワークデバッグモードチェック
  • HTMLインジェクションチェック
  • 安全でない Http メソッドのチェック
  • JSONハイジャック・チェック
  • JSONインジェクション検査
  • オープンリダイレクト検査
  • 機密ファイルチェック
  • 機密情報チェック
  • セッションクッキーチェック
  • SQLインジェクション検査
  • TLS設定チェック
  • トークンのチェック
  • XMLインジェクション検査

利用可能な CI/CD 変数

CI/CD 変数説明
SECURE_ANALYZERS_PREFIXアナライザをダウンロードするDockerレジストリのベースアドレスを指定します。
DAST_API_VERSIONDAST APIコンテナバージョンを指定します。デフォルトは2
DAST_API_IMAGE_SUFFIXコンテナイメージのサフィックスを指定します。デフォルトはnone。
DAST_API_API_PORTDAST API エンジンが使用する通信ポート番号を指定します。デフォルトは5500。 GitLab 15.5 で導入されました
DAST_API_TARGET_URLAPIテスト対象のベースURL。
DAST_API_CONFIGDAST API 設定ファイル。デフォルトは.gitlab-dast-api.yml
DAST_API_PROFILEテスト中に使用する設定プロファイル。デフォルトはQuick
DAST_API_EXCLUDE_PATHSAPI URL パスをテストから除外します。
DAST_API_EXCLUDE_URLSテストからAPI URLを除外GitLab 14.10 で導入されました
DAST_API_EXCLUDE_PARAMETER_ENV除外するパラメータを含むJSON文字列。
DAST_API_EXCLUDE_PARAMETER_FILE除外されたパラメータを含むJSONファイルへのパス。
DAST_API_REQUEST_HEADERS各スキャン要求に含めるヘッダのカンマ区切り (,) リスト。文字セットの制限があるマスク変数にシークレットヘッダ値を格納するときは、DAST_API_REQUEST_HEADERS_BASE64 の使用を考慮してください。
DAST_API_REQUEST_HEADERS_BASE64各スキャンリクエストに含めるヘッダのカンマ区切り (,) リスト。Base64 エンコードされています。GitLab 15.6 で導入されました
DAST_API_OPENAPIOpenAPI 仕様ファイルまたは URL。
DAST_API_OPENAPI_RELAXED_VALIDATIONドキュメント検証を緩和します。デフォルトは無効。GitLab 14.7 で導入されました。GitLabチームメンバーはこちらのイシューをご覧ください:https://gitlab.com/gitlab-org/gitlab/-/issues/345950
DAST_API_OPENAPI_ALL_MEDIA_TYPESリクエストを生成する際に、1つのメディアタイプではなく、サポートされているすべてのメディアタイプを使用します。テスト時間が長くなります。デフォルトは無効です。GitLab 14.10 で導入
DAST_API_OPENAPI_MEDIA_TYPESコロン (:) 区切りのメディアタイプ。デフォルトは無効。GitLab 14.10 で導入
DAST_API_HARHTTP アーカイブ(HAR) ファイル。
DAST_API_GRAPHQLGraphQLエンドポイントへのパス、例えば/api/graphql 。GitLab 15.4で導入されました
DAST_API_GRAPHQL_SCHEMAJSON形式のGraphQLスキーマのURLまたはファイル名。GitLab 15.4で導入
DAST_API_POSTMAN_COLLECTIONPostman コレクションファイル。
DAST_API_POSTMAN_COLLECTION_VARIABLESPostman変数の値を抽出するJSONファイルへのパス。カンマ区切り (,) ファイルのサポートは GitLab 15.1 で導入されました。
DAST_API_OVERRIDES_FILEオーバーライドを含むJSONファイルへのパス。
DAST_API_OVERRIDES_ENVオーバーライドするヘッダーを含む JSON 文字列。
DAST_API_OVERRIDES_CMDコマンドを上書きします。
DAST_API_OVERRIDES_CMD_VERBOSE任意の値に設定するとジョブ出力の一部としてオーバーライドコマンド出力を表示します。GitLab 14.6で導入されました
DAST_API_PRE_SCRIPTスキャンセッションが始まる前にユーザーコマンドやスクリプトを実行します。
DAST_API_POST_SCRIPTスキャン セッション終了後にユーザー コマンドまたはスクリプトを実行します。
DAST_API_OVERRIDES_INTERVALオーバーライド コマンドを実行する頻度を秒単位で指定します。デフォルトは0 (1 回) です。
DAST_API_HTTP_USERNAMEHTTP認証のユーザー名。
DAST_API_HTTP_PASSWORDHTTP認証用のパスワード。代わりにDAST_API_HTTP_PASSWORD_BASE64
DAST_API_HTTP_PASSWORD_BASE64base64エンコードされたHTTP認証用のパスワード。GitLab 15.4で導入されました
DAST_API_SERVICE_START_TIMEOUTターゲットAPIが利用可能になるまでの待ち時間(秒)。デフォルトは300秒です。
DAST_API_TIMEOUTAPIの応答を待つ時間(秒)。デフォルトは30秒です。

オーバーライド

DAST API は、リクエストに特定の項目を追加したりオーバーライドしたりするメソッドを提供します:

  • ヘッダー
  • クッキー
  • クエリ文字列
  • フォームデータ
  • JSONノード
  • XMLノード

これを使用して、セマンティック・バージョン・ヘッダや認証などを注入できます。認証のセクションには、オーバーライドの使用例が記載されています。

オーバーライドは JSON ドキュメントを使用し、オーバーライドの各タイプは JSON オブジェクトで表されます:

{
  "headers": {
    "header1": "value",
    "header2": "value"
  },
  "cookies": {
    "cookie1": "value",
    "cookie2": "value"
  },
  "query":      {
    "query-string1": "value",
    "query-string2": "value"
  },
  "body-form":  {
    "form-param1": "value",
    "form-param2": "value"
  },
  "body-json":  {
    "json-path1": "value",
    "json-path2": "value"
  },
  "body-xml" :  {
    "xpath1":    "value",
    "xpath2":    "value"
  }
}

単一のヘッダーを設定する例:

{
  "headers": {
    "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  }
}

ヘッダーとクッキーの両方を設定する例:

{
  "headers": {
    "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
  },
  "cookies": {
    "flags": "677"
  }
}

body-form オーバーライドを設定する場合の使用例:

{
  "body-form":  {
    "username": "john.doe"
  }
}

オーバーライド・エンジンは、リクエスト・ボディにフォーム・データ・コンテンツのみがある場合にbody-form を使用します。

body-json オーバーライドを設定する場合の使用例:

{
  "body-json":  {
    "$.credentials.access-token": "iddqd!42.$"
  }
}

オブジェクトbody-json 内の各 JSON プロパティ名は、JSON Path式に設定されます。JSON Path 式$.credentials.access-token は、値iddqd!42.$でオーバーライドするノードを識別します。オーバーライド・エンジンは、リクエスト・ボディにJSONコンテンツのみがある場合、body-json を使用します。

例えば、ボディが以下の JSON に設定されている場合:

{
    "credentials" : {
        "username" :"john.doe",
        "access-token" : "non-valid-password"
    }
}

に変更されます:

{
    "credentials" : {
        "username" :"john.doe",
        "access-token" : "iddqd!42.$"
    }
}

body-xml をオーバーライドする例を示します。最初のエントリは XML 属性をオーバーライドし、2 番目のエントリは XML 要素をオーバーライドします:

{
  "body-xml" :  {
    "/credentials/@isEnabled": "true",
    "/credentials/access-token/text()" : "iddqd!42.$"
  }
}

オブジェクトbody-xml 内の各 JSON プロパティ名は、XPath v2式に設定されます。XPath 式/credentials/@isEnabled は、値trueでオーバーライドする属性ノードを識別します。XPath 式/credentials/access-token/text() は、オーバーライドする要素ノードを値iddqd!42.$ で識別します。オーバーライド・エンジンは、リクエスト・ボディにXMLコンテンツのみがある場合にbody-xml を使用します。

例えば、ボディが以下の XML に設定されている場合:

<credentials isEnabled="false">
  <username>john.doe</username>
  <access-token>non-valid-password</access-token>
</credentials>

に変更されます:

<credentials isEnabled="true">
  <username>john.doe</username>
  <access-token>iddqd!42.$</access-token>
</credentials>

このJSONドキュメントは、ファイルまたは環境変数として提供できます。また、JSONドキュメントを生成するコマンドを指定することもできます。このコマンドは、期限切れの値をサポートするために間隔を空けて実行できます。

ファイルの使用

オーバーライドJSONをファイルとして提供するには、DAST_API_OVERRIDES_FILE CI/CD変数が設定されます。パスはジョブの現在の作業ディレクトリからの相対パスです。

以下は.gitlab-ci.yml の例です:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json

CI/CD変数の使用

オーバーライド JSON を CI/CD 変数として提供するには、DAST_API_OVERRIDES_ENV 変数を使用します。これにより、JSON をマスクして保護できる変数として配置できます。

この例では、.gitlab-ci.ymlDAST_API_OVERRIDES_ENV 変数が直接 JSON に設定されます:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_ENV: '{"headers":{"X-API-Version":"2"}}'

この例では、.gitlab-ci.ymlSECRET_OVERRIDES 変数がJSONを提供します。これはUIで定義されたグループまたはインスタンスレベルのCI/CD変数です:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_ENV: $SECRET_OVERRIDES

コマンドの使用

期限切れ時に値を生成または再生成する必要がある場合、DAST API スキャナにプログラムまたはスクリプトを提供して、指定した間隔で実行させることができます。提供されたコマンドは、Python 3 と Bash がインストールされた Alpine Linux コンテナで実行されます。

実行したいプログラムまたはスクリプトに環境変数DAST_API_OVERRIDES_CMD を設定する必要があります。提供されるコマンドは、先に定義したオーバーライドJSONファイルを作成します。

NodeJSやRubyのような他のスクリプト・ランタイムをインストールしたい場合や、overridesコマンドの依存関係をインストールする必要がある場合があります。この場合、DAST_API_PRE_SCRIPT これらの前提条件を提供するスクリプトのファイル・パスに DAST_API_PRE_SCRIPT設定することをお勧めします。DAST_API_PRE_SCRIPT で指定したスクリプトは DAST_API_PRE_SCRIPT、アナライザが起動する前に一度だけ実行されます。

Alpine Linuxパッケージのインストールについては、Alpine Linuxパッケージ管理ページを参照してください。

3つのCI/CD変数を提供する必要があり、それぞれ正しくオペレーションできるように設定されています:

  • DAST_API_OVERRIDES_FILE:提供されたコマンドによって生成されたファイル。
  • DAST_API_OVERRIDES_CMD:定期的にオーバーライドJSONファイルを生成するオーバーライド・コマンド。
  • DAST_API_OVERRIDES_INTERVAL:コマンドの実行間隔(秒

オプション

  • DAST_API_PRE_SCRIPT:スキャン開始前にランタイムまたは依存関係をインストールするスクリプト。
caution
Alpine Linuxでスクリプトを実行するには、まずコマンドchmod実行権限を設定する必要があります。例えば、script.py の実行権限を全員に設定するには、次のコマンドを使用します:chmod a+x script.py.必要であれば、](https://www.gnu.org/software/coreutils/manual/html_node/chmod-invocation.html) に実行権限を設定した状態でバージョンアップしてください。
stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json
  DAST_API_OVERRIDES_CMD: renew_token.py
  DAST_API_OVERRIDES_INTERVAL: 300

デバッグのオーバーライド

GitLab 14.8で導入されました

デフォルトではoverridesコマンドの出力は非表示です。overridesコマンドが0以外の終了コードを返した場合、コマンドはジョブ出力の一部として表示されます。オプションで、変数DAST_API_OVERRIDES_CMD_VERBOSE を任意の値に設定して、overrides コマンド出力を生成時に表示できます。これは、overrides スクリプトをテストするときに便利ですが、テストが遅くなるため、テスト後は無効にしてください。

ジョブが完了または失敗したときに収集されるログファイルに、スクリプトからのメッセージを書き込むこともできます。ログファイルは特定の場所に、命名規則に従って作成する必要があります。

オーバーライド・スクリプトに基本的なロギングを追加しておくと、ジョブの標準実行中にスクリプトが予期せず失敗した場合に便利です。ログファイルはジョブのアーティファクトとして自動的に含まれるため、ジョブ終了後にダウンロードできます。

この例では、環境変数DAST_API_OVERRIDES_CMDrenew_token.py を指定しています。スクリプトの中で2つのことに注目してください:

  • ログファイルは環境変数CI_PROJECT_DIR で指定された場所に保存されます。
  • ログファイル名はgl-*.log と一致する必要があります。
#!/usr/bin/env python

# Example of an overrides command

# Override commands can update the overrides json file
# with new values to be used.  This is a great way to
# update an authentication token that will expire
# during testing.

import logging
import json
import os
import requests
import backoff

# [1] Store log file in directory indicated by env var CI_PROJECT_DIR
working_directory = os.environ.get( 'CI_PROJECT_DIR')
overrides_file_name = os.environ.get('DAST_API_OVERRIDES_FILE', 'dast-api-overrides.json')
overrides_file_path = os.path.join(working_directory, overrides_file_name)

# [2] File name should match the pattern: gl-*.log
log_file_path = os.path.join(working_directory, 'gl-user-overrides.log')

# Set up logger
logging.basicConfig(filename=log_file_path, level=logging.DEBUG)

# Use `backoff` decorator to retry in case of transient errors.
@backoff.on_exception(backoff.expo,
                      (requests.exceptions.Timeout,
                       requests.exceptions.ConnectionError),
                       max_time=30)
def get_auth_response():
    authorization_url = 'https://authorization.service/api/get_api_token'
    return requests.get(
        f'{authorization_url}',
        auth=(os.environ.get('AUTH_USER'), os.environ.get('AUTH_PWD'))
    )

# In our example, access token is retrieved from a given endpoint
try:

    # Performs a http request, response sample:
    # { "Token" : "b5638ae7-6e77-4585-b035-7d9de2e3f6b3" }
    response = get_auth_response()

    # Check that the request is successful. may raise `requests.exceptions.HTTPError`
    response.raise_for_status()

    # Gets JSON data
    response_body = response.json()

# If needed specific exceptions can be caught
# requests.ConnectionError                  : A network connection error problem occurred
# requests.HTTPError                        : HTTP request returned an unsuccessful status code. [Response.raise_for_status()]
# requests.ConnectTimeout                   : The request timed out while trying to connect to the remote server
# requests.ReadTimeout                      : The server did not send any data in the allotted amount of time.
# requests.TooManyRedirects                 : The request exceeds the configured number of maximum redirections
# requests.exceptions.RequestException      : All exceptions that related to Requests
except json.JSONDecodeError as json_decode_error:
    # logs errors related decoding JSON response
    logging.error(f'Error, failed while decoding JSON response. Error message: {json_decode_error}')
    raise
except requests.exceptions.RequestException as requests_error:
    # logs  exceptions  related to `Requests`
    logging.error(f'Error, failed while performing HTTP request. Error message: {requests_error}')
    raise
except Exception as e:
    # logs any other error
    logging.error(f'Error, unknown error while retrieving access token. Error message: {e}')
    raise

# computes object that holds overrides file content.
# It uses data fetched from request
overrides_data = {
    "headers": {
        "Authorization": f"Token {response_body['Token']}"
    }
}

# log entry informing about the file override computation
logging.info("Creating overrides file: %s" % overrides_file_path)

# attempts to overwrite the file
try:
    if os.path.exists(overrides_file_path):
        os.unlink(overrides_file_path)

    # overwrites the file with our updated dictionary
    with open(overrides_file_path, "wb+") as fd:
        fd.write(json.dumps(overrides_data).encode('utf-8'))
except Exception as e:
    # logs any other error
    logging.error(f'Error, unknown error when overwriting file {overrides_file_path}. Error message: {e}')
    raise

# logs informing override has finished successfully
logging.info("Override file has been updated")

# end

overrides コマンドの例では、Python スクリプトはbackoff ライブラリに依存しています。Python スクリプトを実行する前にライブラリがインストールされていることを確認するために、DAST_API_PRE_SCRIPT は overrides コマンドの依存関係をインストールするスクリプトに設定されます。たとえば、次のスクリプトのようになります。user-pre-scan-set-up.sh

#!/bin/bash

# user-pre-scan-set-up.sh
# Ensures python dependencies are installed

echo "**** install python dependencies ****"

python3 -m ensurepip
pip3 install --no-cache --upgrade \
    pip \
    backoff

echo "**** python dependencies installed ****"

# end

DAST_API_PRE_SCRIPT を新しいuser-pre-scan-set-up.sh スクリプトに設定するように設定を更新する必要があります。例えば

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_PRE_SCRIPT: user-pre-scan-set-up.sh
  DAST_API_OVERRIDES_FILE: dast-api-overrides.json
  DAST_API_OVERRIDES_CMD: renew_token.py
  DAST_API_OVERRIDES_INTERVAL: 300

前のサンプルでは、user-pre-scan-set-up.sh スクリプトを使用して、後で overrides コマンドで使用する新しいランタイムやアプリケーションもインストールできました。

リクエストヘッダー

リクエストヘッダ機能を使うと、スキャンセッション中のヘッダに固定値を指定できます。例えば、設定変数DAST_API_REQUEST_HEADERS を使用して、Cache-Control ヘッダーに固定値を設定できます。設定する必要があるヘッダーにAuthorization ヘッダーのような敏感な値が含まれる場合、変数DAST_API_REQUEST_HEADERS_BASE64とともにマスクされた変数機能を使用します。

スキャンの進行中にAuthorization ヘッダーやその他のヘッダーを更新する必要がある場合は、オーバーライド機能の使用を検討してください。

変数DAST_API_REQUEST_HEADERS 、ヘッダのカンマ区切り(,)リストを指定できます。これらのヘッダーはスキャナが実行する各リクエストに含まれます。リストの各ヘッダーエントリは、名前の後にコロン(:)、その後に値で構成されます。キーまたは値の前の空白は無視されます。例えば、ヘッダー名Cache-Control と値max-age=604800 を宣言するには、ヘッダーエントリーはCache-Control: max-age=604800.2つのヘッダー、 Cache-Control: max-age=604800 Age: 100Cache-Control: max-age=604800使用するには Cache-Control: max-age=604800DAST_API_REQUEST_HEADERS 変数をCache-Control: max-age=604800, Age: 100に設定します。

異なるヘッダーを変数に入れる順番はDAST_API_REQUEST_HEADERS 結果に影響しません DAST_API_REQUEST_HEADERSCache-Control: max-age=604800, Age: 100DAST_API_REQUEST_HEADERS 設定しても DAST_API_REQUEST_HEADERSAge: 100, Cache-Control: max-age=604800 に設定したのと同じ結果になります。

Base64

DAST_API_REQUEST_HEADERS_BASE64 変数はDAST_API_REQUEST_HEADERS と同じヘッダーのリストを受け付けますが、唯一の違いは変数の値全体が Base64 エンコードされていなければならないということです。例えば、DAST_API_REQUEST_HEADERS_BASE64 変数をAuthorization: QmVhcmVyIFRPS0VO, Cache-control: bm8tY2FjaGU= に設定するためには、リストをBase64の等価値:QXV0aG9yaXphdGlvbjogUW1WaGNtVnlJRlJQUzBWTywgQ2FjaGUtY29udHJvbDogYm04dFkyRmphR1U9 に変換し、Base64エンコードされた値を使わなければなりません。これは、文字セットの制限があるマスクされた変数にシークレットヘッダー値を格納するときに便利です。

caution
Base64はマスク変数機能をサポートするために使用されます。Base64エンコーディングはそれ自体ではセキュリティ対策にはなりません。

例プレーンテキストを使って各リクエストにヘッダのリストを追加する場合

.gitlab-ci.yml の次の例では、DAST_API_REQUEST_HEADERS 設定変数がリクエストヘッダで説明されているように 2 つのヘッダ値を提供するように設定されています。

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_REQUEST_HEADERS: 'Cache-control: no-cache, Save-Data: on'

例マスクされたCI/CD変数の使用

以下の.gitlab-ci.yml サンプルは、マスクされた変数が SECRET_REQUEST_HEADERS_BASE64 UIで定義されたグループまたはインスタンスレベルのCI/CD変数として定義されて SECRET_REQUEST_HEADERS_BASE64いると仮定しています。SECRET_REQUEST_HEADERS_BASE64 の値は SECRET_REQUEST_HEADERS_BASE64X-ACME-Secret: s3cr3t!, X-ACME-Token: 705d16f5e3fb の Base64 エンコードされたテキストバージョンであるWC1BQ01FLVNlY3JldDogc31jcnt0ISwgWC1BQ01FLVRva2VuOiA3MDVkMTZmNWUzZmI= に設定されます。そして、次のように使用することができます:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_REQUEST_HEADERS_BASE64: $SECRET_REQUEST_HEADERS_BASE64

文字セットの制限があるマスクされた変数にシークレットヘッダーの値を格納するときは、DAST_API_REQUEST_HEADERS_BASE64 の使用を検討してください。

除外パス

GitLab 14.0 で導入されました

APIをテストする際に、特定のパスを除外すると便利です。例えば、認証サービスや古いバージョンのAPIのテストを除外することができます。パスを除外するには、DAST_API_EXCLUDE_PATHS CI/CD 変数を使います。この変数は.gitlab-ci.yml ファイルで指定します。複数のパスを除外するには、; 文字を使用してエントリを区切ります。提供されたパスでは、1文字のワイルドカード? と複数文字のワイルドカード* を使用できます。

パスが除外されていることを確認するには、ジョブ出力のTested OperationsExcluded Operations の部分をレビューします。Tested Operations の下に除外されたパスは表示されないはずです。

2021-05-27 21:51:08 [INF] DAST API: --[ Tested Operations ]-------------------------
2021-05-27 21:51:08 [INF] DAST API: 201 POST http://target:7777/api/users CREATED
2021-05-27 21:51:08 [INF] DAST API: ------------------------------------------------
2021-05-27 21:51:08 [INF] DAST API: --[ Excluded Operations ]-----------------------
2021-05-27 21:51:08 [INF] DAST API: GET http://target:7777/api/messages
2021-05-27 21:51:08 [INF] DAST API: POST http://target:7777/api/messages
2021-05-27 21:51:08 [INF] DAST API: ------------------------------------------------

使用例

この例では/auth リソースを除外します。子リソース (/auth/child) は除外しません。

variables:
  DAST_API_EXCLUDE_PATHS: /auth

/auth 、および子リソース (/auth/child) を除外するには、ワイルドカードを使用します。

variables:
  DAST_API_EXCLUDE_PATHS: /auth*

複数のパスを除外するには、; を使用します。この例では、/auth*/v1/* を除外しています。

variables:
  DAST_API_EXCLUDE_PATHS: /auth*;/v1/*

パス内の1つ以上の入れ子レベルを除外するには、** を使用します。この例では、API エンドポイントをテストしています。planet,moon,star,satellite オブジェクトのmass,brightness,coordinates データを要求するデータクエリの/api/v1//api/v2/ をテストしています。スキャンされる可能性のあるパスの例には以下が含まれますが、これらに限定されるものではありません:

  • /api/v2/planet/coordinates
  • /api/v1/star/mass
  • /api/v2/satellite/brightness

この例では、brightness エンドポイントのみをテストします:

variables:
  DAST_API_EXCLUDE_PATHS: /api/**/mass;/api/**/coordinates

パラメータの除外

GitLab 14.10で導入されました

APIのテスト中に、あるパラメータ(クエリ文字列、ヘッダ、ボディ要素)をテストから除外したいことがあるかもしれません。これは、あるパラメータが常に失敗を引き起こしたり、テストが遅くなったり、その他の理由で必要になることがあります。パラメータを除外するには、次の変数のいずれかを設定します:DAST_API_EXCLUDE_PARAMETER_ENV あるいはDAST_API_EXCLUDE_PARAMETER_FILE

DAST_API_EXCLUDE_PARAMETER_ENV では、除外するパラメータを含む JSON 文字列を指定できます。これは、JSONが短く、頻繁に変更されない場合に有効なオプションです。もう1つのオプションは、変数DAST_API_EXCLUDE_PARAMETER_FILE です。この変数は、リポジトリにチェックインするか、別のジョブがアーティファクトとして作成するか、DAST_API_PRE_SCRIPT を使用してプリスクリプトで実行時に生成できるファイルパスに設定されます。

JSONドキュメントを使用したパラメータの除外

JSONドキュメントにはJSONオブジェクトが含まれており、このオブジェクトは特定のプロパティを使用して、除外するパラメータを特定します。スキャン処理中に特定のパラメータを除外するには、以下のプロパティを指定します:

  • headers:特定のヘッダを除外するには、このプロパティを使用します。プロパティの値は、除外するヘッダ名の配列です。名前の大文字と小文字は区別されません。
  • cookies:特定のクッキーを除外するには、このプロパティの値を使用します。このプロパティの値は、除外するクッキー名の配列です。名前の大文字と小文字は区別されます。
  • query:クエリ文字列から特定のフィールドを除外するには、このプロパティを使用します。プロパティの値は、除外するクエリ文字列のフィールド名の配列です。名前の大文字と小文字は区別されます。
  • body-form:このプロパティを使用して、メディア・タイプapplication/x-www-form-urlencoded を使用する要求から特定のフィールドを除外します。このプロパティの値は、除外する本文のフィールド名の配列です。名前の大文字と小文字は区別されます。
  • body-json:このプロパティを使用して、メディアタイプapplication/json を使用するリクエストから特定の JSON ノードを除外します。プロパティの値は配列で、配列の各エントリはJSON Path式です。
  • body-xml:このプロパティを使用して、メディアタイプapplication/xml を使用する要求から特定の XML ノードを除外します。プロパティの値は配列で、配列の各エントリはXPath v2式です。

したがって、以下のJSONドキュメントは、パラメータを除外するために期待される構造の例です。

{
  "headers": [
    "header1",
    "header2"
  ],
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "query": [
    "query-string1",
    "query-string2"
  ],
  "body-form": [
    "form-param1",
    "form-param2"
  ],
  "body-json": [
    "json-path-expression-1",
    "json-path-expression-2"
  ],
  "body-xml" : [
    "xpath-expression-1",
    "xpath-expression-2"
  ]
}

使用例

単一ヘッダの除外

ヘッダUpgrade-Insecure-Requests を除外するには、header プロパティの値を、ヘッダ名:[ "Upgrade-Insecure-Requests" ] を持つ配列に設定します。例えば、JSONドキュメントは以下のようになります:

{
  "headers": [ "Upgrade-Insecure-Requests" ]
}

ヘッダー名は大文字と小文字を区別しないので、ヘッダー名UPGRADE-INSECURE-REQUESTSUpgrade-Insecure-Requests と同じです。

ヘッダと二つのクッキーの両方を除きます。

ヘッダAuthorization とクッキーPHPSESSIDcsrftoken を除外するには、headers プロパティの値をヘッダ名[ "Authorization" ] の配列に設定し、cookies プロパティの値をクッキー名[ "PHPSESSID", "csrftoken" ] の配列に設定します。例えば、JSONドキュメントは次のようになります:

{
  "headers": [ "Authorization" ],
  "cookies": [ "PHPSESSID", "csrftoken" ]
}
body-form パラメータの除外

application/x-www-form-urlencoded を使用する要求でpassword フィールドを除外するには、body-form プロパティの値をフィールド名[ "password" ] の配列に設定します。例えば、JSONドキュメントは以下のようになります:

{
  "body-form":  [ "password" ]
}

exclude パラメータは、要求がコンテンツ・タイプapplication/x-www-form-urlencoded を使用している場合、body-form を使用します。

JSON Path を使用した特定の JSON ノードの除外

ルート・オブジェクトのschema プロパティを除外するには、body-json プロパティの値を、JSON Path 式[ "$.schema" ] を持つ配列に設定します。

JSON パス式は、JSON ノードを識別するために特別な構文を使用します。$ は JSON ドキュメントのルートを指し、. は現在のオブジェクト (この場合はルート オブジェクト) を指し、schema というテキストはプロパティ名を指します。したがって、JSON パス式$.schema は、ルート オブジェクトのプロパティschema を参照します。インスタンスのJSONドキュメントは次のようになります:

{
  "body-json": [ "$.schema" ]
}

リクエストがコンテンツタイプapplication/json を使用する場合、 exclude パラメータはbody-json を使用します。body-json の各エントリは、JSON Path 式であることが期待されます。$*. などの JSON Path 文字は特別な意味を持ちます。

JSON Path を使用した複数の JSON ノードの除外

ルートレベルの配列users の各エントリでプロパティpassword を除外するには、body-json プロパティの値を、JSON Path 式[ "$.users[*].paswword" ] を持つ配列に設定します。

JSON Path 式は、$ で開始してルート・ノードを参照し、. を使用して現在のノードを参照します。次に、users を使用してプロパティを参照し、[] という文字を使用して、使用する配列のインデックスを囲みます。インデックスとして数値を指定する代わりに、* を使用して任意のインデックスを指定します。インデックス参照の後、. が見つかります。これは、配列内の任意の選択されたインデックスを参照するもので、その前にプロパティ名passwordが付きます。

インスタンスのJSONドキュメントは次のようになります:

{
  "body-json": [ "$.users[*].paswword" ]
}

リクエストがコンテンツタイプapplication/json を使用する場合、 exclude パラメータはbody-json を使用します。body-json の各エントリは、JSON Path 式であることが期待されます。$*. などの JSON Path 文字は特別な意味を持ちます。

XML 属性の除外

ルート要素credentials にあるisEnabled という名前の属性を除外するには、body-xml プロパティの値を、XPath 式[ "/credentials/@isEnabled" ] を持つ配列に設定します。

XPath 式/credentials/@isEnabled は、XML 文書のルートを示す/ で始まり、マッチさせる要素の名前を示すcredentials が続きます。前の XML 要素のノードを参照するために/ を使用し、名前isEnable が属性であることを示すために文字@ を使用します。

インスタンスのJSONドキュメントは次のようになります:

{
  "body-xml": [
    "/credentials/@isEnabled"
  ]
}

リクエストがコンテントタイプapplication/xml を使用している場合、 exclude パラメータはbody-xml を使用します。body-xml の各エントリは、XPath v2 式であることが期待されます。XPath 式では、@/:[] などの文字が特別な意味を持ちます。

XML テキストの要素の除外

ルート・ノードcredentials に含まれるusername 要素のテキストを除外するには、body-xml プロパティの値を、XPath 式[/credentials/username/text()" ] を持つ配列に設定します。

XPath 式/credentials/username/text() では、最初の文字/ はルート XML ノードを指し、その後に XML 要素の名前credentials を示します。同様に、文字/ は現在の要素を参照し、その後に新しい XML 要素の名前username が続きます。最後の部分には、現在の要素を参照する/ があり、現在の要素のテキストを識別するtext() という XPath 関数を使用しています。

インスタンスのJSONドキュメントは次のようになります:

{
  "body-xml": [
    "/credentials/username/text()"
  ]
}

リクエストがコンテントタイプapplication/xml を使用している場合、 exclude パラメータはbody-xml を使用します。body-xml の各エントリは、XPath v2 式であることが期待されます。XPath 式では、@/:[] などの文字が特別な意味を持ちます。

XML 要素の除外

ルート・ノードcredentials に含まれる要素username を除外するには、body-xml プロパティの値を、XPath 式[/credentials/username" ] を持つ配列に設定します。

XPath 式/credentials/username では、最初の文字/ はルート XML ノードを指し、その後に XML 要素の名前credentials を示します。同様に、文字/ は現在の要素を参照し、その後に新しい XML 要素の名前username が続きます。

インスタンスのJSONドキュメントは次のようになります:

{
  "body-xml": [
    "/credentials/username"
  ]
}

リクエストがコンテントタイプapplication/xml を使用している場合、 exclude パラメータはbody-xml を使用します。body-xml の各エントリは、XPath v2 式であることが期待されます。XPath 式では、@/:[] などの文字が特別な意味を持ちます。

名前空間を持つ XML ノードの除外

名前空間s で定義され、credentials ルート・ノード内部に含まれる XML 要素login を除外するには、body-xml プロパティの値を、XPath 式[ "/credentials/s:login" ]を持つ配列に設定します。

XPath 式/credentials/s:login では、最初の文字/ はルート XML ノードを指し、その後に XML 要素の名前credentials を示します。同様に、文字/ は現在の要素を指し、その後に新しい XML 要素の名前s:loginが続きます。:この文字は、名前空間とノード名を分離します。

名前空間名は、ボディ・リクエストの一部である XML ドキュメントで定義されている必要があります。名前空間は、仕様ドキュメント HAR、OpenAPI、または Postman Collection ファイルで確認できます。

{
  "body-xml": [
    "/credentials/s:login"
  ]
}

リクエストがコンテントタイプapplication/xml を使用している場合、 exclude パラメータはbody-xml を使用します。body-xml の各エントリはXPath v2 式であることが期待されます。XPathでは、@,/,:,[,] などの表現文字は特別な意味を持ちます。

JSON 文字列の使用

除外JSONドキュメントを提供するには、変数DAST_API_EXCLUDE_PARAMETER_ENV にJSON文字列を設定します。以下の例では、.gitlab-ci.yml,DAST_API_EXCLUDE_PARAMETER_ENV 変数にJSON文字列が設定されています:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_EXCLUDE_PARAMETER_ENV: '{ "headers": [ "Upgrade-Insecure-Requests" ] }'

ファイルの使用

除外JSONドキュメントを提供するために、変数DAST_API_EXCLUDE_PARAMETER_FILE にJSONファイルパスを設定します。ファイルパスは、ジョブの現在の作業ディレクトリからの相対パスです。次の例.gitlab-ci.yml の内容では、DAST_API_EXCLUDE_PARAMETER_FILE 変数に JSON ファイルパスが設定されています:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_EXCLUDE_PARAMETER_FILE: dast-api-exclude-parameters.json

dast-api-exclude-parameters.json は、exclude パラメータ文書の構造に従った JSON 文書です。

除外URL

GitLab 14.10で導入されました

パスで除外する代わりに、DAST_API_EXCLUDE_URLS CI/CD変数を使ってURL内の他のコンポーネントでフィルタリングすることができます。この変数は.gitlab-ci.yml ファイルで設定できます。この変数にはカンマ(,)で区切られた複数の値を格納することができます。各値は正規表現です。各エントリは正規表現なので、.* のようなエントリは、すべてにマッチする正規表現なので、すべての URL を除外します。

ジョブ出力では、DAST_API_EXCLUDE_URLS から指定された正規表現に一致する URL があるかどうかを確認できます。一致するオペレーションは、[除外されたオペレーション]セクションにリストされています。Excluded OperationsセクションにリストされたオペレーションはTested Operationsセクションにリストされるべきではありません。たとえば、ジョブ出力の次の部分です:

2021-05-27 21:51:08 [INF] DAST API: --[ Tested Operations ]-------------------------
2021-05-27 21:51:08 [INF] DAST API: 201 POST http://target:7777/api/users CREATED
2021-05-27 21:51:08 [INF] DAST API: ------------------------------------------------
2021-05-27 21:51:08 [INF] DAST API: --[ Excluded Operations ]-----------------------
2021-05-27 21:51:08 [INF] DAST API: GET http://target:7777/api/messages
2021-05-27 21:51:08 [INF] DAST API: POST http://target:7777/api/messages
2021-05-27 21:51:08 [INF] DAST API: ------------------------------------------------
note
DAST_API_EXCLUDE_URLS の各値は正規表現です。.*$ などの文字はDAST_API_EXCLUDE_URLS正規DAST_API_EXCLUDE_URLS表現で特別な意味を持ちます。

使用例

URLと子リソースの除外

次の例は、URLhttp://target/api/auth とその子リソースを除外します。

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://target/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_EXCLUDE_URLS: http://target/api/auth
2つのURLを除外し、その子リソースを許可します。

http://target/api/buyhttp://target/api/sell のURLを除外し、その子リソースのスキャンを許可するには、インスタンス:http://target/api/buy/toy またはhttp://target/api/sell/chair.http://target/api/buy/$,http://target/api/sell/$という値を使用できます。この値は、, 文字で区切られた 2 つの正規表現を使用しています。したがって、http://target/api/buy$http://target/api/sell$をコンテナとして含んでいます。 それぞれの正規表現において、末尾の$ 文字は、マッチする URL がどこで終わるべきかを示しています。

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://target/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_EXCLUDE_URLS: http://target/api/buy/$,http://target/api/sell/$
つのURLとその子リソースの除外

http://target/api/buyhttp://target/api/sell のURLとその子リソースを除外します。複数のURLを指定するには、, の文字を次のように使用します:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://target/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_EXCLUDE_URLS: http://target/api/buy,http://target/api/sell
正規表現を使用したURLの除外

https://target/api/v1/user/createhttps://target/api/v2/user/create 、またはその他のバージョン(v3v4 、およびその他)を正確に除外するには。https://target/api/v.*/user/create$. は任意の文字、* は0回以上を表し、さらに$ は URL がそこで終わることを表します。

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://target/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_EXCLUDE_URLS: https://target/api/v.*/user/create$

最初のスキャンの実行

正しく設定されている場合、CI/CDパイプラインはdast ステージとdast_api ジョブを含んでいます。ジョブが失敗するのは、無効な設定が提供されたときだけです。典型的なオペレーションでは、テスト中に脆弱性が特定されたとしても、ジョブは常に成功します。

脆弱性はセキュリティパイプラインタブにスイート名とともに表示されます。リポジトリのデフォルトブランチに対してテストを行う場合、DAST API の脆弱性はセキュリティとコンプライアンスの脆弱性レポートページにも表示されます。

報告される脆弱性の数が過剰になるのを防ぐため、DAST API スキャナはオペレーションごとに報告する脆弱性の数を制限しています。

DAST API 脆弱性の表示

DAST API アナライザは、脆弱性を GitLab 脆弱性スクリーンに入力するために収集・使用される JSON レポートを作成します。

報告される偽陽性の数を制限するための設定変更については、偽陽性の処理を参照してください。

DAST API 脆弱性の詳細を見る

脆弱性の詳細を表示するには、以下の手順に従ってください:

  1. プロジェクトまたはマージリクエストの脆弱性を表示できます:

    • プロジェクトで、プロジェクトのセキュリティ > 脆弱性レポートページに移動します。このページには、デフォルトブランチからのすべての脆弱性のみが表示されます。
    • マージリクエストでは、マージリクエストの [セキュリティ] セクションに移動し、[展開] ボタンを選択します。DAST API 脆弱性は、DAST detected N potential vulnerabilitiesというラベルの付いたセクションで確認できます。タイトルを選択すると、脆弱性の詳細が表示されます。
  2. 脆弱性のタイトルを選択すると、詳細が表示されます。これらの詳細については、以下の表を参照してください。

    項目説明
    説明何が変更されたかを含む脆弱性の説明。
    プロジェクト脆弱性が検出された名前空間とプロジェクト。
    方法脆弱性の検出に使用される HTTP メソッド。
    URL脆弱性が検出されたURL。
    リクエスト脆弱性の原因となった HTTP リクエスト。
    変更されていないレスポンス変更されていないリクエストのレスポンスです。これが典型的なレスポンスです。
    実際のレスポンステストリクエストから受信したレスポンス。
    証拠脆弱性が発生したと判断した方法。
    識別子この脆弱性を発見するために使用された DAST API 検査。
    深刻度脆弱性の深刻度。
    スキャナの種類テストに使用するスキャナ。

セキュリティダッシュボード

セキュリティダッシュボードは、あなたのグループ、プロジェクト、パイプラインのすべてのセキュリティ脆弱性の概要を把握するのに適した場所です。詳細については、セキュリティダッシュボードのドキュメントを参照してください。

脆弱性との対話

脆弱性が見つかったら、それに対処することができます。脆弱性へのアドレスについては、こちらをご覧ください。

誤検出への対処

誤検出にはいくつかの対処法があります:

  • 脆弱性を棄却します。
  • 検査によっては、脆弱性が特定されたときにそれを検出するためのいくつかの方法(_アサーションと_呼ばれる)があります。アサーションはオフにしたり設定したりすることもできます。例えば、DAST API スキャナのデフォルトでは、HTTP ステータスコードを使用して、何かが本当のイシューであることを識別します。テスト中にAPIが500エラーを返すと、脆弱性が発生します。フレームワークによっては500エラーを頻繁に返すものもあるので、これは必ずしも望ましいことではありません。
  • 偽陽性を生成するチェックをオフにしてください。これは、チェックが脆弱性を生成するのを防ぎます。チェックの例としては、SQL インジェクションチェックや JSON ハイジャックチェックがあります。

チェックをオフに

チェックは特定のタイプのテストを実行し、特定の設定プロファイルに対してオン/オフを切り替えることができます。提供される設定ファイルには、使用できるプロファイルがいくつか定義されています。設定ファイルのプロファイル定義には、スキャン中にアクティブになるすべてのチェックがリストされています。特定のチェックをオフにするには、設定ファイルのプロファイル定義からそのチェックを削除します。プロファイルは、設定ファイルのProfiles セクションで定義します。

プロファイル定義の例:

Profiles:
  - Name: Quick
    DefaultProfile: Empty
    Routes:
      - Route: *Route0
        Checks:
          - Name: ApplicationInformationCheck
          - Name: CleartextAuthenticationCheck
          - Name: FrameworkDebugModeCheck
          - Name: HtmlInjectionCheck
          - Name: InsecureHttpMethodsCheck
          - Name: JsonHijackingCheck
          - Name: JsonInjectionCheck
          - Name: SensitiveInformationCheck
          - Name: SessionCookieCheck
          - Name: SqlInjectionCheck
          - Name: TokenCheck
          - Name: XmlInjectionCheck

JSONハイジャックチェックをオフにするには、以下の行を削除してください:

          - Name: JsonHijackingCheck

この結果、YAMLは次のようになります:

- Name: Quick
  DefaultProfile: Empty
  Routes:
    - Route: *Route0
      Checks:
        - Name: ApplicationInformationCheck
        - Name: CleartextAuthenticationCheck
        - Name: FrameworkDebugModeCheck
        - Name: HtmlInjectionCheck
        - Name: InsecureHttpMethodsCheck
        - Name: JsonInjectionCheck
        - Name: SensitiveInformationCheck
        - Name: SessionCookieCheck
        - Name: SqlInjectionCheck
        - Name: TokenCheck
        - Name: XmlInjectionCheck

チェックのアサーションをオフにします

アサーションは、検査によって生成されたテストの脆弱性を検出します。多くの検査では、ログ解析、レスポンス解析、ステータスコードなど、複数のアサーションをサポートしています。脆弱性が検出されると、使用されるアサーションが提供されます。どのアサーションがデフォルトで有効になっているかを確認するには、設定ファイルの Checks default configuration を参照してください。Checks というセクションがあります。

この例はSQLインジェクション・チェックを示しています:

- Name: SqlInjectionCheck
  Configuration:
    UserInjections: []
  Assertions:
    - Name: LogAnalysisAssertion
    - Name: ResponseAnalysisAssertion
    - Name: StatusCodeAssertion

デフォルトで 3 つのアサーションがオンになっていることがわかります。よくある誤検出の原因はStatusCodeAssertion です。これをオフにするには、Profiles セクションの設定を変更してください。この例では、他の2つのアサーション (LogAnalysisAssertion,ResponseAnalysisAssertion) だけを提供しています。これにより、SqlInjectionCheckStatusCodeAssertionを使用することを防ぎます:

Profiles:
  - Name: Quick
    DefaultProfile: Empty
    Routes:
      - Route: *Route0
        Checks:
          - Name: ApplicationInformationCheck
          - Name: CleartextAuthenticationCheck
          - Name: FrameworkDebugModeCheck
          - Name: HtmlInjectionCheck
          - Name: InsecureHttpMethodsCheck
          - Name: JsonHijackingCheck
          - Name: JsonInjectionCheck
          - Name: SensitiveInformationCheck
          - Name: SessionCookieCheck
          - Name: SqlInjectionCheck
            Assertions:
              - Name: LogAnalysisAssertion
              - Name: ResponseAnalysisAssertion
          - Name: TokenCheck
          - Name: XmlInjectionCheck

オフライン環境での DAST API の実行

インターネットを介した外部リソースへのアクセスが制限されている、制限されている、または断続的な環境にある自己管理型 GitLab インスタンスでは、DAST API テストジョブを正常に実行するためにいくつかの調整が必要です。

ステップ

  1. ローカルのコンテナレジストリにDockerイメージをホストします。
  2. SECURE_ANALYZERS_PREFIX をローカル・コンテナ・レジストリに設定します。

DAST API 用の Docker イメージを公開レジストリからプル(ダウンロード)し、ローカルレジストリにプッシュ(インポート)する必要があります。Dockerイメージをローカルにホストするには、GitLabコンテナレジストリを使用します。このプロセスは特別なテンプレートを使って実行できます。手順についてはオフラインホストへのDockerイメージのロードを参照してください。

Dockerイメージがローカルにホストされると、SECURE_ANALYZERS_PREFIX 変数にローカルレジストリの場所が設定されます。この変数は、/api-security:2 を連結すると有効なイメージの場所になるように設定する必要があります。

note
DAST APIとAPI Fuzzingはどちらも同じDockerイメージapi-security:2 を使用します。

例えば、以下の行はregistry.gitlab.com/security-products/api-security:2 というイメージのレジストリを設定します:

SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/security-products"

note
SECURE_ANALYZERS_PREFIX を設定すると、すべてのGitLab SecureテンプレートのDockerイメージレジストリの場所が変更されます。

詳細については、オフライン環境を参照してください。

パフォーマンス・チューニングとテスト速度

DAST API のような、動的な分析テストを実施するセキュリティツールは、実行中のアプリケーションのインスタンスにリクエストを 送ることによってテストを実施します。リクエストは、アプリケーションに存在するかもしれない特定の脆弱性をテストするように設計されています。動的解析テストの速度は、以下に依存します:

  • ファジングツールがアプリケーションに送信できる1秒あたりのリクエスト数
  • アプリケーションがリクエストに応答する速度
  • アプリケーションのテストに必要なリクエスト数
    • APIがいくつのオペレーションで構成されているか
    • 各オペレーションに含まれるフィールドの数(JSONボディ、ヘッダー、クエリ文字列、クッキーなど)

このパフォーマンスガイドのアドバイスに従っても、DAST API テストジョブに予想以上の時間がかかる場合は、サポートにお問い合わせください。

パフォーマンスの問題の診断

パフォーマンスの問題を解決するための最初のステップは、テスト時間が予想よりも遅い原因となっている貢献者を理解することです。よく見られるイシューは以下のとおりです:

  • DAST APIが低速またはシングルCPUのGitLab Runner上で動作している(GitLab Shared RunnerはシングルCPUです)
  • アプリケーションが低速/シングル CPU インスタンスにデプロイされ、テストの負荷に追いついていない場合。
  • アプリケーションに全体的なテスト速度に影響を与える遅いオペレーションが含まれている(1/2 秒以上)
  • アプリケーションに、大量のデータを返すオペレーションが含まれている(> 500K+) 場合。
  • アプリケーションに大量のオペレーションが含まれている (> 40)

アプリケーションに全体的なテスト速度に影響を与える遅いオペレーションが含まれている(1/2 秒以上)

DAST API のジョブ出力には、テスト速度、テスト中の各オペレーションの応答速度、サマリー情報などの有用な情報が含まれています。いくつかのサンプル出力を見て、パフォーマンスの問題を追跡する際にどのように使用できるかを見てみましょう:

DAST API: Loaded 10 operations from: assets/har-large-response/large_responses.har
DAST API:
DAST API: Testing operation [1/10]: 'GET http://target:7777/api/large_response_json'.
DAST API:  - Parameters: (Headers: 4, Query: 0, Body: 0)
DAST API:  - Request body size: 0 Bytes (0 bytes)
DAST API:
DAST API: Finished testing operation 'GET http://target:7777/api/large_response_json'.
DAST API:  - Excluded Parameters: (Headers: 0, Query: 0, Body: 0)
DAST API:  - Performed 767 requests
DAST API:  - Average response body size: 130 MB
DAST API:  - Average call time: 2 seconds and 82.69 milliseconds (2.082693 seconds)
DAST API:  - Time to complete: 14 minutes, 8 seconds and 788.36 milliseconds (848.788358 seconds)

このジョブコンソールの出力スニペットは、いくつのオペレーションが見つかったか(10)から始まり、特定のオペレーションでテストが開始されたことの通知と、オペレーションが完了したことの要約が続きます。要約はこのログ出力のもっとも興味深い部分です。要約では、このオペレーションとその関連フィールドを完全にテストするのに DAST API 767 リクエストを要したことがわかります。また、平均応答時間は2秒で、この1つのオペレーションが完了するまでの時間は14分でした。

平均応答時間が2秒であることは、この特定のオペレーションがテストに時間がかかることを示す最初の良い指標です。さらに、レスポンスのボディ・サイズがかなり大きいことがわかります。各リクエストで多くのデータを転送することが、2秒の大部分を占めているのです。

このイシューに対して、チームは次のことを決定するかもしれません:

チームの要件が5-7分の範囲にあると仮定すると、これらの解決策を組み合わせて、許容可能なテスト時間を達成することが考えられます。

パフォーマンス問題へのアドレス

以下のセクションでは、DAST APIのパフォーマンス問題に対処するための様々なオプションについて説明します:

マルチCPUランナーの使用

DAST APIを使ったマルチCPUランナーを使うことで、最も簡単にパフォーマンスを向上させることができます。この表はJava Spring Boot REST APIのベンチマークで収集された統計情報です。このベンチマークでは、ターゲットとDAST APIは単一のRunnerインスタンスを共有しています。

CPU数リクエスト/秒
1CPU(共有ランナー)75
4 CPU255
8 CPU400

この表からわかるように、RunnerのCPU数を増やすことは、テストのスピード/パフォーマンスに大きな影響を与えます。

マルチCPUを使うには、通常、セルフマネージドGitLab RunnerをマルチCPUマシンやクラウドコンピュートインスタンスにデプロイする必要があります。

複数のタイプのGitLab Runnerが使用可能な場合、様々なインスタンスは一般的にジョブ定義でランナーのタイプを選択するために使用できるタグで設定されています。

以下は DAST API 用のジョブ定義の例で、multi-cpu というタグでtags セクションを追加しています。このジョブはDAST APIテンプレートに含まれるジョブ定義を自動的に拡張します。

dast_api:
  tags:
  - multi-cpu

DAST API がランナー内で複数の CPU を検出できることを確認するには、完了したジョブのアーティファクトからgl-api-security-scanner.log ファイルをダウンロードします。このファイルで文字列Starting work item processor を検索し、レポーターの最大 DOP (並列度) を調べます。最大DOPは、ランナーに割り当てられたCPU数以上でなければなりません。設定変数によって強制されない限り、シングルCPU Runnerであっても、値が2より小さくなることはありません。レポートされた値がランナーに割り当てられたCPU数より小さい場合、ランナーのデプロイに何か問題があります。問題を特定できない場合は、サポートにチケットを提出してください。

ログエントリの例

17:00:01.084 [INF] <Peach.Web.Core.Services.WebRunnerMachine> Starting work item processor with 2 max DOP

低速オペレーションの除外

遅いオペレーションが1つまたは2つある場合、チームはそのオペレーションのテストを省略することを決定するかもしれません。オペレーションを除外するには、このセクションで説明するようにDAST_API_EXCLUDE_PATHS 設定変数を使用します。

この例では、大量のデータを返すオペレーションがあります。このオペレーションはGET http://target:7777/api/large_response_json です。これを除外するために、DAST_API_EXCLUDE_PATHS 設定変数にオペレーションURLのパス部分/api/large_response_jsonを指定します。

オペレーションが除外されていることを確認するには、DAST API ジョブを実行し、ジョブコンソール出力をレビューします。テストの最後に、含まれるオペレーションと除外されるオペレーションのリストが含まれています。

dast_api:
  variables:
    DAST_API_EXCLUDE_PATHS: /api/large_response_json

オペレーションをテストから除外すると、脆弱性が発見されない可能性があります。{: .alert .alert-warning} {: .alert .alert-warning

テストの複数ジョブへの分割

DAST API では、DAST_API_EXCLUDE_PATHS およびDAST_API_EXCLUDE_URLSを使用することで、テストを複数のジョブに分割することができます。テストを分割する場合、dast_api のジョブを無効にし、それを識別名のついた 2 つのジョブで置き換えるのがよいパターンです。この例では 2 つのジョブがあり、それぞれのジョブが API のバージョンをテストしているので、名前もそれを反映しています。しかし、このテクニックはAPIのバージョンに限らず、どんな状況にも適用できます。

dast_api_v1dast_api_v2 のジョブで使用しているルールは、DAST API テンプレートからコピーしたものです。

# Disable the main dast_api job
dast_api:
  rules:
  - if: $CI_COMMIT_BRANCH
    when: never

dast_api_v1:
  extends: dast_api
  variables:
    DAST_API_EXCLUDE_PATHS: /api/v1/**
  rules:
  - if: $DAST_API_DISABLED == 'true' || $DAST_API_DISABLED == '1'
    when: never
  - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH == 'true' &&
        $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
    when: never
  - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH == '1' &&
        $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
    when: never
  - if: $CI_COMMIT_BRANCH &&
        $CI_GITLAB_FIPS_MODE == "true"
    variables:
      DAST_API_IMAGE_SUFFIX: "-fips"
  - if: $CI_COMMIT_BRANCH

dast_api_v2:
  variables:
    DAST_API_EXCLUDE_PATHS: /api/v2/**
  rules:
  - if: $DAST_API_DISABLED == 'true' || $DAST_API_DISABLED == '1'
    when: never
  - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH == 'true' &&
        $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
    when: never
  - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH == '1' &&
        $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
    when: never
  - if: $CI_COMMIT_BRANCH &&
        $CI_GITLAB_FIPS_MODE == "true"
    variables:
      DAST_API_IMAGE_SUFFIX: "-fips"
  - if: $CI_COMMIT_BRANCH

機能ブランチでのオペレーションを除外し、デフォルトブランチでのオペレーションは除外しないこと。

遅いオペレーションがひとつふたつある場合、チームはそのオペレーションのテストを省略するか、 あるいはそのオペレーションを feature ブランチのテストからは除外して default ブランチのテストには含めることにします。オペレーションを除外するには、DAST_API_EXCLUDE_PATHS 設定変数を使います。

この例では、大量のデータを返すオペレーションがあります。このオペレーションはGET http://target:7777/api/large_response_json です。このオペレーションを除外するには、DAST_API_EXCLUDE_PATHS 設定変数にオペレーションURL/api/large_response_jsonのパス部分を指定します。この設定では、メインのdast_api ジョブを無効にし、2つの新しいdast_api_main ジョブとdast_api_branch.は dast_api_branch、長いオペレーションを除外し、デフォルト以外のブランチ (たとえば機能ブランチ) でのみ実行するように設定されています。ブランチは dast_api_main、デフォルトブランチ (この例ではmain ) でのみ実行されるように設定されています。dast_api_branch のジョブは高速に実行され、開発サイクルを短縮できます。一方、dast_api_main のジョブはデフォルトブランチのビルドでのみ実行され、実行に時間がかかります。

オペレーションが除外されていることを確認するには、DAST API ジョブを実行し、ジョブコンソール出力をレビューします。テストの最後に、含まれるオペレーションと除外されるオペレーションのリストが含まれています。

# Disable the main job so we can create two jobs with
# different names
dast_api:
  rules:
  - if: $CI_COMMIT_BRANCH
    when: never

# DAST API for feature branch work, excludes /api/large_response_json
dast_api_branch:
  extends: dast_api
  variables:
    DAST_API_EXCLUDE_PATHS: /api/large_response_json
  rules:
  - if: $DAST_API_DISABLED == 'true' || $DAST_API_DISABLED == '1'
    when: never
  - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH == 'true' &&
        $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
    when: never
  - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH == '1' &&
        $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
    when: never
  - if: $CI_COMMIT_BRANCH &&
        $CI_GITLAB_FIPS_MODE == "true"
    variables:
      DAST_API_IMAGE_SUFFIX: "-fips"
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    when: never
  - if: $CI_COMMIT_BRANCH

# DAST API for default branch (main in our case)
# Includes the long running operations
dast_api_main:
  extends: dast_api
  rules:
  - if: $DAST_API_DISABLED == 'true' || $DAST_API_DISABLED == '1'
    when: never
  - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH == 'true' &&
        $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
    when: never
  - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH == '1' &&
        $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
    when: never
  - if: $CI_COMMIT_BRANCH &&
        $CI_GITLAB_FIPS_MODE == "true"
    variables:
      DAST_API_IMAGE_SUFFIX: "-fips"
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

トラブルシューティング

DAST APIジョブがN時間後にタイムアウトします。

DAST APIジョブがタイムアウトする理由の上位2つは、オペレーションが遅い(1秒以上)ことと、DAST APIにシングルCPUランナーを使用していることです(GitLab共有ランナーはシングルCPUです)。さらに問題を診断する前に、ジョブを完了させて出力を分析する必要があります。まずマルチCPUランナーで開始し、ジョブが完了して出力がさらにレビューできるようになるまで、APIオペレーションの一部を除外することをお勧めします。

支援については、以下のドキュメント・セクションを参照してください:

DAST APIジョブの完了に時間がかかりすぎる

パフォーマンス・チューニングとテスト速度を参照

エラー:Error waiting for DAST API 'http://127.0.0.1:5000' to become available

v1.6.196 より前のバージョンの DAST API アナライザには、特定の条件下でバックグラウンドプロセスが失敗するバグが存在します。この問題を解決するには、DAST API アナライザを新しいバージョンに更新してください。

バージョン情報は、dast_api ジョブの詳細に記載されています。

もしv1.6.196以上のバージョンでイシューが発生している場合は、以下の情報をサポートまでご連絡ください:

  1. このトラブルシューティングのセクションを参照し、イシューをDynamic Analysis Teamにエスカレーションするよう依頼してください。
  2. ジョブの完全なコンソール出力。
  3. ジョブのアーティファクトとして利用可能なgl-api-security-scanner.log ファイル。ジョブの詳細ページの右側のパネルで、Browseボタンを選択します。
  4. .gitlab-ci.yml ファイルのdast_api ジョブ定義。

エラーメッセージ

  • GitLab 15.6 以降ではError waiting for DAST API 'http://127.0.0.1:5000' to become available
  • GitLab 15.5以前では、Error waiting for API Security 'http://127.0.0.1:5000' to become available

Failed to start scanner session (version header not found)

DAST API エンジンは、スキャナーアプリケーションコンポーネントとの接続を確立できない場合にエラーメッセージを出力します。エラーメッセージはdast_api ジョブのジョブ出力ウィンドウに表示されます。この問題の一般的な原因は、DAST_API_API 変数をデフォルトから変更することです。

エラーメッセージ

  • GitLab 13.11以降ではFailed to start scanner session (version header not found).
  • GitLab 13.10以前では、API Security version header not found. Are you sure that you are connecting to the DAST API server?

解決方法

  • .gitlab-ci.yml ファイルからDAST_API_API 変数を削除します。この値はDAST API CI/CDテンプレートから継承されます。手動で値を設定する代わりに、この方法をお勧めします。
  • 変数を削除できない場合は、DAST API CI/CD テンプレートの最新バージョンでこの値が変更されていないか確認してください。もしそうであれば、.gitlab-ci.yml ファイルの値を更新してください。

Failed to start session with scanner. Please retry, and if the problem persists reach out to support.

スキャナアプリケーションコンポーネントとの接続を確立できない場合、DAST API エンジンはエラーメッセージを出力します。エラーメッセージはdast_api ジョブのジョブ出力ウィンドウに表示されます。この問題の一般的な原因は、バックグラウンドコンポーネントが選択したポートをすでに使用しているため使用できないことです。このエラーは、タイミングが関係する場合(競合状態)、断続的に発生することがあります。このイシューはKubernetes環境で、他のサービスがコンテナにマッピングされてポートの競合を引き起こしている場合によく発生します。

解決策を進める前に、そのポートがすでに使用されているためにエラーメッセージが表示されたことを確認することが重要です。これが原因であることを確認するには

  1. ジョブコンソールに移動します。

  2. アーティファクトgl-api-security-scanner.log を探します。ダウンロード] を選択してすべてのアーティファクトをダウンロードしてからファイルを検索するか、[参照]を選択して直接検索を開始できます。

  3. ファイルgl-api-security-scanner.log をテキストエディタで開きます。

  4. ポートがすでに使用されていたためにエラーメッセージが表示された場合は、ファイルに以下のようなメッセージが表示されているはずです:

  • GitLab 15.5以降では

     Failed to bind to address http://127.0.0.1:5500: address already in use.
  • GitLab 15.4以前の場合:

     Failed to bind to address http://[::]:5000: address already in use.

http://[::]:5000 例えば、http://[::]:5500http://127.0.0.1:5500 などです。エラーメッセージの残りの部分が同じであれば、そのポートはすでに使われていると考えてもよいでしょう。

ポートが既に取られているという証拠が見つからなかった場合、ジョブコンソール出力に表示された同じエラーメッセージをアドレスとする他のトラブルシューティングのセクションもチェックしてください。これ以上の選択肢がない場合は、サポートを受けるか、適切なルートで改善を要求してください。

ポートが既に取られていたためにイシューが発生したことを確認したら、GitLab 15.5をインストールしてください。その後、GitLab 15.5以降では設定変数DAST_API_API_PORT が導入されました。この設定変数により、スキャナバックグラウンドコンポーネントの固定ポート番号を設定することができます。

解決方法

  1. .gitlab-ci.yml ファイルが設定変数DAST_API_API_PORT を定義していることを確認してください。
  2. DAST_API_API_PORT の値を1024以上の任意のポート番号に更新してください。新しい値がGitLabによって使用されていないか確認することをお勧めします。GitLabが使用するポートの一覧はPackage defaultsをご覧ください。

Application cannot determine the base URL for the target API

DAST API エンジンは、OpenAPI ドキュメントを検査してもターゲット API を特定できない場合にエラーメッセージを出力します。このエラーメッセージは、ターゲット API が.gitlab-ci.yml ファイルに設定されていない場合、environment_url.txt ファイルで利用できない場合、OpenAPI ドキュメントを使用して計算できなかった場合に表示されます。

DAST API エンジンが異なるソースをチェックする際にターゲット API を取得しようとする優先順位があります。DAST_API_TARGET_URL環境変数が設定されていない場合、DAST API エンジンはenvironment_url.txt ファイルの environment_url.txt使用を試みます。environment_url.txt ファイルが environment_url.txtない場合、DAST API エンジンは OpenAPI ドキュメントのコンテンツとDAST_API_OPENAPI で提供された URL(URL が提供されている場合)を使用してターゲット API の計算を試みます。

最適なソリューションは、ターゲットAPIがデプロイごとに変更されるかどうかによって異なります。静的環境の場合、ターゲット API はデプロイごとに同じであるため、静的環境のソリューションを参照してください。ターゲット API がデプロイごとに変更される場合は、動的環境ソリューションを適用する必要があります。

静的環境ソリューション

このソリューションは、ターゲットAPIのURLが変更されない(静的である)パイプラインのためのものです。

環境変数を追加します。

ターゲットAPIが変わらない環境では、DAST_API_TARGET_URL 環境変数を使ってターゲットURLを指定することをお勧めします。.gitlab-ci.yml 内に、変数DAST_API_TARGET_URL を追加してください。この変数には、APIテスト対象のベースURLを設定してください。例えば

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OPENAPI: test-api-specification.json

動的環境ソリューション

動的環境では、異なるデプロイごとにターゲットAPIが変更されます。この場合、可能な解決策は1つだけではありません。動的環境を扱う場合は、environment_url.txt ファイルを使用することをお勧めします。

environment_url.txtを使用してください。

各パイプラインでターゲット API URL が変更される動的な環境をサポートするために、DAST API エンジンは使用する URL を含むenvironment_url.txt ファイルの使用をサポートしています。このファイルはリポジトリにチェックインされるのではなく、テストターゲットをデプロイするジョブによってパイプライン中に作成され、パイプラインの後のジョブで使用できるアーティファクトとして収集されます。environment_url.txt ファイルを作成するジョブは、DAST API エンジンのジョブの前に実行する必要があります。

  1. テストターゲットのデプロイジョブを変更し、プロジェクトのルートにあるenvironment_url.txt ファイルにベース URL を追加します。
  2. environment_url.txt をアーティファクトとして収集するテスト ターゲットのデプロイ ジョブを修正します。

使用例:

deploy-test-target:
  script:
    # Perform deployment steps
    # Create environment_url.txt (example)
    - echo http://${CI_PROJECT_ID}-${CI_ENVIRONMENT_SLUG}.example.org > environment_url.txt

  artifacts:
    paths:
      - environment_url.txt

無効なスキーマで OpenAPI を使用

文書が無効なスキーマで自動生成されたり、手動で適時に編集できない場合があります。このような場合、DAST API は変数DAST_API_OPENAPI_RELAXED_VALIDATION を設定することで、緩やかな検証を行うことができます。予期せぬ動作を防ぐために、完全に準拠したOpenAPIドキュメントを提供することを推奨します。

非準拠OpenAPIファイルの編集

OpenAPI仕様に準拠していない要素を検出して修正するには、エディタの使用をお勧めします。エディタは一般的に、ドキュメントの検証や、スキーマに準拠した OpenAPI ドキュメントを作成するための提案を行います。推奨されるエディタは以下の通りです:

エディタ|OpenAPI 2.0|OpenAPI 3.0.x|OpenAPI 3.1.x| –| –| –||Swaggerエディタ |{check-circle}|YAML、JSONYAML、JSON|{check-circle}YAML、JSON|{check-circle}JSONYAML、JSON|{dotted-circle} YAML、JSON|{dotted-circle}YAML、JSONYAML, JSON Stoplight Studio {チェック-サークル} YAML, JSON{チェック-サークルYAML、JSON|{チェック-サークル}|Stoplight Studio|{チェック-サークルYAML, JSON{チェック・サークル} YAML, JSON{チェック・サークルYAML、JSON|チェック・サークル

OpenAPIドキュメントが手動で生成されている場合、ドキュメントをエディタに読み込み、非準拠な部分を修正します。ドキュメントが自動的に生成された場合は、それをエディタで読み込んでスキーマのイシューを特定し、アプリケーションに移動して、使用しているフレームワークに基づいて修正を行います。

OpenAPI緩和検証を有効にします

緩和されたバリデーションは、OpenAPIドキュメントがOpenAPI仕様に適合していないけれども、さまざまなツールで利用するのに十分なコンテンツを持っているような場合のためのものです。検証は行われますが、ドキュメントスキーマに関してはそれほど厳密ではありません。

DAST API は、OpenAPI 仕様に完全に適合していない OpenAPI ドキュメントを消費しようとすることができます。DAST API に緩和されたバリデーションの実行を指示するには、変数DAST_API_OPENAPI_RELAXED_VALIDATION に任意の値を設定します:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_PROFILE: Quick
  DAST_API_TARGET_URL: http://test-deployment/
  DAST_API_OPENAPI: test-api-specification.json
  DAST_API_OPENAPI_RELAXED_VALIDATION: 'On'

No operation in the OpenAPI document is consuming any supported media type

DAST API は OpenAPI ドキュメントで指定されたメディアタイプを使用してリクエストを生成します。サポートされているメディアタイプがないためにリクエストを作成できない場合、エラーがスローされます。

エラーメッセージ

  • GitLab 14.10以降の場合、Error, no operation in the OpenApi document is consuming any supported media type. Check 'OpenAPI Specification' to check the supported media types.

解決方法

  1. OpenAPI Specificationセクションでサポートされているメディアタイプをレビューしてください。
  2. OpenAPI ドキュメントを編集して、少なくとも指定されたオペレーションが、サポートされているメディアタイプのどれでも受け入れられるようにします。あるいは、サポートされるメディアタイプを OpenAPI ドキュメントレベルで設定し、すべてのオペレーションに適用することもできます。このステップでは、サポートされているメディアタイプがアプリケーションで受け入れられるように、アプリケーションの変更が必要になるかもしれません。

Error, error occurred trying to download `<URL>`: There was an error when retrieving content from Uri:' <URL>'. Error:The SSL connection could not be established, see inner exception.

DAST API は、古いプロトコルや暗号を含む幅広い TLS 設定に対応しています。幅広いサポートにもかかわらず、接続エラーが発生する場合があります。このエラーは、DAST API が指定された URL のサーバとのセキュアな接続を確立できなかったために発生します。

イシューを解決するには

エラーメッセージのホストが非TLS接続をサポートしている場合は、設定でhttps://http:// に変更してください。たとえば、以下の設定でエラーが発生した場合:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: https://test-deployment/
  DAST_API_OPENAPI: https://specs/openapi.json

DAST_API_OPENAPI のプレフィックスをhttps:// からhttp:// に変更します:

stages:
  - dast

include:
  - template: DAST-API.gitlab-ci.yml

variables:
  DAST_API_TARGET_URL: https://test-deployment/
  DAST_API_OPENAPI: http://specs/openapi.json

URLにアクセスするために非TLS接続を使用できない場合は、サポートチームにお問い合わせください。

testssl.shツールを使用すると、調査を迅速に行うことができます。Bashシェルがあり、影響を受けるサーバーに接続できるマシンから:

  1. 最新リリースのzip またはtar.gz ファイルをダウンロードし、https://github.com/drwetter/testssl.sh/releasesから展開します。
  2. ./testssl.sh --log https://specs を実行してください。
  3. ログファイルをサポートチケットに添付してください。

ERROR: Job failed: failed to pull image

このエラーメッセージは、アクセスに認証が必要な(公開されていない)コンテナレジストリからイメージを取り出したときに発生します。

ジョブコンソールの出力では、エラーは次のようになります:

Running with gitlab-runner 15.6.0~beta.186.ga889181a (a889181a)
  on blue-2.shared.runners-manager.gitlab.com/default XxUrkriX
Resolving secrets
00:00
Preparing the "docker+machine" executor
00:06
Using Docker executor with image registry.gitlab.com/security-products/api-security:2 ...
Starting service registry.example.com/my-target-app:latest ...
Pulling docker image registry.example.com/my-target-app:latest ...
WARNING: Failed to pull image with policy "always": Error response from daemon: Get https://registry.example.com/my-target-app/manifests/latest: unauthorized (manager.go:237:0s)
ERROR: Job failed: failed to pull image "registry.example.com/my-target-app:latest" with specified policies [always]: Error response from daemon: Get https://registry.example.com/my-target-app/manifests/latest: unauthorized (manager.go:237:0s)

エラーメッセージ

  • GitLab 15.9 以前では、ERROR: Job failed: failed to pull image の後にError response from daemon: Get IMAGE: unauthorized.

解決方法

認証情報は、「非公開のコンテナレジストリからイメージにアクセスする」のセクションで説明されている方法で提供されます。使用する方法は、コンテナレジストリのプロバイダとその設定によって決まります。クラウドプロバイダー(Azure、Google Could(GCP)、AWS など)のようなサードパーティーが提供するコンテナレジストリを使用している場合は、プロバイダーのコンテナレジストリへの認証方法に関する情報をプロバイダーのドキュメントで確認してください。

以下の例では、静的に定義された認証情報を使用します。この例では、コンテナレジストリはregistry.example.com で、イメージはmy-target-app:latest です。

  1. DOCKER_AUTH_CONFIG データの決定方法 を読んで、DOCKER_AUTH_CONFIG の変数値の計算方法を理解してください。設定変数DOCKER_AUTH_CONFIG には、適切な認証情報を提供するためのDocker JSON設定が含まれています。例えば、非公開コンテナレジストリregistry.example.com に認証情報aGVsbG8gd29ybGQKでアクセスする場合、Docker JSONは以下のようになります:

    {
        "auths": {
            "registry.example.com": {
                "auth": "aGVsbG8gd29ybGQK"
            }
        }
    }
    
  2. CI/CD 変数としてDOCKER_AUTH_CONFIG を追加します。設定変数を.gitlab-ci.ymlファイルに直接追加する代わりに、プロジェクトCI/CD 変数を作成する必要があります。
  3. ジョブを再実行すると、静的に定義された認証情報が非公開コンテナレジストリregistry.example.com にサインインするために使用され、イメージmy-target-app:latest をプルできるようになります。成功すると、ジョブコンソールに次のような出力が表示されます:

    Running with gitlab-runner 15.6.0~beta.186.ga889181a (a889181a)
      on blue-4.shared.runners-manager.gitlab.com/default J2nyww-s
    Resolving secrets
    00:00
    Preparing the "docker+machine" executor
    00:56
    Using Docker executor with image registry.gitlab.com/security-products/api-security:2 ...
    Starting service registry.example.com/my-target-app:latest ...
    Authenticating with credentials from $DOCKER_AUTH_CONFIG
    Pulling docker image registry.example.com/my-target-app:latest ...
    Using docker image sha256:139c39668e5e4417f7d0eb0eeb74145ba862f4f3c24f7c6594ecb2f82dc4ad06 for registry.example.com/my-target-app:latest with digest registry.example.com/my-target-
    app@sha256:2b69fc7c3627dbd0ebaa17674c264fcd2f2ba21ed9552a472acf8b065d39039c ...
    Waiting for services to be up and running (timeout 30 seconds)...

サポートまたは改善要求

特定の問題についてサポートを受けるには、ヘルプを得るためのチャンネルをご利用ください。

GitLab.com の GitLab イシュー・トラッカーは、API セキュリティと DAST API に関するバグや機能提案に適した場所です。DAST API に関する新しいイシューを発行する際には~"Category:API Security" ラベルを使用し、適切な担当者が迅速にレビューできるようにしてください。レビュアーがいつレスポンスを受け取るかについては、レビュアーレポート SLOを参照してください。

自分自身の課題を提出する前に、類似のエントリがないかイシュー・トラッカーを検索してください。絵文字によるリアクションやディスカッションへの参加で、あなたのサポートを示しましょう。

期待通りに動作しない動作が発生した場合は、コンテキスト情報を提供することを検討してください:

  • セルフマネージドインスタンスを使用している場合は GitLab のバージョン。
  • .gitlab-ci.yml ジョブの定義
  • 完全なジョブコンソール出力。
  • gl-api-security-scanner.log という名前のジョブアーティファクトとして利用可能なスキャナログファイル。
caution
サポート・イシューに添付されたデータをサニタイズします。クレデンシャル、パスワード、トークン、キー、シークレットなどの機密情報を削除します。

用語解説

  • アサート:アサーションは、脆弱性をトリガーするためにチェックが使用する検出モジュールです。多くのアサーションには設定があります。チェックは複数のアサーションを使用することができます。例えば、「ログ解析」、「レスポンス解析」、「ステータスコード」は、検査で一緒に使用される一般的なアサーションです。複数のアサーションを使用する検査では、アサーションのオンとオフを切り替えることができます。
  • チェック:特定のタイプのテストを実行するか、脆弱性のタイプに対するチェックを実行します。例えば、SQL インジェクションチェックは、SQL インジェクション脆弱性に対する DAST テストを実行します。DAST API スキャナは複数のチェックで構成されています。チェックはプロファイルでオン/オフできます。
  • プロファイル:設定ファイルには 1 つ以上のテストプロファイル、あるいはサブ設定があります。機能ブランチ用のプロファイルと、メインブランチ用の特別なテスト用のプロファイルがあるかもしれません。