✍️
ツールごとのOPA/Regoの書き方
Regoとは
KubernetesやTerraformの静的解析で既存のルールでは足りないときや自分でカスタマイズしたいときにRegoというポリシー言語でコードを書く
Regoを利用できるツールの例
- conftest
- https://www.conftest.dev/
- 自分で全部書く
- trivy
- https://aquasecurity.github.io/trivy/latest/docs/scanner/misconfiguration/custom/
- セキュリティ関連のポリシーが予め備わっている
- kics
- https://docs.kics.io/latest/creating-queries/
- 何でもあるので足りないものだけ書く
- コントリビュートを待ってる
Are you using a custom query?
If so, feel free to contribute to KICS!
conftest
- サンプルマニフェスト
ns.yaml
apiVersion: v1
kind: Namespace
metadata:
name: hoge
labels:
name: hoge
istio.io/rev: stable
- Namespaceにistioのrevisionが設定されているか検査する
istio.rego
package main
deny[msg] {
input[i].contents.kind == "Namespace"
labels := input[i].contents.metadata.labels
not object.get(labels, "istio.io/rev", false)
msg := "Isito not injected."
}
deny[msg] {
input[i].contents.kind == "Namespace"
labels := input[i].contents.metadata.labels
object.get(labels, "istio.io/rev", false) != "stable"
msg := "Revision is not stable."
}
-
書き方
-
リファレンス
-
関数
-
実行
-
--combine
で複数のリソースが書かれているyamlに対応できる -
--combine
を指定するとinput.kind
がinput[i].contents.kind
になる
conftest test ns.yaml --combine --policy istio.rego
-
trivy
ns.yaml
apiVersion: v1
kind: Namespace
metadata:
name: hoge
labels:
name: hoge
istio.io/rev: stable
- conftestのregoと内容は同じだが書き方が少しだけ違う
istio.rego
# METADATA
# title: Istio Injection
# description: Istio revision is not set.
# schemas:
# - input: schema["kubernetes"]
# custom:
# id: ID001
# severity: HIGH
# input:
# combine: true
# selector:
# - type: kubernetes
package user.kubernetes.ID001
deny[res] {
input[i].contents.kind == "Namespace"
resource := input[i].contents
labels := resource.metadata.labels
not object.get(labels, "istio.io/rev", false)
res := result.new("Isito not injected.", resource.kind)
}
deny[res] {
input[i].contents.kind == "Namespace"
resource := input[i].contents
labels := resource.metadata.labels
object.get(labels, "istio.io/rev", false) != "stable"
res := result.new("Revision is not stable.", resource.kind)
}
-
METADATAが利用できる
- https://aquasecurity.github.io/trivy/latest/docs/scanner/misconfiguration/custom/#metadata
- combineは実行時ではなく記述時に指定
- combineは別途ドキュメントページがあるが更新されていないので参考にしない
-
result.new(msg, cause)が結果
- msgは問題の発生を表す文字列
- causeは問題が発生したプロパティ/オブジェクト
-
実行
-
package user.kubernetes.ID001
にしたのでuser
を指定
trivy conf --config-policy istio.rego --policy-namespaces user ns.yaml
-
kics
ns.yaml
apiVersion: v1
kind: Namespace
metadata:
name: hoge
labels:
name: hoge
istio.io/rev: stable
- trivyだとregoファイルに書いていたmetadataが外に切り出されている
- https://docs.kics.io/latest/creating-queries/#guidelines
- idは
kics generate-id
で生成 - severity: HIGH, MEDIUM, LOW or INFO
- 下記以外にdescriptionIDやdescriptionUrlがありドキュメントを書くことが当然のようなフォーマットになっている
queries/istio/metadata.json
{
"id": "88add025-722a-4ec5-9b7d-e058779f24a9",
"queryName": "Istio Injection",
"severity": "HIGH",
"category": "Build Process",
"platform": "Kubernetes",
"descriptionText": "Istio revision is not set."
}
- trivyと同様に書き方が異なる
queries/istio/query.rego
package Cx
CxPolicy[result] {
document := input.document[i]
labels := document.metadata.labels
not object.get(labels, "istio.io/rev", false)
result := {
"documentId": document.id,
"resourceType": document.kind,
"resourceName": document.metadata.name,
"searchKey": sprintf("Namespace name: %s", [document.metadata.name]),
"issueType": "MissingAttribute",
"keyExpectedValue": "labels: istio.io/rev",
"keyActualValue": "labels: ",
}
}
CxPolicy[result] {
document := input.document[i]
labels := document.metadata.labels
rev := object.get(labels, "istio.io/rev", false)
rev != "stable"
result := {
"documentId": document.id,
"resourceType": document.kind,
"resourceName": document.metadata.name,
"searchKey": sprintf("Namespace name: %s", [document.metadata.name]),
"issueType": "IncorrectValue",
"keyExpectedValue": "labels: istio.io/rev: stable",
"keyActualValue": sprintf("labels: istio.io/rev: %s", [rev]),
}
}
-
package
は必ずCx
-
deny
ではなくCxPolicy
-
結果
- searchKey: 引っ掛かったリソースを調べる情報。S3バケットならタグなど
- issueType: IncorrectValue, MissingAttribute, RedundantAttribute
- keyExpectedValue: 期待値
- keyActualValue: 実際の値
-
実行
- デバッグ時や詳細を知りたいとき
-v scan
-
scan --log-level
のデフォルトがINFOなのでDEBUGやTRACEにする
kics scan -t Kubernetes -q queries -p ns.yaml
- デバッグ時や詳細を知りたいとき
-
ライブラリ
- https://github.com/Checkmarx/kics/tree/master/assets/libraries
- よくある処理が関数としてライブラリに纏められている
hoge.rego
package Cx
import data.generic.common as common_lib
import data.generic.k8s as k8sLib
CxPolicy[result] {
document := input.document[i]
metadata := document.metadata
specInfo := k8sLib.getSpecInfo(document)
...
Discussion