# ワークフロー

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

:::info

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

![](/docs/ja/_md-assets/58b466f0b6-workflows.png)

:::

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

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

![](/docs/ja/_md-assets/005ec9db77-how-workflows-work.ja.png)

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

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

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

```yaml
version: 0.1.0
id: "example-workflow"
triggers:
  schedule:
    # 10 分おきに実行
    - cron: "*/10 * * * *"
# ...
```

```yaml
version: 0.1.0
id: "example-workflow"
triggers:
  github:
    # デフォルトブランチへの push イベント時に実行
    - push:
        branches:
          - :default_branch
```

### 各ジョブの発火

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

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

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

![](/docs/ja/_md-assets/2aa0a73b37-decide-block.png)

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

![](/docs/ja/_md-assets/b7175a123e-notify-block.png)

### `decide` ブロックの実行

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

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

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

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

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

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

:::info
この GraphQL クエリに関わるドキュメントを閲覧したり、クエリ発行をお試しいただける [GraphQL Playground](https://cloud.shisho.dev/*/playground/query) を提供しております（α）。
:::

#### 評価結果の登録

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

![](/docs/ja/_md-assets/623135318e-findings.png)

#### ポリシーコードの実行

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

### `notify` ブロックの実行

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

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

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

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

#### ポリシーコードの実行

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

## ワークフローの作成

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

- [ワークフローの一覧画面](https://cloud.shisho.dev/*/workflows)中の「ワークフローを追加」ボタンから作成する
- `shishoctl workflow apply` コマンドから作成する

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

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

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

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

:::info
実際の再検査の実行方法については、[こちらのページ](/docs/ja/g/getting-started/review-findings.md#re-run) をご参照ください。
:::

:::warning
現在、本機能は限られた[リソース](/docs/ja/g/concepts/resource.md)に対してのみ実行可能です。今後、対応を拡大していく予定です。
:::

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

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

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

本機能では GraphQL クエリの実行時に GraphQL スキーマ内に付与されたディレクティブを参照し、もし対象のフィールドが以下の条件を満たし、対象の[リソース ID](/docs/ja/g/concepts/resource.md#resource-id)が指定されている場合、**一部の[リソース](/docs/ja/g/concepts/resource.md)のみ**取得します。

1. `@canBePartial` ディレクティブが付与されている
2. `@resource` ディレクティブにて[リソース種別](/docs/ja/g/concepts/resource.md#resource-kind)が示されている

```graphql
type GoogleCloudComputeEngine {

  ...

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

  ...

}
```

:::info
Shisho Cloud 内で定義された GraphQL ディレクティブの詳細については、[こちらのページ](/docs/ja/g/concepts/graphql.md#gql-directives) をご参照ください。
:::

ここで [リソース ID](/docs/ja/g/concepts/resource.md#resource-id)による対象[リソース](/docs/ja/g/concepts/resource.md)の指定について、もう少し詳しく説明します。

[「検査の再実行」](/docs/ja/g/getting-started/review-findings.md#re-run)セクションでお伝えした通り、本機能は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](/docs/ja/g/concepts/resource.md#resource-id) のプレフィックスは、[リソース種別](/docs/ja/g/concepts/resource.md#resource-kind)を示します。これにより、Shisho Cloud は受け取った[リソース ID](/docs/ja/g/concepts/resource.md#resource-id) を元に、どの GraphQL クエリ上のフィールドに対して、本機能を実行すべきか判断します。

1. `@canBePartial` ディレクティブが付与されているか
2. `@resource` ディレクティブにて[リソース種別](/docs/ja/g/concepts/resource.md#resource-kind)が示されているか
3. 対象の[リソース ID](/docs/ja/g/concepts/resource.md#resource-id)のプレフィックスが、`@resource` ディレクティブと一致するか

もし、上記の条件を全て満たす場合、検索条件として一意の識別子をデータソースに渡し、対象の[リソース](/docs/ja/g/concepts/resource.md)を絞り込み、一致する[リソース](/docs/ja/g/concepts/resource.md)のみ取得します。

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

[リソース ID](/docs/ja/g/concepts/resource.md#resource-id)による対象[リソース](/docs/ja/g/concepts/resource.md)の絞り込みに加え、`@locatable` ディレクティブを利用することにより、更に絞り込むことが可能です。

:::info
`@locatable` ディレクティブの詳細については、[こちらのページ](/docs/ja/g/concepts/graphql.md#locatable) をご参照ください。
:::

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

```graphql
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`）フィールドを特定するためのロケータ情報は、シナリオのハッシュ値です。
:::

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

ここまで[リソース](/docs/ja/g/concepts/resource.md)の絞り込みについて見てきましたが、ここで下記のケースを見てみましょう。

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

            ...

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

              ...

            }
          }
        }
      }
    }
  }
}
```

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

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

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

            ...

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

              ...

            }
          }
        }
      }
    }
  }
}
```

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

:::info
`@mustBeTotal` ディレクティブの詳細については、[こちらのページ](/docs/ja/g/concepts/graphql.md#mustbetotal) をご参照ください。
:::
