camtool 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3f150b39a20695aa69a3bde1a84e1f22f78e1fc007920b10a8a49c332c3d0512
4
+ data.tar.gz: 94f865410c2a203d77e4ca8fcbc3db3422b12e79412a9caf8cbed2ce06c86f2e
5
+ SHA512:
6
+ metadata.gz: 2c7c82e135f38b92b6fb70468c9fe42c4647e0fc3af17fd2208d38e4326e6f2e43d6d03965abc769341697181fbe6ebf498e1442a0013a7a33de9c809614a9ba
7
+ data.tar.gz: 187a61ec87799ac4c7e9546b624263a252948396d2a96fabd967313028fc6bd01629dd62893f0c126a13bb73acccf5e84d889754a1e71b7432cf46ce9e53f693
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2015-2019 University of Bristol, University of Cambridge,
4
+ Harvard University, University of British Columbia http://camflow.org
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ # camflow-ruby
2
+
3
+ ```
4
+ sudo dnf install ruby ruby-devel redhat-rpm-config graphviz
5
+ ```
6
+
7
+ ```
8
+ gem install json rgl mqtt rake bundler
9
+ ```
10
+
11
+ ## install
12
+
13
+ ```
14
+ git clone https://github.com/tfjmp/camtool
15
+ cd camtool
16
+ rake install
17
+ ```
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'camtool.rb'
4
+ require 'rgl/dot'
5
+ require 'rgl/topsort'
6
+ require 'rgl/transitivity'
7
+
8
+ instruction = ARGV[0]
9
+ target = ARGV[1]
10
+
11
+ if instruction == '--version' || instruction == '-v'
12
+ CamTool.version
13
+ elsif instruction == '--info'
14
+ print CamTool::ProvJSONtoRGL.new.read_log_file(target).information
15
+ CamTool::EdgeCounter.new.read_log_file(target).show
16
+ CamTool::VertexCounter.new.read_log_file(target).show
17
+ elsif instruction == '--publish'
18
+ CamTool::MQTTBreaker.new.break_log_file target
19
+ elsif instruction == '--break'
20
+ CamTool::LogBreaker.new.break_log_file target
21
+ elsif instruction == '--validate'
22
+ CamTool::ProvJSONtoRGL.new.read_log_file(target).validate
23
+ puts 'Graph structure verified...'
24
+ CamTool::EdgeValidator.new.read_log_file(target)
25
+ puts 'Relations verified...'
26
+ elsif instruction == '--packet'
27
+ CamTool::CheckPacket.new.read_log_file(target)
28
+ elsif instruction == '--png'
29
+ print CamTool::ProvJSONtoRGL.new.read_log_file(target).png
30
+ elsif instruction == '--list'
31
+ types = ARGV[2]
32
+ CamTool::ProvJSONtoRGL.new.read_log_file(target).list(types)
33
+ else
34
+ puts '--version'
35
+ puts '--info <path to log file>'
36
+ puts '--publish <path to log file>'
37
+ puts '--break <path to log file>'
38
+ puts '--png <path to log file>'
39
+ puts '--packet <path to log file>'
40
+ puts '--validate <path to log file>'
41
+ puts '--list <path to log file> [optional comma-separated list of element type e.g. "path,argv"]'
42
+ end
@@ -0,0 +1,9 @@
1
+ require 'camtool/provjson_parser'
2
+ require 'camtool/provjson_to_rgl'
3
+ require 'camtool/edge_counter'
4
+ require 'camtool/edge_validator'
5
+ require 'camtool/vertex_counter'
6
+ require 'camtool/log_breaker'
7
+ require 'camtool/check_packet.rb'
8
+ require 'camtool/breaker_mqtt'
9
+ require 'camtool/version'
@@ -0,0 +1,24 @@
1
+ require 'mqtt'
2
+ require 'zlib'
3
+ require 'base64'
4
+
5
+ module CamTool
6
+ class MQTTBreaker < LogBreaker
7
+ def initialize
8
+ conn_opts = {
9
+ remote_host: 'm12.cloudmqtt.com',
10
+ remote_port: 17065,
11
+ username: 'camflow',
12
+ password: 'test',
13
+ }
14
+ @c = MQTT::Client.connect conn_opts
15
+ end
16
+
17
+ def new_entry entry
18
+ comp = Zlib::Deflate.deflate entry
19
+ ready = Base64.encode64 comp
20
+ @c.publish 'camflow/test', ready
21
+ sleep 5
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ module CamTool
2
+ class CheckPacket < ProvJSONParser
3
+ def initialize
4
+ end
5
+
6
+ def entity k, v
7
+ puts v['cf:jiffies']+"\t"+v['prov:label'] unless v['prov:type'] != 'packet'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,41 @@
1
+ module CamTool
2
+ class EdgeCounter < ProvJSONParser
3
+ attr_reader :map
4
+
5
+ def initialize
6
+ @map = Hash.new(0)
7
+ end
8
+
9
+ def add key
10
+ @map[key]=@map[key]+1
11
+ end
12
+
13
+ def used k, v
14
+ self.add v['prov:type']
15
+ end
16
+
17
+ def wasGeneratedBy k, v
18
+ self.add v['prov:type']
19
+ end
20
+
21
+ def wasDerivedFrom k, v
22
+ self.add v['prov:type']
23
+ end
24
+
25
+ def wasInformedBy k, v
26
+ self.add v['prov:type']
27
+ end
28
+
29
+ def wasAssociatedWith k, v
30
+ self.add v['prov:type']
31
+ end
32
+
33
+ def show
34
+ puts "\n\n-------------\nEdge types\n-------------\n"
35
+ @map = @map.sort_by { |key, value| value }.reverse
36
+ @map.each do |key, value|
37
+ puts "#{key}:#{value}"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,74 @@
1
+ module CamTool
2
+ class EdgeValidator < ProvJSONParser
3
+ def initialize
4
+ end
5
+
6
+ def print_relation_bytes id
7
+ id = id.gsub 'cf:', ''
8
+ bytes = Base64.decode64(id).bytes.to_a
9
+ type = bytes[7] & 0xF0
10
+ puts type.to_s(16)
11
+ type = bytes[8]
12
+ puts type.to_s(16)
13
+ end
14
+
15
+ def is_relation? id
16
+ id = id.gsub 'cf:', ''
17
+ bytes = Base64.decode64(id).bytes.to_a
18
+ type = bytes[7] & 0xF0
19
+ return type == 0x80
20
+ end
21
+
22
+ def is_activity? id
23
+ id = id.gsub 'cf:', ''
24
+ bytes = Base64.decode64(id).bytes.to_a
25
+ type = bytes[7] & 0xF0
26
+ return type == 0x40
27
+ end
28
+
29
+ def is_entity? id
30
+ id = id.gsub 'cf:', ''
31
+ bytes = Base64.decode64(id).bytes.to_a
32
+ type = bytes[7] & 0xF0
33
+ return type == 0x20
34
+ end
35
+
36
+ def is_agent? id
37
+ id = id.gsub 'cf:', ''
38
+ bytes = Base64.decode64(id).bytes.to_a
39
+ type = bytes[7] & 0xF0
40
+ return type == 0x10
41
+ end
42
+
43
+ def used k, v
44
+ abort "used prov:entity is of wrong type: #{v}." unless is_entity? v['prov:entity']
45
+ abort "used prov:activity is of wrong type: #{v}." unless is_activity? v['prov:activity']
46
+ end
47
+
48
+ def wasGeneratedBy k, v
49
+ abort "wasGeneratedBy prov:entity is of wrong type: #{v}." unless is_entity? v['prov:entity']
50
+ abort "wasGeneratedBy prov:activity is of wrong type: #{v}." unless is_activity? v['prov:activity']
51
+ end
52
+
53
+ def wasDerivedFrom k, v
54
+ abort "wasDerivedFrom prov:usedEntity is of wrong type: #{v}." unless is_entity? v['prov:usedEntity']
55
+ abort "wasDerivedFrom prov:generatedEntity is of wrong type: #{v}." unless is_entity? v['prov:generatedEntity']
56
+ end
57
+
58
+ def wasInformedBy k, v
59
+ abort "wasInformedBy prov:informant is of wrong type: #{v}." unless is_activity? v['prov:informant']
60
+ abort "wasInformedBy prov:informed is of wrong type: #{v}." unless is_activity? v['prov:informed']
61
+ end
62
+
63
+ def wasAssociatedWith k, v
64
+ abort "wasAssociatedWith prov:activity is of wrong type: #{v}." unless is_activity? v['prov:activity']
65
+ abort "wasAssociatedWith prov:agent is of wrong type: #{v}." unless is_agent? v['prov:agent']
66
+ end
67
+
68
+ def relation k, v
69
+ print_relation_bytes k
70
+ puts v
71
+ abort "relation should not be used"
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,32 @@
1
+ module CamTool
2
+ class LogBreaker
3
+ def break_log_file filename
4
+ if filename != nil
5
+ open(filename) do |file|
6
+ @i=0
7
+ file.each_line do |line|
8
+ ok = true
9
+ line = line.sub /\[[0-9 :-]*\]\t[A-Z]*[ ]*:[ ]*/, ''
10
+ line = line.gsub "\n", ''
11
+ begin
12
+ JSON.parse(line)
13
+ rescue JSON::ParserError
14
+ abort "Error #{ex.class}, message: #{ex.message}"
15
+ end
16
+ self.new_entry line unless !ok
17
+ end
18
+ end unless !File.file?(filename)
19
+ print "File does not exist\n" unless File.file?(filename)
20
+ end
21
+ self
22
+ end
23
+
24
+ def new_entry entry
25
+ fname="./#{@i}.break"
26
+ @i=@i+1
27
+ File.open(fname, 'w+') do |f|
28
+ f.write entry
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,104 @@
1
+ require 'json'
2
+
3
+ module CamTool
4
+ class ProvJSONParser
5
+ def read_json_file filename
6
+ if filename != nil
7
+ parse_json File.read(filename).gsub("\n", '') unless !File.file?(filename)
8
+ print "File does not exist\n" unless File.file?(filename)
9
+ end
10
+ self
11
+ end
12
+
13
+ def read_log_file filename
14
+ if filename != nil
15
+ open(filename) do |file|
16
+ file.each_line do |line|
17
+ parse_json line.gsub("\n", '')
18
+ end
19
+ end unless !File.file?(filename)
20
+ print "File does not exist\n" unless File.file?(filename)
21
+ end
22
+ self
23
+ end
24
+
25
+ def used k, v
26
+ end
27
+
28
+ def wasGeneratedBy k, v
29
+ end
30
+
31
+ def wasDerivedFrom k, v
32
+ end
33
+
34
+ def wasInformedBy k, v
35
+ end
36
+
37
+ def wasAssociatedWith k, v
38
+ end
39
+
40
+ def relation k, v
41
+ end
42
+
43
+ def prefix k, v
44
+ end
45
+
46
+ def entity k, v
47
+ end
48
+
49
+ def activity k, v
50
+ end
51
+
52
+ def agent k, v
53
+ end
54
+
55
+ def parse_json string
56
+ begin
57
+ json = JSON.parse(string)
58
+ rescue JSON::ParserError => ex
59
+ puts "Length: #{string.length}\n"
60
+ abort "Error #{ex.class}, message: #{ex.message}"
61
+ end
62
+
63
+ json['prefix'].each do |k, v|
64
+ self.prefix k, v
65
+ end unless !json.key? 'prefix'
66
+
67
+ json['entity'].each do |k, v|
68
+ self.entity k, v
69
+ end unless !json.key? 'entity'
70
+
71
+ json['activity'].each do |k, v|
72
+ self.activity k, v
73
+ end unless !json.key? 'activity'
74
+
75
+ json['agent'].each do |k, v|
76
+ self.activity k, v
77
+ end unless !json.key? 'agent'
78
+
79
+ json['used'].each do |k, v|
80
+ self.used k, v
81
+ end unless !json.key? 'used'
82
+
83
+ json['wasGeneratedBy'].each do |k, v|
84
+ self.wasGeneratedBy k, v
85
+ end unless !json.key? 'wasGeneratedBy'
86
+
87
+ json['wasDerivedFrom'].each do |k, v|
88
+ self.wasDerivedFrom k, v
89
+ end unless !json.key? 'wasDerivedFrom'
90
+
91
+ json['wasInformedBy'].each do |k, v|
92
+ self.wasInformedBy k, v
93
+ end unless !json.key? 'wasInformedBy'
94
+
95
+ json['relation'].each do |k, v|
96
+ self.relation k, v
97
+ end unless !json.key? 'relation'
98
+
99
+ json['wasAssociatedWith'].each do |k, v|
100
+ self.wasAssociatedWith k, v
101
+ end unless !json.key? 'wasAssociatedWith'
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,103 @@
1
+ require 'rgl/adjacency'
2
+ require 'rgl/dot'
3
+ require 'rgl/topsort'
4
+ require 'rgl/transitivity'
5
+
6
+ module CamTool
7
+ class ProvJSONtoRGL < ProvJSONParser
8
+ attr_reader :dg
9
+ attr_reader :map
10
+ attr_reader :edges
11
+
12
+ def initialize
13
+ @dg = RGL::DirectedAdjacencyGraph.new # initialise the graph structure
14
+ @map = Hash.new
15
+ @edges = Hash.new
16
+ end
17
+
18
+ def entity k, v
19
+ @map[k] = v
20
+ end
21
+
22
+ def activity k, v
23
+ @map[k] = v
24
+ end
25
+
26
+ def agent k, v
27
+ @map[k] = v
28
+ end
29
+
30
+ def used k, v
31
+ @dg.add_edge v['prov:activity'], v['prov:entity']
32
+ @edges[v['prov:activity']+v['prov:entity']] = v
33
+ end
34
+
35
+ def wasGeneratedBy k, v
36
+ @dg.add_edge v['prov:entity'], v['prov:activity']
37
+ @edges[v['prov:entity']+v['prov:activity']] = v
38
+ end
39
+
40
+ def wasDerivedFrom k, v
41
+ @dg.add_edge v['prov:generatedEntity'], v['prov:usedEntity']
42
+ @edges[v['prov:generatedEntity']+v['prov:usedEntity']] = v
43
+ end
44
+
45
+ def wasInformedBy k, v
46
+ @dg.add_edge v['prov:informed'], v['prov:informant']
47
+ @edges[v['prov:informed']+v['prov:informant']] = v
48
+ end
49
+
50
+ def wasAssociatedWith k, v
51
+ @dg.add_edge v['prov:activity'], v['prov:agent']
52
+ @edges[v['prov:activity']+v['prov:agent']] = v
53
+ @dg.add_edge v['prov:agent'], v['prov:plan'] unless !v.key? 'prov:plan'
54
+ end
55
+
56
+ def information
57
+ str = "Graph:\n"
58
+ if @dg.directed?
59
+ str += "directed\n"
60
+ else
61
+ str += "not directed\n"
62
+ end
63
+
64
+ if @dg.acyclic?
65
+ str += "acyclic\n"
66
+ else
67
+ str += "not acyclic\n"
68
+ end
69
+
70
+ str += @dg.num_edges.to_s() +" edges.\n"
71
+ str += @dg.num_vertices.to_s() +" vertices.\n"
72
+ str += (@dg.num_edges.to_f/@dg.num_vertices).to_s() + " edges/vertices ratio.\n"
73
+ end
74
+
75
+ def validate
76
+ abort 'Graph is not directed!' unless @dg.directed?
77
+ abort 'Graph is not acyclic!' unless @dg.acyclic?
78
+ end
79
+
80
+ def svg
81
+ @dg.write_to_graphic_file('svg')
82
+ end
83
+
84
+ def jpg
85
+ @dg.write_to_graphic_file('jpg')
86
+ end
87
+
88
+ def png
89
+ @dg.write_to_graphic_file('png')
90
+ end
91
+
92
+ def list types
93
+ a = @dg.topsort_iterator.to_a
94
+ a_type = types.split(',')
95
+ a.each do |v|
96
+ if a_type.include?(@map[v]['prov:type']) || types.nil?
97
+ puts v + ' ' + @map[v]['prov:label'] unless @map[v]['prov:label'].nil?
98
+ puts v + ' no label' unless !@map[v]['prov:label'].nil?
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,7 @@
1
+ module CamTool
2
+ VERSION = "0.1.0"
3
+
4
+ def self.version
5
+ puts VERSION
6
+ end
7
+ end
@@ -0,0 +1,33 @@
1
+ module CamTool
2
+ class VertexCounter < ProvJSONParser
3
+ attr_reader :map
4
+
5
+ def initialize
6
+ @map = Hash.new(0)
7
+ end
8
+
9
+ def add key
10
+ @map[key]=@map[key]+1
11
+ end
12
+
13
+ def entity k, v
14
+ self.add v['prov:type']
15
+ end
16
+
17
+ def activity k, v
18
+ self.add v['prov:type']
19
+ end
20
+
21
+ def agent k, v
22
+ self.add v['prov:type']
23
+ end
24
+
25
+ def show
26
+ puts "\n\n-------------\nVertex types\n-------------\n"
27
+ @map = @map.sort_by { |key, value| value }.reverse
28
+ @map.each do |key, value|
29
+ puts "#{key}:#{value}"
30
+ end
31
+ end
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: camtool
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Pasquier
8
+ - Xuehuan "Michael" Han
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-01-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rgl
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0.5'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0.5'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rinruby
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '2.0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '2.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: json
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '2.1'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '2.1'
56
+ - !ruby/object:Gem::Dependency
57
+ name: mqtt
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0.5'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0.5'
70
+ - !ruby/object:Gem::Dependency
71
+ name: bundler
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '1.16'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '1.16'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rake
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '10.0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '10.0'
98
+ description: Allow to test, publish and manipulate camflow log files.
99
+ email:
100
+ - tfjmp@seas.harvard.edu
101
+ executables:
102
+ - camtool
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - LICENSE
107
+ - README.md
108
+ - bin/camtool
109
+ - lib/camtool.rb
110
+ - lib/camtool/breaker_mqtt.rb
111
+ - lib/camtool/check_packet.rb
112
+ - lib/camtool/edge_counter.rb
113
+ - lib/camtool/edge_validator.rb
114
+ - lib/camtool/log_breaker.rb
115
+ - lib/camtool/provjson_parser.rb
116
+ - lib/camtool/provjson_to_rgl.rb
117
+ - lib/camtool/version.rb
118
+ - lib/camtool/vertex_counter.rb
119
+ homepage: https://github.com/tfjmp/camtool
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubygems_version: 3.0.2
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Tool to manipulate CamFlow log files.
142
+ test_files: []