メインコンテンツまでスキップ

ワークフロー

Shisho Cloud における GitHub 上のリソースの検査や、評価結果(Findings)の登録は、全て「ワークフロー(Workflow)」により定義されています。

info

始めから定義されているワークフローは、画面上部バーの「ワークフロー(Workflow)」メニュー押下時に表示される、以下の画面からご閲覧いただけます:

ワークフローによる検査/監査の流れ

ワークフローによる検査/監査は、以下のような流れに従って行われます:

ワークフロー中のトリガーの発火

各ワークフローは トリガー(trigger) を定義しています。 トリガーとは、そのワークフローがいつ実行されるべきかを定義するものです。 Shisho Cloud は、このトリガの定義に従い、必要なときだけに必要なワークフローを実行します。

例えば、以下のようなマニフェストで定義されたワークフローは、それぞれ時間経過や非同期イベントの発生を起点に実行されます:

version: 0.1.0
id: "example-workflow"
triggers:
schedule:
# 10 分おきに実行
- cron: "*/10 * * * *"
# ...
version: 0.1.0
id: "example-workflow"
triggers:
github:
# デフォルトブランチへの push イベント時に実行
- push:
branches:
- :default_branch

各ジョブの発火

ワークフローは複数の ジョブ(Job) を定義しています。 一つ一つのジョブは以下のように、どんなデータを・どのように検査/監査するかを定義する decide ブロック と、ジョブ実行の各フェーズにおいて、何を・どのように通知するかを定義する notify ブロック を含んでいます:

jobs:
- id: notify
name: Notify Job Status
decide:
rego: |
# ...
input:
schema: |
# ...
notify:
input:
schema: |
# ...
rego: |
# ...

トリガーによりワークフローの実行が決定されたとき、Shisho Cloud は、まず decide ブロックの規定に従って、検査/監査データの生成・取得を実施します。

その傍ら、notify ブロックの規定に従って、必要に応じて外部サービス(GitHub や Slack 等)へ通知します。

decide ブロックの実行

ジョブの実行時の、decide ブロックの評価は、次の手順で行われます:

  1. データソースからのデータ取得
  2. ポリシーコードの実行

データソースからのデータ取得

各ジョブの decide ブロック 以下には、ポリシーコードに流し込むデータ、すなわち検査/監査対象のデータの定義として、GraphQL クエリの定義が含まれています。 例えば以下のようなものです:

query {
aws {
accounts {
metadata {
id
}
iam {
passwordPolicy {
passwordReusePrevention
}
}
}
}
}

Shisho Cloud は、このようなクエリの定義に従って各ジョブごとにデータを取得し、ポリシーコードにそれを流し込みます。 これによりお客様は、AWS, Google Cloud, GitHub 等の API に自力でアクセスしたり、そのデータを元に各種メトリクスや既知脆弱性情報との紐付けを行わなくても、簡単に検査/監査対象のデータをポリシーに流し込むことが出来ます。

info

この GraphQL クエリに関わるドキュメントを閲覧したり、クエリ発行をお試しいただける GraphQL Playground を提供しております(α)。

評価結果の登録

Shisho Cloud は、実行されたポリシーコードから出力されたの値を取りまとめ、評価結果(Finding)として記録します。 これにより、お客様は、ポリシーの評価結果をダッシュボード等の画面から閲覧できるようになります:

ポリシーコードの実行

Shisho Cloud は、GraphQL クエリにより定義されたデータの取得後、decide ブロックで定義された Rego ポリシーを実行します。

notify ブロックの実行

decide ブロックのジョブ実行と並行して、ジョブのステータスが変わるたびに、notify ブロックが次の手順で評価・実行されます:

  1. データソースからのデータ取得
  2. ポリシーコードの実行

データソースからのデータ取得

Shisho Cloud は、decide ブロックの評価時と同じように、notify ブロック中で定義された GraphQL クエリを元にポリシーへの入力を生成します。

ポリシーコードの実行

Shisho Cloud は、GraphQL クエリにより定義されたデータの取得後、decide ブロックで定義された Rego ポリシーを実行します。

ワークフローの作成

ワークフローは以下の 2 つの手段のどちらかで作成できます:

発展: ワークフロー実行の最適化

通常、一つのワークフローには複数のジョブが含まれ、そのジョブごとに全ての監査対象データに対して検査が行われますが、下記の機能の拡充により、検査の高速化を実現しています。

  • ワークフロー内に複数あるジョブに対して、一部のジョブのみを実行する機能
  • ワークフローのジョブ内で、一部の監査対象データのみを取得し、検査コードを実行する機能

本稿では主にデータ取得に関する最適化について説明します。なお、以下で度々言及している監査対象リソースとは監査対象データと同義です。リソースの定義については、こちらのページ をご参照ください。

info

実際の再検査の実行方法については、こちらのページ をご参照ください。

警告

現在、本機能は限られたリソースに対してのみ実行可能です。今後、対応を拡大していく予定です。

データソースからのデータ取得の最適化

ワークフロー内にある各ジョブの decide ブロックnotify ブロック 以下には、GraphQL クエリの定義が含まれ、基本的にはその定義に従って全てのリソースを取得し、ポリシーコードに流し込みます。例えば以下のクエリは、Google Cloud プロジェクト内の 全ての Compute Engine インスタンスを取得しています。

{
googleCloud {
projects {
computeEngine {
instances {
metadata {
id
displayName
}
shieldedInstanceConfiguration {
enableSecureBoot
}
}
} 
}
}
}

本機能では GraphQL クエリの実行時に GraphQL スキーマ内に付与されたディレクティブを参照し、もし対象のフィールドが以下の条件を満たし、対象のリソース IDが指定されている場合、一部のリソースのみ取得します。

  1. @canBePartial ディレクティブが付与されている
  2. @resource ディレクティブにてリソース種別が示されている
type GoogleCloudComputeEngine {

...

"""
All Google Cloud Compute Engine instances
"""
instances(
condition: GoogleCloudComputeEngineCondition
): [GoogleCloudComputeEngineInstance!]!
@resource(kind: "googlecloud-ce-instance")
@canBePartial

...

}
info

Shisho Cloud 内で定義された GraphQL ディレクティブの詳細については、こちらのページ をご参照ください。

ここで リソース IDによる対象リソースの指定について、もう少し詳しく説明します。

「検査の再実行」セクションでお伝えした通り、本機能はShisho Cloud コンソール上で実行可能ですが、内部的にはワークフロー実行時に対象のジョブ IDに加え、下記のようなリストが渡されています。

  • googlecloud-ce-instance|489621111111|asia-northeast1-b|5121584011111111111
  • googlecloud-ce-instance|489621111111|asia-northeast1-b|5121584011111111112
  • user-web-application|WA01J1C82HCBZWKN9M7R5TJ1GEDV

Shisho Cloud リソース ID のプレフィックスは、リソース種別を示します。これにより、Shisho Cloud は受け取ったリソース ID を元に、どの GraphQL クエリ上のフィールドに対して、本機能を実行すべきか判断します。

  1. @canBePartial ディレクティブが付与されているか
  2. @resource ディレクティブにてリソース種別が示されているか
  3. 対象のリソース IDのプレフィックスが、@resource ディレクティブと一致するか

もし、上記の条件を全て満たす場合、検索条件として一意の識別子をデータソースに渡し、対象のリソースを絞り込み、一致するリソースのみ取得します。

ロケータによる更なるリソースの絞り込み

リソース IDによる対象リソースの絞り込みに加え、@locatable ディレクティブを利用することにより、更に絞り込むことが可能です。

info

@locatable ディレクティブの詳細については、こちらのページ をご参照ください。

以下は例となりますが、Shisho Cloud 内でシナリオ(scenarios)フィールドは、「 Web アプリケーション」("user-web-application")の子リソースとして定義されています。

type Query {
"""
All data from web application integration
"""
webApps: [WebApp!]! @resource(kind: "user-web-application")
}

type WebApp {
"""
Scenarios that the finding relates to
"""
scenarios: [WebAppScenario!]! @locatable(parentKind: "user-web-application")

...
}

ワークフロー実行時に下記のようなリソースごとのロケータ情報を指定することにより、特定の Web アプリケーションに紐づくシナリオのみ取得できます。

  • user-web-application|WA01J1C82HCBZWKN9M7R5TJ1GEDV
    • dd6390cc9f7b1af728b78109f78b8034f9487624c77056cdab064e658df7b5f0
  • user-web-application|WA01J1C82HCBZWKN9M7R5TJ1GEDW
    • dd6390cc9f7b1af728b78109f78b8034f9487624c77056cdab064e658df7b5f1
info

ロケータ情報は各リソースごとに異なります。ちなみにシナリオ(scenarios)フィールドを特定するためのロケータ情報は、シナリオのハッシュ値です。

リソースの全件取得の明示

ここまでリソースの絞り込みについて見てきましたが、ここで下記のケースを見てみましょう。

{
aws {
accounts {
network {
vpcs {
routeTables { # 一部のルートテーブルを取得
id

...

}
}
}
ec2 {
instances {
vpc {
routeTables { # 一部のルートテーブルを取得
metadata {
id
}

...

}
}
}
}
}
}
}

この場合、もしリソースを絞り込むための条件が aws.accounts.network.vpcs.routeTables フィールドと aws.accounts.ec2.instances.vpc.routeTables フィールド、共に満たされていた場合、それぞれのフィールドに対して監査対象リソースの絞り込みが行われます。

しかしながら、全てのリソースをポリシーコードに流し込むべきケースもあるはずです。その場合、GraphQL クエリ上の対象フィールドに対して、 @mustBeTotal ディレクティブを付与することにより、全てのリソースを取得できます。

{
aws {
accounts {
network {
vpcs {
routeTables @mustBeTotal { # 全てのルートテーブルを必ず取得する
id

...

}
}
}
ec2 {
instances {
vpc {
routeTables { # 一部のルートテーブル取得を取得
metadata {
id
}

...

}
}
}
}
}
}
}

今後、既存のワークフローを改変する場合や、カスタムワークフローを作成する場合で、GraphQL クエリ内に同一のリソース種別を持つフィールドが複数ある場合は、このディレクティブの利用を必要に応じてご検討ください。

info

@mustBeTotal ディレクティブの詳細については、こちらのページ をご参照ください。