plunk 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9995468d364aaf1391ad67f6d1f8ddb4e65a6553
4
- data.tar.gz: f1594cf5f75541b1cfec6a2d82fa9eb55d243345
3
+ metadata.gz: 599c26a054ac47928ba6b476dcf62c2731b07305
4
+ data.tar.gz: d10dbfe0b2c3d3d26611a509b1e699bc42b8e412
5
5
  SHA512:
6
- metadata.gz: 26187e0add2cc39f6fe1e915e701bf237a8638c61d81331c430c934f98f588a89007edf2813765dde894c3da5238b86dadb671f3b7e408a03ee24e8a99d64117
7
- data.tar.gz: 95473787d59e19a6d984a170a78f64ff8dad05e9f69592ffdc57c33d0a5fe4e6bc548328af6c25719c8083e25e3b89d294cec53b3a912f02cb4ecc25c6703d03
6
+ metadata.gz: 1f5facdc7cedcfdb9a94d7f51a148ad72319b1ebd55ae54449c6e860f6a173149da2f5ec95697ef2a7e23bcd2af46535154bfba46030345864f07ab2c244144d
7
+ data.tar.gz: 0b8b372f4b1b5ca0ae46cfcb3d2214e68dcc5490432b9117bb02d84f8e2cbf564f8322b961d385eb0ea57116e1b4b3b2b542d16f105364702573c8a4a0a56ec9
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- plunk (0.0.6)
4
+ plunk (0.0.7)
5
5
  activesupport
6
6
  json
7
7
  parslet
@@ -19,7 +19,7 @@ class Plunk::Parser < Parslet::Parser
19
19
  # Field / value
20
20
  rule(:identifier) { match['_@a-zA-Z.'].repeat(1) }
21
21
  rule(:wildcard) { match('[a-zA-Z0-9.*]').repeat(1) }
22
- rule(:searchop) { match('[=]').as(:op) >> space? }
22
+ rule(:searchop) { match('[=]').as(:op) }
23
23
 
24
24
  # boolean operators search
25
25
  rule(:concatop) { (str('OR') | str('AND')) >> space? }
@@ -30,27 +30,27 @@ class Plunk::Parser < Parslet::Parser
30
30
 
31
31
  # Grammar parts
32
32
  rule(:rhs) {
33
- (regex | wildcard | integer | subsearch |
34
- (lparen >> (space? >> (wildcard | integer) >>
35
- (space >> concatop).maybe).repeat(1) >> rparen))
33
+ regexp | subsearch | integer | wildcard |
34
+ (lparen >> (space? >> (wildcard | integer) >>
35
+ (space >> concatop).maybe).repeat(1) >> rparen).maybe
36
36
  }
37
37
 
38
- rule(:regex) {
38
+ rule(:regexp) {
39
39
  str('/') >> match('[^/]').repeat >> str('/')
40
40
  }
41
41
 
42
+ rule(:last) {
43
+ str("last") >> space >> timerange.as(:timerange) >> (space >>
44
+ search.as(:search)).maybe
45
+ }
46
+
42
47
  rule(:search) {
43
48
  identifier.as(:field) >> space? >> searchop >> space? >>
44
49
  rhs.as(:value) | rhs.as(:match)
45
50
  }
46
51
 
47
- rule(:last) {
48
- str("last") >> space >> timerange.as(:timerange) >> space >>
49
- search.as(:search)
50
- }
51
-
52
52
  rule(:binaryop) {
53
- (paren | search).as(:left) >> space? >> operator >> job.as(:right)
53
+ (search | paren).as(:left) >> space? >> operator >> job.as(:right)
54
54
  }
55
55
 
56
56
  rule(:subsearch) {
@@ -58,12 +58,9 @@ class Plunk::Parser < Parslet::Parser
58
58
  }
59
59
 
60
60
  rule(:nested_search) {
61
- match('[^|]').repeat.as(:term) >> str('|') >> space? >>
61
+ match('[^|]').repeat.as(:initial_query) >> str('|') >> space? >>
62
62
  match('[^`]').repeat.as(:extractors)
63
- }
64
-
65
- rule(:joined_search) {
66
-
63
+ # job >> str('|') >> space? >>
67
64
  }
68
65
 
69
66
  rule(:paren) {
@@ -71,7 +68,7 @@ class Plunk::Parser < Parslet::Parser
71
68
  }
72
69
 
73
70
  rule(:job) {
74
- binaryop | paren | last | search
71
+ last | search | binaryop | paren
75
72
  }
76
73
 
77
74
  # root :job
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "plunk"
3
- s.version = "0.0.7"
3
+ s.version = "0.0.8"
4
4
  s.date = "2013-12-03"
5
5
  s.add_runtime_dependency "json"
6
6
  s.add_runtime_dependency "parslet"
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'basic searches' do
4
+ before :each do
5
+ @parsed = @parser.parse 'bar'
6
+ end
7
+
8
+ it 'should parse a single keyword' do
9
+ expect(@parsed[:match].to_s).to eq 'bar'
10
+ end
11
+
12
+ context 'transformed' do
13
+ before :each do
14
+ @result_set = @transformer.apply(@parsed)
15
+ end
16
+
17
+ it 'should be a proper query' do
18
+ @result_set.query.should eq({
19
+ query: {
20
+ query_string: {
21
+ query: 'bar'
22
+ }}})
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'boolean searches' do
4
+ it 'should parse last command with boolean' do
5
+ @parsed = @parser.parse 'last 1h (foo OR bar)'
6
+ expect(@parsed[:search][:match].to_s).to eq '(foo OR bar)'
7
+ end
8
+
9
+ it 'should parse a single field / value complex boolean expression' do
10
+ @parsed = @parser.parse 'ids.attackers=(bar OR car)'
11
+ expect(@parsed[:field].to_s).to eq 'ids.attackers'
12
+ expect(@parsed[:value].to_s).to eq '(bar OR car)'
13
+ expect(@parsed[:op].to_s).to eq '='
14
+ end
15
+
16
+ it 'should parse a single boolean expression' do
17
+ @parsed = @parser.parse '(bar OR car)'
18
+ expect(@parsed[:match].to_s).to eq '(bar OR car)'
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'field / value searches' do
4
+ it 'should parse a single field/value combo' do
5
+ @parsed = @parser.parse 'tshark.http.@src_ip=bar'
6
+ expect(@parsed[:field].to_s).to eq 'tshark.http.@src_ip'
7
+ expect(@parsed[:value].to_s).to eq 'bar'
8
+ expect(@parsed[:op].to_s).to eq '='
9
+ end
10
+
11
+ it 'should parse a single field / parenthesized value' do
12
+ @parsed = @parser.parse 'ids.attacker=(10.150.44.195)'
13
+ expect(@parsed[:field].to_s).to eq 'ids.attacker'
14
+ expect(@parsed[:value].to_s).to eq '(10.150.44.195)'
15
+ expect(@parsed[:op].to_s).to eq '='
16
+ end
17
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'the last command' do
4
+ context 'basic' do
5
+ it 'should parse a standalone last command' do
6
+ @parsed = @parser.parse 'last 24h'
7
+ expect(@parsed[:timerange][:quantity].to_s).to eq '24'
8
+ expect(@parsed[:timerange][:quantifier].to_s).to eq 'h'
9
+ end
10
+ end
11
+
12
+ context 'complex' do
13
+ before :all do
14
+ @parsed = @parser.parse 'last 24w tshark.@src_ip = bar'
15
+ end
16
+
17
+ it 'should parse last command with a search' do
18
+ expect(@parsed[:timerange][:quantity].to_s).to eq '24'
19
+ expect(@parsed[:timerange][:quantifier].to_s).to eq 'w'
20
+ expect(@parsed[:search][:field].to_s).to eq 'tshark.@src_ip'
21
+ expect(@parsed[:search][:value].to_s).to eq 'bar'
22
+ end
23
+
24
+ context 'transformation' do
25
+ before :each do
26
+ @result_set = @transformer.apply(@parsed)
27
+ end
28
+
29
+ it 'should have the proper result set' do
30
+ @result_set.should be_a Plunk::ResultSet
31
+ @result_set.query.should be_present
32
+
33
+ query = { query: {
34
+ query_string: {
35
+ query: "tshark.@src_ip:bar"
36
+ },
37
+ range: {
38
+ '@timestamp' => {
39
+ gte: 24.weeks.ago,
40
+ lte: Time.now
41
+ }}}}
42
+
43
+ @result_set.query.to_json.should eq query.to_json
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'nested searches' do
4
+ it 'should parse a nested basic search' do
5
+ @parsed = @parser.parse 'tshark.len = ` 226 | tshark.frame.time_epoch,tshark.ip.src`'
6
+ expect(@parsed[:field].to_s).to eq 'tshark.len'
7
+ expect(@parsed[:op].to_s).to eq '='
8
+ expect(@parsed[:value][:initial_query].to_s).to eq '226 '
9
+ expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
10
+ end
11
+
12
+ it 'should parse a nested regexp' do
13
+ @parsed = @parser.parse 'tshark.len = ` cif.malicious_ips=/foo/ | tshark.frame.time_epoch,tshark.ip.src`'
14
+ expect(@parsed[:field].to_s).to eq 'tshark.len'
15
+ expect(@parsed[:op].to_s).to eq '='
16
+ expect(@parsed[:value][:initial_query].to_s).to eq 'cif.malicious_ips=/foo/ '
17
+ expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
18
+ end
19
+
20
+ it 'should parse a nested basic boolean' do
21
+ @parsed = @parser.parse 'tshark.len = `(foo OR bar) | tshark.frame.time_epoch,tshark.ip.src`'
22
+ expect(@parsed[:field].to_s).to eq 'tshark.len'
23
+ expect(@parsed[:op].to_s).to eq '='
24
+ expect(@parsed[:value][:initial_query].to_s).to eq '(foo OR bar) '
25
+ expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
26
+ end
27
+
28
+ it 'should parse a nested field / value boolean' do
29
+ @parsed = @parser.parse 'tshark.len = `baz=(foo OR bar AND (bar OR fez)) | tshark.frame.time_epoch,tshark.ip.src`'
30
+ expect(@parsed[:field].to_s).to eq 'tshark.len'
31
+ expect(@parsed[:op].to_s).to eq '='
32
+ expect(@parsed[:value][:initial_query].to_s).to eq 'baz=(foo OR bar AND (bar OR fez)) '
33
+ expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
34
+ end
35
+
36
+ it 'should parse a nested last standalone timerange' do
37
+ @parsed = @parser.parse 'tshark.len = `last 24h | tshark.frame.time_epoch,tshark.ip.src`'
38
+ expect(@parsed[:field].to_s).to eq 'tshark.len'
39
+ expect(@parsed[:op].to_s).to eq '='
40
+ expect(@parsed[:value][:initial_query].to_s).to eq 'last 24h '
41
+ expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
42
+ end
43
+
44
+ it 'should parse a nested last timerange and field / value pair' do
45
+ @parsed = @parser.parse 'tshark.len = `last 24h foo=bar | tshark.frame.time_epoch,tshark.ip.src`'
46
+ expect(@parsed[:field].to_s).to eq 'tshark.len'
47
+ expect(@parsed[:op].to_s).to eq '='
48
+ expect(@parsed[:value][:initial_query].to_s).to eq 'last 24h foo=bar '
49
+ expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'regexp searches' do
4
+ context 'simple' do
5
+ it 'should parse a basic regexp search' do
6
+ @parsed = @parser.parse 'foo=/blah foo/'
7
+ expect(@parsed[:field].to_s).to eq 'foo'
8
+ expect(@parsed[:value].to_s).to eq '/blah foo/'
9
+ end
10
+ end
11
+
12
+ context 'complex' do
13
+ it 'should parse key/value with regex' do
14
+ @parsed = @parser.parse 'foo=bar fe.ip=/whodunnit/'
15
+ expect(@parsed[0][:field].to_s).to eq 'foo'
16
+ expect(@parsed[0][:value].to_s).to eq 'bar'
17
+ expect(@parsed[1][:field].to_s).to eq 'fe.ip'
18
+ expect(@parsed[1][:value].to_s).to eq '/whodunnit/'
19
+ end
20
+
21
+ it 'should parse last command with a regex' do
22
+ @parsed = @parser.parse 'last 24w foo=/blah/'
23
+ expect(@parsed[:timerange][:quantity].to_s).to eq '24'
24
+ expect(@parsed[:timerange][:quantifier].to_s).to eq 'w'
25
+ expect(@parsed[:search][:field].to_s).to eq 'foo'
26
+ expect(@parsed[:search][:value].to_s).to eq '/blah/'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ require 'rspec'
2
+ require 'plunk'
3
+ require 'plunk/parser'
4
+ require 'plunk/transformer'
5
+ require 'plunk/result_set'
6
+ require 'parslet/rig/rspec'
7
+
8
+ # Print ascii_tree when exception occurs
9
+ class Plunk::ParserWrapper < Plunk::Parser
10
+ def parse(query)
11
+ begin
12
+ super(query)
13
+ rescue Parslet::ParseFailed => failure
14
+ puts failure.cause.ascii_tree
15
+ end
16
+ end
17
+ end
18
+
19
+ RSpec.configure do |config|
20
+ config.before :all do
21
+ @parser = Plunk::ParserWrapper.new
22
+ @transformer = Plunk::Transformer.new
23
+ end
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plunk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ram Mehta
@@ -101,10 +101,14 @@ files:
101
101
  - lib/plunk/result_set.rb
102
102
  - lib/plunk/transformer.rb
103
103
  - plunk.gemspec
104
+ - spec/basic_spec.rb
105
+ - spec/boolean_spec.rb
104
106
  - spec/elasticsearch_spec.rb
105
- - spec/parser_spec.rb
106
- - spec/result_set_spec.rb
107
- - spec/transformer_spec.rb
107
+ - spec/field_value_spec.rb
108
+ - spec/last_spec.rb
109
+ - spec/nested_search_spec.rb
110
+ - spec/regexp_spec.rb
111
+ - spec/spec_helper.rb
108
112
  homepage: https://github.com/elbii/plunk
109
113
  licenses:
110
114
  - MIT
@@ -1,128 +0,0 @@
1
- require 'plunk'
2
- require 'plunk/parser'
3
-
4
- # Print ascii_tree when exception occurs
5
- class Plunk::ParserWrapper < Plunk::Parser
6
- def parse(query)
7
- begin
8
- super(query)
9
- rescue Parslet::ParseFailed => failure
10
- puts failure.cause.ascii_tree
11
- end
12
- end
13
- end
14
-
15
- describe Plunk::Parser do
16
- before :all do
17
- @parser = Plunk::ParserWrapper.new
18
- @transformer = Plunk::Transformer.new
19
- end
20
-
21
- context 'single-query searches' do
22
- it 'should parse a single keyword' do
23
- @parsed = @parser.parse 'bar'
24
- expect(@parsed[:match].to_s).to eq 'bar'
25
- end
26
-
27
- it 'should parse a single field/value combo' do
28
- @parsed = @parser.parse 'tshark.http.@src_ip=bar'
29
- expect(@parsed[:field].to_s).to eq 'tshark.http.@src_ip'
30
- expect(@parsed[:value].to_s).to eq 'bar'
31
- expect(@parsed[:op].to_s).to eq '='
32
- end
33
-
34
- it 'should parse a single boolean expression' do
35
- @parsed = @parser.parse '(bar OR car)'
36
- expect(@parsed[:match].to_s).to eq '(bar OR car)'
37
- end
38
-
39
- it 'should parse a single field / value complex boolean expression' do
40
- @parsed = @parser.parse 'ids.attackers=(bar OR car)'
41
- expect(@parsed[:field].to_s).to eq 'ids.attackers'
42
- expect(@parsed[:value].to_s).to eq '(bar OR car)'
43
- expect(@parsed[:op].to_s).to eq '='
44
- end
45
-
46
- it 'should parse a single field / parenthesized value' do
47
- @parsed = @parser.parse 'ids.attacker=(10.150.44.195)'
48
- expect(@parsed[:field].to_s).to eq 'ids.attacker'
49
- expect(@parsed[:value].to_s).to eq '(10.150.44.195)'
50
- expect(@parsed[:op].to_s).to eq '='
51
- end
52
-
53
- it 'should parse a basic regex search' do
54
- @parsed = @parser.parse 'foo=/blah foo/'
55
- expect(@parsed[:field].to_s).to eq 'foo'
56
- expect(@parsed[:value].to_s).to eq '/blah foo/'
57
- end
58
-
59
- context 'the last command' do
60
- before :each do
61
- @parsed = @parser.parse 'last 24w tshark.@src_ip = bar'
62
- end
63
-
64
- it 'should parse last command with a search' do
65
- expect(@parsed[:timerange][:quantity].to_s).to eq '24'
66
- expect(@parsed[:timerange][:quantifier].to_s).to eq 'w'
67
- expect(@parsed[:search][:field].to_s).to eq 'tshark.@src_ip'
68
- expect(@parsed[:search][:value].to_s).to eq 'bar'
69
- end
70
-
71
- context 'transformation' do
72
- before :each do
73
- @result_set = @transformer.apply(@parsed)
74
- end
75
-
76
- it 'should have the proper result set' do
77
- @result_set.should be_a Plunk::ResultSet
78
- @result_set.query.should be_present
79
-
80
- query = { query: {
81
- query_string: {
82
- query: "tshark.@src_ip:bar"
83
- },
84
- range: {
85
- '@timestamp' => {
86
- gte: 24.weeks.ago,
87
- lte: Time.now
88
- }}}}
89
-
90
- @result_set.query.to_json.should eq query.to_json
91
- end
92
- end
93
- end
94
-
95
- context 'chained searches' do
96
- it 'should parse last command with a regex' do
97
- @parsed = @parser.parse 'last 24w foo=/blah/'
98
- expect(@parsed[:timerange][:quantity].to_s).to eq '24'
99
- expect(@parsed[:timerange][:quantifier].to_s).to eq 'w'
100
- expect(@parsed[:search][:field].to_s).to eq 'foo'
101
- expect(@parsed[:search][:value].to_s).to eq '/blah/'
102
- end
103
- end
104
-
105
- it 'should parse last command with boolean' do
106
- @parsed = @parser.parse 'last 1h (foo OR bar)'
107
- expect(@parsed[:search][:match].to_s).to eq '(foo OR bar)'
108
- end
109
-
110
- it 'should parse key/value with regex' do
111
- @parsed = @parser.parse 'foo=bar fe.ip=/whodunnit/'
112
- expect(@parsed[0][:field].to_s).to eq 'foo'
113
- expect(@parsed[0][:value].to_s).to eq 'bar'
114
- expect(@parsed[1][:field].to_s).to eq 'fe.ip'
115
- expect(@parsed[1][:value].to_s).to eq '/whodunnit/'
116
- end
117
- end
118
-
119
- context 'nested search' do
120
- it 'should parse the nested search' do
121
- @parsed = @parser.parse 'tshark.len = ` 226 | tshark.frame.time_epoch,tshark.ip.src`'
122
- expect(@parsed[:field].to_s).to eq 'tshark.len'
123
- expect(@parsed[:op].to_s).to eq '='
124
- expect(@parsed[:value][:term].to_s).to eq '226 '
125
- expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
126
- end
127
- end
128
- end
@@ -1,4 +0,0 @@
1
- require 'plunk/result_set'
2
-
3
- describe Plunk::ResultSet do
4
- end
@@ -1,4 +0,0 @@
1
- require 'plunk/transformer'
2
-
3
- describe Plunk::Transformer do
4
- end