nexpose_thycotic 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9cfe89f9e59547499a62f7d17adf19c1a3ab78cc
4
+ data.tar.gz: 84d2068ae67621f761ecc896c4deb666aa85513d
5
+ SHA512:
6
+ metadata.gz: ce4458b781b8a05ace7d0303cfd261b95d0290871b89df994cae754547b33d489fe1df6ec3ffb3bf9db6d9a3477b593b65208c6c08022e06800fd26199cc2b70
7
+ data.tar.gz: ed741b2f034eabc2f0434c8040391983df6f4dd295f7d3bb7df882195e282d877b8ebf3e033c7b7a1fbfff0d711cac6d8881434ff5fe923239e7a651fe4126f0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nexpose_thycotic.gemspec
4
+ gemspec
@@ -0,0 +1,58 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ nexpose_thycotic (0.0.2)
5
+ nexpose
6
+ rubyntlm
7
+ savon
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ akami (1.2.2)
13
+ gyoku (>= 0.4.0)
14
+ nokogiri
15
+ builder (3.2.2)
16
+ gyoku (1.1.1)
17
+ builder (>= 2.1.2)
18
+ httpi (2.2.5)
19
+ rack
20
+ librex (0.0.70)
21
+ macaddr (1.7.1)
22
+ systemu (~> 2.6.2)
23
+ mime-types (1.25.1)
24
+ mini_portile (0.6.0)
25
+ nexpose (0.8.3)
26
+ librex (~> 0.0, >= 0.0.68)
27
+ nokogiri (~> 1.6, >= 1.6.2)
28
+ nokogiri (1.6.3.1)
29
+ mini_portile (= 0.6.0)
30
+ nori (2.4.0)
31
+ rack (1.5.2)
32
+ rake (0.9.2.2)
33
+ rubyntlm (0.4.0)
34
+ savon (2.6.0)
35
+ akami (~> 1.2.0)
36
+ builder (>= 2.1.2)
37
+ gyoku (~> 1.1.0)
38
+ httpi (~> 2.2.3)
39
+ nokogiri (>= 1.4.0)
40
+ nori (~> 2.4.0)
41
+ uuid (~> 2.3.7)
42
+ wasabi (~> 3.3.0)
43
+ systemu (2.6.4)
44
+ uuid (2.3.7)
45
+ macaddr (~> 1.0)
46
+ wasabi (3.3.0)
47
+ httpi (~> 2.0)
48
+ mime-types (< 2.0.0)
49
+ nokogiri (>= 1.4.0)
50
+
51
+ PLATFORMS
52
+ ruby
53
+ x86-mingw32
54
+
55
+ DEPENDENCIES
56
+ bundler (~> 1.5)
57
+ nexpose_thycotic!
58
+ rake
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Rapid7
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,23 @@
1
+ # NexposeThycotic
2
+
3
+ Nexpose Thycotic Gem allows users to import credentials from Thycotic SecretServer into their Nexpose instance.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'nexpose_thycotic'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install nexpose_thycotic
18
+
19
+ ## Usage
20
+
21
+ Edit the nx_thycotic.rb file in the /bin folder with a text editor. Add a proper username/password for both nexpose
22
+ and SecretServer, followed by the URL for SecretServer webservice.
23
+ Add the Site # to be managed by this integration, save and run on schedule.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # Please refer to the configuration documentation for instructions on how to run this gem
3
+ # Do NOT run this gem without proper pre-configuration.
4
+ require 'nexpose_thycotic'
5
+
6
+ # Thycotic SecretServer URL.
7
+ thycotic_url = 'http://YOURIP/SecretServer/webservices/sswebservice.asmx?wsdl'
8
+ # Thycotic username.
9
+ thycotic_username = 'nxadmin'
10
+ # Thycotic password
11
+ thycotic_password = 'nxadmin'
12
+
13
+
14
+ ### NEXPOSE CONFIGURATION ###
15
+ # Nexpose IP Address
16
+ nexpose_ip = 'your_nexpose_installation_ip'
17
+ # Nexpose username
18
+ nexpose_username = 'nxadmin'
19
+ # Nexpose password
20
+ nexpose_password = 'nxadmin'
21
+ # Sites to collect credentials on, separated by commas.
22
+ sites = [ 7 ]
23
+
24
+
25
+ ### DO NOT EDIT AFTER THIS LINE ###
26
+ NexposeThycotic::NxLogger.log_message('Testing', 'debug')
27
+ vault_options = { url: thycotic_url, username: thycotic_username, password: thycotic_password }
28
+ nexpose_options = { nexpose_ip: nexpose_ip, nexpose_username: nexpose_username, nexpose_password: nexpose_password, sites: sites }
29
+ NexposeThycotic.update_credentials(vault_options, nexpose_options)
@@ -0,0 +1,39 @@
1
+ require "nexpose_thycotic/version"
2
+ require 'nexpose_thycotic/operations'
3
+ require 'nexpose_thycotic/nx_logger'
4
+ require 'nexpose'
5
+
6
+ module NexposeThycotic
7
+ def self.update_credentials(vault_options, nexpose_options = nil)
8
+ NxLogger.log_message('Starting integration.', 'info')
9
+ ss = ThycoticOperations.new(vault_options[:url])
10
+ NxLogger.log_message("Logging to Thycotic at #{vault_options[:url]}", 'info')
11
+ token = ss.authenticate(vault_options[:username], vault_options[:password])
12
+ @nx = NexposeOperations.new(nexpose_options[:nexpose_ip], nexpose_options[:nexpose_username], nexpose_options[:nexpose_password])
13
+ NxLogger.log_message('Processing sites', 'info')
14
+
15
+ nexpose_options[:sites].each do |site_id|
16
+ NxLogger.log_message("Processing site #{site_id}", 'debug')
17
+ ips = @nx.get_ips_from_site(site_id)
18
+ site_credentials = []
19
+ ips.each do |ip|
20
+ ip_from = ip.instance_of?(Nexpose::HostName) ? ip.host : ip.from
21
+ NxLogger.log_message("Getting credentials for #{ip_from}", 'debug')
22
+ secret_summary = ss.get_secret_id(token, ip_from)
23
+ unless secret_summary.nil?
24
+ NxLogger.log_message("Found credentials for #{ip_from}", 'debug')
25
+ # Gets OS
26
+ asset_data = {}
27
+ asset_data[:ip] = ip_from
28
+ res = ss.get_secret_simple(token, secret_summary[:secret_id])
29
+ asset_data[:username] = res[:username]
30
+ asset_data[:password] = res[:password]
31
+ credential = Nexpose::Credential.for_service(ss.check_type(secret_summary[:secret_type]), asset_data[:username], asset_data[:password], nil, ip.from )
32
+ site_credentials.push(credential)
33
+ end
34
+ end
35
+ @nx.save_site(site_id, site_credentials)
36
+ NxLogger.log_message("Finished processing #{site_id}", 'info')
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,19 @@
1
+ module NexposeThycotic
2
+ module NxLogger
3
+ require 'logger'
4
+ LOGGER_FILE = File.join(File.dirname(__FILE__), '/log/nx_thycotic.log')
5
+ directory = File.dirname(LOGGER_FILE)
6
+ FileUtils.mkdir_p(directory) unless File.directory?(directory)
7
+ @log = Logger.new(LOGGER_FILE, 'monthly')
8
+ @log.level = Logger::INFO
9
+
10
+ def self.log_message(message, level)
11
+ case level
12
+ when 'info' then @log.info(message)
13
+ when 'debug' then @log.debug(message)
14
+ when 'error' then @log.error(message)
15
+ when 'warn' then @log.warn(message)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,132 @@
1
+ module NexposeThycotic
2
+ class NexposeOperations
3
+ require 'nexpose'
4
+ include Nexpose
5
+ attr_reader :nsc
6
+
7
+ def initialize(ip, user, pass, port = 3780)
8
+ @nsc = Connection.new(ip, user, pass, port)
9
+ @nsc.login
10
+ end
11
+ def get_ips_from_site(site_id)
12
+ site = Site.load(@nsc, site_id)
13
+ site.assets
14
+ end
15
+
16
+ def save_site(site_id, credentials)
17
+ site = Site.load(@nsc, site_id)
18
+ site.credentials = credentials
19
+ site.save(@nsc)
20
+ end
21
+
22
+ def delete_site_credentials(site_id)
23
+ site = Site.load(@nsc, site_id)
24
+ site.credentials = []
25
+ site.save(@nsc)
26
+ end
27
+
28
+ def start_scan(site_id)
29
+ site = Site.load(@nsc, site_id)
30
+ site.scan(@nsc)
31
+ end
32
+
33
+ def scan_status(scan_id)
34
+ @nsc.scan_status(scan_id)
35
+ end
36
+ end
37
+
38
+ class ThycoticOperations
39
+ require 'savon'
40
+ attr_accessor :client
41
+ def initialize(url = nil)
42
+ # log: true, log_level: :info
43
+ @client = Savon.client(wsdl: url)
44
+ end
45
+
46
+ def operations
47
+ puts @client.operations
48
+ end
49
+
50
+ def check_type(type)
51
+ case type
52
+ when /.*unix.*/i then 'ssh'
53
+ when /.*windows.*/i then 'cifs'
54
+ when /.*ftp.*/i then 'ftp'
55
+ when /.*400.*/i then 'as400'
56
+ when /.*lotus.*/i then 'notes'
57
+ when /.*Microsoft.*SQL.*Server.*/i then 'tds'
58
+ when /.*Sybase.*SQL.*Server.*/i then 'sybase'
59
+ when /.*mysql.*/i then 'mysql'
60
+ when /.*DB2.*/i then 'db2'
61
+ when /.*postgresql.*/i then 'postgresql'
62
+ when /.*pop.*/i then 'pop'
63
+ when /.*Simple.*Network.*Management.*/i then 'snmp'
64
+ when /.*telnet.*/i then 'telnet'
65
+ end
66
+ end
67
+
68
+ def authenticate(username, password)
69
+ auth = @client.call(:authenticate, message: { username: username, password: password })
70
+ auth_response = auth.hash
71
+ auth_result = auth_response[:envelope][:body][:authenticate_response][:authenticate_result]
72
+ CheckForErrors(auth_result)
73
+ @token = auth_result[:token]
74
+ end
75
+
76
+ def parse_field(secret_response_result, fieldName)
77
+ items = secret_response_result[:secret][:items]
78
+ for item in items[:secret_item]
79
+ if item[:field_display_name].downcase == fieldName.downcase then
80
+ return item[:value]
81
+ end
82
+ end
83
+ end
84
+
85
+ def get_secret_id(token, ip)
86
+ secret_id = @client.call( :search_secrets_by_field_value, message: { token: token, fieldName: 'machine', searchTerm: ip, showDeleted: true, showRestricted: true})
87
+ secret_result = secret_id.hash
88
+ unless secret_result[:envelope][:body][:search_secrets_by_field_value_response][:search_secrets_by_field_value_result][:secret_summaries].nil? then
89
+ secret_summary = secret_result[:envelope][:body][:search_secrets_by_field_value_response][:search_secrets_by_field_value_result][:secret_summaries][:secret_summary]
90
+ secret_info = { secret_id: secret_summary[:secret_id], secret_type: secret_summary[:secret_type_name] }
91
+ end
92
+ end
93
+
94
+ def get_secret_simple(token, secret_id)
95
+ secret = @client.call( :get_secret_legacy, message: { token: token, secretId: secret_id } )
96
+ secret_response = secret.hash
97
+ secret_response_result = secret_response[:envelope][:body][:get_secret_legacy_response][:get_secret_legacy_result]
98
+ CheckForErrors(secret_response_result)
99
+ username = parse_field(secret_response_result, "Username")
100
+ password = parse_field(secret_response_result, "Password")
101
+ asset = { username: username, password: password }
102
+
103
+ end
104
+
105
+ def get_secret(token, secret_id)
106
+ #Code Responses are used if additional information is required when getting the Secret (Ex: Requires Comment is turned on so need to pass Code Response as..)
107
+ code_response = nil
108
+ #code_response = @client.new("codeResponse") #Code is not working, need to create object of type codeResponse from the wsdl
109
+ #code_response.ErrorCode = "COMMENT";
110
+ #code_response.Comment = "Running scan";
111
+
112
+ #CodeResponses is an array because there could be multiple additional responses needed
113
+ code_responses = [code_response]
114
+
115
+ secret = @client.call( :get_secret, message: { token: token, secretId: secret_id, CodeResponse: code_responses } )
116
+ secret_response = secret.hash
117
+ secret_response_result = secret_response[:envelope][:body][:get_secret_response][:get_secret_result]
118
+ CheckForErrors(secret_response_result)
119
+ username = parse_field(secret_response_result, "Username")
120
+ password = parse_field(secret_response_result, "Password")
121
+ end
122
+
123
+ def CheckForErrors(result)
124
+ errors = result[:errors]
125
+ if !errors.blank? then
126
+ puts errors
127
+ raise Exception.new(errors)
128
+ end
129
+
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,6 @@
1
+ module NexposeThycotic
2
+ VERSION = "0.0.2"
3
+ def self.show_version
4
+ puts VERSION
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nexpose_thycotic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Damian Finol
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: savon
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubyntlm
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: nexpose
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: This gem allows Nexpose users to poll credentials from Thycotic SecretServer
84
+ into Nexpose
85
+ email:
86
+ - damian_finol@rapid7.com
87
+ executables:
88
+ - nx_thycotic.rb
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE.txt
95
+ - Rakefile
96
+ - README.md
97
+ - lib/nexpose_thycotic/nx_logger.rb
98
+ - lib/nexpose_thycotic/operations.rb
99
+ - lib/nexpose_thycotic/version.rb
100
+ - lib/nexpose_thycotic.rb
101
+ - bin/nx_thycotic.rb
102
+ homepage: http://www.rapid7.com/
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.0.14
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Nexpose Thycotic Gem Integration
126
+ test_files: []