nexpose_sourcefire 0.2.0 → 0.2.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 +4 -4
- data/bin/nexpose_sourcefire +1 -2
- data/lib/sourcefire/nx_logger.rb +44 -33
- data/lib/sourcefire/version.rb +1 -1
- data/lib/sourcefire_connector.rb +38 -5
- metadata +6 -6
- data/sourcefire.gemspec +0 -25
- data/sourcefire.iml +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66a0bd838b05bf5c28eb153bc0189f16709555c3
|
4
|
+
data.tar.gz: f546f226efeb05c8c57b726b64354b6df78019f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac24ce75871839767af860c5168ac9b87d54c2253e7ab302cb4e23bda9adab55cc6235d04811c76c06758227d2f9b27b925cc2f8e7590864ab41b063008f139c
|
7
|
+
data.tar.gz: eb4de1ee51d40cdb57e843ada389d28b98700511065984472bbd54bbbf4c1450315084fa1f1791a8a08a586dc587198eb04d4eb707ac8f5d1efed07be9ba4205
|
data/bin/nexpose_sourcefire
CHANGED
@@ -25,8 +25,7 @@ raise 'Must configure SourceFire settings before starting' if ENV['SOURCEFIRE_AD
|
|
25
25
|
|
26
26
|
log = Sourcefire::NxLogger.instance
|
27
27
|
log.setup_statistics_collection(Sourcefire::PRODUCT, Sourcefire::VENDOR, Sourcefire::VERSION)
|
28
|
-
|
29
|
-
log.setup_logging(logging_enabled,
|
28
|
+
log.setup_logging(configuration_settings[:options][:logging_enabled],
|
30
29
|
configuration_settings[:options][:log_level])
|
31
30
|
|
32
31
|
configuration_settings[:nexpose_address] = ENV['NEXPOSE_URL']
|
data/lib/sourcefire/nx_logger.rb
CHANGED
@@ -6,27 +6,23 @@ require 'singleton'
|
|
6
6
|
module Sourcefire
|
7
7
|
class NxLogger
|
8
8
|
include Singleton
|
9
|
-
attr_accessor :options, :statistic_key, :product, :logger_file
|
10
9
|
LOG_PATH = "./logs/rapid7_%s.log"
|
11
10
|
KEY_FORMAT = "external.integration.%s"
|
12
11
|
PRODUCT_FORMAT = "%s_%s"
|
13
12
|
|
14
13
|
DEFAULT_LOG = 'integration'
|
15
|
-
PRODUCT_RANGE =
|
14
|
+
PRODUCT_RANGE = 4..30
|
16
15
|
KEY_RANGE = 3..15
|
17
16
|
|
18
17
|
ENDPOINT = '/data/external/statistic/'
|
19
18
|
|
20
19
|
def initialize()
|
21
|
-
|
20
|
+
create_calls
|
21
|
+
@logger_file = get_log_path @product
|
22
22
|
setup_logging(true, 'info')
|
23
23
|
end
|
24
24
|
|
25
25
|
def setup_statistics_collection(vendor, product_name, gem_version)
|
26
|
-
#Remove illegal characters
|
27
|
-
vendor.to_s.gsub!('-', '_')
|
28
|
-
product_name.to_s.gsub!('-', '_')
|
29
|
-
|
30
26
|
begin
|
31
27
|
@statistic_key = get_statistic_key vendor
|
32
28
|
@product = get_product product_name, gem_version
|
@@ -35,13 +31,14 @@ module Sourcefire
|
|
35
31
|
end
|
36
32
|
end
|
37
33
|
|
38
|
-
def setup_logging(enabled, log_level = 'info')
|
39
|
-
|
40
|
-
log_message('Logging disabled.')
|
41
|
-
return
|
42
|
-
end
|
34
|
+
def setup_logging(enabled, log_level = 'info', stdout=false)
|
35
|
+
@stdout = stdout
|
43
36
|
|
44
|
-
|
37
|
+
log_message('Logging disabled.') unless enabled || @log.nil?
|
38
|
+
@enabled = enabled
|
39
|
+
return unless @enabled
|
40
|
+
|
41
|
+
@logger_file = get_log_path @product
|
45
42
|
|
46
43
|
require 'logger'
|
47
44
|
directory = File.dirname(@logger_file)
|
@@ -58,24 +55,19 @@ module Sourcefire
|
|
58
55
|
log_message("Logging enabled at level <#{log_level}>")
|
59
56
|
end
|
60
57
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
# Logs an error message
|
72
|
-
def log_error_message(message)
|
73
|
-
@log.error(message) unless @log.nil?
|
58
|
+
def create_calls
|
59
|
+
levels = [:info, :debug, :error, :warn]
|
60
|
+
levels.each do |level|
|
61
|
+
method_name =
|
62
|
+
define_singleton_method("log_#{level.to_s}_message") do |message|
|
63
|
+
puts message if @stdout
|
64
|
+
@log.send(level, message) unless !@enabled || @log.nil?
|
65
|
+
end
|
66
|
+
end
|
74
67
|
end
|
75
68
|
|
76
|
-
|
77
|
-
|
78
|
-
@log.warn(message) unless @log.nil?
|
69
|
+
def log_message(message)
|
70
|
+
log_info_message message
|
79
71
|
end
|
80
72
|
|
81
73
|
def log_stat_message(message)
|
@@ -92,13 +84,28 @@ module Sourcefire
|
|
92
84
|
return nil
|
93
85
|
end
|
94
86
|
|
87
|
+
vendor.gsub!('-', '_')
|
88
|
+
vendor.slice! vendor.rindex('_') until vendor.count('_') <= 1
|
89
|
+
|
90
|
+
vendor.delete! "^A-Za-z0-9\_"
|
91
|
+
|
95
92
|
KEY_FORMAT % vendor[0...KEY_RANGE.max].downcase
|
96
93
|
end
|
97
94
|
|
98
95
|
def get_product(product, version)
|
99
|
-
return nil if (product.nil? ||
|
96
|
+
return nil if ((product.nil? || product.empty?) ||
|
97
|
+
(version.nil? || version.empty?))
|
98
|
+
|
99
|
+
product.gsub!('-', '_')
|
100
|
+
product.slice! product.rindex('_') until product.count('_') <= 1
|
101
|
+
|
102
|
+
product.delete! "^A-Za-z0-9\_"
|
103
|
+
version.delete! "^A-Za-z0-9\.\-"
|
104
|
+
|
100
105
|
product = (PRODUCT_FORMAT % [product, version])[0...PRODUCT_RANGE.max]
|
101
106
|
|
107
|
+
product.slice! product.rindex(/[A-Z0-9]/i)+1..-1
|
108
|
+
|
102
109
|
if product.length < PRODUCT_RANGE.min
|
103
110
|
log_stat_message("Product length below minimum <#{PRODUCT_RANGE.min}>.")
|
104
111
|
return nil
|
@@ -107,9 +114,12 @@ module Sourcefire
|
|
107
114
|
end
|
108
115
|
|
109
116
|
def generate_payload(statistic_value='')
|
110
|
-
|
111
|
-
|
112
|
-
|
117
|
+
product_name, separator, version = @product.to_s.rpartition('_')
|
118
|
+
payload_value = {'version' => version}.to_json
|
119
|
+
|
120
|
+
payload = {'statistic-key' => @statistic_key.to_s,
|
121
|
+
'statistic-value' => payload_value,
|
122
|
+
'product' => product_name}
|
113
123
|
JSON.generate(payload)
|
114
124
|
end
|
115
125
|
|
@@ -126,6 +136,7 @@ module Sourcefire
|
|
126
136
|
log_stat_message "Received code #{response.code} from Nexpose console."
|
127
137
|
log_stat_message "Received message #{response.msg} from Nexpose console."
|
128
138
|
log_stat_message 'Finished sending statistics data to Nexpose.'
|
139
|
+
|
129
140
|
response.code
|
130
141
|
end
|
131
142
|
|
data/lib/sourcefire/version.rb
CHANGED
data/lib/sourcefire_connector.rb
CHANGED
@@ -84,13 +84,17 @@ module Sourcefire
|
|
84
84
|
redo
|
85
85
|
end
|
86
86
|
|
87
|
-
assets << current_asset
|
87
|
+
assets << current_asset unless current_asset.nil?
|
88
88
|
@log.log_message("Total of #{assets.count} assets")
|
89
89
|
assets
|
90
90
|
end
|
91
91
|
|
92
92
|
def process_nexpose_data(report_file)
|
93
|
-
|
93
|
+
#Originally using the value returned from SourceFire as the max data size.
|
94
|
+
#However, this caused issues with some ticket creation / batching, and the
|
95
|
+
#reduced value was hard-coded below.
|
96
|
+
#max_data_size = 524288
|
97
|
+
max_data_size = 450000
|
94
98
|
|
95
99
|
@log.log_message('Creating data sets')
|
96
100
|
header = "SetSource,NeXpose Scan Report\n"
|
@@ -107,7 +111,7 @@ module Sourcefire
|
|
107
111
|
@log.log_message("Got a message of type <#{msg_details[0]}> and size <#{msg_details[1]}>")
|
108
112
|
max_size = read_from_socket(ssl_socket, msg_details[1], msg_details[0])
|
109
113
|
@log.log_message("Max message length is <#{max_size}>")
|
110
|
-
max_data_size = max_size.first
|
114
|
+
#max_data_size = max_size.first
|
111
115
|
end
|
112
116
|
ssl_socket.close
|
113
117
|
|
@@ -116,11 +120,19 @@ module Sourcefire
|
|
116
120
|
|
117
121
|
assets.each do |asset|
|
118
122
|
if data_sets[-1].nil?
|
119
|
-
|
123
|
+
if (asset + footer).bytesize < max_data_size
|
124
|
+
data_sets << header.dup + asset
|
125
|
+
else
|
126
|
+
batch_single_ip(data_sets, asset, header, footer, max_data_size)
|
127
|
+
end
|
120
128
|
elsif (data_sets[-1].to_s + asset + footer).bytesize < max_data_size
|
121
129
|
data_sets[-1] += asset
|
122
|
-
|
130
|
+
elsif (header.dup + asset + footer).bytesize < max_data_size
|
131
|
+
data_sets[-1] += footer
|
123
132
|
data_sets << header.dup + asset
|
133
|
+
else
|
134
|
+
data_sets[-1] += footer
|
135
|
+
batch_single_ip(data_sets, asset, header, footer, max_data_size)
|
124
136
|
end
|
125
137
|
end
|
126
138
|
|
@@ -137,6 +149,27 @@ module Sourcefire
|
|
137
149
|
data_sets
|
138
150
|
end
|
139
151
|
|
152
|
+
def batch_single_ip(data_sets, asset, header, footer, max_data_size)
|
153
|
+
split_asset = nil
|
154
|
+
initial = true
|
155
|
+
update_footer = "ScanUpdate"
|
156
|
+
|
157
|
+
asset.each_line do |line|
|
158
|
+
if split_asset.nil?
|
159
|
+
split_asset = header.dup + line
|
160
|
+
elsif (split_asset + line + footer).bytesize < max_data_size
|
161
|
+
split_asset += line
|
162
|
+
else
|
163
|
+
data_sets << split_asset + (initial ? footer : update_footer)
|
164
|
+
initial = false
|
165
|
+
split_asset = header.dup
|
166
|
+
redo
|
167
|
+
end
|
168
|
+
end
|
169
|
+
data_sets << split_asset + update_footer
|
170
|
+
data_sets << header.dup
|
171
|
+
end
|
172
|
+
|
140
173
|
def process_nexpose_data_alt(report_file)
|
141
174
|
max_data_size = 524288
|
142
175
|
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nexpose_sourcefire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JJ Cassidy
|
8
8
|
- David Valente
|
9
|
+
- Adam Robinson
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2016-
|
13
|
+
date: 2016-07-15 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: bundler
|
@@ -56,7 +57,7 @@ dependencies:
|
|
56
57
|
description: This GEM allows enables the importing of Nexpose host and vulnerability
|
57
58
|
data into SourceFire
|
58
59
|
email:
|
59
|
-
-
|
60
|
+
- support@rapid7.com
|
60
61
|
executables:
|
61
62
|
- nexpose_sourcefire
|
62
63
|
extensions: []
|
@@ -75,8 +76,6 @@ files:
|
|
75
76
|
- lib/sourcefire/queries.rb
|
76
77
|
- lib/sourcefire/version.rb
|
77
78
|
- lib/sourcefire_connector.rb
|
78
|
-
- sourcefire.gemspec
|
79
|
-
- sourcefire.iml
|
80
79
|
homepage: http://www.rapid7.com
|
81
80
|
licenses:
|
82
81
|
- MIT
|
@@ -97,8 +96,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
96
|
version: '0'
|
98
97
|
requirements: []
|
99
98
|
rubyforge_project:
|
100
|
-
rubygems_version: 2.4.
|
99
|
+
rubygems_version: 2.4.3
|
101
100
|
signing_key:
|
102
101
|
specification_version: 4
|
103
102
|
summary: Nexpose SourceFire Integration GEM
|
104
103
|
test_files: []
|
104
|
+
has_rdoc:
|
data/sourcefire.gemspec
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'sourcefire/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = 'nexpose_sourcefire'
|
8
|
-
spec.version = Sourcefire::VERSION
|
9
|
-
spec.authors = ['JJ Cassidy', 'David Valente']
|
10
|
-
spec.email = ['integrations_support@rapid7.com']
|
11
|
-
|
12
|
-
spec.summary = 'Nexpose SourceFire Integration GEM'
|
13
|
-
spec.description = 'This GEM allows enables the importing of Nexpose host and vulnerability data into SourceFire'
|
14
|
-
spec.homepage = 'http://www.rapid7.com'
|
15
|
-
spec.license = 'MIT'
|
16
|
-
|
17
|
-
spec.files = Dir['[A-Z]*'] + Dir['lib/**/*'] + Dir['bin/**']
|
18
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.10"
|
22
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
-
spec.add_runtime_dependency 'nexpose', "~> 0.9"
|
24
|
-
spec.required_ruby_version = '>= 1.9'
|
25
|
-
end
|
data/sourcefire.iml
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<module type="RUBY_MODULE" version="4">
|
3
|
-
<component name="FacetManager">
|
4
|
-
<facet type="gem" name="Ruby Gem">
|
5
|
-
<configuration>
|
6
|
-
<option name="GEM_APP_ROOT_PATH" value="$MODULE_DIR$" />
|
7
|
-
<option name="GEM_APP_TEST_PATH" value="" />
|
8
|
-
<option name="GEM_APP_LIB_PATH" value="" />
|
9
|
-
</configuration>
|
10
|
-
</facet>
|
11
|
-
</component>
|
12
|
-
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
13
|
-
<exclude-output />
|
14
|
-
<content url="file://$MODULE_DIR$" />
|
15
|
-
<orderEntry type="jdk" jdkName="RVM: ruby-1.9.3-p547 [global]" jdkType="RUBY_SDK" />
|
16
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
17
|
-
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.10.4, RVM: ruby-1.9.3-p547 [global]) [gem]" level="application" />
|
18
|
-
<orderEntry type="library" scope="PROVIDED" name="nexpose (v0.9.8, RVM: ruby-1.9.3-p547 [global]) [gem]" level="application" />
|
19
|
-
<orderEntry type="library" scope="PROVIDED" name="rake (v10.4.2, RVM: ruby-1.9.3-p547 [global]) [gem]" level="application" />
|
20
|
-
<orderEntry type="library" scope="PROVIDED" name="rex (v2.0.7, RVM: ruby-1.9.3-p547 [global]) [gem]" level="application" />
|
21
|
-
</component>
|
22
|
-
</module>
|