# GraphQL によるデータ取得

Shisho Cloud では、リソースの検査や、評価結果（decision）の登録は、ワークフローにて定義されています。また、その検査に必要な検査/監査対象のデータに関しては、ワークフロー内に GraphQL クエリ形式で定義されています。本ページでは、Shisho Cloud における GraphQL の仕様について説明します。なお、ワークフローの詳細については、[こちらのページ](/docs/ja/g/concepts/workflow.md) で詳しく説明しているので、参照してください。

:::info
GraphQL は API 向けに作られたクエリ言語で、クライアントが必要とするデータのみを取得できるなど、柔軟なアプローチが特徴です。詳しくは [GraphQL (英語)](https://graphql.org/)をご参照ください。
:::

## ワークフローと GraphQL クエリ

ワークフローは複数の ジョブ（Job）を持ち、各ジョブの `decide/notify` ブロック に、`input` ブロックがあります。その `input` ブロックに記述されているのが GraphQL クエリで、検査/監査対象のデータを定義しています。 Shisho Cloud は、このようなクエリの定義に従って各ジョブごとにデータを取得し、その取得したデータをポリシーコードに入力します。

```yaml
jobs:
  - id: example
    name: Example Job
    decide:
      input:
        schema: |
          query {
            ...
          }
  - id: notify
    name: Notify Job Status
    decide:
      input:
        schema: |
          query {
            ...
          }
```

例えば以下の GraphQL クエリは、AWS アカウント内の VPC がデフォルトかどうかを示す `isDefault` を取得しています。

```yaml
jobs:
  - id: example
    name: Example Job
    decide:
      input:
        schema: |
          query {
            aws {
              accounts {
                network {
                  vpcs {
                    metadata {
                      id
                    }
                    isDefault
                  }
                }
              }
            }
          }
```

## GraphQL クエリの検索条件

通常、リソースは全件取得されますが、 いくつかのフィールドでは特定のリソースのみを取得するための検索条件（`condition`）を指定できる`input`フィールドを持ち、これにより特定のリソースのみ取得できます。

下記のケースでは、`AWSNetworkCondition` を利用し、特定のリージョン（`regions`）、`ap-northeast-1`, `us-west-2`の 「AWS VPC リソース」（`"aws-vpc"`）のみを取得できます。

```graphql
type AWSNetwork {
  """
  VPC networks
  """
  vpcs(condition: AWSNetworkCondition): [AWSVPC!]!
    @resource(kind: "aws-vpc")

  ...

}

input AWSNetworkCondition {
  """
  Regions of networks

  If no list is specified (i.e. null), this field returns networks in *any* zone.
  """
  regions: [AWSRegion!] @testdata(constraint: { array: { length: 2 } })
}

```

```yaml
jobs:
  - id: example
    name: Example Job
    decide:
      input:
        schema: |
          query {
            aws {
              accounts {
                network {
                  vpcs (condition: { regions: ["ap-northeast-1", "us-west-2"] }){
                    metadata {
                      id
                    }
                    isDefault
                  }
                }
              }
            }
          }
```

## `shishoctl` CLI による GraphQL クエリの実行

`shishoctl` CLI は Shisho Cloud を操作するための CLI です。 様々なコマンドを用意していますが、その中には GraphQL クエリを実行するためのコマンドもあります。

```sh
 shishoctl query run --org <ORGANIZATION_ID> <GRAPHQL_QUERY_FILE_NAME>.graphql
```

例えば、以下のようなコマンドを実行することで、`shisho-cloud-demo`という組織に対して、 `example.graphql` というファイルに記述された GraphQL クエリを実行できます。

```sh
shishoctl query run --org shisho-cloud-demo example.graphql
```

```graphql title="example.graphql"
query {
  aws {
    accounts {
      network {
        vpcs {
          metadata {
            id
          }
          isDefault
        }
      }
    }
  }
}
```

:::info
`shishoctl` CLI についての詳細は、[こちら](/docs/ja/c/accessing-via-shishoctl-cli/index.md) をご参照ください。
:::

## 発展: GraphQL ディレクティブ（directives） {#gql-directives}

Shisho Cloud は GraphQL をスキーマ/クエリ言語として採用し、ユーザーが検査/監査したいデータを簡単に定義・取得できるようにしています。いま、スキーマにはいくつかの GraphQL ディレクティブ（directive）が定義されており、これによりスキーマからデータ取得ロジックの仕様が読み解きやすいようになっています。また、クエリ時にも Shisho Cloud 独特の GraphQL ディレクティブを用いて、検査/監査データ取得の挙動をカスタマイズできるようになっています。

本セクションでは、Shisho Cloud が対応している GraphQL ディレクティブについて説明します。

:::info
なお、下記の説明文において、リソースというキーワードが出てきます。Shisho Cloud では 監査対象データのエンティティを**リソース**と定義しています。リソースの詳細については、[こちら](/docs/ja/g/concepts/resource.md) をご参照ください。
:::

### GraphQL スキーマ内に付与されたディレクティブ

GraphQL ディレクティブは、GraphQL スキーマ内の GraphQL オブジェクトやフィールドに対して付与されることがあります。Shisho Cloud においても同様で、スキーマ内におけるディレクティブは、主にオブジェクトやフィールドの仕様を表現するために用いられています。以下では Shisho Cloud で定義されている GraphQL ディレクティブのうち、主としてスキーマで用いられる想定のものを列挙します。

#### `@resource`

`@resource` ディレクティブはリソースの種別（resource kind）を明示するために利用されます。以下の例では、`vpcs` フィールドが、Shisho Cloud 内で「AWS VPC リソース」（`"aws-vpc"`）として扱われるリソースを返却することがスキーマ内で明示されています。

```graphql
type AWSNetwork {
  """
  VPC networks
  """
  vpcs(condition: AWSNetworkCondition): [AWSVPC!]!
    @resource(kind: "aws-vpc")

  ...

}
```

#### `@canBePartial`

`@canBePartial` ディレクティブは、リソースの一部のみを取得できるかどうかを示すために利用されます。このディレクティブがスキーマ上で付与されたフィールドに対しては、ある方法でクエリ発行時に リソース ID を指定することで、当該リソースに関するデータのみが取得できるようになります。この方法は「 GraphQL クエリの検索条件」セクションで説明した検索条件（`condition`）とはまた別の形で、取得するリソースを絞り込む仕組みで、Shisho Cloud が再診断を高速に提供するために暗黙のうちに利用されています。

:::info
再診断や対象リソースの指定方法など、詳細を確認したい場合は [こちらのページ](/docs/ja/g/getting-started/review-findings.md) をご参照ください。
:::

以下の例では、VPC リソース一覧の一部のみを取得できることを示しています。

```graphql
type AWSNetwork {
  """
  VPC networks
  """
  vpcs(condition: AWSNetworkCondition): [AWSVPC!]!　@canBePartial

  ...

}

```

#### `@locatable` {#locatable}

`@locatable` ディレクティブは、付与されたフィールドのロケーションを指定することで、リソースを絞り込めるかどうかを明示します。このディレクティブは `parentKind` フィールドを持ち、**親リソース**の種別（resource kind）が併せて明示されています。

以下は例となりますが、Shisho Cloud 内でシナリオ（`scenarios`）フィールドは、「 Web アプリケーションリソース」（`"user-web-application"`）の**子リソース**として定義されています。また、シナリオ（`scenarios`）フィールドに対して、`@locatable` ディレクティブが付与されており、シナリオを絞り込むためのロケーション情報を指定することで、特定の Web アプリケーションリソースに紐づくシナリオのみを取得できます。

```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")

  ...
}
```

#### `@testdata`

`@testdata` ディレクティブは、[GraphQL クエリのテスト用 Playground](https://cloud.shisho.dev/*/playground/query) で利用されているテストデータの生成に関わる情報が定義されています。そのため、実際の[ワークフロー](/docs/ja/g/concepts/workflow.md) には影響せず、あくまでテスト用 Playground に関する仕様です。なお、以下の例では、`minimumTtl` フィールドに対して、10 から 60 の範囲でテストデータを生成することを示しています。

```graphql
type AWSCloudFrontCachePolicyConfiguration {
  """
  The minimum amount of time, in seconds, that you want objects to stay in the CloudFront cache before CloudFront sends another request to the origin to see if the object has been updated
  """
  minimumTtl: Int64! @testdata(constraint: { int: { min: 10, max: 60 } })

  ...

}
```

### GraphQL クエリ内で利用できるディレクティブ

GraphQL クエリ内でもいくつかのディレクティブが利用でき、これにより GraphQL クエリの評価時に特別な挙動を引き起こせます。以下では、GraphQL クエリ内で利用できるディレクティブを列挙します。

#### `@mustBeTotal` {#mustbetotal}

`@mustBeTotal` ディレクティブは、クエリの実行時に必ず全てのデータが取得される必要があることを宣言するためのものです。

通常、GraphQL クエリの実行時はリソースは全件取得されますが、Shisho Cloud の再診断機能を始めとした一部の機能は不必要なデータ取得を避けるような最適化を暗黙的に実施することがあります。したがって、GraphQL クエリの結果を処理する Rego 等のポリシーコードは、必ずしも全てのデータが取得されない前提で記述せねばなりません。

一方、ポリシーの判定ロジックの都合上、常にデータ全件が必要な場合もあります。クエリ発行時に、そのような制約の表明に利用できるのがこのディレクティブです。

以下の例では、全てのVPC 傘下のルートテーブル （`aws.accounts.network.vpcs.routeTables`）取得に関して、全て取得するよう要求しています。対して、 EC2 インスタンスに紐づく VPC のルートテーブル（`aws.accounts.ec2.instances.vpc.routeTables`）に関しては、その限りではありません。

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

            ...

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

              ...

            }
          }
        }
      }
    }
  }
}
```
