Skip to content

Instantly share code, notes, and snippets.

@moio
Created June 6, 2023 15:52
Show Gist options
  • Save moio/4b9f03778941ce71e61342d2be876f16 to your computer and use it in GitHub Desktop.
Save moio/4b9f03778941ce71e61342d2be876f16 to your computer and use it in GitHub Desktop.
Rancher audit log to CSV converter for Excel analysis
#!/usr/bin/env ruby
# encoding: UTF-8
# EXAMPLE
#
# {
# "kind": "Event",
# "apiVersion": "audit.k8s.io/v1",
# "level": "Metadata",
# "auditID": "f6618a15-8e4f-4f82-95b3-7592ed544eb9",
# "stage": "ResponseComplete",
# "requestURI": "/apis/node.k8s.io/v1?timeout=15m0s",
# "verb": "get",
# "user": {
# "username": "system:serviceaccount:cattle-system:rancher-webhook",
# "uid": "9c2d1a92-e9a2-4df3-bd8e-cdcea0428e22",
# "groups": [
# "system:serviceaccounts",
# "system:serviceaccounts:cattle-system",
# "system:authenticated"
# ],
# "extra": {
# "authentication.kubernetes.io/pod-name": [
# "rancher-webhook-85bb446df8-n7lgd"
# ],
# "authentication.kubernetes.io/pod-uid": [
# "a8830d81-2803-47f4-b71a-431a7743e020"
# ]
# }
# },
# "sourceIPs": [
# "10.30.21.143"
# ],
# "userAgent": "webhook/v0.0.0 (linux/amd64) kubernetes/$Format",
# "responseStatus": {
# "metadata": {},
# "code": 200
# },
# "requestReceivedTimestamp": "2023-05-28T06:58:43.155675Z",
# "stageTimestamp": "2023-05-28T06:58:43.160599Z",
# "annotations": {
# "authorization.k8s.io/decision": "allow",
# "authorization.k8s.io/reason": "RBAC: allowed by ClusterRoleBinding \"rancher-webhook\" of ClusterRole \"cluster-admin\" to ServiceAccount \"rancher-webhook/cattle-system\""
# }
# }
require 'json'
require 'csv'
out = CSV.generate do |csv|
csv << ["Timestamp", "Duration", "Verb", "Query", "User", "User-Agent"]
raw_events = ARGV.map do |file|
File.readlines(file).map do |line|
JSON.parse(line)
end
end.flatten
events = raw_events.map do |event|
event["requestTimestamp"] = DateTime.parse(event["requestTimestamp"]).to_time
event["responseTimestamp"] = DateTime.parse(event["responseTimestamp"]).to_time
event
end.sort do |e1, e2|
e1["requestTimestamp"] <=> e2["requestTimestamp"]
end.map do |event|
verb = if event["method"] == "GET" && event["requestURI"].include?("watch=true")
"watch"
else
event["method"].downcase
end
duration = if verb != "watch" then (event["responseTimestamp"] - event["requestTimestamp"]) else 0 end
csv << [event["requestTimestamp"].strftime("%Y-%m-%d %H:%M:%S"), duration, verb, event["requestURI"], event["user"]["name"], event["requestHeader"]["User-Agent"]]
end
end
puts out
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment