通知を設定する
Shisho Cloud における通知は、そのタイミングや内容の全てを ワークフロー として制御できるようになっています。また、プロジェクトごとに複数のデフォルト通知先を事前に設定し、それぞれの通知先に送信できます。わざわざ深く学ばなくても便利に使えるように、標準の通知ワークフローが用意されており、検出事項の緊急度に応じた通知 が行えます。
Slack通知の例
メールによる通知の例
- 通知ワークフロー
- プロジェクトごとの通知ワークフロー
通知ワークフローは標準で含まれているワークフローの一つで、組織内の全リソースを対象とした問題の発見・トリアージ時に下記の方法で通知します。
- Slack チャンネルへ通知
- 指定のメールアドレスへ送信
- 通知グループに紐付けられた送信先へ通知
id: notification-security
name: "Prebundle: Notify important security events in a variety of ways"
version: 0.1.0
triggers:
triage:
- event:
- updated
status_changed_to:
- awaiting_review
- acknowledged
- action_required
- secure
- deleted
- event:
- created
status_changed_to:
- awaiting_review
jobs:
- id: triage
name: Notify triage status updation
notify:
rego: |
package notification.triage
import data.shisho
import data.shisho.notification.slack
import data.shisho.notification.group
minimum_severity := severity_intl(data.params.minimum_severity) {
data.params
data.params.minimum_severity != ""
} else := shisho.decision.severity_critical
severity_intl(x) := shisho.decision.severity_info {
x == "INFO"
} else := shisho.decision.severity_low {
x == "LOW"
} else := shisho.decision.severity_medium {
x == "MEDIUM"
} else := shisho.decision.severity_high {
x == "HIGH"
} else := shisho.decision.severity_critical {
x == "CRITICAL"
} else := shisho.decision.severity_low
severity_string(x) := "参考情報(info)" {
x == shisho.decision.severity_info
} else := "低(low)" {
x == shisho.decision.severity_low
} else := "中(medium)" {
x == shisho.decision.severity_medium
} else := "高(high)" {
x == shisho.decision.severity_high
} else := "緊急(critical)" {
x == shisho.decision.severity_critical
} else := x
severity_emoji(x) := ":information_source:" {
x == shisho.decision.severity_info
} else := ":eyes:" {
x == shisho.decision.severity_low
} else := ":warning:" {
x == shisho.decision.severity_medium
} else := ":rotating_light:" {
x == shisho.decision.severity_high
} else := ":sos:" {
x == shisho.decision.severity_critical
} else := ":memo:"
triage_status(x) := "要レビュー" {
x == "AWAITING_REVIEW"
} else := "要対応" {
x == "ACTION_REQUIRED"
} else := "リスク受容中" {
x == "ACKNOWLEDGED"
} else := "セキュア" {
x == "SECURE"
} else := "削除済" {
x == "DELETED"
} else := x
triage_status_emoji(x) := ":eyes:" {
x == "AWAITING_REVIEW"
} else := ":heavy_exclamation_mark:" {
x == "ACTION_REQUIRED"
} else := ":arrow_right:" {
x == "ACKNOWLEDGED"
} else := ":large_green_circle:" {
x == "SECURE"
} else := ":wastebasket:" {
x == "DELETED"
} else := ":memo:"
title(explanation, api_version, kind) := explanation.title {
explanation
} else := "" {
concat(":", [api_version, kind])
}
slack_headline(type, status) := "*新たなポリシー違反が検出されました。*\n対応を検討しましょう。" {
type == "CREATED"
} else := "*ポリシー違反が解決されました* :tada:" {
type == "UPDATED"
status == "SECURE"
} else := "*ポリシーに違反した設定の対応状況が変化しました。*\n引き続き対応を進めましょう。"
slack_triage_information(target) := [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":mega: トリアージ者: ", target.triageInitiator.displayName]))]),
slack.context_block([slack.text_element(concat("", [":memo: コメント: ", target.triageComment]))]),
] {
target.triageInitiator.displayName != ""
target.triageComment != ""
} else := [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":mega: トリアージ者: ", target.triageInitiator.displayName]))]),
] {
target.triageInitiator.displayName != ""
target.triageComment == ""
} else := []
# send notifications by Slack
notifications[n] {
# send notification only if the channel is specified
data.params.slack_channel != ""
workspace_id := split(data.params.slack_channel, ":")[0]
channel_id := split(data.params.slack_channel, ":")[1]
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
n := shisho.notification.to_slack_channel(
workspace_id,
channel_id,
{"blocks": array.concat(
[slack.text_section(
slack_headline(event.type, event.status),
{"fields": [
# The first row
slack.text_element("*:memo: 違反が見られた観点*"),
slack.text_element("*:dart: 対象リソース*"),
slack.text_element(concat("", ["<", event.target.viewer, "|", title(event.target.explanation, event.target.apiVersion, event.target.kind), ">"])),
slack.text_element(concat("", ["<", event.target.subject.viewer, "|", event.target.subject.displayName, ">"])),
# The second row
slack.text_element(concat("", [severity_emoji(target_severity), " *深刻度*"])),
slack.text_element(concat("", [triage_status_emoji(event.status), " *対応状況*"])),
slack.text_element(severity_string(target_severity)),
slack.text_element(concat("", ["*", triage_status(event.status), "* に変化しました"])),
]},
)],
# The footer
array.concat(slack_triage_information(event.target), [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":shield: *Powered by \"<", event.target.createdBy.viewer, "|", event.target.createdBy.name, ">\" on Shisho Cloud*"]))]),
slack.divider_block,
]),
)},
)
}
headline(type, status) := "新たなポリシー違反が検出されました。対応を検討しましょう。" {
type == "CREATED"
} else := "ポリシー違反が解決されました" {
type == "UPDATED"
status == "SECURE"
} else := "ポリシーに違反した設定の対応状況が変化しました。引き続き対応を進めましょう。"
triage_information(target) := [
concat("", ["トリアージ者: ", target.triageInitiator.displayName, "\n"]),
concat("", ["コメント: ", target.triageComment, "\n"]),
] {
target.triageInitiator.displayName != ""
target.triageComment != ""
} else := [
concat("", ["トリアージ者: ", target.triageInitiator.displayName, "\n"]),
] {
target.triageInitiator.displayName != ""
target.triageComment == ""
} else := []
# send notifications by email
notifications[n] {
# send notification only if the email address is specified
data.params.email_address != ""
email = data.params.email_address
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
n := shisho.notification.to_email(
email,
concat("", [
headline(event.type, event.status),
"\n\n",
"違反が見られた観点: ",
concat("", [title(event.target.explanation, event.target.apiVersion, event.target.kind), " (", event.target.viewer, ")", "\n"]),
"対象リソース: ",
concat("", [event.target.subject.displayName, " (", event.target.subject.viewer, ")", "\n"]),
"深刻度: ",
severity_string(target_severity),
"\n",
"対応状況: ",
concat("", [triage_status(event.status), "に変化しました", "\n"]),
"\n",
concat("", triage_information(event.target)),
"\n",
concat("", ["Powered by \"", event.target.createdBy.name, " (", event.target.createdBy.viewer, ")", "\" on Shisho Cloud"]),
]),
)
}
# send notifications with a notification group
notifications[n] {
# send notification only if the notification group ID is specified
data.params.notification_group != ""
group_id = data.params.notification_group
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
n := shisho.notification.to_group(
group_id,
concat("", [
headline(event.type, event.status),
"\n\n",
"違反が見られた観点: ",
concat("", [title(event.target.explanation, event.target.apiVersion, event.target.kind), " (", event.target.viewer, ")", "\n"]),
"対象リソース: ",
concat("", [event.target.subject.displayName, " (", event.target.subject.viewer, ")", "\n"]),
"深刻度: ",
severity_string(target_severity),
"\n",
"対応状況: ",
concat("", [triage_status(event.status), "に変化しました", "\n"]),
"\n",
concat("", triage_information(event.target)),
"\n",
concat("", ["Powered by \"", event.target.createdBy.name, " (", event.target.createdBy.viewer, ")", "\" on Shisho Cloud"]),
]),
)
}
input:
schema: |
query {
shisho {
event {
__typename
... on ShishoTriageStatusEvent {
type
status
target {
apiVersion
kind
subject {
displayName
parentDisplayName
viewer
}
severity
viewer
explanation(locale: JA_JP) {
title
description
}
createdBy {
name
viewer
}
triageComment
triageInitiator {
id
type
displayName
}
}
}
}
}
}
with:
slack_channel:
type: slack_channel
descrition: The Slack channel to send notifications.
value: ""
email_address:
type: string
descrition: The email channel to send notifications.
value: ""
notification_group:
type: notification_target
descrition: The notification group to send notifications.
value: ""
minimum_severity:
type: string
description: The minimum severity to notify.
value: HIGH
oneof:
- INFO
- LOW
- MEDIUM
- HIGH
- CRITICAL
プロジェクトごとの通知ワークフローはプロジェクトのスコープ(リソース)を対象とした問題の発見・トリアージ時に各種通知先へ通知します。このワークフローは標準で含まれていませんので、必要応じて下記のYAMLをコピーし新規作成してください。
version: 0.1.0
id: "notification-project-security"
name: "Prebundle: Notify Shisho Cloud project's important security events"
triggers:
triage:
# send notifications when...
- event: [updated]
status_changed_to:
# the issue is calling your review.
- awaiting_review
# the issue is acknowledged, and no further action is not expected.
- acknowledged
# the issue is marked to need your fix.
- action_required
# the issue was fixed :tada:
- secure
# the resource with security issue(s) gets deleted.
- deleted
# send notifications on a finding needs your action
- event: [created]
status_changed_to:
- awaiting_review
jobs:
- id: triage
name: Notify triage status updation
notify:
rego: |
package notification.project_security.triage
import data.shisho
import data.shisho.notification.slack
import data.shisho.notification.group
minimum_severity := severity_intl(data.params.minimum_severity) {
data.params
data.params.minimum_severity != ""
} else := shisho.decision.severity_critical
severity_intl(x) := shisho.decision.severity_info {
x == "INFO"
} else := shisho.decision.severity_low {
x == "LOW"
} else := shisho.decision.severity_medium {
x == "MEDIUM"
} else := shisho.decision.severity_high {
x == "HIGH"
} else := shisho.decision.severity_critical {
x == "CRITICAL"
} else := shisho.decision.severity_low
severity_string(x) := "参考情報(info)" {
x == shisho.decision.severity_info
} else := "低(low)" {
x == shisho.decision.severity_low
} else := "中(medium)" {
x == shisho.decision.severity_medium
} else := "高(high)" {
x == shisho.decision.severity_high
} else := "緊急(critical)" {
x == shisho.decision.severity_critical
} else := x
severity_emoji(x) := ":information_source:" {
x == shisho.decision.severity_info
} else := ":eyes:" {
x == shisho.decision.severity_low
} else := ":warning:" {
x == shisho.decision.severity_medium
} else := ":rotating_light:" {
x == shisho.decision.severity_high
} else := ":sos:" {
x == shisho.decision.severity_critical
} else := ":memo:"
triage_status(x) := "要レビュー" {
x == "AWAITING_REVIEW"
} else := "要対応" {
x == "ACTION_REQUIRED"
} else := "リスク受容中" {
x == "ACKNOWLEDGED"
} else := "セキュア" {
x == "SECURE"
} else := "削除済" {
x == "DELETED"
} else := x
triage_status_emoji(x) := ":eyes:" {
x == "AWAITING_REVIEW"
} else := ":heavy_exclamation_mark:" {
x == "ACTION_REQUIRED"
} else := ":arrow_right:" {
x == "ACKNOWLEDGED"
} else := ":large_green_circle:" {
x == "SECURE"
} else := ":wastebasket:" {
x == "DELETED"
} else := ":memo:"
title(explanation, api_version, kind) := explanation.title {
explanation
} else := "" {
concat(":", [api_version, kind])
}
slack_headline(type, status) := "*新たなポリシー違反が検出されました。*\n対応を検討しましょう。" {
type == "CREATED"
} else := "*ポリシー違反が解決されました* :tada:" {
type == "UPDATED"
status == "SECURE"
} else := "*ポリシーに違反した設定の対応状況が変化しました。*\n引き続き対応を進めましょう。"
slack_triage_information(target) := [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":mega: トリアージ者: ", target.triageInitiator.displayName]))]),
slack.context_block([slack.text_element(concat("", [":memo: コメント: ", target.triageComment]))]),
] {
target.triageInitiator.displayName != ""
target.triageComment != ""
} else := [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":mega: トリアージ者: ", target.triageInitiator.displayName]))]),
] {
target.triageInitiator.displayName != ""
target.triageComment == ""
} else := []
# send notifications by Slack
notifications[n] {
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send a notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
# send a notification to the default project notification channels
project := event.target.subject.projectsBelongingTo[_]
channel := project.defaultNotificationChannels[_]
channel.__typename == "ShishoNotificationChannelSlack"
n := shisho.notification.to_slack_channel(
channel.workspaceId,
channel.channelId,
{"blocks": array.concat(
[slack.text_section(
slack_headline(event.type, event.status),
{"fields": [
# The first row
slack.text_element("*:memo: 違反が見られた観点*"),
slack.text_element("*:dart: 対象リソース*"),
slack.text_element(concat("", ["<", event.target.viewer, "|", title(event.target.explanation, event.target.apiVersion, event.target.kind), ">"])),
slack.text_element(concat("", ["<", event.target.subject.viewer, "|", event.target.subject.displayName, ">"])),
# The second row
slack.text_element(concat("", [severity_emoji(target_severity), " *深刻度*"])),
slack.text_element(concat("", [triage_status_emoji(event.status), " *対応状況*"])),
slack.text_element(severity_string(target_severity)),
slack.text_element(concat("", ["*", triage_status(event.status), "* に変化しました"])),
]},
)],
# The footer
array.concat(slack_triage_information(event.target), [
slack.divider_block,
slack.context_block([slack.text_element(concat("", [":shield: *Powered by \"<", event.target.createdBy.viewer, "|", event.target.createdBy.name, ">\" on Shisho Cloud*"]))]),
slack.divider_block,
]),
)},
)
}
headline(type, status) := "新たなポリシー違反が検出されました。対応を検討しましょう。" {
type == "CREATED"
} else := "ポリシー違反が解決されました" {
type == "UPDATED"
status == "SECURE"
} else := "ポリシーに違反した設定の対応状況が変化しました。引き続き対応を進めましょう。"
triage_information(target) := [
concat("", ["トリアージ者: ", target.triageInitiator.displayName, "\n"]),
concat("", ["コメント: ", target.triageComment, "\n"]),
] {
target.triageInitiator.displayName != ""
target.triageComment != ""
} else := [
concat("", ["トリアージ者: ", target.triageInitiator.displayName, "\n"]),
] {
target.triageInitiator.displayName != ""
target.triageComment == ""
} else := []
# send notifications by email
notifications[n] {
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send a notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
# send a notification to the default project notification channels
project := event.target.subject.projectsBelongingTo[_]
channel := project.defaultNotificationChannels[_]
channel.__typename == "ShishoNotificationChannelEmail"
n := shisho.notification.to_email(
channel.email,
concat("", [
headline(event.type, event.status),
"\n\n",
"違反が見られた観点: ",
concat("", [title(event.target.explanation, event.target.apiVersion, event.target.kind), " (", event.target.viewer, ")", "\n"]),
"対象リソース: ",
concat("", [event.target.subject.displayName, " (", event.target.subject.viewer, ")", "\n"]),
"深刻度: ",
severity_string(target_severity),
"\n",
"対応状況: ",
concat("", [triage_status(event.status), "に変化しました", "\n"]),
"\n",
concat("", triage_information(event.target)),
"\n",
concat("", ["Powered by \"", event.target.createdBy.name, " (", event.target.createdBy.viewer, ")", "\" on Shisho Cloud"]),
]),
)
}
# send notifications with a notification group
notifications[n] {
event := input.query.shisho.event
event.__typename == "ShishoTriageStatusEvent"
input.running_state == shisho.job.running_state_preprocessing
# send a notification only if the severity of the target decision is higher than the minimum severity
target_severity := severity_intl(event.target.severity)
minimum_severity <= target_severity
# send a notification to the default project notification channels
project := event.target.subject.projectsBelongingTo[_]
channel := project.defaultNotificationChannels[_]
channel.__typename == "ShishoNotificationChannelGroup"
n := shisho.notification.to_group(
channel.id,
concat("", [
headline(event.type, event.status),
"\n\n",
"違反が見られた観点: ",
concat("", [title(event.target.explanation, event.target.apiVersion, event.target.kind), " (", event.target.viewer, ")", "\n"]),
"対象リソース: ",
concat("", [event.target.subject.displayName, " (", event.target.subject.viewer, ")", "\n"]),
"深刻度: ",
severity_string(target_severity),
"\n",
"対応状況: ",
concat("", [triage_status(event.status), "に変化しました", "\n"]),
"\n",
concat("", triage_information(event.target)),
"\n",
concat("", ["Powered by \"", event.target.createdBy.name, " (", event.target.createdBy.viewer, ")", "\" on Shisho Cloud"]),
]),
)
}
input:
schema: |
query {
shisho {
event {
__typename
... on ShishoTriageStatusEvent {
type
status
target {
apiVersion
kind
subject {
displayName
parentDisplayName
viewer
projectsBelongingTo {
id
name
defaultNotificationChannels {
__typename
... on ShishoNotificationChannelSlack {
workspaceId
channelId
name
}
... on ShishoNotificationChannelGroup {
id
name
}
... on ShishoNotificationChannelEmail {
email
}
}
}
}
severity
viewer
explanation(locale: JA_JP) {
title
description
}
createdBy {
name
viewer
}
triageComment
triageInitiator {
id
type
displayName
}
}
}
}
}
}
with:
minimum_severity:
type: string
description: The minimum severity to notify.
value: HIGH
oneof:
- INFO
- LOW
- MEDIUM
- HIGH
- CRITICAL
では、順に設定方法を見ていきましょう。
通知ワークフローの設定
ここでは通知ワークフローの設定を変更し、問題の発見・トリアージ時の通知を設定してみましょう。
通知ワークフローの設定ページにアクセスする
通知ワークフローの編集画面にアクセスすると、以下のような画面が開くはずです。
パラメータを編集する
画面右上を確認すると、各種通知先の設定項目と、どの緊急度(severity)の検出事項からを通知するかの 2 つの設定項目が確認できます。それぞれの項目を設定し、保存 を押下してください。
通知を設定するには、事前に各種通知ターゲットの設定が必要となります。詳細は こちら を参照してください。
Slack通知をテストする
Slack チャンネルへの通知を利用する場合、テスト通知を送信 ボタンを押下することで、実際にテスト通知を送信できます。もし以下のようなメッセージが確認できれば、通知設定は完了です。
プロジェクトごとの通知ワークフローの設定
一律、同じ通知先に送信したいケースもあれば、プロジェクトごとに異なる通知先に送信したいケースもあるでしょう。上記のプロジェクトごとの通知ワークフローを利用してください。
対象のプロジェクトの設定ページにアクセスする
まずはプロジェクトの一覧画面から通知先を設定したいプロジェクトを選択し、設定ページにアクセスしてください。
通知先を設定する
設定ページにて、ご希望の通知先を選択し追加・更新してください。
なお、現在、プロジェクトの通知先として追加できるのは下記となります。また、それぞれ事前に設定が必要となりますので、ご希望の通知先が選択肢として表示されない場合はご確認ください。
- Slack チャンネル:通知ターゲットの「 Slack 通知の設定をする」をご覧ください。
- 通知グループ:通知グループの設定をご覧ください。
- Email:通知ターゲットの「 Email 通知の設定をする」をご覧ください。
プロジェクトごとの通知ワークフローの設定ページにアクセスする
すでにプロジェクトの設定ページにて通知先の設定を終えたので、改めてパラメータを通じ設定する必要はありません。なお、緊急度(severity)の検出事項を変更したい場合は、プロジェクトごとの通知ワークフローの編集ページにアクセスし、パラメータを編集してください。