# データの部分取得

通常、一つのワークフローには**複数のジョブ**が含まれ、そのジョブごとに**全ての監査対象データ**に対して検査が行われます。そのため、ワークフローに複数のジョブが含まれる場合や、監査対象データが多いケースでは検査に時間がかかる可能性があります。

Shisho Cloudでは下記の機能の拡充により、検査の高速化を実現しています。

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

本稿ではデータ取得に関する最適化について説明します。なお、現在、データの部分取得機能については、ワークフローの部分実行時に特定条件が満たされると、自動的に適用される機能となっています。ワークフローの特定のジョブのみを実行する方法については、[こちらのページ](/docs/ja/g/concepts/partial-workflow-execution.md) をご参照ください。

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

:::info
以下で度々言及している監査対象リソースとは監査対象データと同義です。リソースの定義については、[こちらのページ](/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 クエリと GraphQL スキーマ上に付与されているそれぞれのディレクティブを参照し、もし対象のフィールドが以下の条件を満たし、対象の[リソース ID](/docs/ja/g/concepts/resource.md#resource-id)が指定されている場合、**一部の[リソース](/docs/ja/g/concepts/resource.md)のみ**取得します。

1. GraphQL スキーマ上の対象フィールドに`@canBePartial` ディレクティブが**付与されている**
2. GraphQL スキーマ上の対象フィールドに`@resource` ディレクティブを用いて[**リソース種別**](/docs/ja/g/concepts/resource.md#resource-kind)が示されている
3. GraphQL クエリ上の対象フィールドに`@mustBeTotal` ディレクティブが**付与されていない**

3の`@mustBeTotal` ディレクティブについては、[リソースの全件取得の明示](/docs/ja/g/concepts/partial-data-fetch.md#partial-fetch-total)セクションにて詳細を説明します。

```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) をご参照ください。
:::

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

データの部分取得機能によるの監査対象[リソース](/docs/ja/g/concepts/resource.md)の絞り込みについて説明してきました。一部の[リソース](/docs/ja/g/concepts/resource.md)については、 GraphQL スキーマ内の対象フィールドに付与される`@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 アプリケーションに紐づくシナリオのみ**取得できます。

### リソースの全件取得の明示 {#partial-fetch-total}

ここまで[リソース](/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) をご参照ください。
:::

## まとめ

データの部分取得機能については、ワークフローの部分実行時に特定条件が満たされると、自動的に適用される機能となっています。そのため、ユーザーにて特に意識せずとも、普段通りにワークフローを書いていただければ、自動的に最適化されます。また、`@mustBeTotal` ディレクティブを用いて、明示的にデータの部分取得機能を回避する方法も用意しています。ぜひ、ご利用ください。
