nexpose_paloalto 0.1.1 → 0.1.2
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/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/{lib/bin/nexpose_paloalto.rb → bin/nexpose_paloalto} +3 -0
- data/lib/paloalto.rb +23 -15
- data/lib/paloalto/nexpose_helper.rb +3 -2
- data/lib/paloalto/nx_logger.rb +159 -20
- data/lib/paloalto/version.rb +3 -1
- metadata +10 -10
- data/nexpose_paloalto.gemspec +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4031017be8639d09edbb9fef2ffb3ec43b21330e
|
4
|
+
data.tar.gz: f75c2a16d0ce151d132a77eaf11c9e3b377b2cbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 410ba9dfbe608b1465fdc6bd5967f561537e1ef3b36799ff9454d9440de7a3d708f68a80ba82112b68f88ac7196a6c5941d9f9ed6c0fea48a36a88980b4a9034
|
7
|
+
data.tar.gz: 3495a3363873daa1faa9fc2956262907d37f6e7122e1ae269094c41c01cce8f12f5d910df0cda6dc579b076d271699de2252779dee83b7be5935525f79c9866c
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -59,5 +59,5 @@ For Windows systems, make sure they are on the Environment Variables section in
|
|
59
59
|
* (Optional) Review the log file under the logs folder in the Gem path.
|
60
60
|
|
61
61
|
|
62
|
-
For any support requests, please email
|
62
|
+
For any support requests, please email support@rapid7.com with a description of the issue and any logs
|
63
63
|
available.
|
@@ -1,3 +1,4 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
1
2
|
require 'paloalto'
|
2
3
|
|
3
4
|
# Obtain Nexpose settings from Environment Variables.
|
@@ -6,6 +7,8 @@ raise 'Must configure nexpose settings before starting' if ENV['NEXPOSE_URL'].ni
|
|
6
7
|
nexpose_settings[:nexpose_url] = ENV['NEXPOSE_URL']
|
7
8
|
nexpose_settings[:nexpose_username] = ENV['NEXPOSE_USERNAME']
|
8
9
|
nexpose_settings[:nexpose_password] = ENV['NEXPOSE_PASSWORD']
|
10
|
+
# User can change the port if Nexpose does not use port 3780
|
11
|
+
nexpose_settings[:nexpose_port] = 3780
|
9
12
|
|
10
13
|
# Obtain PAN's info.
|
11
14
|
pan_settings = Hash.new
|
data/lib/paloalto.rb
CHANGED
@@ -16,6 +16,7 @@ module Paloalto
|
|
16
16
|
nexpose_url = nexpose_settings[:nexpose_url]
|
17
17
|
nexpose_username = nexpose_settings[:nexpose_username]
|
18
18
|
nexpose_password = nexpose_settings[:nexpose_password]
|
19
|
+
nexpose_port = nexpose_settings[:nexpose_port]
|
19
20
|
|
20
21
|
pan_url = pan_settings[:pan_url]
|
21
22
|
pan_username = pan_settings[:pan_username]
|
@@ -24,7 +25,11 @@ module Paloalto
|
|
24
25
|
report_timeout = nexpose_settings[:timeout]
|
25
26
|
|
26
27
|
#Setup logging
|
27
|
-
@log = Paloalto::
|
28
|
+
@log = Paloalto::NxLogger.instance
|
29
|
+
@log.setup_statistics_collection(Paloalto::VENDOR,
|
30
|
+
Paloalto::PRODUCT,
|
31
|
+
Paloalto::VERSION)
|
32
|
+
@log.setup_logging(true, 'info')
|
28
33
|
|
29
34
|
#Nexpose sites and DAGs to import. Uses Site Id and DAG ID e.g. 'sites = [1,2,3,4]'. Leave as nil to run on all sites and DAGs the user has access to or
|
30
35
|
# set as an empty array e.g. 'dags=[]' to not run on any sites/dags.
|
@@ -34,9 +39,12 @@ module Paloalto
|
|
34
39
|
@log.log_message("Running with user configured site IDs <#{sites}> and dynamic asset group IDs #{dags}.")
|
35
40
|
|
36
41
|
# Log in to nexpose.
|
37
|
-
nsc = Paloalto::NexposeHelper.login(nexpose_url,
|
42
|
+
nsc = Paloalto::NexposeHelper.login(nexpose_url,
|
43
|
+
nexpose_username,
|
44
|
+
nexpose_password,
|
45
|
+
nexpose_port)
|
38
46
|
|
39
|
-
#Gather the sites
|
47
|
+
# Gather the sites
|
40
48
|
all_sites = nsc.sites
|
41
49
|
all_sites.delete_if {|site| !(sites.include? site.id)} unless sites.nil?
|
42
50
|
all_sites_names = []
|
@@ -53,53 +61,53 @@ module Paloalto
|
|
53
61
|
# Login to PAN.
|
54
62
|
pan_key = Paloalto::Ngfw.login(pan_url, pan_username, pan_password)
|
55
63
|
|
56
|
-
#Get the device config
|
64
|
+
# Get the device config
|
57
65
|
device_config_xml = Paloalto::Ngfw.retrieve_device_config(pan_url, pan_key)
|
58
66
|
|
59
|
-
#Get the device names
|
67
|
+
# Get the device names
|
60
68
|
device_name = Paloalto::Ngfw.parse_device_name(device_config_xml)
|
61
69
|
vsys_name = Paloalto::Ngfw.parse_vsys_name(device_config_xml)
|
62
70
|
|
63
71
|
@log.log_message("Found device configuration. Name <#{device_name}> and vsys <#{vsys_name}>.")
|
64
72
|
|
65
|
-
#Get this device's config
|
73
|
+
# Get this device's config
|
66
74
|
vsys_config = Paloalto::Ngfw.retrieve_device_config(pan_url, pan_key, device_name, vsys_name)
|
67
75
|
|
68
|
-
#Get the existing tags
|
76
|
+
# Get the existing tags
|
69
77
|
existing_tags = Paloalto::Ngfw.parse_existing_tags(vsys_config)
|
70
78
|
|
71
|
-
#Gather the tags we want to create
|
79
|
+
# Gather the tags we want to create
|
72
80
|
wanted_tags = []
|
73
81
|
all_sites_names.each {|site_name| wanted_tags << site_name.gsub(/[()]/, "")}
|
74
82
|
wanted_tags << 'Nexpose'
|
75
83
|
all_nexpose_dag_details.each {|details| wanted_tags << details[1].gsub(/[()']/, "")}
|
76
84
|
|
77
|
-
#
|
85
|
+
# Finds which new tags need to be created
|
78
86
|
tags_to_create = wanted_tags - existing_tags
|
79
87
|
|
80
88
|
@log.log_message("New tags to be created <#{tags_to_create}>.")
|
81
89
|
|
82
|
-
#Find the existing DAGs
|
90
|
+
# Find the existing DAGs
|
83
91
|
existing_dags = Paloalto::Ngfw.parse_existing_dags(vsys_config)
|
84
92
|
|
85
|
-
#Gather the dags we want to create
|
93
|
+
# Gather the dags we want to create
|
86
94
|
wanted_dags = []
|
87
95
|
all_sites_names.each {|site_name| wanted_dags << site_name.gsub(/[()]/, "")}
|
88
96
|
wanted_dags << 'Nexpose'
|
89
97
|
all_nexpose_dag_details.each {|details| wanted_dags << details[1].gsub(/[()']/, "")}
|
90
98
|
|
91
|
-
#Find which new dags need to be created
|
99
|
+
# Find which new dags need to be created
|
92
100
|
dags_to_create = wanted_dags - existing_dags
|
93
101
|
|
94
102
|
@log.log_message("New DAGs to be created <#{dags_to_create}>.")
|
95
103
|
|
96
|
-
#Create the new tags
|
104
|
+
# Create the new tags
|
97
105
|
@log.log_message("Creating tags...")
|
98
106
|
tags_element=''
|
99
107
|
tags_to_create.each {|tag_to_create| tags_element << Paloalto::Ngfw.generate_tag_xml(tag_to_create, 'color3', "Nexpose tag for asset grouping: #{tag_to_create}")}
|
100
108
|
response = Paloalto::Ngfw.create_tags(pan_url, pan_key, device_name, vsys_name, tags_element) unless tags_element.empty?
|
101
109
|
|
102
|
-
#Create the new dags
|
110
|
+
# Create the new dags
|
103
111
|
@log.log_message("Creating DAGs...")
|
104
112
|
dags_element=''
|
105
113
|
dags_to_create.each {|dag_to_create| dags_element << Paloalto::Ngfw.generate_dag_xml(dag_to_create, "'Nexpose' AND '#{dag_to_create}'", dag_to_create)}
|
@@ -107,7 +115,7 @@ module Paloalto
|
|
107
115
|
|
108
116
|
@log.log_message('Committing the changes...')
|
109
117
|
|
110
|
-
#Commit the changes
|
118
|
+
# Commit the changes
|
111
119
|
response = Paloalto::Ngfw.commit(pan_url, pan_key)
|
112
120
|
|
113
121
|
@log.log_message("Commit response <#{response}>")
|
@@ -5,10 +5,11 @@ module Paloalto
|
|
5
5
|
require 'paloalto/nx_logger'
|
6
6
|
|
7
7
|
# Logs in to Nexpose using the url, username and password.
|
8
|
-
def self.login(url=nil, username=nil, password=nil)
|
8
|
+
def self.login(url=nil, username=nil, password=nil, port=3780)
|
9
9
|
raise 'Nexpose connection must be set in environment variables.' if url.nil? || username.nil? || password.nil?
|
10
|
-
nsc = Nexpose::Connection.new(url, username, password)
|
10
|
+
nsc = Nexpose::Connection.new(url, username, password, port)
|
11
11
|
nsc.login
|
12
|
+
Paloalto::NxLogger.instance.on_connect(url, port, nsc.session_id, "{}")
|
12
13
|
nsc
|
13
14
|
end
|
14
15
|
|
data/lib/paloalto/nx_logger.rb
CHANGED
@@ -1,27 +1,166 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'json'
|
3
|
+
require 'net/http'
|
4
|
+
require 'singleton'
|
5
|
+
|
1
6
|
module Paloalto
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
7
|
+
class NxLogger
|
8
|
+
include Singleton
|
9
|
+
LOG_PATH = "./logs/rapid7_%s.log"
|
10
|
+
KEY_FORMAT = "external.integration.%s"
|
11
|
+
PRODUCT_FORMAT = "%s_%s"
|
12
|
+
|
13
|
+
DEFAULT_LOG = 'integration'
|
14
|
+
PRODUCT_RANGE = 4..30
|
15
|
+
KEY_RANGE = 3..15
|
16
|
+
|
17
|
+
ENDPOINT = '/data/external/statistic/'
|
18
|
+
|
19
|
+
def initialize()
|
20
|
+
create_calls
|
21
|
+
@logger_file = get_log_path @product
|
22
|
+
setup_logging(true, 'info')
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup_statistics_collection(vendor, product_name, gem_version)
|
26
|
+
begin
|
27
|
+
@statistic_key = get_statistic_key vendor
|
28
|
+
@product = get_product product_name, gem_version
|
29
|
+
rescue => e
|
30
|
+
#Continue
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup_logging(enabled, log_level = 'info', stdout=false)
|
35
|
+
@stdout = stdout
|
36
|
+
|
37
|
+
log_message('Logging disabled.') unless enabled || @log.nil?
|
38
|
+
@enabled = enabled
|
39
|
+
return unless @enabled
|
40
|
+
|
41
|
+
@logger_file = get_log_path @product
|
42
|
+
|
43
|
+
require 'logger'
|
44
|
+
directory = File.dirname(@logger_file)
|
45
|
+
FileUtils.mkdir_p(directory) unless File.directory?(directory)
|
46
|
+
io = IO.for_fd(IO.sysopen(@logger_file, 'a'), 'a')
|
47
|
+
io.autoclose = false
|
48
|
+
io.sync = true
|
49
|
+
@log = Logger.new(io, 'weekly')
|
50
|
+
@log.level = if log_level.to_s.casecmp('info') == 0
|
51
|
+
Logger::INFO
|
52
|
+
else
|
53
|
+
Logger::DEBUG
|
54
|
+
end
|
55
|
+
log_message("Logging enabled at level <#{log_level}>")
|
56
|
+
end
|
57
|
+
|
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
|
19
66
|
end
|
20
67
|
end
|
21
68
|
|
22
|
-
# Logs a message
|
23
69
|
def log_message(message)
|
24
|
-
|
70
|
+
log_info_message message
|
71
|
+
end
|
72
|
+
|
73
|
+
def log_stat_message(message)
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_log_path(product)
|
77
|
+
product.downcase! unless product.nil?
|
78
|
+
File.join(File.dirname(__FILE__), LOG_PATH % (product || DEFAULT_LOG))
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_statistic_key(vendor)
|
82
|
+
if vendor.nil? || vendor.length < KEY_RANGE.min
|
83
|
+
log_stat_message("Vendor length is below minimum of <#{KEY_RANGE}>")
|
84
|
+
return nil
|
85
|
+
end
|
86
|
+
|
87
|
+
vendor.gsub!('-', '_')
|
88
|
+
vendor.slice! vendor.rindex('_') until vendor.count('_') <= 1
|
89
|
+
|
90
|
+
vendor.delete! "^A-Za-z0-9\_"
|
91
|
+
|
92
|
+
KEY_FORMAT % vendor[0...KEY_RANGE.max].downcase
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_product(product, version)
|
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
|
+
|
105
|
+
product = (PRODUCT_FORMAT % [product, version])[0...PRODUCT_RANGE.max]
|
106
|
+
|
107
|
+
product.slice! product.rindex(/[A-Z0-9]/i)+1..-1
|
108
|
+
|
109
|
+
if product.length < PRODUCT_RANGE.min
|
110
|
+
log_stat_message("Product length below minimum <#{PRODUCT_RANGE.min}>.")
|
111
|
+
return nil
|
112
|
+
end
|
113
|
+
product.downcase
|
114
|
+
end
|
115
|
+
|
116
|
+
def generate_payload(statistic_value='')
|
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}
|
123
|
+
JSON.generate(payload)
|
25
124
|
end
|
125
|
+
|
126
|
+
def send(nexpose_address, nexpose_port, session_id, payload)
|
127
|
+
header = {'Content-Type' => 'application/json',
|
128
|
+
'nexposeCCSessionID' => session_id,
|
129
|
+
'Cookie' => "nexposeCCSessionID=#{session_id}"}
|
130
|
+
req = Net::HTTP::Put.new(ENDPOINT, header)
|
131
|
+
req.body = payload
|
132
|
+
http_instance = Net::HTTP.new(nexpose_address, nexpose_port)
|
133
|
+
http_instance.use_ssl = true
|
134
|
+
http_instance.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
135
|
+
response = http_instance.start { |http| http.request(req) }
|
136
|
+
log_stat_message "Received code #{response.code} from Nexpose console."
|
137
|
+
log_stat_message "Received message #{response.msg} from Nexpose console."
|
138
|
+
log_stat_message 'Finished sending statistics data to Nexpose.'
|
139
|
+
|
140
|
+
response.code
|
141
|
+
end
|
142
|
+
|
143
|
+
def on_connect(nexpose_address, nexpose_port, session_id, value)
|
144
|
+
log_stat_message 'Sending statistics data to Nexpose'
|
145
|
+
|
146
|
+
if @product.nil? || @statistic_key.nil?
|
147
|
+
log_stat_message('Invalid product name and/or statistics key.')
|
148
|
+
log_stat_message('Statistics collection not enabled.')
|
149
|
+
return
|
150
|
+
end
|
151
|
+
|
152
|
+
begin
|
153
|
+
payload = generate_payload value
|
154
|
+
send(nexpose_address, nexpose_port, session_id, payload)
|
155
|
+
rescue => e
|
156
|
+
#Let the program continue
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
#Used by net library for debugging
|
161
|
+
def <<(value)
|
162
|
+
log_debug_message(value)
|
163
|
+
end
|
164
|
+
|
26
165
|
end
|
27
|
-
end
|
166
|
+
end
|
data/lib/paloalto/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nexpose_paloalto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Damian Finol
|
8
8
|
- JJ Cassidy
|
9
9
|
autorequire:
|
10
|
-
bindir:
|
10
|
+
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-05-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -45,14 +45,14 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '3.2'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '3.2'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: curb
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,8 +84,9 @@ dependencies:
|
|
84
84
|
description: This Gem allows usage of Nexpose Dynamic Asset groups with Palo Alto
|
85
85
|
TAGs.
|
86
86
|
email:
|
87
|
-
-
|
88
|
-
executables:
|
87
|
+
- support@rapid7.com
|
88
|
+
executables:
|
89
|
+
- nexpose_paloalto
|
89
90
|
extensions: []
|
90
91
|
extra_rdoc_files: []
|
91
92
|
files:
|
@@ -94,13 +95,12 @@ files:
|
|
94
95
|
- LICENSE.txt
|
95
96
|
- README.md
|
96
97
|
- Rakefile
|
97
|
-
-
|
98
|
+
- bin/nexpose_paloalto
|
98
99
|
- lib/paloalto.rb
|
99
100
|
- lib/paloalto/nexpose_helper.rb
|
100
101
|
- lib/paloalto/ngfw.rb
|
101
102
|
- lib/paloalto/nx_logger.rb
|
102
103
|
- lib/paloalto/version.rb
|
103
|
-
- nexpose_paloalto.gemspec
|
104
104
|
homepage: http://www.rapid7.com
|
105
105
|
licenses:
|
106
106
|
- MIT
|
@@ -121,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
121
|
version: '0'
|
122
122
|
requirements: []
|
123
123
|
rubyforge_project:
|
124
|
-
rubygems_version: 2.
|
124
|
+
rubygems_version: 2.5.1
|
125
125
|
signing_key:
|
126
126
|
specification_version: 4
|
127
127
|
summary: Nexpose Palo Alto Gem Integration
|
data/nexpose_paloalto.gemspec
DELETED
@@ -1,28 +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 'paloalto/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "nexpose_paloalto"
|
8
|
-
spec.version = Paloalto::VERSION
|
9
|
-
spec.authors = ['Damian Finol', 'JJ Cassidy']
|
10
|
-
spec.email = ['integrations_support@rapid7.com']
|
11
|
-
|
12
|
-
spec.summary = 'Nexpose Palo Alto Gem Integration'
|
13
|
-
spec.description = 'This Gem allows usage of Nexpose Dynamic Asset groups with Palo Alto TAGs.'
|
14
|
-
spec.homepage = "http://www.rapid7.com"
|
15
|
-
spec.license = "MIT"
|
16
|
-
|
17
|
-
spec.files = Dir['[A-Z]*'] + Dir['lib/**/*'] + Dir['bin/**']
|
18
|
-
spec.bindir = "exe"
|
19
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
-
spec.require_paths = ["lib"]
|
21
|
-
|
22
|
-
spec.add_development_dependency "bundler", "~> 1.8"
|
23
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
-
spec.add_runtime_dependency 'nexpose', "~> 0.9"
|
25
|
-
spec.add_runtime_dependency 'curb', "~> 0.8.7"
|
26
|
-
spec.add_runtime_dependency 'nokogiri', "~> 1.6"
|
27
|
-
spec.required_ruby_version = '~> 2.0'
|
28
|
-
end
|