bqm 1.3.0 → 1.5.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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/DOC.md +4 -0
  3. data/bin/bqm +53 -8
  4. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d78da6d030479d62b8fc734bde08fddc8ff97ca4502855287cb543b1d5f50fd
4
- data.tar.gz: 836675f08cab5fe97744eae3c4f53182e2bbc9928f099540e94c36af576f3b56
3
+ metadata.gz: 1a14c962fd0bf2a8c456bf7b9ff5416036289f61a8d4030ed246a77b6115aec0
4
+ data.tar.gz: d9d0bf051756b2eba968cdb37945fd953db2746b646f6a9888c4100207979792
5
5
  SHA512:
6
- metadata.gz: 8d3f43f194866b90855ec27c36dfecdd3ba5131b424616f08eaf7ac0f75c02975d92553ae02f0f807246cfe61fd198ee2da06f6068b0e3d0e9c284f57ec41eca
7
- data.tar.gz: fa5e9708365a8ac529c0a67b8c46bbc3aa901c91dac6d01b706d390c1211a534887eedcfaf31cfcbe0fd3350e4f5d9b1d1047fb6303e1543c7a4ec38d9b9079b
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
@@ -14,13 +14,42 @@ def find_dataset
14
14
  raise IOError, "The dataset file #{source_file} does not exist or is unreadable."
15
15
  end
16
16
 
17
- def merge(source)
17
+ # Merge remote sets defined in data/query-sets.json
18
+ def merge_remote(source, verbose: false)
18
19
  sets = get_datasets(source)
19
20
  queries = []
20
21
  sets.each do |s|
21
22
  customqueries = Net::HTTP.get(URI(s))
22
23
  data = JSON.parse(customqueries)
23
24
  queries += data['queries']
25
+ puts " [*] File merged: #{s}" if verbose
26
+ end
27
+ queries
28
+ end
29
+
30
+ # Merge local sets provided by the user
31
+ def merge_local(sources, verbose: false)
32
+ queries = []
33
+ sources.each do |source|
34
+ # If it's a file parse it
35
+ if File.file?(source) && File.readable?(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"
43
+ end
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)
50
+ else
51
+ raise IOError, "The dataset file/directory #{source} does not exist or is unreadable."
52
+ end
24
53
  end
25
54
  queries
26
55
  end
@@ -59,27 +88,40 @@ def pretty_link(lst)
59
88
  end
60
89
 
61
90
  def get_datasets(source)
91
+ src = json_load(source)
92
+ src['sets']
93
+ end
94
+
95
+ def json_load(file)
62
96
  # ruby 3.0+
63
97
  begin
64
- src = JSON.load_file(source)
98
+ src = JSON.load_file(file)
65
99
  rescue NoMethodError # ruby 2.7 retro-compatibility
66
- src = JSON.parse(File.read(source))
100
+ src = JSON.parse(File.read(file))
67
101
  end
68
- src['sets']
102
+ src
69
103
  end
70
104
 
71
105
  if __FILE__ == $PROGRAM_NAME
72
106
  source = find_dataset
73
107
 
74
108
  require 'optparse'
75
- options = {}
109
+ options = {
110
+ 'local-sets': []
111
+ }
76
112
  OptionParser.new do |parser|
77
113
  parser.banner = 'Usage: bqm [options]'
78
114
 
79
115
  parser.on('-o', '--output-path PATH', 'Path where to store the query file')
80
116
  parser.on('-l', '--list', 'List available datasets')
117
+ parser.on('-i', '--local-sets FILE,DIRECTORY,...', Array, 'Local custom queries files/directories') do |f|
118
+ options[:'local-sets'] += f
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')
81
122
  parser.separator ''
82
123
  parser.separator 'Example: bqm -o ~/.config/bloodhound/customqueries.json'
124
+ parser.separator 'Example: bqm -o /tmp/customqueries.json -i /tmp/a.json,/home/user/folder'
83
125
  end.parse!(into: options)
84
126
 
85
127
  out = options[:'output-path']
@@ -95,15 +137,18 @@ if __FILE__ == $PROGRAM_NAME
95
137
  if File.file?(out) && File.readable?(out)
96
138
  puts "[+] The output path #{out} already exists"
97
139
  puts '[?] Do you want to overwrite it? [y/n]'
98
- if gets.chomp == 'y'
140
+ if $stdin.gets.chomp == 'y'
99
141
  puts '[?] What to do with the existing queries? (merge / discard) [m/d]'
100
- flags[:merge_actual] = true if gets.chomp == 'm'
142
+ flags[:merge_actual] = true if $stdin.gets.chomp == 'm'
101
143
  else
102
144
  exit
103
145
  end
104
146
  end
105
147
  puts '[+] Fetching and merging datasets'
106
- data = merge(source)
148
+ data = []
149
+ data = merge_remote(source, verbose: options[:verbose]) unless options[:'ignore-default']
150
+ local_set = options[:'local-sets']
151
+ data += merge_local(local_set, verbose: options[:verbose]) if local_set
107
152
  if flags[:merge_actual]
108
153
  puts '[+] Merging your existing queries'
109
154
  data += JSON.parse(File.read(out))['queries']
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.3.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-02-27 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
@@ -26,6 +27,8 @@ licenses:
26
27
  - MIT
27
28
  metadata:
28
29
  bug_tracker_uri: https://github.com/Acceis/bqm/issues
30
+ changelog_uri: https://github.com/Acceis/bqm/releases
31
+ documentation_uri: https://acceis.github.io/bqm/
29
32
  homepage_uri: https://github.com/Acceis/bqm
30
33
  source_code_uri: https://github.com/Acceis/bqm/
31
34
  rubygems_mfa_required: 'true'