torizon_audit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/torizon_audit.rb +147 -0
  3. metadata +43 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 500ba44874ca4f8acf49a1b7f16d861353cf049be7be4b0518689a722d4277ed
4
+ data.tar.gz: dee0a4946b52cb837bc847bd87d91d6baf0b13672726400e6917891939ddef92
5
+ SHA512:
6
+ metadata.gz: fb17aabf9a1ef454d77df1afdd2a5f75254fd910b54862a063a05322192af17ff05f9dfc3b192ec728f04559385ba060d2537a4390df8ab0398a47f9c751863f
7
+ data.tar.gz: 9b8b2345dedd9f1a0f3d7140c16a9bfa46b8c6aee3885fc1217ea642253b65cf356d099d9d4391d54225ef7198b9d9976fd3d5bd68f25f5a16fc1d0930f7a242
@@ -0,0 +1,147 @@
1
+ require "bundler/setup"
2
+ require "optparse"
3
+ require "optparse/time"
4
+ require "json"
5
+ require "elasticsearch"
6
+
7
+
8
+ class Query
9
+ def self.timeFormat(t)
10
+ return t.strftime("%Y-%m-%dT%0k:%0M:%0SZ")
11
+ end
12
+
13
+ def self.matchQuery(key, value, analyzer="standard", operator="OR")
14
+ return {
15
+ "match" => {
16
+ key => {
17
+ "query" => value,
18
+ "analyzer" => analyzer,
19
+ "operator" => operator
20
+ }
21
+ }
22
+ }
23
+ end
24
+
25
+ def initialize(maxNumLogs = 10000)
26
+ @query = {
27
+ "from" => 0,
28
+ "size" => maxNumLogs,
29
+ "query" => {
30
+ "bool" => {
31
+ "filter" => [
32
+ {
33
+ "range" => {
34
+ "@timestamp" => {
35
+ "gte" => "2023-03-13T00:00:00.00Z",
36
+ "lte" => Query.timeFormat(Time.now),
37
+ "format" => "strict_date_optional_time"
38
+ }
39
+ }
40
+ },
41
+ ]
42
+ }
43
+ }
44
+ }
45
+ end
46
+ def timeRange(from, to)
47
+ @query["query"]["bool"]["filter"].find{|h| h.key?("range")}["range"]["@timestamp"]["gte"] = from
48
+ @query["query"]["bool"]["filter"].find{|h| h.key?("range")}["range"]["@timestamp"]["lte"] = to
49
+ end
50
+
51
+ def httpMethod(method)
52
+ @query["query"]["bool"]["filter"].append(Query.matchQuery("request_method", method))
53
+ end
54
+
55
+ def appName(name)
56
+ @query["query"]["bool"]["filter"].append(Query.matchQuery("kubernetes.labels.app", name))
57
+ end
58
+
59
+ def uri(path)
60
+ @query["query"]["bool"]["filter"].append(Query.matchQuery("uri", path, "standard", "AND"))
61
+ end
62
+
63
+ def originNamespace(namespace)
64
+ @query["query"]["bool"]["filter"].append(Query.matchQuery("origin_namespace", namespace))
65
+ end
66
+
67
+ def toJson()
68
+ return @query.to_json
69
+ end
70
+
71
+ def to_s
72
+ @query.to_s
73
+ end
74
+ end
75
+
76
+ # TODO:
77
+ # Keys rotated offline (tuf-reposerver, director, keyserver)
78
+ # PUT, POST, DELETE
79
+
80
+ class Audit
81
+ @@actionsMap = {
82
+ "api/v1/user_repo/targets$" => {"PUT" => "Upload signed targets.json"},
83
+ "api/v1/user_repo/targets/.*" => {"PUT" => "Create Tuf Target", "POST" => "Create TUF target", "PATCH" => "Modify TUF target", "DELETE" => "Delete TUF target"},
84
+ "api/v1/user_repo/trusted-delegations/.*/remote/refresh" => {"PUT" => "Refresh remote delegation"},
85
+ "api/v1/user_repo/trusted-delegations/.*" => {"PUT" => "Create or modify trusted-delegations"},
86
+ "api/v1/user_repo/delegations/.*" => {"PUT" => "Create or modify delegation metadata"},
87
+ "api/v1/multi_target_updates" => {"POST" => "Create multi-target-update"},
88
+ "api/v1/assignments" => {"POST" => "Create device assignment"},
89
+ "api/v1/admin/repo/offline-updates/.*" => {"POST" => "Create or modify lockbox", "PUT" => "Create or modify lockbox"},
90
+ "api/accounts/users/clients$" => {"POST" => "Create third-party API client"},
91
+ "api/accounts/users/clients/.*" => {"DELETE" => "Revoke third-party API client"},
92
+ "api/accounts/users/.*/keys/credentials.zip" => {"GET" => "Download credentials.zip"},
93
+ "api/accounts/organizations/share/.*/users$" => {"POST" => "Share organization with user"},
94
+ "api/accounts/organizations/share/.*/users/.*" => {"DELETE" => "Revoke organization access for user", "PUT" => "Change organization access level for user"},
95
+ "api/accounts/devices$" => {"POST" => "Provision device"},
96
+ "api/v1/device_groups$" => {"POST" => "Create device fleet"},
97
+ "api/v1/device_groups/.*/devices/.*" => {"POST" => "Add device to fleet", "DELETE" => "Remove device from fleet"},
98
+ "api/v1/device_groups/.*/rename" => {"PUT" => "Rename device fleet"},
99
+ "api/v1/device_groups/.*" => {"DELETE" => "Delete device fleet"},
100
+ "api/v1/devices/.*" => {"DELETE" => "Delete device"},
101
+ }
102
+
103
+ def initialize(client)
104
+ @client = client
105
+ end
106
+
107
+ def findAction(method, uri)
108
+ @@actionsMap.each {|uriPattern, methodActions|
109
+ if uri.match(uriPattern)
110
+ if methodActions.key?(method)
111
+ return methodActions[method]
112
+ end
113
+ end
114
+ }
115
+ return "Unknown Action"
116
+ end
117
+
118
+ def userActions(from, to, namespace, dropUnknownActions = true)
119
+ query = Query.new()
120
+ query.timeRange(Query.timeFormat(from), Query.timeFormat(to))
121
+ query.appName("ota-kong-kong")
122
+ query.originNamespace(namespace)
123
+
124
+ response = @client.search index: 'logstash*', body: query.toJson
125
+
126
+ actions = response["hits"]["hits"].map{ |obj|
127
+ src = obj["_source"]
128
+ {
129
+ "method" => src.key?("request_method") ? src["request_method"] : "",
130
+ "path" => src.key?("uri") ? src["uri"]: "",
131
+ "at" => src.key?("@timestamp") ? src["@timestamp"]: "",
132
+ "namespace" => src.key?("namespace") ? src["namespace"]: "",
133
+ "origin_namespace" => src.key?("origin_namespace") ? src["origin_namespace"]: "",
134
+ "status_code" => src.key?("status") ? src["status"]: "",
135
+ "ip" => src.key?("client_addr") ? src["client_addr"]: "",
136
+ "query" => src.key?("query_string") ? src["query_string"]: "",
137
+ "log_id" => obj.key?("_id") ? obj["_id"]: "",
138
+ "action" => self.findAction(src.key?("request_method") ? src["request_method"] : "", src.key?("uri") ? src["uri"]: "")
139
+ }
140
+ }
141
+ if dropUnknownActions
142
+ return actions.select{|req| req["action"] != "Unknown Action"}
143
+ end
144
+ return actions
145
+ end
146
+
147
+ end
metadata ADDED
@@ -0,0 +1,43 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: torizon_audit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ben Clouser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-03-15 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Fetch user actions from torizon platform
14
+ email: ben.clouser@toradex.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/torizon_audit.rb
20
+ homepage:
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubygems_version: 3.3.25
40
+ signing_key:
41
+ specification_version: 4
42
+ summary: Fetch user actions from torizon platform
43
+ test_files: []