nexpose_sccm 0.4.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.
- checksums.yaml +7 -0
- data/Gemfile +14 -0
- data/MIT-LICENSE +21 -0
- data/README.md +212 -0
- data/bin/encrypt_settings.rb +135 -0
- data/bin/nexpose_sccm +69 -0
- data/bin/vuln_ids.csv +7 -0
- data/conf/logging.yml +8 -0
- data/conf/nexpose.yml +8 -0
- data/conf/postgres.yml +8 -0
- data/conf/queries.yml +87 -0
- data/conf/sccm.yml +30 -0
- data/conf/secret.yml +4 -0
- data/lib/nexpose_sccm.rb +294 -0
- data/lib/nexpose_sccm/collection.rb +42 -0
- data/lib/nexpose_sccm/connection.rb +165 -0
- data/lib/nexpose_sccm/data_source.rb +67 -0
- data/lib/nexpose_sccm/deployment_package.rb +37 -0
- data/lib/nexpose_sccm/device.rb +11 -0
- data/lib/nexpose_sccm/helpers/nexpose_helper.rb +65 -0
- data/lib/nexpose_sccm/helpers/pg_helper.rb +26 -0
- data/lib/nexpose_sccm/powershell.rb +111 -0
- data/lib/nexpose_sccm/remediation_item.rb +5 -0
- data/lib/nexpose_sccm/software_update_group.rb +54 -0
- data/lib/nexpose_sccm/utilities/nx_logger.rb +171 -0
- data/lib/nexpose_sccm/utilities/utility_config.rb +59 -0
- data/lib/nexpose_sccm/version.rb +5 -0
- data/lib/nexpose_sccm/wql.rb +35 -0
- data/nexpose_sccm.gemspec +35 -0
- metadata +128 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'winrm'
|
2
|
+
require_relative 'powershell'
|
3
|
+
|
4
|
+
module NexposeSCCM
|
5
|
+
# Configuration settings for creating a Software Update Group
|
6
|
+
#
|
7
|
+
# * *Args* :
|
8
|
+
# - +name+ - A String identifying the display name of the Software Update Group
|
9
|
+
# - +description+ - A String identifying the description of the Software Update Group
|
10
|
+
# - +ci_ids+ - An Array identifying the list of ci_ids to add to a Software Update Group
|
11
|
+
#
|
12
|
+
class SoftwareUpdateGroup
|
13
|
+
attr_accessor :name, :description, :ci_ids
|
14
|
+
|
15
|
+
def initialize(name, description, ci_ids, ci_id=nil)
|
16
|
+
@name = name
|
17
|
+
@description = description
|
18
|
+
@ci_ids = ci_ids
|
19
|
+
@ci_id = ci_id
|
20
|
+
end
|
21
|
+
|
22
|
+
def save(conn)
|
23
|
+
if @ci_id.nil?
|
24
|
+
if @ci_ids.length > 0
|
25
|
+
Powershell.run(conn.conn,
|
26
|
+
:create_software_update_group,
|
27
|
+
conn.namespace,
|
28
|
+
conn.host,
|
29
|
+
@name,
|
30
|
+
@description,
|
31
|
+
@ci_ids.join(','))
|
32
|
+
else
|
33
|
+
NexposeSCCM.logger.debug('No CI_IDs to add to Software Update Group, going to next...')
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
else
|
37
|
+
if @ci_ids.length > 0
|
38
|
+
Powershell.run(conn.conn,
|
39
|
+
:update_software_update_group,
|
40
|
+
conn.namespace,
|
41
|
+
conn.host,
|
42
|
+
@ci_id,
|
43
|
+
@ci_ids.join(','))
|
44
|
+
else
|
45
|
+
Powershell.run(conn.conn,
|
46
|
+
:update_software_update_group_empty,
|
47
|
+
conn.namespace,
|
48
|
+
conn.host,
|
49
|
+
@ci_id)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'json'
|
3
|
+
require 'net/http'
|
4
|
+
require 'singleton'
|
5
|
+
|
6
|
+
module NexposeSCCM
|
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,
|
35
|
+
log_level = 'info',
|
36
|
+
stdout=false,
|
37
|
+
rotation='weekly',
|
38
|
+
log_size=nil)
|
39
|
+
@stdout = stdout
|
40
|
+
|
41
|
+
log_message('Logging disabled.') unless enabled || @log.nil?
|
42
|
+
@enabled = enabled
|
43
|
+
return unless @enabled
|
44
|
+
|
45
|
+
@logger_file = get_log_path @product
|
46
|
+
|
47
|
+
require 'logger'
|
48
|
+
directory = File.dirname(@logger_file)
|
49
|
+
FileUtils.mkdir_p(directory) unless File.directory?(directory)
|
50
|
+
io = IO.for_fd(IO.sysopen(@logger_file, 'a'), 'a')
|
51
|
+
io.autoclose = false
|
52
|
+
io.sync = true
|
53
|
+
@log = Logger.new(io, rotation, log_size)
|
54
|
+
@log.level = if log_level.to_s.casecmp('info') == 0
|
55
|
+
Logger::INFO
|
56
|
+
else
|
57
|
+
Logger::DEBUG
|
58
|
+
end
|
59
|
+
log_message("Logging enabled at level <#{log_level}>")
|
60
|
+
end
|
61
|
+
|
62
|
+
def create_calls
|
63
|
+
levels = [:info, :debug, :error, :warn]
|
64
|
+
levels.each do |level|
|
65
|
+
method_name = "log_#{level.to_s}_message"
|
66
|
+
define_singleton_method(method_name) do |message|
|
67
|
+
puts message if @stdout
|
68
|
+
@log.send(level, message) unless !@enabled || @log.nil?
|
69
|
+
end
|
70
|
+
singleton_class.send(:alias_method, level, method_name.to_sym)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def log_message(message)
|
75
|
+
log_info_message message
|
76
|
+
end
|
77
|
+
|
78
|
+
def log_stat_message(message)
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_log_path(product)
|
82
|
+
product.downcase! unless product.nil?
|
83
|
+
File.join(File.dirname(__FILE__), LOG_PATH % (product || DEFAULT_LOG))
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_statistic_key(vendor)
|
87
|
+
if vendor.nil? || vendor.length < KEY_RANGE.min
|
88
|
+
log_stat_message("Vendor length is below minimum of <#{KEY_RANGE}>")
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
|
92
|
+
vendor.gsub!('-', '_')
|
93
|
+
vendor.slice! vendor.rindex('_') until vendor.count('_') <= 1
|
94
|
+
|
95
|
+
vendor.delete! "^A-Za-z0-9\_"
|
96
|
+
|
97
|
+
KEY_FORMAT % vendor[0...KEY_RANGE.max].downcase
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_product(product, version)
|
101
|
+
return nil if ((product.nil? || product.empty?) ||
|
102
|
+
(version.nil? || version.empty?))
|
103
|
+
|
104
|
+
product.gsub!('-', '_')
|
105
|
+
product.slice! product.rindex('_') until product.count('_') <= 1
|
106
|
+
|
107
|
+
product.delete! "^A-Za-z0-9\_"
|
108
|
+
version.delete! "^A-Za-z0-9\.\-"
|
109
|
+
|
110
|
+
product = (PRODUCT_FORMAT % [product, version])[0...PRODUCT_RANGE.max]
|
111
|
+
|
112
|
+
product.slice! product.rindex(/[A-Z0-9]/i)+1..-1
|
113
|
+
|
114
|
+
if product.length < PRODUCT_RANGE.min
|
115
|
+
log_stat_message("Product length below minimum <#{PRODUCT_RANGE.min}>.")
|
116
|
+
return nil
|
117
|
+
end
|
118
|
+
product.downcase
|
119
|
+
end
|
120
|
+
|
121
|
+
def generate_payload(statistic_value='')
|
122
|
+
product_name, separator, version = @product.to_s.rpartition('_')
|
123
|
+
payload_value = {'version' => version}.to_json
|
124
|
+
|
125
|
+
payload = {'statistic-key' => @statistic_key.to_s,
|
126
|
+
'statistic-value' => payload_value,
|
127
|
+
'product' => product_name}
|
128
|
+
JSON.generate(payload)
|
129
|
+
end
|
130
|
+
|
131
|
+
def send(nexpose_address, nexpose_port, session_id, payload)
|
132
|
+
header = {'Content-Type' => 'application/json',
|
133
|
+
'nexposeCCSessionID' => session_id,
|
134
|
+
'Cookie' => "nexposeCCSessionID=#{session_id}"}
|
135
|
+
req = Net::HTTP::Put.new(ENDPOINT, header)
|
136
|
+
req.body = payload
|
137
|
+
http_instance = Net::HTTP.new(nexpose_address, nexpose_port)
|
138
|
+
http_instance.use_ssl = true
|
139
|
+
http_instance.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
140
|
+
response = http_instance.start { |http| http.request(req) }
|
141
|
+
log_stat_message "Received code #{response.code} from Nexpose console."
|
142
|
+
log_stat_message "Received message #{response.msg} from Nexpose console."
|
143
|
+
log_stat_message 'Finished sending statistics data to Nexpose.'
|
144
|
+
|
145
|
+
response.code
|
146
|
+
end
|
147
|
+
|
148
|
+
def on_connect(nexpose_address, nexpose_port, session_id, value)
|
149
|
+
log_stat_message 'Sending statistics data to Nexpose'
|
150
|
+
|
151
|
+
if @product.nil? || @statistic_key.nil?
|
152
|
+
log_stat_message('Invalid product name and/or statistics key.')
|
153
|
+
log_stat_message('Statistics collection not enabled.')
|
154
|
+
return
|
155
|
+
end
|
156
|
+
|
157
|
+
begin
|
158
|
+
payload = generate_payload value
|
159
|
+
send(nexpose_address, nexpose_port, session_id, payload)
|
160
|
+
rescue => e
|
161
|
+
#Let the program continue
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
#Used by net library for debugging
|
166
|
+
def <<(value)
|
167
|
+
log_debug_message(value)
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module UtilityConfig
|
2
|
+
def self.load_config(settings_locations, settings_dir=nil)
|
3
|
+
# Load settings.yml from -s option or parse known locations for configuration file
|
4
|
+
begin
|
5
|
+
settings_dir = settings_dir.nil? ? settings_locations : [settings_dir]
|
6
|
+
settings = nil
|
7
|
+
|
8
|
+
settings_dir.each do |dir|
|
9
|
+
Dir.glob(File.join(dir, '*.yml')) do |yml_file|
|
10
|
+
tmp_settings = YAML::load_file(yml_file)
|
11
|
+
next if tmp_settings.nil?
|
12
|
+
settings = settings.nil? ? tmp_settings.dup : settings.merge(tmp_settings.to_h)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
rescue Exception => e
|
16
|
+
abort("Could not parse or load settings file: #{e}")
|
17
|
+
end
|
18
|
+
settings
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.load_encrypt(settings)
|
22
|
+
# Load encrypted settings if defined
|
23
|
+
begin
|
24
|
+
if settings[:secret]
|
25
|
+
priv_key = OpenSSL::PKey::RSA.new(File.read(File.join(settings[:secret][:encrypt_key_dir], 'rsa_key')))
|
26
|
+
dec_buf = priv_key.private_decrypt(Base64.decode64(File.read(settings[:secret][:encrypt_cred_file])))
|
27
|
+
YAML::load(dec_buf).each do |key,value|
|
28
|
+
value.each do |k,v|
|
29
|
+
if v.class == String
|
30
|
+
settings[key][k] = v
|
31
|
+
elsif v.class == Hash
|
32
|
+
v.each do |k2,v2|
|
33
|
+
settings[key][k][k2] = v2
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
return settings
|
40
|
+
rescue Exception => e
|
41
|
+
abort("Could not parse or load encrypted file #{settings[:secret][:encrypt_cred_file]} : #{e}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.save_encrypt(settings_locations, settings_dir=nil)
|
46
|
+
begin
|
47
|
+
settings_dir = settings_dir.nil? ? settings_locations : [settings_dir]
|
48
|
+
settings_dir.each do |dir|
|
49
|
+
Dir.glob(File.join(dir, '*.yml')) do |yml_file|
|
50
|
+
text = File.read(yml_file)
|
51
|
+
new_contents = text.gsub(/:\s+[\'\"]\(enc\).*[\'\"][\r\n]*/, ": 'secret'\n")
|
52
|
+
File.open(yml_file, "w") {|file| file.puts new_contents}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
rescue Exception => e
|
56
|
+
abort("Could not parse or save settings file: #{e}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'winrm'
|
2
|
+
|
3
|
+
module NexposeSCCM
|
4
|
+
module Wql
|
5
|
+
|
6
|
+
@queries = {
|
7
|
+
:get_ci_ids => "SELECT ci_id FROM SMS_SoftwareUpdate WHERE CI_UniqueID=\"%s\"",
|
8
|
+
:get_sups => "SELECT ci_id, localizeddisplayname, localizeddescription FROM SMS_AuthorizationList WHERE LocalizedDisplayName like \"Rapid7%%\"",
|
9
|
+
:get_collections => "SELECT * FROM SMS_Collection WHERE Name LIKE \"Rapid7%%\"",
|
10
|
+
:get_collection_by_name => "SELECT * FROM SMS_Collection WHERE Name = \"%s\"",
|
11
|
+
:get_collection_members => "SELECT * FROM SMS_FullCollectionMembership WHERE CollectionId=\"%s\"",
|
12
|
+
:get_devices => "SELECT * FROM SMS_R_System WHERE client IS NOT NULL",
|
13
|
+
:get_device_by_id => "SELECT * FROM SMS_R_System WHERE ResourceID = \"%s\"",
|
14
|
+
:get_asset_mac => "SELECT * FROM SMS_R_System WHERE MACAddresses = \"%s\"",
|
15
|
+
:get_asset_ip => "SELECT * FROM SMS_R_System WHERE IPAddresses = \"%s\"",
|
16
|
+
:get_asset_hostname => "SELECT * FROM SMS_R_System WHERE Name = \"%s\"",
|
17
|
+
:get_update_url => "SELECT FileName,SourceURL from SMS_CIContentfiles WHERE ContentID=\"%s\"",
|
18
|
+
:ci_to_contentid => "SELECT contentid FROM SMS_CIToContent WHERE ci_id = \"%s\"",
|
19
|
+
:get_deployment_package => "SELECT * FROM SMS_SoftwareUpdatesPackage WHERE Name = \"%s\""
|
20
|
+
}
|
21
|
+
|
22
|
+
def self.run(conn, namespace, query, *args)
|
23
|
+
unless @queries.key?(query)
|
24
|
+
NexposeSCCM.logger.error("Invalid query supplied: #{query}")
|
25
|
+
end
|
26
|
+
wql = @queries[query] % [*args]
|
27
|
+
results = []
|
28
|
+
conn.run_wql(wql, "#{namespace.gsub('\\','/')}/*") do |_, item|
|
29
|
+
item = item.inject({}){|i,(k,v)| i[k.to_sym] = v; i}
|
30
|
+
results.push(item)
|
31
|
+
end
|
32
|
+
results
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative './lib/nexpose_sccm/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'nexpose_sccm'
|
7
|
+
spec.version = NexposeSCCM::VERSION
|
8
|
+
spec.authors = ['Ben Glass', 'Zac Youtz', 'Adam Robinson']
|
9
|
+
spec.email = ['support@rapid7.com']
|
10
|
+
spec.summary = %q{Ruby Gem for Nexpose SCCM Integration}
|
11
|
+
spec.description = %q{This gem pulls data from InsightVM/Nexpose and creates content in SCCM for remediation}
|
12
|
+
spec.homepage = 'http://www.rapid7.com/'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = Dir.glob("{bin,conf,lib}/**/*")
|
16
|
+
spec.files += Dir['README.md', 'nexpose_sccm.gemspec', 'MIT-LICENSE', 'Gemfile']
|
17
|
+
spec.files.reject! { |f| f.match(%r{(logs)/}) }
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
spec.executables = ['nexpose_sccm']
|
20
|
+
spec.bindir = 'bin'
|
21
|
+
|
22
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
23
|
+
# delete this section to allow pushing this gem to any host.
|
24
|
+
if spec.respond_to?(:metadata)
|
25
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
26
|
+
else
|
27
|
+
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
|
28
|
+
end
|
29
|
+
|
30
|
+
spec.add_runtime_dependency 'nexpose', '~> 7.2'
|
31
|
+
spec.add_runtime_dependency 'pg', '~> 0.21.0'
|
32
|
+
spec.add_runtime_dependency 'winrm', '~> 2.2', '>= 2.2.3'
|
33
|
+
|
34
|
+
spec.required_ruby_version = ['>= 2.3.1', '< 2.5.0']
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nexpose_sccm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben Glass
|
8
|
+
- Zac Youtz
|
9
|
+
- Adam Robinson
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2018-04-13 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: nexpose
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '7.2'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - "~>"
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '7.2'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: pg
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - "~>"
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 0.21.0
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.21.0
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: winrm
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '2.2'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 2.2.3
|
53
|
+
type: :runtime
|
54
|
+
prerelease: false
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.2'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 2.2.3
|
63
|
+
description: This gem pulls data from InsightVM/Nexpose and creates content in SCCM
|
64
|
+
for remediation
|
65
|
+
email:
|
66
|
+
- support@rapid7.com
|
67
|
+
executables:
|
68
|
+
- nexpose_sccm
|
69
|
+
extensions: []
|
70
|
+
extra_rdoc_files: []
|
71
|
+
files:
|
72
|
+
- Gemfile
|
73
|
+
- MIT-LICENSE
|
74
|
+
- README.md
|
75
|
+
- bin/encrypt_settings.rb
|
76
|
+
- bin/nexpose_sccm
|
77
|
+
- bin/vuln_ids.csv
|
78
|
+
- conf/logging.yml
|
79
|
+
- conf/nexpose.yml
|
80
|
+
- conf/postgres.yml
|
81
|
+
- conf/queries.yml
|
82
|
+
- conf/sccm.yml
|
83
|
+
- conf/secret.yml
|
84
|
+
- lib/nexpose_sccm.rb
|
85
|
+
- lib/nexpose_sccm/collection.rb
|
86
|
+
- lib/nexpose_sccm/connection.rb
|
87
|
+
- lib/nexpose_sccm/data_source.rb
|
88
|
+
- lib/nexpose_sccm/deployment_package.rb
|
89
|
+
- lib/nexpose_sccm/device.rb
|
90
|
+
- lib/nexpose_sccm/helpers/nexpose_helper.rb
|
91
|
+
- lib/nexpose_sccm/helpers/pg_helper.rb
|
92
|
+
- lib/nexpose_sccm/powershell.rb
|
93
|
+
- lib/nexpose_sccm/remediation_item.rb
|
94
|
+
- lib/nexpose_sccm/software_update_group.rb
|
95
|
+
- lib/nexpose_sccm/utilities/nx_logger.rb
|
96
|
+
- lib/nexpose_sccm/utilities/utility_config.rb
|
97
|
+
- lib/nexpose_sccm/version.rb
|
98
|
+
- lib/nexpose_sccm/wql.rb
|
99
|
+
- nexpose_sccm.gemspec
|
100
|
+
homepage: http://www.rapid7.com/
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata:
|
104
|
+
allowed_push_host: https://rubygems.org
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: 2.3.1
|
114
|
+
- - "<"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 2.5.0
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.6.11
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Ruby Gem for Nexpose SCCM Integration
|
128
|
+
test_files: []
|