nexpose_sourcefire 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|