ワークフローのマニフェスト
ワークフローは YAML フォーマットで記述された マニフェ スト(Manifest) により定義されます:

このマニフェストを記述し、Shisho Cloud 上のワークフローを作成することで、監査・検査やその後の対応をコードとして定義できます。
大構造
ワークフローのマニフェストは、以下の 5 つから構成されます:
version: 定数 (0.1.0)id: ワークフローに対する一意な IDname: ワークフローのわかりやすい表示名triggers: ワークフローの実行タイミングの設定jobs: ワークフロー内で行う監査・監査やその後の対応の設定
つまり、ワークフローのマニフェストは、以下のようなフォーマットに従う YAML ファイルだということです:
version: 0.1.0
id: "example-workflow"
name: "Example"
triggers:
# ...
jobs:
# ....
トリガー
ワークフローは複数の トリガー を triggers ブロックとして定義します:
version: 0.1.0
id: "example-workflow"
# 複数のトリガーの定義
triggers:
# ...
1 つ 1 つのトリガーは、そのワークフローがいつ実行されるべきかを定義するものです。「一定時間おきにトリガーを実行する」といった時間に基づく定義や、「他サービスからの Webhook メッセージを受け取ったら実行する」というようなイベントに基づく定義が利用できます。
より具体的には、以下のようなトリガーを利用できます:
scheduleトリガーgithubトリガー
schedule トリガー
schedule トリガーは、cron フォーマットを用いてワークフローの実行タイミングを定義するためのトリガーです。
schedule トリガーには cron フォーマットでの実行タイミング設定を 1 つ以上含めることができ、少なくとも 1 つの cron 設定にマッチする時刻 にワークフローが実行されるようになります。
例えば、以下のようなトリガーを持つワークフローは 10 分おきに実行されます:
version: 0.1.0
id: "example-workflow"
triggers:
schedule:
# 10 分おきに実行
- cron: "*/10 * * * *"
# ...
以下は複数の cron 設定を含む schedule トリガーの例です:
version: 0.1.0
id: "example-workflow"
triggers:
schedule:
- cron: "*/10 * * * *"
- cron: "*/30 * * * *"
# ...
複数の cron 設定が、同一時刻でのワークフローの実行を指示する場合であっても、ワークフローの実行は 少なくとも 1 回 しか保証されません。
github トリガー
github トリガーは、GitHub から Shisho Cloud に対して届けられた Webhook メッセージを用いてワークフローの実行タイミングを定義するためのトリガーです。
github トリガーには、Webhook メッセージに基づくワークフローの実行条件を、1 つまたは複数個設定できます。
そのような設定のもと、GitHub から届いた Webhook メッセージ が少なくとも 1 つの設定にマッチする場合 にワークフローが実行されるようになります。
例えば、以下のようなトリガーを持つワークフローは、各リポジトリのデフォルトブランチに対する push イベントが発生した際に実行されます:
version: 0.1.0
id: "example-workflow"
triggers:
github:
- push:
branches:
- :default_branch
以下は複数の条件を含む github トリガーの例です:
version: 0.1.0
id: "example-workflow"
triggers:
github:
- push:
branches:
- :default_branch
- push:
branches:
- staging
GitHub が Webhook メッセージを通して配信するイベント情報のうち、Shisho Cloud は現在、以下のようなイベントを処理できます:
pushイベント (GitHub によるドキュメント)pull_requestイベント (GitHub によるドキュメント)
push イベントの処理
push イベントに基づきワ ークフローの実行を制御する場合、以下のようなフィルタをご利用いただけます:
organization: push 先のリポジトリが所属する GitHub Organization 名が、指定した文字列と一致するname: push 先のリポジトリ名が、指定した文字列と一致するpush.branches: 指定された パターン のうち、少なくとも 1 つに push 先のブランチ名が一致する- パターンと push 先ブランチ名を比較する際には、パターン中の以下の文字/文字列が特殊な挙動をとる
*:/を除く 1 文字以上の文字列にマッチ**: 1 文字以上の文字列にマッチ- 3 つ以上
*が続く場合:*が奇数個: 最後が/でない 1 文字以上の文字列*が偶数個: 1 文字以上の文字列にマッチ
- パターンが以下のどれかに完全一致する場合、一致の検証は特別な挙動をとる
:default_branch: パターンと push 先ブランチ名を比較する代わりに、当該リポジトリのデフォルトブランチ名と push 先ブランチ名を比較する
- パターンと push 先ブランチ名を比較する際には、パターン中の以下の文字/文字列が特殊な挙動をとる
push.branches_ignore: 指定された パターン のどれとも push 先のブランチ名が一致しない- パターン中では
branches同等の特殊文字・特殊な識別子が利用可能
- パターン中では
push.tags: 指定された パターン のうち少なくとも 1 つに push されたタグ名が一致する- パターンと push されたタグ名を比較する際には、パターン中の以下の文字/文字列が特殊な挙動をとる
*:/を除く 1 文字以上の文字列にマッチ**: 1 文字以上の文字列にマッチ- 3 つ以上
*が続く場合:*が奇数個: 最後が/でない 1 文字以上の文字列*が偶数個: 1 文字以上の文字列にマッチ
- パターンと push されたタグ名を比較する際には、パターン中の以下の文字/文字列が特殊な挙動をとる
push.tags_ignore: 指定された パターン のどれとも push されたタグ名が一致しない- パターン中では
tags同等の特殊文字が利用可能
- パターン中では
上述のフィルタが複数指定された場合は、それらは AND 条件として扱われます。つまり、全てのフィルタにマッチする場合のみ、ワークフローが実行されるようになります。
以下は上述のフィルタの利用例です:
triggers:
github:
# GitHub からの push イベントに基づきワークフローを実行する。ただし:
# - octcat/Hello-World に対する push イベントのみに反応する
# - staging ブランチ、または feat/ から始まるブランチにのみ反応する
- organization: "octcat"
name: "Hello-World"
push:
branches:
- staging
- feat/**
pull_request イベントの処理
pull_request イベントに基づきワークフローの実行を制御する場合、以下のようなフィルタをご利用いただけます:
organization: push 先のリポジトリが所属する GitHub Organization 名が、指定した文字列と一致するname: push 先のリポジトリ名が、指定した文字列と一致するpull_request.types:pull_requestイベントの種別が、指定したリストの中に含まれるpull_request.branches: 指定された パターン のうち、少なくとも 1 つにpull_requestのベースブランチ名が一 致する- パターンと
pull_requestの ベースブランチ名を比較する際には、パターン中の以下の文字/文字列が特殊な挙動をとる*:/を除く 1 文字以上の文字列にマッチ**: 1 文字以上の文字列にマッチ
- パターンが以下のどれかに完全一致する場合、一致の検証は特別な挙動をとる
:default_branch: パターンとpull_requestのベースブランチ名を比較する代わりに、当該リポジトリのデフォルトブランチ名とpull_requestのベースブランチ名を比較する
- パターンと
PULL_REQUEST.branches_ignore: 指定された パターン のどれともpull_requestのベースブランチ名が一致しない- パターン中では
branches同等の特殊文字・特殊な識別子が利用可能
- パターン中では
上述のフィルタが複数指定された場合は、それらは AND 条件として扱われます。つまり、全てのフィルタにマッチする場合のみ、ワークフローが実行されるようになります。
以下は上述のフィルタの利用例です:
triggers:
github:
# GitHub からの pull_request イベントに基づきワークフローを実行する。ただし:
# - octcat/Hello-World に対する pull_request イベントのみに反応する
# - synchronize, opened, reopened イベントにのみ反応する
- organization: "octcat"
name: "Hello-World"
pull_request:
types:
- synchronize
- opened
- reopened
ジョブ
ワークフローは複数の ジョブ(Job) を定義します:
version: 0.1.0
id: "example-workflow"
# 複数のジョブの定義
jobs:
# ....
一つ一つのジョブは以下を含んでいます:
id: ジョブのワークフロー内で一意な IDname: ジョブのわかりやすい表示名decide: どんなデータを・どのように検査/監査するかnotify(optional): ジョブ実行の各フェーズにおいて、どのように通知するか
decide ブロック
どんなデータを・どのように検査/監査するかを定義するために、ジョブは必ず一つの decide ブロックを含みます:
version: 0.1.0
id: "example-workflow"
jobs:
- id: "..."
name: "..."
# decide ブロック
decide:
# ...
構造
「どんなデータを・どのように検査/監査するか」のうち、「どんなデータを」の部分を定義するものとして、decide ブロックには必ず以下が含まれます:
inputブロック
「どのように検査/監査するか」の部分を定義するものとしては、を必ず以下の少なくとも一方が含まれます:
regoブロックusesブロック
図示すると、検査/監査の対象(画像左部分)と、検査/監査の方法(画像中央部分)を規定するのがこれら 2 つの要素です:

input ブロック
input ブロックは、GraphQL クエリの形で、検査/監査対象のデータを定義するものです。
Shisho Cloud は、このようなクエリの定義に従って各ジョブごとにデータを取得し、その取得したデータをポリシーコー ドに入力します。
jobs:
- decide:
input:
# GraphQL クエリ
schema: |
query {
...
}
GraphQL クエリの仕様確認や記述のためには、簡易的な Playground が利用できます。
以下に「連携済みの GitHub Organization やリポジトリ群」を取得するための GraphQL クエリの例を示します:
query {
github {
organizations {
login
metadata {
id
}
repositories {
metadata {
id
}
name
}
}
}
}
rego ブロック
rego ブロックはポリシー言語 Rego を用 いて、「どのように検査/監査するか」を規定するためのものです。
ポリシーは、ジョブ中の GraphQL クエリの定義通りに Shisho Cloud により取得されたデータを受け取ります。
そして、複数の Decision と呼ばれるデータを出力することで、Shisho Cloud に対して検査/監査の結果を伝達します。
Shisho Cloud は、この伝達されたデータを元に、セキュリティ状況の可視化や改善をサポートします。
より具体的には、Shisho Cloud と Rego で書かれたポリシーは、以下のような形で値のやり取りします:
- ポリシーへの入力: Rego 上の変数
input経由で与えられる - ポリシーからの出力: Rego 上の変数
decisions経由で行う
GraphQL クエリに従うデータのポリシーへの入力
Shisho Cloud は、ジョブ中の input ブロックで記述された GraphQL クエリを用いてデータを取得し、それをポリシーに入力します。取得されたデータは、input 変数 からアクセスできるようになっています。
例えば GitHub 組織の一覧を取得し、それに対して検査/監査を実施するために、ジョブ中の input ブロックで、以下のようなクエリを記述したとします:
query {
github {
organizations {
login
requiresTwoFactorAuthentication
}
}
}
このとき、Rego ポリシー中からアクセスできる input という変数に、以下のようなオブジェクトが格納されます:
{
"github": {
"organizations": [
{
"login": "octcat",
"requiresTwoFactorAuthentication": true
},
{
"login": "your-org-name",
"requiresTwoFactorAuthentication": false
}
]
}
}
そのため、以下のような記述を Rego ポリシー中で行うことにより、GraphQL クエリを用いて取得した GitHub 組織の一覧が取得できます:
input.github.organizations
もし各 GitHub 組織に関する requiresTwoFactorAuthentication の値(組織中のメンバーに二要素認証の使用を強制しているかを表す bool 値)を検証したい場合は、以下のように記述できます:
org := input.github.organizations[_]
allowed := org.requiresTwoFactorAuthentication == true
shishoctl コマンドを利用すると、記述した GraphQL クエリを元にポリシーに対するテスト入力を作成できます。
同コマンドは、Rego ポリシーを Open Policy Agent (OPA) コマンドでテストする場合に利用できます。
以下に jobs[].decide.rego ポリシーに対する入力として利用できる JSON 形式のテストデータを、GraphQL クエリから生成するコ マンドの例を示します:
shishoctl testcase generate \
--type decision \
--org (Shisho Cloud 組織の ID) \
--query-path (GraphQL クエリが格納されたファイルへのパス)
ポリシー記述に Rego 以外を利用している場合や、ポリシーの利用箇所が jobs[].notify 以下である場合も、上記のコマンドのオプションを変更することで対応できます。
詳しくは shishoctl testcase generate --help コマンドの出力を確認してください。