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

イベントを通知する

このチュートリアルでは、Shisho Cloud 上で起こったイベントを各種通知先に通知するための、ポリシーの記述とデプロイ方法を説明します。 その具体例として、連携済みの GitHub 組織内のリポジトリの、デフォルトブランチ上からの依存が発見された既知脆弱性情報の数を、事前に作成した通知グループに対して通知する方法を紹介します。

ゴール

  • Shisho Cloud における通知のポリシーによる制御方法を知る
  • 作成したポリシーのデプロイ方法を知る

準備

このページ を参照し、同ページ中の ./shisho-cloud-workflows ディレクトリ同等の構造のディレクトリを用意してください。 具体的には、以下のような構造のディレクトリです:

./shisho-cloud-workflows
├── lib
│ ├── README.md
│ ├── decision
│ │ ├── dependency
│ │ │ ├── package.gen.rego
│ │ │ ├── package.pb.rego
│ │ │ └── vulnerability.rego

...

├── prebundle-workflow-github-regularly
│   ├── manifest.yaml
│   ├── review-regularly
│   │   └── decide
│   │   ├── input.graphql
│   │   ├── policy.rego
│   │   └── policy_test.rego
...

ワークフロー中のポリシーを修正する

以降では、以下のディレクトリ以下でファイルを作成・編集していくことを通して、デフォルトブランチ上からの依存が発見された既知脆弱性情報の数を通知できるよう設定していきます。

prebundle-workflow-github-regularly

manifest.yaml

現状は同ディレクトリ内の manifest.yaml は、以下のように review-regularly/decide/policy.rego 等で定義されたジョブを通して、既知脆弱性情報を検査・処理しています。

id: prebundle-workflow-github-regularly
name: "Prebundle: Review Contents on GitHub (Scheduled)"
version: 0.1.0
triggers:
schedule:
- cron: 0 */6 * * *
jobs:
# ...

- id: review-regularly
name: Review all regularly
decide:
rego: !include review-regularly/decide/policy.rego
input:
schema: !include review-regularly/decide/input.graphql
# ...

ワークフロー機能についての項 で述べられているように、Shisho Cloud にワークフロー機能中から通知を行うように指示する(notify ブロックを定義する)ことで、任意の通知を送ることができます:

以降では、同ジョブに notify ブロックを定義することで、通知設定を行うことにします。

review-regularly/notify/input.graphql

まずは review-regularly/notify/input.graphql に、以下のような内容の GraphQL クエリを保存しましょう:

query {
github {
organizations {
login

repositories {
policyReportId
name

defaultBranchRef {
target {
id
packages(condition: { onlyVulnerablePackages: true }) {
name
version
found_at

vulnerabilities {
reference {
id
namespace
}
constraint

description
advisories {
link
}

severity
}
}
}
}
}
}
}
}

このクエリは、Shisho Cloud 中に連携されている GitHub 組織が持つ、すべての GitHub リポジトリを列挙します。 その上で、そのデフォルトブランチ内で検出された既知脆弱性を持つパッケージを取得します。

review-regularly/notify/policy.rego

次に、review-regularly/notify/policy.rego に、以下のような内容の Rego ポリシーを作成しましょう:

info

target_notification_group 定数の値は、予め作成した通知グループの ID に置換してください。

package policy.prebundle_workflow_github_regularly.review_regularly.notify

import data.shisho

target_notification_group := "id-of-notification-group"

notifications[n] {
input.running_state == shisho.job.running_state_completed

org := input.query.github.organizations[_]
repo := org.repositories[_]
pkgs := repo.defaultBranchRef.target.packages

# notify only if there's at least one known vulnerability
total_int := count([v |
p := pkgs[_]
v := p.vulnerabilities[_]
])
total_int > 0

# compute data to notify
total := format_int(total_int, 10)

critical := format_int(
count(vulnerabilities_filtered_by_severity(pkgs, "Critical")),
10,
)
high := format_int(
count(vulnerabilities_filtered_by_severity(pkgs, "High")),
10,
)
medium := format_int(
count(vulnerabilities_filtered_by_severity(pkgs, "Medium")),
10,
)
low := format_int(
count(vulnerabilities_filtered_by_severity(pkgs, "Low")),
10,
)
info := format_int(
count(vulnerabilities_filtered_by_severity(pkgs, "Info")),
10,
)

# construct a notification message
msg := concat("", [
"The number of known vulnerabilities in default branches of ", org.login, "/", repo.name , ": ", total, "\n",
"- Critical: ", critical, "\n",
"- High: ", high, "\n",
"- Medium: ", medium, "\n",
"- Low: ", low, "\n",
"- Info: ", info, "\n",
"- To suppress this sort of comments for this pull request, visit to the workflow configuration page: http://cloud.shisho.dev/", input.organization_id, "/workflows/edit?wfid=", input.workflow_id, "\n",
])

# construct the notification target
target := shisho.notification.to_notification_group(target_notification_group)

# construct a notification
n := shisho.notification.new(target, msg)
}

# utilities
############

patterns_matched_with(target, patterns) = x {
x := [p |
p := patterns[_]
glob.match(p, ["/"], target)
]
}

vulnerabilities_filtered_by_severity(pkgs, severity) = x {
x := [v |
pkg := pkgs[_]
v := pkg.vulnerabilities[_]
v.severity == severity
]
}

このポリシーは、Rego インラインポリシーに関する API で定義された入力を受け取り、同じく同 API の期待通りに Notification オブジェクトnotifications 変数に出力することで、Shisho Cloud に通知の送信を指示するものです。

review-regularly/notify/policy_test.rego

その上で、review-regularly/notify/policy_test.rego に、作成した Rego ポリシーの単体テストを格納しておきましょう:

package policy.prebundle_workflow_github_regularly.review_regularly.notify

import data.shisho
import future.keywords

testdata_with_repo(login, name) := x if {
x := {"github": {"organizations": [{
"login": login,
"repositories": [{
"name": name,
"policyReportId": "dummy",
"defaultBranchRef": {"target": {
"id": "xxx",
"packages": [
{
"name": "awesome-package-name",
"version": "0.3.0",
"found_at": "sub-directory/package.json",
"vulnerabilities": [{
"reference": {
"id": "CVE-XXXX-XXXX",
"namespace": "nve",
},
"constraint": "xxxx",
"description": "xxxx",
"advisories": {"link": "xxxx"},
"severity": "Critical",
}],
},
{
"name": "awesome-package-name-two",
"version": "0.3.0",
"found_at": "sub-directory/package.json",
"vulnerabilities": [{
"reference": {
"id": "CVE-XXXX-XXXX",
"namespace": "nve",
},
"constraint": "xxxx",
"description": "xxxx",
"advisories": {"link": "xxxx"},
"severity": "Low",
}],
},
],
}},
}],
}]}}
}

test_notification if {
count([n |
notifications[n]
]) == 1 with input as {
"running_state": shisho.job.running_state_completed,
"organization_id": "org-a",
"workflow_id": "workflow-b",
"query": testdata_with_repo("ignored-org", "unignored-repo"),
}

count([n |
notifications[n]
trace(n.message)
message_contains(n, "Critical: 1")
message_contains(n, "High: 0")
message_contains(n, "Medium: 0")
message_contains(n, "Low: 1")
message_contains(n, "Info: 0")
]) == 1 with input as {
"running_state": shisho.job.running_state_completed,
"organization_id": "org-a",
"workflow_id": "workflow-b",
"query": testdata_with_repo("ignored-org", "unignored-repo"),
}
}

message_contains(n, message) if {
contains(n.message, message)
} else = false if true

記述したテストは、Open Policy Agent をインストール した後に以下のようなコマンドを実行することで、実際に実行することができます:

# in your ./shisho-cloud-workflows
opa test ./prebundle-workflow-github-regularly/review-regularly/notify ./lib --verbose

ここまでのステップが適切に実行できていれば、以下のようにテストが PASS するはずです:

prebundle-workflow-github-regularly/review-regularly/notify/policy_test.rego:
data.policy.prebundle_workflow_github_regularly.review_regularly.notify.test_notification: PASS (15.236084ms)
--------------------------------------------------------------------------------
PASS: 1/1

manifest.yaml

最後に、manifest.yaml 内で定義されたジョブ review-regularlynotify ブロックを追加しましょう:

id: prebundle-workflow-github-regularly
name: "Prebundle: Review Contents on GitHub (Scheduled)"
version: 0.1.0
triggers:
schedule:
- cron: 0 */6 * * *
jobs:
# ...

- id: review-regularly
name: Review all regularly
decide:
rego: !include review-regularly/decide/policy.rego
input:
schema: !include review-regularly/decide/input.graphql

# NOTE: here's the added block
notify:
rego: !include review-regularly/notify/policy.rego
input:
schema: !include review-regularly/notify/input.graphql

# ...

ワークフローを適用・実行する

最後に、変更済みのワークフローを Shisho Cloud にデプロイしてみましょう! これは shishoctl workflow apply コマンドにより実現できます:

# Run the following in your ./shisho-cloud-workflows
# (need to set the ID of your Shisho Cloud organization to $YOUR_ORG_ID)
shishoctl workflow apply \
-o $YOUR_ORG_ID \
-f ./prebundle-workflow-github-regularly/manifest.yaml