Auditingで誰が何をしたのかをみる
本番環境やそれに相当するようなセンシティブな環境では、監査要件として
『誰がどのようなコマンドを打ったか』
を収集することがよくある。
自分の場合、大体は(内部向け説明がしやすい)従来の運用方法を踏襲するような形で上記要件をクリアする(してしまう)が、
KubernetesのAuditingを使うことで似たような情報を収集することができる。
(「どのようなコマンドか」ではなく「どのようなリクエストか」を収集)
どのような出力がされるのか、試しにみてみる。
環境
- minikube v1.9.2
疎通
AuditPolicyの作成
minikube stop mkdir -p ~/.minikube/files/etc/ssl/certs cat <<EOF > ~/.minikube/files/etc/ssl/certs/audit-policy.yaml # Log all requests at the Metadata level. apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata EOF
minikubeの起動
minikube start \ --extra-config=apiserver.audit-policy-file=/etc/ssl/certs/audit-policy.yaml \ --extra-config=apiserver.audit-log-path=-
Audit logの確認
kubectl logs kube-apiserver-minikube -n kube-system | grep audit.k8s.io/v1
出力の例
{ "kind": "Event", "apiVersion": "audit.k8s.io/v1", "level": "Metadata", "auditID": "e8b44217-4018-4cac-b25a-978349d428e0", "stage": "RequestReceived", "requestURI": "/apis/batch/v1beta1/cronjobs?limit=500", "verb": "list", "user": { "username": "system:serviceaccount:kube-system:cronjob-controller", "uid": "5eb6b4b2-a6e3-4551-800f-1d1aeb638e0f", "groups": [ "system:serviceaccounts", "system:serviceaccounts:kube-system", "system:authenticated" ] }, "sourceIPs": [ "192.168.99.100" ], "userAgent": "kube-controller-manager/v1.18.0 (linux/amd64) kubernetes/9e99141/system:serviceaccount:kube-system:cronjob-controller", "objectRef": { "resource": "cronjobs", "apiGroup": "batch", "apiVersion": "v1beta1" }, "requestReceivedTimestamp": "2020-04-22T01:56:52.416692Z", "stageTimestamp": "2020-04-22T01:56:52.416692Z" }
grepの条件をところをminikube-user
に変えてみる。
{ "kind": "Event", "apiVersion": "audit.k8s.io/v1", "level": "Metadata", "auditID": "105f9973-cbca-49ed-9d6b-41e232225738", "stage": "ResponseStarted", "requestURI": "/api/v1/namespaces/kube-system/pods/kube-apiserver-minikube/log?follow=true", "verb": "get", "user": { "username": "minikube-user", "groups": [ "system:masters", "system:authenticated" ] }, "sourceIPs": [ "192.168.99.1" ], "userAgent": "kubectl/v1.15.3 (linux/amd64) kubernetes/2d3c76f", "objectRef": { "resource": "pods", "namespace": "kube-system", "name": "kube-apiserver-minikube", "apiVersion": "v1", "subresource": "log" }, "responseStatus": { "metadata": {}, "code": 200 }, "requestReceivedTimestamp": "2020-04-22T02:00:11.412922Z", "stageTimestamp": "2020-04-22T02:00:11.424775Z", "annotations": { "authorization.k8s.io/decision": "allow", "authorization.k8s.io/reason": "" } }
kubectl logs
を打っているので、その情報が出力されていることがわかる。
出力する情報を増やしたいので、minikube-user
のみRequest
レベルのAudit Logを出力するようaudit-policy.yamlを修正し、Minikubeを再起動。
apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Request users: ["minikube-user"]
試しにkubectl create
してみる
kubectl create deployment --image=nginx nginx-app
上記コマンドを実行すると、Audit logは下記のようになり、
{ "kind": "Event", "apiVersion": "audit.k8s.io/v1", "level": "Request", "auditID": "2e935f75-6162-479e-a4b6-1bd311a4ff86", "stage": "ResponseComplete", "requestURI": "/apis/apps/v1/namespaces/default/deployments", "verb": "create", "user": { "username": "minikube-user", "groups": [ "system:masters", "system:authenticated" ] }, "sourceIPs": [ "192.168.99.1" ], "userAgent": "kubectl/v1.15.3 (linux/amd64) kubernetes/2d3c76f", "objectRef": { "resource": "deployments", "namespace": "default", "name": "nginx-app", "apiGroup": "apps", "apiVersion": "v1" }, "responseStatus": { "metadata": {}, "code": 201 }, "requestObject": { "kind": "Deployment", "apiVersion": "apps/v1", "metadata": { "name": "nginx-app", "creationTimestamp": null, "labels": { "app": "nginx-app" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx-app" } }, "template": { "metadata": { "creationTimestamp": null, "labels": { "app": "nginx-app" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx", "resources": {}, "terminationMessagePath": "/dev/termination-log", "terminationMessagePolicy": "File", "imagePullPolicy": "Always" } ], "restartPolicy": "Always", "terminationGracePeriodSeconds": 30, "dnsPolicy": "ClusterFirst", "securityContext": {}, "schedulerName": "default-scheduler" } }, "strategy": { "type": "RollingUpdate", "rollingUpdate": { "maxUnavailable": "25%", "maxSurge": "25%" } }, "revisionHistoryLimit": 10, "progressDeadlineSeconds": 600 }, "status": {} }, "requestReceivedTimestamp": "2020-04-22T02:05:52.184886Z", "stageTimestamp": "2020-04-22T02:05:52.203978Z", "annotations": { "authorization.k8s.io/decision": "allow", "authorization.k8s.io/reason": "" } }
.user.username
(minikube-user
)が.requestObject
(Deployment
)を.verb
(create
)した
ことがわかる。
上記ではAudit LevelをRequest
にしたが、他にもあるのでいろいろ試してみると良いと思う。
Level | 内容 |
---|---|
None | don’t log events that match this rule. |
Metadata | log request metadata (requesting user, timestamp, resource, verb, etc.) but not request or response body. |
Request | log event metadata and request body but not response body. This does not apply for non-resource requests. |
RequestResponse | log event metadata, request and response bodies. This does not apply for non-resource requests. |
余談
上記機能もあるにはあるが、いろいろなアレコレによって「どのようなコマンドか」が重要だったりするので、結局は従来の方法に沿う形で落ち着いた。 監査系の要件は組織文化だけでなく法令などもかかわるレイヤなので調整がいろいろ難しい。
Event Resourceとして出力されるが、kubeletの--event-qps
とか影響あるんだろうか
(監査だから抜けたりするのちょっと困る)
あとkubectlのversion古いのであげておかないといけない