nexpose_thycotic 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []