エビデンス

エビデンスの収集は、DevSecOps 参照アーキテクチャーの重要な側面の 1 つです。 コンプライアンス・エビデンスは、コンプライアンス監査のときに監査員が探す監査証跡となります。 DevSecOps の目標の 1 つは、エビデンスを生成して監査可能なエビデンス・ロッカーに保管することを自動で行うことです。

DevSecOps、パイプラインがエビデンス(ファイル形式とロッカー構造)を扱う方法は以下の通りである:

エビデンスの作成

エビデンスは、単体テストの結果や、XML ファイルまたは JSON ファイルなどの、パイプラインのステージのステップで作成される成果物とは異なります。 各タスクは、エビデンスの作成、形式設定、および保管などのエビデンスの処理を行う複数のツールに対して報告をしなければなりません。

一般的なテスト、検査、またはスキャンでは、以下の図に示す DevSecOps ツールまたはパイプライン内のステップを使用することで、パイプラインのステージ内でエビデンスを生成することができます。 DevSecOps ツールは、タスクの結果を受け取り、証拠を作成し、それを証拠品ロッカーに保管できなければならない。

証拠作成
証拠作成

エビデンスの形式には、タスクの結果 (合格または不合格)、作成された成果物へのリンク、タスクの結果に基づいて作成されたインシデント Issue へのリンクが含まれます。

これらのツールは、エビデンスの収集のみに特化しており、ビルド・プロセスの動作は変更しません。 タスクの結果が失敗でも、そのせいで DevSecOps 参照パイプラインが中断するということはありません。 検査と失敗のエビデンスが存在し、チームに通知され、デプロイメントの際に作成される変更要求にこれらの問題のエビデンスが示され、その変更要求が手動で承認されれば、失敗したテストや脆弱性があってもイメージをビルドしてデプロイすることは可能です。

エビデンスのフロー

以下の図は、エビデンスがどのように扱われ、継続的インテグレーションと継続的デプロイの段階をどのように流れるかを示している。

エビデンスフロー
エビデンスフロー

DevOps アーキテクチャーのさまざまなステージで収集される個々のエビデンスが、監査可能なエビデンス・ロッカーに保管されます。 デプロイメントの際は、このエビデンスが収集されてエビデンス・サマリーが作成され、それがデプロイメント実行の終わりにエビデンス・ロッカーに保存されます。

エビデンス・サマリーが変更要求にアタッチされ、変更要求ストアに送信されます。 変更要求を手動で承認するとき、承認者はビルド時に見つかった問題を認識します。

v2 エビデンス (現行フォーマット)

v2 エビデンス・ロッカー

証拠はフラットな階層構造で保存され、各証拠はそれ自身の SHA256 ハッシュによって識別される。これは完全性保護のレイヤーを提供する(つまり、証拠内容のいかなる変更も検出できる)。 各証拠は1つ以上の資産に関連しているため、証拠要約アルゴリズムは資産に基づいて関連する証拠を発見する。

唯一の階層は、タイプの差異化と、 Git ハッシュ・オブジェクトの構造に類似したハッシュ・グループ化です。

.
└── raw/
    ├── assets/
    │   └── xx/
    │       └── abcdef123456789/
    │           ├── evidences/
    │           │   ├── 00abcdef123456789
    │           │   └── 01abcdef123456789
    │           └── index.json
    ├── attachments/
    │   ├── aa/
    │   │   └── abcdef123456789/
    │   │       └── content
    │   └── ab/
    │       └── abcdef123456789/
    │           └── content
    ├── cd/
    │   ├── c9b77749-fd59-4d32-bbdb-18e55db1615d/
    │          └── summary.json
    |          └── evdience-checks.json
    ├── cc/
    │   ├── absd7749-fd59-4d32-bbdb-18e55db1615d/
    │          └── summary.json
    |          └── evdience-checks.json              
    └── evidences/
        ├── 00/
        │   └── abcdef123456789/
        │       └── index.json
        └── 01 /
            └── abcdef123456789/
                └── index.json      

v2 エビデンス収集

v2 のエビデンスは、エビデンスの結果を作成したプロセスにできるだけ近い場所で収集する必要があります。 各スキャンの実行後 (例えば、各テストの後)。

証拠を収集するために、collect-evidence スクリプトをDevSecOpsパイプラインで使用することができる。

v2 エビデンス・フォーマット

エビデンスの一部は、スキャン、テストなどの結果を表します。 エビデンスは常に、少なくとも 1 つの資産に接続されます。 複数の資産が許可されます。例えば、複数の資産を一緒にテストする可能性が高い単一のエンドツーエンド・テスト・スイートなどです。

アセットは、テストやスキャンなどが可能なものを表します。例えば、リポジトリー内の Git commit 、Docker image、または URI を持つ任意の generic アセットなどです。

Evidence タイプと Asset タイプは、 v2 ロッカー・エレメント (エビデンスとアセット) のスキーマを表します。 このスキーマでは Typescript 構文が使用されていますが、JSON スキーマを使用するものにこれを変換することができます。

type SHA1 = string;          // 40 character string representing a SHA-1 hash in hexadecimal format
type SHA256 = string;        // 64 character string representing a SHA256 hash in hexadecimal format
type IssueURL = string;      // Link to issues on a git service provide like GitHub or GitLab
type RepositoryURL = string; // Link to a git repository
type AssetURI = string;      // URI of an Asset, like an image or a repository link and git hash
type FileName = string;      // file basename of the attachment


interface Evidence {
  version: 2;
  id: SHA256;
  date: string;
  evidence_type_id: string;
  evidence_type_version: string;
  origin: {
    // scope defines a contextual set for multiple evidence, usually a SHA256 identifier or a CI/CD run ID
    scope: SHA256;  

    // any further IDs can be used to determine evidence origin, see example
    [index: string]: string;
  },
  details: {
    result: 'success' | 'failure' | 'pending';
    tool: string;

    // field "details" can have any arbitrary key-value pairs to provide metadata
    [index: string]: string;
  }
  attachments: Record<string, string> | EvidenceAssetAttachment[];
  assets: string[] | EvidenceAssetAttachment[];
  issues: IssueURL[],
  findings?: IncidentFinding[];
}

export interface IncidentFinding {
  id: string;
  url: string;
  due_date: string;
  first_found?: string;
  severity: ("high", "medium", "low", "critical, "informational");
  has_exempt: boolean;
  found_status: ("new", "existing", "autoclosed", "readonly");
}

export interface EvidenceAssetAttachment {
  url: string; // hash of the asset or attachment
  hash: string; // complete url of the asset or attachment
  uri?: string; // name of the asset
}

interface Asset {
    version: 1;
    id: SHA256;
    uri: AssetURI;
    date: string;
    type: 'commit' | 'image' | 'generic';
    origin: {
      // any IDs can be used to determine asset origin, see example
      [index: string]: string;
    },
    details: Record<string, string>,

    // Assets can relate to each other, for example
    // an Image Asset can relate to the Git Commit Asset
    // it was built from on code level
    related: SHA256[];
}

v2 資産の例
{
  "version": "1",
  "id": "cdd3ee20188d2f5bfb7f14bdb9c7fa99b22184ca195d9fa0a953dfbe9b1769cb",
  "uri": "https://github.com/<org-name>/e2e-hello-compliance-app-20220412084808399.git#8c2a65373cb4fd27bccff646e8bdf63d02cae856",
  "origin": {
    "toolchain_crn": "crn:v1:bluemix:public:toolchain:us-south:a/40111714589c4f7099032529b26a7a63:fd3f2bf6-00f1-417f-b1a2-7df894223115::",
    "pipeline_run_id": "a5e89ecc-a413-4dcb-b129-ff870ef3be85",
    "pipeline_id": "66b583d9-3d1b-4b34-9e3a-cb807bf0c5ab"
  },
  "details": {
    "sha": "8c2a65373cb4fd27bccff646e8bdf63d02cae856",
    "repository": "https://github.com/<org-name>/e2e-hello-compliance-app-20220412084808399.git"
  },
  "date": "2022-04-20T09:26:46.226Z",
  "type": "commit",
  "related": [
    "26a0f02126461e6505d5001d50ac71e585c280479a01cc70e36397a784440bf8"
  ]
}
v2 エビデンスの例
{
  "version": "2",
  "id": "3fd209270fbaf46137ec3966affac2a431a835e750301c7c44d583e0e426e29e",
  "date": "2022-04-20T09:33:43.782Z",
  "evidence_type_id": "com.ibm.code_vulnerability_scan",
  "evidence_type_version": "1.0.0",
  "details": {
    "result": "failure",
    "tool": "cra"
  },
  "origin": {
    "toolchain_crn": "crn:v1:bluemix:public:toolchain:us-south:a/779c0808c946b9e15cc2e63013fded8c:68213c68-4794-4d5e-ab50-f33d0d6190e4::",
    "pipeline_id": "c17f18a6-24dd-4949-abb7-2b374f4691b6",
    "pipeline_run_id": "d7a88836-72a1-402b-bb28-701439a543ae",
    "pipeline_run_url": "https://cloud.ibm.com/devops/pipelines/tekton/c17f18a6-24dd-4949-abb7-2b374f4691b6/runs/d7a88836-72a1-402b-bb28-701439a543ae/code-compliance-checks/run-stage/?env_id=ibm:yp:us-south",
    "scope": "117458e26512b0308d93cf6852958e5e875294a982d2b4ea2e9f463b4551a846"
  },
  "assets": [
    {
      "hash": "cdd3ee20188d2f5bfb7f14bdb9c7fa99b22184ca195d9fa0a953dfbe9b1769cb",
      "uri": "https://github.com/<org-name>/e2e-hello-compliance-app-20220412084808399.git#8c2a65373cb4fd27bccff646e8bdf63d02cae856",
      "url": "https://s3.private.us-south.cloud-object-storage.appdomain.cloud/test/assets/cdd3ee20188d2f5bfb7f14bdb9c7fa99b22184ca195d9fa0a953dfbe9b1769cb/index.json"
    }
  ],
  "issues": [
    "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/1",
    "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/2",
    "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/3",
  ],
  "findings": [
    {
      "id": "CVE-2022-42011",
      "due_date": "2024-04-20",
      "severity": "medium",
      "first_found": "2024-03-06",
      "url": "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/3",
      "found_status": "new",
      "has_exempt": true
    },
    {
      "id": "CVE-2022-42010",
      "due_date": "2024-04-20",
      "severity": "medium",
      "first_found": "2024-03-06",
      "url": "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/1",
      "found_status": "existing",
      "has_exempt": false
    },
    {
      "id": "CVE-2023-34969",
      "due_date": "2024-04-20",
      "severity": "medium",
      "first_found": "2024-03-06",
      "url": "https://github.com/<org-name>/e2e-compliance-incident-issues-20220412084808401/issues/2",
      "found_status": "existing",
      "has_exempt": true
    }
  ],
  "attachments": [
    {
      "hash": "9a841ef856a5de813dbe440b102b9bff3ca1831630292cff7323c557704f386b",
      "url": "https://s3.private.us-south.cloud-object-storage.appdomain.cloud/test/assets/9a841ef856a5de813dbe440b102b9bff3ca1831630292cff7323c557704f386b/index.json"
    }
  ]
}

v2 のエビデンスの要約

DevSecOps パイプラインは、エビデンスのサマリー文書を作成します。 この文書には、イメージをデプロイする各継続的インテグレーションのビルド中に作成されるすべてのエビデンスと、デプロイそのもの中に作成されるエビデンスの最新のものが含まれています。 この要約は、任意のステージをデプロイするために必要な変更要求に対して作成されます。

interface Summary {
  version: '2.0';                // schema version
  date: string;                  // ISO-8601, UTC, ie. YYYY-MM-DDThh:mm:ssZ
  toolchain_crn: string;         // CRN of the toolchain that generated the summary
  pipeline_id: string;           // ID of the pipeline that generated the summary
  pipeline_run_id: string;       // ID of the pipeline run that generated the summary
  evidences: Evidence[];
}

この要約では、結果の集約は実行されません。 変更要求に関連する資産について発見された、 v2 の証拠として収集された生のデータです。