bqm 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/DOC.md +4 -0
  3. data/bin/bqm +37 -21
  4. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a7ea69f913278933cdcbae6a764b166d7990931ce1f68c1264f3c0127f548ad
4
- data.tar.gz: 65a2b6a2aa1e78864e48671a2f8b5e4ce395fa0eaead13ce3098806cc6391ce9
3
+ metadata.gz: 1a14c962fd0bf2a8c456bf7b9ff5416036289f61a8d4030ed246a77b6115aec0
4
+ data.tar.gz: d9d0bf051756b2eba968cdb37945fd953db2746b646f6a9888c4100207979792
5
5
  SHA512:
6
- metadata.gz: be95aaeccf71fb47aac6179e3be127d5d456fc88e4f67b1798b46dfafcf24cba0220cc6c5569fba98acbd24b9ca2f6bde71adb2604e9b0d9e2e4afeb56bb743f
7
- data.tar.gz: c752dc0e0d790b2b9e5337d5622cf05fd5d553558d7c3cb6654829ad54d8fb88157849e4d70c5a55589327c136dd2d442a857089d244923062953ba6b3a06f83
6
+ metadata.gz: 2283d7f843cfec5c8de3cf92044a12ed3731474125c6fa70675476cbce028b6dc26d8bdfd6ceafd8dd940d2a33a7d763558834a7ecbc709ab72b1ebcba18dc0c
7
+ data.tar.gz: 5f22350ef473520e98f26facab2a7a583b07739f0aa03b9d0fb312199a696e074ae311191476883af12bd46b1bf2413e4c519dd997a257d9ddca52e022ce4222
data/DOC.md ADDED
@@ -0,0 +1,4 @@
1
+ ## Options
2
+
3
+ - `-i`, `--local-sets`: if several items are provided, they must be comma (`,`) separated. Items can be either a Bloodhound custom query file, a bqm or a folder. In case of a bqm query sets file (similar to `query-sets.json`) or a folder, bqm will try to parse all JSON files inside it, so the folder should not contain other types of JSON files.
4
+ - `--ignore-default`: ignore the default `query-sets.json`. It's useful for **offline** usage or if you don't want the default data sets.
data/bin/bqm CHANGED
@@ -15,30 +15,40 @@ def find_dataset
15
15
  end
16
16
 
17
17
  # Merge remote sets defined in data/query-sets.json
18
- def merge_remote(source)
18
+ def merge_remote(source, verbose: false)
19
19
  sets = get_datasets(source)
20
20
  queries = []
21
21
  sets.each do |s|
22
22
  customqueries = Net::HTTP.get(URI(s))
23
23
  data = JSON.parse(customqueries)
24
24
  queries += data['queries']
25
+ puts " [*] File merged: #{s}" if verbose
25
26
  end
26
27
  queries
27
28
  end
28
29
 
29
30
  # Merge local sets provided by the user
30
- def merge_local(sources)
31
+ def merge_local(sources, verbose: false)
31
32
  queries = []
32
33
  sources.each do |source|
34
+ # If it's a file parse it
33
35
  if File.file?(source) && File.readable?(source)
34
- begin
35
- data = JSON.load_file(source)
36
- rescue NoMethodError # ruby 2.7 retro-compatibility
37
- data = JSON.parse(File.read(source))
36
+ data = json_load(source)
37
+ if data['queries']
38
+ queries += data['queries']
39
+ elsif data['sets']
40
+ queries += merge_remote(source, verbose: verbose)
41
+ else
42
+ raise KeyError, "The file #{source} is neiter a Bloodhound custom query file nor a bqm query sets file"
38
43
  end
39
- queries += data['queries']
44
+ puts " [*] File merged: #{source}" if verbose
45
+ # If it's a folder, retrieve all JSON files and assumes there are queries files
46
+ # Then recursive call for a normal file parsing
47
+ elsif File.directory?(source) && File.readable?(source)
48
+ qfiles = Dir.glob('*.json', base: source).map { |f| File.absolute_path(f, source) }
49
+ queries += merge_local(qfiles, verbose: verbose)
40
50
  else
41
- raise IOError, "The dataset file #{source} does not exist or is unreadable."
51
+ raise IOError, "The dataset file/directory #{source} does not exist or is unreadable."
42
52
  end
43
53
  end
44
54
  queries
@@ -78,13 +88,18 @@ def pretty_link(lst)
78
88
  end
79
89
 
80
90
  def get_datasets(source)
91
+ src = json_load(source)
92
+ src['sets']
93
+ end
94
+
95
+ def json_load(file)
81
96
  # ruby 3.0+
82
97
  begin
83
- src = JSON.load_file(source)
98
+ src = JSON.load_file(file)
84
99
  rescue NoMethodError # ruby 2.7 retro-compatibility
85
- src = JSON.parse(File.read(source))
100
+ src = JSON.parse(File.read(file))
86
101
  end
87
- src['sets']
102
+ src
88
103
  end
89
104
 
90
105
  if __FILE__ == $PROGRAM_NAME
@@ -92,19 +107,21 @@ if __FILE__ == $PROGRAM_NAME
92
107
 
93
108
  require 'optparse'
94
109
  options = {
95
- :'local-sets' => []
110
+ 'local-sets': []
96
111
  }
97
112
  OptionParser.new do |parser|
98
113
  parser.banner = 'Usage: bqm [options]'
99
114
 
100
115
  parser.on('-o', '--output-path PATH', 'Path where to store the query file')
101
116
  parser.on('-l', '--list', 'List available datasets')
102
- parser.on('-i', '--local-sets FILE,...', Array, 'Local custom queries files') do |f|
117
+ parser.on('-i', '--local-sets FILE,DIRECTORY,...', Array, 'Local custom queries files/directories') do |f|
103
118
  options[:'local-sets'] += f
104
119
  end
120
+ parser.on('--ignore-default', 'Ignore the default query-sets.json')
121
+ parser.on('-v', '--verbose', 'Display the name of the merged files/sets')
105
122
  parser.separator ''
106
123
  parser.separator 'Example: bqm -o ~/.config/bloodhound/customqueries.json'
107
- parser.separator 'Example: bqm -o /tmp/customqueries.json -i /tmp/a.json,/tmp/b.json'
124
+ parser.separator 'Example: bqm -o /tmp/customqueries.json -i /tmp/a.json,/home/user/folder'
108
125
  end.parse!(into: options)
109
126
 
110
127
  out = options[:'output-path']
@@ -120,20 +137,19 @@ if __FILE__ == $PROGRAM_NAME
120
137
  if File.file?(out) && File.readable?(out)
121
138
  puts "[+] The output path #{out} already exists"
122
139
  puts '[?] Do you want to overwrite it? [y/n]'
123
- if STDIN.gets.chomp == 'y'
140
+ if $stdin.gets.chomp == 'y'
124
141
  puts '[?] What to do with the existing queries? (merge / discard) [m/d]'
125
- flags[:merge_actual] = true if STDIN.gets.chomp == 'm'
142
+ flags[:merge_actual] = true if $stdin.gets.chomp == 'm'
126
143
  else
127
144
  exit
128
145
  end
129
146
  end
130
147
  puts '[+] Fetching and merging datasets'
131
- data = merge_remote(source)
148
+ data = []
149
+ data = merge_remote(source, verbose: options[:verbose]) unless options[:'ignore-default']
132
150
  local_set = options[:'local-sets']
133
- if local_set
134
- data += merge_local(local_set)
135
- end
136
- if flags[:'merge_actual']
151
+ data += merge_local(local_set, verbose: options[:verbose]) if local_set
152
+ if flags[:merge_actual]
137
153
  puts '[+] Merging your existing queries'
138
154
  data += JSON.parse(File.read(out))['queries']
139
155
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bqm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre ZANNI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-26 00:00:00.000000000 Z
11
+ date: 2023-06-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Deduplicate custom BloudHound queries from different datasets and merge
14
14
  them in one customqueries.json file.
@@ -18,6 +18,7 @@ executables:
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - DOC.md
21
22
  - LICENSE
22
23
  - bin/bqm
23
24
  - data/query-sets.json