backscatterio 1.0.0 → 1.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5508c62631c77d734b28d680bbb89c49a56eda99
4
- data.tar.gz: ce8ae7f744ba3b595c591a7fc3bc8ebcd283c9f0
3
+ metadata.gz: fe9d8b796f4fd06e225d8819340b518b86356c39
4
+ data.tar.gz: 6a463a6f64fc97f3cefea14525da0531f017caf1
5
5
  SHA512:
6
- metadata.gz: f78082fa1777ec84a86bf497876bc2d79c633682129588ae287bff6c3e1634ffb012bfe0a77e1718d6ae10524954c21c598717f9871f27c104d5f6945f4cca69
7
- data.tar.gz: c2f87dc57d467364a7192f6af912da489ab5cc6e63d42f2e01383b8491d050b0d4d3522e15407e8add4db4ec68d831cefa451b42d295e1dbb3bb0d0f88ee3834
6
+ metadata.gz: e6bb446c2769eff38953008851c26e6adfad0707c54c1cb56718704311861775d973cee02af9d404bf28069b9de459868801ebd7ae7267cda88206afea4342b0
7
+ data.tar.gz: f633883a98397bc5cf335f8a51d7b0262bdf77a03a833ec88aef27d8ccff1865f3afa0f71e4b1522a1227499be3456a5b7cb5af34a7bbf3434d81cbe71985dba
Binary file
@@ -40,6 +40,6 @@ Gem::Specification.new do |s|
40
40
 
41
41
  s.files = `find *`.split("\n").uniq.sort.select { |f| !f.empty? }
42
42
  s.test_files = `find spec/*`.split("\n")
43
- s.executables = []
43
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
44
44
  s.require_paths = ["lib"]
45
45
  end
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'backscatterio'
4
+ require 'getoptlong'
5
+ require 'json'
6
+ require 'ipaddr'
7
+ require 'fileutils'
8
+
9
+ module BackscatterIO
10
+ class CLInterface
11
+ def self.detect_query(query)
12
+ begin
13
+ if query.index('/') and IPAddr.new(query[0, query.index('/')])
14
+ return 'network'
15
+ elsif IPAddr.new query
16
+ return 'ip'
17
+ end
18
+ rescue
19
+ if query =~ /^[A-Z]{2}$/i
20
+ return 'country'
21
+ elsif query =~ /^AS\d+$/i
22
+ return 'asn'
23
+ elsif query =~ /^(TCP|UDP)\d+$/i or [21, 22, 23, 25, 53, 80, 81, 113, 139, 443, 445, 1433, 5222, 5900, 8080].index(query.to_i)
24
+ return 'port'
25
+ else
26
+ return 'asn'
27
+ end
28
+ end
29
+ end
30
+
31
+ def self.parse_command_line(args)
32
+ origARGV = ARGV.dup
33
+ ARGV.replace(args)
34
+ opts = GetoptLong.new(
35
+ [ '--api-key', '-k', GetoptLong::REQUIRED_ARGUMENT ],
36
+ [ '--query', '-q', GetoptLong::REQUIRED_ARGUMENT ],
37
+ [ '--type', '-t', GetoptLong::REQUIRED_ARGUMENT ],
38
+ [ '--format', '-f', GetoptLong::REQUIRED_ARGUMENT ],
39
+ [ '--scope', '-z', GetoptLong::REQUIRED_ARGUMENT ],
40
+ [ '--count', '-c', GetoptLong::REQUIRED_ARGUMENT ],
41
+ [ '--config', '-a', GetoptLong::REQUIRED_ARGUMENT ],
42
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
43
+ [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ]
44
+ )
45
+
46
+ options = {
47
+ :command => 'trends',
48
+ :api_key => nil,
49
+ :query => nil,
50
+ :type => nil,
51
+ :format => 'json',
52
+ :scope => '7d',
53
+ :count => nil,
54
+ :help => false,
55
+ :verbose => false,
56
+ :version => 'v0',
57
+ :config_file => "#{ENV['HOME']}/.config/backscatter/config.json"
58
+ }
59
+
60
+ opts.each do |opt, arg|
61
+ case opt
62
+ when '--api-key'
63
+ options[:api_key] = arg
64
+ when '--query'
65
+ options[:query] = arg
66
+ when '--type'
67
+ options[:type] = arg
68
+ when '--format'
69
+ options[:format] = arg
70
+ when '--scope'
71
+ options[:scope] = arg
72
+ when '--count'
73
+ options[:count] = arg
74
+ when '--config'
75
+ options[:config_file] = arg
76
+ when '--help'
77
+ options[:help] = true
78
+ when '--verbose'
79
+ options[:verbose] = true
80
+ else
81
+ raise "Unknown option #{opt}"
82
+ end
83
+ end
84
+
85
+ if options[:config_file]
86
+ if File.exist?(options[:config_file])
87
+ data = JSON.parse(open(options[:config_file]).read)
88
+ options[:api_key] = data["api_key"]
89
+ options[:version] = data["version"]
90
+ end
91
+ end
92
+
93
+ [options, args]
94
+ end
95
+
96
+ def self.error(message)
97
+ puts message
98
+ exit
99
+ end
100
+
101
+
102
+ def self.run(args)
103
+ options, items = parse_command_line(args)
104
+ if items[0]
105
+ options[:command] = items[0]
106
+ end
107
+
108
+ if not options[:api_key]
109
+ error("An API key is required to use the Backscatter.io service. Please specify one via -k or in a configuration file #{ENV['HOME']}/.config/backscatter/config.json")
110
+ end
111
+
112
+ if options[:help]
113
+ usage
114
+ exit
115
+ end
116
+
117
+ BackscatterIO.configure do |config|
118
+ # Configure API key authorization: ApiKeyAuth
119
+ config.api_key['X-API-KEY'] = options[:api_key]
120
+ end
121
+
122
+ client = BackscatterIO::Api.new
123
+
124
+ case options[:command]
125
+ when 'observations'
126
+ if not options[:query]
127
+ error("-q <query_item> is a required parameter to the observations command")
128
+ end
129
+ options[:type] ||= detect_query(options[:query])
130
+ if not options[:type]
131
+ error "Could not determine the format of the query, please use the -t flag to specify the type"
132
+ end
133
+ results = client.observations(options[:type], options[:query], { "scope" => options[:scope] })
134
+ when 'trends'
135
+ options[:type] ||= 'ip'
136
+ results = client.trends(options[:type], { "scope" => options[:scope], "count" => options[:count] })
137
+ when 'enrich'
138
+ if not options[:query]
139
+ error "-q <query_item> is a required parameter to the enrich command"
140
+ end
141
+ options[:type] ||= detect_query(options[:query])
142
+ if not options[:type]
143
+ error "Could not determine the format of the query, please use the -t flag to specify the type"
144
+ end
145
+ case options[:type]
146
+ when 'ip'
147
+ results = client.enrich_ip(options[:query])
148
+ when 'network'
149
+ results = client.enrich_network(options[:query])
150
+ when 'asn'
151
+ results = client.enrich_asn(options[:query])
152
+ else
153
+ error "Enrichment is not available for #{options[:type]}"
154
+ end
155
+ when 'setup'
156
+ dirname = File.dirname(options[:config_file])
157
+ if not File.exist?(dirname)
158
+ FileUtils.mkdir_p(dirname)
159
+ end
160
+ fh = open(options[:config_file], 'w')
161
+ fh.write(JSON.pretty_generate({"version" => options[:version], "api_key" => options[:api_key]}))
162
+ fh.close
163
+ results = { "message" => "Configuration saved" }
164
+ else
165
+ error "Unknown command #{options[:command]}"
166
+ end
167
+
168
+ if options[:format] == 'json'
169
+ return results.to_hash.to_json
170
+ else
171
+ return tabulate(results)
172
+ end
173
+ end
174
+
175
+ def self.tabulate(results)
176
+ if not results.success
177
+ return "Unsuccessful"
178
+ end
179
+
180
+ table = ""
181
+
182
+ if results.query == nil or results.query.type == "top_x_query"
183
+ maxlen = 0
184
+ results.results.each do |k,v|
185
+ if k.length > maxlen
186
+ maxlen = k.length
187
+ end
188
+ end
189
+ maxlen += 1
190
+ results.results.keys.sort {|a,b| results.results[b] <=> results.results[a]}.each do |k|
191
+ table += "#{k.to_s.ljust(maxlen)}: #{results.results[k]}\n"
192
+ end
193
+ else
194
+ headers = {}
195
+ headers = {'observed' => 9, 'src_ip' => 7, 'protocol' => 9,
196
+ 'fragment_flags' => 15, 'id' => 3, 'dst_port' => 9, 'length' => 7, 'ttl' => 4, 'tos' => 4,
197
+ 'precedence' => 11, 'window' => 7}
198
+ results.results.observations.each do |item|
199
+ headers.each_key do |h|
200
+ vl = item.__send__(h).length + 1
201
+ if vl > headers[h]
202
+ headers[h] = vl
203
+ end
204
+ end
205
+ end
206
+ headers.each_key do |h|
207
+ table += "#{h.ljust(headers[h])}"
208
+ end
209
+ table += "\n"
210
+ results.results.observations.each do |item|
211
+ headers.each_key do |h|
212
+ table += "#{item.__send__(h).ljust(headers[h])}"
213
+ end
214
+ table += "\n"
215
+ end
216
+ end
217
+ table
218
+ end
219
+
220
+ def self.usage
221
+ usage = <<EOD
222
+ Usage: #{ARGV[0]} [setup|observations|trends|enrich] [options]
223
+ setup: Configure this client with your API key in order to run commands without issue. Find your API key at https://backscatter.io/account.
224
+ -k Specify an API key to save to your configuration file [required]
225
+
226
+ observations: queries observations matching your query. https://backscatter.io/developers#observations
227
+ -k Specify an API key to use for the API [required if not specified in the configuration]
228
+ -q Specify an IP, netblock, ASN, country, or port [required]
229
+ -t The type of the query you wish to make: ip, netblock, ASN, country, or port [autodetects]
230
+ -f Output format of the results. table or json, defaults to json
231
+ --scope Days to search back through (integer)
232
+
233
+ trends: queries trends (top N) of items of a given type seen withing the scope
234
+ -k Specify an API key to use for the API [required if not specified in the configuration]
235
+ -t Trend type: ip, network, asn, port, or country, defaults to ip
236
+ -f Output format of the results. table or json, defaults to json
237
+ --scope Days to search back through (integer)
238
+
239
+ enrich: adds enriching information to the queried item
240
+ -k Specify an API key to use for the API [required if not specified in the configuration]
241
+ -q Specify an IP, netblock, ASN, country, or port [required]
242
+ -t The type of the query you wish to make: ip, netblock, ASN, country, or port [autodetects]
243
+ -f Output format of the results. table or json, defaults to json
244
+ EOD
245
+ puts usage
246
+ end
247
+ end
248
+ # Alias for the CLInterface class
249
+ CLI = BackscatterIO::CLInterface
250
+ end
251
+
252
+ results = BackscatterIO::CLI.run(ARGV)
253
+ puts results
@@ -11,5 +11,5 @@ Swagger Codegen version: 2.4.0
11
11
  =end
12
12
 
13
13
  module BackscatterIO
14
- VERSION = '1.0.0'
14
+ VERSION = '1.0.1'
15
15
  end
@@ -0,0 +1,387 @@
1
+ ---
2
+ swagger: "2.0"
3
+ info:
4
+ description: |
5
+ [This is the Backscatter.io API.](https://backscatter.io/developers)
6
+ version: 1.0.0
7
+ title: Backscatter.io
8
+ termsOfService: https://backscatter.io/tos
9
+ contact:
10
+ email: info@backscatter.io
11
+ license:
12
+ name: Apache 2.0
13
+ url: http://www.apache.org/licenses/LICENSE-2.0.html
14
+ host: api.backscatter.io
15
+ basePath: /v0
16
+ schemes:
17
+ - https
18
+ security:
19
+ - ApiKeyAuth: []
20
+ paths:
21
+ /hello:
22
+ get:
23
+ summary: authenticate to the service
24
+ operationId: hello
25
+ consumes:
26
+ - application/json
27
+ produces:
28
+ - application/json
29
+ parameters: []
30
+ responses:
31
+ 200:
32
+ description: authenticated
33
+ schema:
34
+ $ref: '#/definitions/Hello'
35
+ 405:
36
+ description: Invalid input
37
+ /observations/{queryType}:
38
+ get:
39
+ summary: fetches observations for a given querytype
40
+ operationId: observations
41
+ consumes:
42
+ - application/json
43
+ produces:
44
+ - application/json
45
+ parameters:
46
+ - name: queryType
47
+ in: path
48
+ description: query type ip, network, asn, port, country
49
+ required: true
50
+ type: string
51
+ - name: query
52
+ in: query
53
+ description: ip address, cidr block, asn, port, or country
54
+ required: true
55
+ type: string
56
+ - name: scope
57
+ in: query
58
+ description: timeframe to search over, e.g., 1d, 7d
59
+ required: false
60
+ type: string
61
+ responses:
62
+ 200:
63
+ description: observations
64
+ schema:
65
+ $ref: '#/definitions/Observations'
66
+ 405:
67
+ description: Invalid input
68
+ /trends/popular/{trendType}:
69
+ get:
70
+ summary: Top N items
71
+ description: A listing of the top N items observered over the query scope
72
+ operationId: trends
73
+ produces:
74
+ - application/json
75
+ parameters:
76
+ - name: trendType
77
+ in: path
78
+ description: which item type you want to perform a trend over
79
+ required: true
80
+ type: string
81
+ enum:
82
+ - ip
83
+ - network
84
+ - asn
85
+ - port
86
+ - country
87
+ - name: scope
88
+ in: query
89
+ description: timeframe to search over, e.g., 1d, 7d
90
+ required: false
91
+ type: string
92
+ responses:
93
+ 200:
94
+ description: observations
95
+ schema:
96
+ $ref: '#/definitions/Trends'
97
+ 405:
98
+ description: Invalid input
99
+ /enrichment/ip:
100
+ get:
101
+ summary: enriches ip
102
+ description: returns enrichment data for an ip
103
+ operationId: enrich_ip
104
+ produces:
105
+ - application/json
106
+ parameters:
107
+ - name: query
108
+ in: query
109
+ required: true
110
+ type: string
111
+ responses:
112
+ 200:
113
+ description: ip_enrichment
114
+ schema:
115
+ $ref: '#/definitions/IPEnrichment'
116
+ 405:
117
+ description: Invalid input
118
+ /enrichment/network:
119
+ get:
120
+ summary: enriches network
121
+ description: returns enrichment data for a network
122
+ operationId: enrich_network
123
+ produces:
124
+ - application/json
125
+ parameters:
126
+ - name: query
127
+ in: query
128
+ required: true
129
+ type: string
130
+ responses:
131
+ 200:
132
+ description: network_enrichment
133
+ schema:
134
+ $ref: '#/definitions/NetworkEnrichment'
135
+ 405:
136
+ description: Invalid input
137
+ /enrichment/asn:
138
+ get:
139
+ summary: enriches asn
140
+ description: returns enrichment data for an ASN
141
+ operationId: enrich_asn
142
+ produces:
143
+ - application/json
144
+ parameters:
145
+ - name: query
146
+ in: query
147
+ required: true
148
+ type: string
149
+ responses:
150
+ 200:
151
+ description: asn_enrichment
152
+ schema:
153
+ $ref: '#/definitions/ASNEnrichment'
154
+ 405:
155
+ description: Invalid input
156
+ securityDefinitions:
157
+ ApiKeyAuth:
158
+ type: apiKey
159
+ name: X-API-KEY
160
+ in: header
161
+ definitions:
162
+ Hello:
163
+ type: object
164
+ properties:
165
+ message:
166
+ type: string
167
+ success:
168
+ type: boolean
169
+ Observations:
170
+ type: object
171
+ properties:
172
+ query:
173
+ $ref: '#/definitions/Query'
174
+ results:
175
+ $ref: '#/definitions/Results'
176
+ success:
177
+ type: boolean
178
+ Query:
179
+ type: object
180
+ properties:
181
+ after_time:
182
+ type: string
183
+ focus:
184
+ type: string
185
+ scope:
186
+ type: string
187
+ type:
188
+ type: string
189
+ enum:
190
+ - ip_query
191
+ - network_query
192
+ - asn_query
193
+ - port_query
194
+ - country_query
195
+ - top_x_query
196
+ Results:
197
+ type: object
198
+ properties:
199
+ observations:
200
+ type: array
201
+ items:
202
+ $ref: '#/definitions/Observation'
203
+ summary:
204
+ $ref: '#/definitions/Summary'
205
+ unique:
206
+ $ref: '#/definitions/Unique'
207
+ Observation:
208
+ type: object
209
+ properties:
210
+ dst_port:
211
+ type: string
212
+ fragment_flags:
213
+ type: string
214
+ id:
215
+ type: string
216
+ length:
217
+ type: string
218
+ observed:
219
+ type: string
220
+ precedence:
221
+ type: string
222
+ protocol:
223
+ type: string
224
+ res:
225
+ type: string
226
+ src_ip:
227
+ type: string
228
+ src_port:
229
+ type: string
230
+ tcp_flags:
231
+ type: string
232
+ tos:
233
+ type: string
234
+ ttl:
235
+ type: string
236
+ window:
237
+ type: string
238
+ Summary:
239
+ type: object
240
+ properties:
241
+ autonomous_system_count:
242
+ type: integer
243
+ format: int32
244
+ has_observations:
245
+ type: boolean
246
+ ip_address_count:
247
+ type: array
248
+ items:
249
+ type: string
250
+ network_count:
251
+ type: integer
252
+ format: int32
253
+ observations:
254
+ type: boolean
255
+ observations_count:
256
+ type: integer
257
+ format: int32
258
+ port_count:
259
+ type: integer
260
+ format: int32
261
+ protocol_count:
262
+ type: integer
263
+ format: int32
264
+ Unique:
265
+ type: object
266
+ properties:
267
+ autonomous_systems:
268
+ type: array
269
+ items:
270
+ type: string
271
+ countries:
272
+ type: array
273
+ items:
274
+ type: string
275
+ ip_addresses:
276
+ type: array
277
+ items:
278
+ type: string
279
+ networks:
280
+ type: array
281
+ items:
282
+ type: string
283
+ ports:
284
+ type: array
285
+ items:
286
+ type: string
287
+ protocols:
288
+ type: array
289
+ items:
290
+ type: string
291
+ Trends:
292
+ type: object
293
+ properties:
294
+ query:
295
+ $ref: '#/definitions/Query'
296
+ results:
297
+ type: object
298
+ properties: {}
299
+ success:
300
+ type: boolean
301
+ IPEnrichment:
302
+ type: object
303
+ properties:
304
+ results:
305
+ $ref: '#/definitions/IPEnrichment_results'
306
+ success:
307
+ type: boolean
308
+ NetworkEnrichment:
309
+ type: object
310
+ properties:
311
+ results:
312
+ $ref: '#/definitions/NetworkEnrichment_results'
313
+ success:
314
+ type: boolean
315
+ ASNEnrichment:
316
+ type: object
317
+ properties:
318
+ results:
319
+ $ref: '#/definitions/ASNEnrichment_results'
320
+ success:
321
+ type: boolean
322
+ IPEnrichment_results:
323
+ properties:
324
+ as_name:
325
+ type: string
326
+ as_num:
327
+ type: integer
328
+ format: int32
329
+ city:
330
+ type: string
331
+ country_iso:
332
+ type: string
333
+ country_name:
334
+ type: string
335
+ ip:
336
+ type: string
337
+ ip_hex:
338
+ type: string
339
+ ip_version:
340
+ type: integer
341
+ format: int8
342
+ latitude:
343
+ type: number
344
+ longitude:
345
+ type: number
346
+ network:
347
+ type: string
348
+ network_broadcast:
349
+ type: string
350
+ network_hostmask:
351
+ type: string
352
+ network_netmask:
353
+ type: string
354
+ network_size:
355
+ type: integer
356
+ format: int32
357
+ postal_code:
358
+ type: string
359
+ region_iso:
360
+ type: string
361
+ region_name:
362
+ type: string
363
+ NetworkEnrichment_results:
364
+ properties:
365
+ cidr:
366
+ type: string
367
+ network_addresses:
368
+ type: array
369
+ items:
370
+ type: string
371
+ network_size:
372
+ type: integer
373
+ format: int32
374
+ ASNEnrichment_results:
375
+ properties:
376
+ as_num:
377
+ type: integer
378
+ format: int32
379
+ as_name:
380
+ type: string
381
+ prefix_count:
382
+ type: integer
383
+ format: int32
384
+ prefixes:
385
+ type: array
386
+ items:
387
+ type: string
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backscatterio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - rubygems@chrislee.dhs.org
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-31 00:00:00.000000000 Z
11
+ date: 2019-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: typhoeus
@@ -193,7 +193,8 @@ dependencies:
193
193
  description: "[This is the Backscatter.io API.](https://backscatter.io/developers) "
194
194
  email:
195
195
  - rubygems@chrislee.dhs.org
196
- executables: []
196
+ executables:
197
+ - backscatterio-rb
197
198
  extensions: []
198
199
  extra_rdoc_files: []
199
200
  files:
@@ -201,7 +202,9 @@ files:
201
202
  - LICENSE
202
203
  - README.md
203
204
  - Rakefile
205
+ - backscatterio-1.0.0.gem
204
206
  - backscatterio.gemspec
207
+ - bin/backscatterio-rb
205
208
  - docs/ASNEnrichment.md
206
209
  - docs/ASNEnrichmentResults.md
207
210
  - docs/Api.md
@@ -256,6 +259,7 @@ files:
256
259
  - spec/models/trends_spec.rb
257
260
  - spec/models/unique_spec.rb
258
261
  - spec/spec_helper.rb
262
+ - swagger.yaml
259
263
  homepage: https://github.com/backscatterio/ruby
260
264
  licenses:
261
265
  - Unlicense