schatz 0.0.4
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.
- data/Gemfile +8 -0
- data/Gemfile.lock +21 -0
- data/README.txt +14 -0
- data/bin/schatz +12 -0
- data/config/config.yml +10 -0
- data/install.rb +5 -0
- data/lib/schatz.rb +31 -0
- data/lib/schatz/cli/configuration.rb +45 -0
- data/lib/schatz/cli/runner.rb +35 -0
- data/lib/schatz/input/connection.rb +94 -0
- data/lib/schatz/input/connection_result.rb +14 -0
- data/lib/schatz/input/export.rb +14 -0
- data/lib/schatz/input/incr_export.rb +81 -0
- data/lib/schatz/input/incr_line_parser.rb +35 -0
- data/lib/schatz/input/parser.rb +53 -0
- data/lib/schatz/input/result.rb +7 -0
- data/lib/schatz/input/text_export.rb +35 -0
- data/lib/schatz/input/txt_line_parser.rb +29 -0
- data/lib/schatz/output/cmd.rb +30 -0
- data/lib/schatz/output/html.rb +69 -0
- data/lib/schatz/output/out.rb +9 -0
- data/lib/schatz/schemes/direct_tcp.rb +17 -0
- data/lib/schatz/schemes/proxy_http.rb +19 -0
- data/lib/schatz/schemes/proxy_https.rb +18 -0
- data/lib/schatz/testers/incr_test.rb +46 -0
- metadata +71 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
nokogiri (1.5.0-x86-mingw32)
|
5
|
+
rainbow (1.1.3)
|
6
|
+
win32-api (1.4.8-x86-mingw32)
|
7
|
+
win32console (1.3.0-x86-mingw32)
|
8
|
+
windows-api (0.4.0)
|
9
|
+
win32-api (>= 1.4.5)
|
10
|
+
windows-pr (1.2.1)
|
11
|
+
win32-api (>= 1.4.5)
|
12
|
+
windows-api (>= 0.3.0)
|
13
|
+
|
14
|
+
PLATFORMS
|
15
|
+
x86-mingw32
|
16
|
+
|
17
|
+
DEPENDENCIES
|
18
|
+
nokogiri
|
19
|
+
rainbow
|
20
|
+
win32console
|
21
|
+
windows-pr
|
data/README.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
= Tools for connectivity checking
|
2
|
+
== Description
|
3
|
+
Gem provides means for testing TCP direct connections as well as HTTP web services through HTTP proxy.
|
4
|
+
How to install gem:
|
5
|
+
* $ gem install schatz
|
6
|
+
Testing INCRs
|
7
|
+
|
8
|
+
schatz -f file_name [-po] [-do] [-g 123456]
|
9
|
+
|
10
|
+
-f name of the export(.html ior .htm extension) or name of .txt file
|
11
|
+
-po test only http/https links via proxies
|
12
|
+
-do test only direct connections
|
13
|
+
-p test via specified proxy
|
14
|
+
-h help
|
data/bin/schatz
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
|
3
|
+
require File.expand_path(File.dirname(__FILE__)+ "/../lib/schatz")
|
4
|
+
begin
|
5
|
+
Schatz::Cli::Runner.run(ARGV.dup, STDOUT, STDERR)
|
6
|
+
rescue SystemExit => e
|
7
|
+
Kernel.exit(e.status)
|
8
|
+
rescue Exception => e
|
9
|
+
STDERR.puts("#{e.message} (#{e.class})")
|
10
|
+
STDERR.puts(e.backtrace.join("\n"))
|
11
|
+
Kernel.exit(1)
|
12
|
+
end
|
data/config/config.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#please add necessary proxies
|
2
|
+
---
|
3
|
+
proxies:
|
4
|
+
1: "http://10.233.46.129:8080"
|
5
|
+
2: "http://10.233.46.130:8080"
|
6
|
+
3: "http://10.233.46.131:8080"
|
7
|
+
4: "http://10.233.46.132:8080"
|
8
|
+
5: "http://10.237.46.130:8080"
|
9
|
+
6: "http://10.237.46.131:8080"
|
10
|
+
7: "http://10.237.46.132:8080"
|
data/install.rb
ADDED
data/lib/schatz.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.push File.expand_path(File.dirname(__FILE__) + "/../lib")
|
2
|
+
require 'rubygems'
|
3
|
+
require 'optparse'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'schatz/cli/runner'
|
6
|
+
require 'schatz/cli/configuration'
|
7
|
+
require 'schatz/input/export'
|
8
|
+
require 'schatz/testers/incr_test'
|
9
|
+
require 'schatz/input/incr_export'
|
10
|
+
require 'schatz/input/text_export'
|
11
|
+
require 'schatz/input/connection'
|
12
|
+
require 'schatz/input/connection_result'
|
13
|
+
require 'schatz/input/txt_line_parser'
|
14
|
+
require 'schatz/input/incr_line_parser'
|
15
|
+
require 'schatz/output/out'
|
16
|
+
require 'schatz/output/html'
|
17
|
+
require 'schatz/output/cmd'
|
18
|
+
require 'schatz/schemes/direct_tcp'
|
19
|
+
require 'schatz/schemes/proxy_http'
|
20
|
+
require 'schatz/schemes/proxy_https'
|
21
|
+
require 'schatz/input/parser'
|
22
|
+
require 'timeout'
|
23
|
+
require 'rainbow'
|
24
|
+
module Schatz
|
25
|
+
exceptions = %w(IncorrentParameters IncorrectIncrFormat ExportedIncrFieldErrorPorts FileNotExistInCurrentDirectory IncorrectFileFormat SheetNotFound ExportedIncrFieldErrorUnrecognized
|
26
|
+
IncorrectTextFormat NotImplementedMethod)
|
27
|
+
exceptions.each do |exc|
|
28
|
+
const_set exc, Class.new(StandardError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
Sickill::Rainbow.enabled = true
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Cli
|
3
|
+
class Configuration
|
4
|
+
attr_accessor :opt, :options, :stdout, :stderr
|
5
|
+
def initialize(output=STDOUT, error=STDERR,options={})
|
6
|
+
@stdout = output
|
7
|
+
@stderr = error
|
8
|
+
@options =options
|
9
|
+
@opt = OptionParser.new
|
10
|
+
@opt.banner = "Usage: schatz [file_name]"
|
11
|
+
@opt.separator "Options:"
|
12
|
+
@opt.on("-f", "--file [file]") {|file| @options[:file_name] = file}
|
13
|
+
@opt.on("-h", "--help") {|ignore| @options[:help] = true}
|
14
|
+
@opt.on("--po") {|ignore| @options[:proxy_only] = true}
|
15
|
+
@opt.on("--do") {|ignore| @options[:direct_only] = true}
|
16
|
+
@opt.on("-g", "--gcm [gcm]") {|gcm| @options[:gcm] = "gcm000000" +gcm}
|
17
|
+
@opt.on("-p", "--prx [proxy]") {|proxy| @options[:proxies] = {1 => proxy}}
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse!(argv)
|
21
|
+
raise ArgumentError, "expected array of argv" unless argv.is_a?(Array)
|
22
|
+
raise ArgumentError, "you should provide at least a name of the incr" if argv.empty? || argv.first=="-f" && argv.length==1
|
23
|
+
@opt.parse(argv)
|
24
|
+
@options[:file_name] = full_file_name(@options[:file_name]) if @options[:file_name]
|
25
|
+
@options[:proxies] ||= read_config
|
26
|
+
show_info
|
27
|
+
end
|
28
|
+
|
29
|
+
def show_info
|
30
|
+
puts @opt if @options[:help]
|
31
|
+
puts "GCM number is not provided so will check all links. If you want to test only those implemented after specified GCM please mention it".foreground(:yellow) unless @options[:gcm]
|
32
|
+
end
|
33
|
+
|
34
|
+
def full_file_name(file_name)
|
35
|
+
raise FileNotExistInCurrentDirectory until File.exist?(file_name)
|
36
|
+
raise IncorrectFileFormat until file_name =~ /\.xlsx?/ || file_name =~ /\.html?/ || file_name =~ /\.txt?/
|
37
|
+
File.expand_path(file_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def read_config
|
41
|
+
YAML::load_file(File.expand_path(File.dirname(__FILE__)+"./../../../config/config.yml"))["proxies"]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module Schatz
|
3
|
+
module Cli
|
4
|
+
class Runner
|
5
|
+
attr_accessor :options, :output, :error, :configuration
|
6
|
+
def self.run(argv, output, error, options={})
|
7
|
+
new(argv, output, error, options).run
|
8
|
+
end
|
9
|
+
def initialize(argv, output, error, options={})
|
10
|
+
@output = output
|
11
|
+
@error = error
|
12
|
+
@configuration = Configuration.new(output, error, options)
|
13
|
+
@configuration.parse!(argv)
|
14
|
+
@options = @configuration.options
|
15
|
+
end
|
16
|
+
def run
|
17
|
+
trap_interrupt
|
18
|
+
source = case @options[:file_name]
|
19
|
+
when /\.htm/
|
20
|
+
Input::IncrExport.new(@options)
|
21
|
+
when /\.txt/
|
22
|
+
Input::TextExport.new(@options)
|
23
|
+
else
|
24
|
+
raise IncorrectFileFormat
|
25
|
+
end
|
26
|
+
outputters = [Output::CMD.new(@options), Output::HTML.new(@options)]
|
27
|
+
tester = Testers::IncrTest.new(@options, outputters)
|
28
|
+
tester.check_connections(source.get_conversations + source.get_links )
|
29
|
+
end
|
30
|
+
def trap_interrupt
|
31
|
+
trap("INT") {exit!}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Input
|
3
|
+
class Connection
|
4
|
+
attr_accessor :scheme, :host, :port, :gcm, :result, :color, :description
|
5
|
+
def initialize
|
6
|
+
@port = 80
|
7
|
+
@scheme = "http"
|
8
|
+
yield self
|
9
|
+
if @port=="" || @port==0
|
10
|
+
case @scheme
|
11
|
+
when "http"
|
12
|
+
@port = 80
|
13
|
+
when "https"
|
14
|
+
@port = 443
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def eql?(b)
|
19
|
+
self.scheme == b.scheme && self.host == b.host && self.port == b.port && self.gcm == b.gcm ? true : false
|
20
|
+
end
|
21
|
+
|
22
|
+
def result=(value)
|
23
|
+
@result=value
|
24
|
+
mark
|
25
|
+
end
|
26
|
+
def scheme=(value)
|
27
|
+
@scheme = value.downcase
|
28
|
+
end
|
29
|
+
def gcm=(value)
|
30
|
+
@gcm = value.downcase
|
31
|
+
end
|
32
|
+
|
33
|
+
def http?
|
34
|
+
@scheme="http"
|
35
|
+
end
|
36
|
+
|
37
|
+
def https?
|
38
|
+
@scheme="https"
|
39
|
+
end
|
40
|
+
|
41
|
+
def mark
|
42
|
+
direct? ? mark_hosts : mark_links
|
43
|
+
end
|
44
|
+
|
45
|
+
def direct?
|
46
|
+
scheme.downcase == "tcp" || scheme.downcase == "udp"
|
47
|
+
end
|
48
|
+
|
49
|
+
def link?
|
50
|
+
scheme.downcase == "http" || scheme.downcase == "https"
|
51
|
+
end
|
52
|
+
|
53
|
+
def mark_hosts
|
54
|
+
self.color = result == "open" ? "green" : "red"
|
55
|
+
end
|
56
|
+
|
57
|
+
def mark_links
|
58
|
+
self.color, self.description= case result
|
59
|
+
when /30[12]/ then ["green", "Redirection to websso"]
|
60
|
+
when "200" then ["green", "OK"]
|
61
|
+
when /40[13]/ then ["green", "Error authorization"]
|
62
|
+
else ["red", result]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def check
|
67
|
+
direct? ? host_check : link_check
|
68
|
+
end
|
69
|
+
def link_check
|
70
|
+
raise ArgumentError unless @proxy
|
71
|
+
begin
|
72
|
+
self.result = case scheme
|
73
|
+
when "http"
|
74
|
+
Schemes::ProxyHttp.http_test(self, @proxy)
|
75
|
+
when "https"
|
76
|
+
Schemes::ProxyHttps.https_test(self, @proxy)
|
77
|
+
end
|
78
|
+
rescue Exception => e
|
79
|
+
self.result = e.message
|
80
|
+
end
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
def host_check
|
85
|
+
begin
|
86
|
+
self.result = Schemes::DirectTcp.direct_test(self.host, self.port, 0.5) ? "open" : "closed"
|
87
|
+
rescue Exception => e
|
88
|
+
self.result = "closed"
|
89
|
+
end
|
90
|
+
self
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Input
|
3
|
+
class ConnectionResult < Connection
|
4
|
+
attr_accessor :proxy
|
5
|
+
def initialize(connection, proxy=nil)
|
6
|
+
@scheme = connection.scheme
|
7
|
+
@host = connection.host
|
8
|
+
@port = connection.port
|
9
|
+
@gcm = connection.gcm
|
10
|
+
@proxy = proxy
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/https'
|
4
|
+
require 'schatz/input/parser'
|
5
|
+
require 'timeout'
|
6
|
+
module Schatz
|
7
|
+
module Input
|
8
|
+
class IncrExport < Export
|
9
|
+
include ParserHelper
|
10
|
+
attr_accessor :options, :file
|
11
|
+
|
12
|
+
def initialize(options)
|
13
|
+
@options = options
|
14
|
+
@file = Nokogiri::HTML(File.open(@options[:file_name], 'r'))
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_links
|
18
|
+
Schatz::Input::IncrLineParser.new(rows_in_links_table).links
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_conversations
|
22
|
+
Schatz::Input::IncrLineParser.new(rows_in_conversation_table).connections
|
23
|
+
end
|
24
|
+
|
25
|
+
# eliminate the first row(names of the fields)
|
26
|
+
def rows_in_conversation_table
|
27
|
+
get_rid_of_header(find_conv_table).select {|row| row =~ CONVERSATION_ROW }
|
28
|
+
end
|
29
|
+
|
30
|
+
def rows_in_links_table
|
31
|
+
get_rid_of_header(find_links_table)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_rid_of_header(table_number)
|
35
|
+
rows = @file.xpath("//table[#{table_number+1}]//tr")
|
36
|
+
rows.map {|row| delete_mess(row) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete_mess(row)
|
40
|
+
row.text.gsub(/[\n\t]/, "").gsub(/\u00A0/, " ").gsub(/\r\r/, " ").gsub(/\r/, "")
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_table options={}
|
44
|
+
allowed_keys= ["table_id"]
|
45
|
+
raise ArgumentError if options.empty?
|
46
|
+
options.keys.each {|key| raise IncorrentParameters unless allowed_keys.include? key.to_s}
|
47
|
+
@file.xpath("/html/body/table")[options[:table_id].to_i]
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_conv_table
|
51
|
+
reg1 = Regexp.new 'Conversation Type'
|
52
|
+
reg2 = Regexp.new 'CR/GCM Number'
|
53
|
+
reg3 = Regexp.new 'Destination Host'
|
54
|
+
find_table([reg1, reg2, reg3])
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_links_table
|
58
|
+
reg1 = Regexp.new 'Intranet Site'
|
59
|
+
reg2 = Regexp.new 'Reason and Activity'
|
60
|
+
reg3 = Regexp.new 'CR/GCM Number'
|
61
|
+
find_table([reg1, reg2, reg3])
|
62
|
+
end
|
63
|
+
|
64
|
+
def find_table(regs)
|
65
|
+
tables = @file.xpath("/html/body/table")
|
66
|
+
conv_table = tables.select {|t| regs.all?{ |regexp| t.text =~ regexp} }
|
67
|
+
raise IncorrectIncrFormat if conv_table.size > 1
|
68
|
+
tables.index(conv_table.first)
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete_source_subnets(row)
|
72
|
+
row.match(SOURCE_SUBNET).to_a.each{|reg| row.gsub!(/#{reg}/, "")} while row =~ SOURCE_SUBNET
|
73
|
+
row
|
74
|
+
end
|
75
|
+
|
76
|
+
def scan_gcm_numbers(rows)
|
77
|
+
rows.map{ |row| row.scan(GCM_NUMBER).first }.compact.map(&:downcase)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Input
|
3
|
+
class IncrLineParser < Parser
|
4
|
+
include ParserHelper
|
5
|
+
def initialize(lines)
|
6
|
+
super(lines)
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse(line)
|
10
|
+
case line
|
11
|
+
when IncrExport::LINK_HTML
|
12
|
+
@links << Connection.new do |c|
|
13
|
+
c.gcm = $1.downcase
|
14
|
+
c.scheme = $2
|
15
|
+
c.host = $3
|
16
|
+
c.port = $4.to_i if $4
|
17
|
+
end
|
18
|
+
when IncrExport::CONVERSATION_HTML
|
19
|
+
gcm = $1
|
20
|
+
scheme = $4
|
21
|
+
line.scan(IP_ADDRESS).map do |address|
|
22
|
+
parse_ports_field(line.match(IncrExport::PORTS_WITH_PROTOCOL).captures.first).map do |port|
|
23
|
+
@connections << Connection.new do |c|
|
24
|
+
c.gcm = gcm
|
25
|
+
c.scheme = scheme
|
26
|
+
c.host = address.first
|
27
|
+
c.port = port.to_i
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Input
|
3
|
+
class Parser
|
4
|
+
attr_accessor :connections, :links
|
5
|
+
def initialize(lines)
|
6
|
+
@connections = []
|
7
|
+
@links = []
|
8
|
+
lines.map { |line| parse(line)}
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse(line)
|
12
|
+
raise NotImplementedMethod
|
13
|
+
end
|
14
|
+
end
|
15
|
+
module ParserHelper
|
16
|
+
|
17
|
+
LINK = Regexp.new '(https?):\/\/([a-zA-Z0-9\.\-]+\.?d?b?.com):?(\d{1,5}*)'
|
18
|
+
LINK_HTML = Regexp.new '(gcm\d{12}|GCM\d{12}).*(https?):\/\/([a-zA-Z0-9\.\-]+\.?d?b?.com):?(\d{1,5}*).*'
|
19
|
+
SOURCE_SUBNET = Regexp.new '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\ *\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
|
20
|
+
GCM_NUMBER = Regexp.new 'gcm\d{12}|GCM\d{12}'
|
21
|
+
REGEXP_HOST = Regexp.new '^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.+(\d{1,5}[\-\,]?)+$'
|
22
|
+
REGEXP_HOST_PORTS = Regexp.new '^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\ +(\d{1,5}\-\d{1,5}|\d{1,5}(\,\d{1,5})*)$'
|
23
|
+
ONE_PORT = Regexp.new '^\d{1,5}$'
|
24
|
+
ONE_HYPHEN = Regexp.new '^\d{1,5}(\-)+\d{1,5}$'
|
25
|
+
ONE_OR_MORE_COMMA = Regexp.new'^\d{1,5}(,\d{1,5})+$'
|
26
|
+
IP_ADDRESS = Regexp.new '(10\.\d{1,3}\.\d{1,3}\.\d{1,3})(?#matches ip address)(?!.*255\.\d{1,3}\.\d{1,3}\.\d{1,3})'
|
27
|
+
PORTS_WITH_PROTOCOL= Regexp.new '([\d\-\,]{1,450}) ?(TCP|UDP)'
|
28
|
+
CONVERSATION_HTML = Regexp.new "(#{GCM_NUMBER.source}).*#{IP_ADDRESS.source}.*#{PORTS_WITH_PROTOCOL.source}.*"
|
29
|
+
CONVERSATION_ROW = Regexp.new ".*#{IP_ADDRESS.source}.*#{PORTS_WITH_PROTOCOL.source}.*"
|
30
|
+
|
31
|
+
def parse_ports_field(ports)
|
32
|
+
raise ArgumentError, "received nil instead of string for ports" unless ports
|
33
|
+
raise ArgumentError, "received blank instead of string for ports" if ports.empty?
|
34
|
+
ports.gsub!(/ /, "")
|
35
|
+
case ports
|
36
|
+
when ONE_HYPHEN
|
37
|
+
start_range, end_range = ports.split("-")
|
38
|
+
[*start_range..end_range].map(&:to_i)
|
39
|
+
when ONE_OR_MORE_COMMA
|
40
|
+
ports.split(",").map(&:to_i)
|
41
|
+
when ONE_PORT
|
42
|
+
[ports.to_i]
|
43
|
+
else ports
|
44
|
+
raise ExportedIncrFieldErrorPorts, "for #{ports}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def push_connection(host, port, protocol, gcm, hosts)
|
49
|
+
hosts << {:host => host, :port => port.to_i, :protocol => protocol, :gcm => gcm}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'schatz/input/parser'
|
2
|
+
module Schatz
|
3
|
+
module Input
|
4
|
+
class TextExport < Export
|
5
|
+
include ParserHelper
|
6
|
+
attr_accessor :file, :options
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
@addresses_with_ports = []
|
10
|
+
@conversations = []
|
11
|
+
@links_with_ports = []
|
12
|
+
@file = File.open(@options[:file_name], 'r')
|
13
|
+
check_format
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_links
|
17
|
+
TxtLineParser.new(split_lines).links
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_conversations
|
21
|
+
TxtLineParser.new(split_lines).connections
|
22
|
+
end
|
23
|
+
|
24
|
+
# split txt file into lines
|
25
|
+
def split_lines
|
26
|
+
@file.pos=0
|
27
|
+
@file.read.split(/\n/).map{ |line| line.gsub /\r/, "" }
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_format
|
31
|
+
raise IncorrectTextFormat, "format of txt file is incorrect" unless split_lines.all? { |line| line =~ REGEXP_HOST || line =~ LINK }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Input
|
3
|
+
class TxtLineParser < Parser
|
4
|
+
include ParserHelper
|
5
|
+
def initialize(lines)
|
6
|
+
super(lines)
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse(line)
|
10
|
+
case line
|
11
|
+
when REGEXP_HOST_PORTS
|
12
|
+
parse_ports_field($2).map do |port|
|
13
|
+
@connections << Connection.new do |c|
|
14
|
+
c.host = $1
|
15
|
+
c.port = port
|
16
|
+
c.scheme = "tcp"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
when LINK
|
20
|
+
@links << Connection.new do |c|
|
21
|
+
c.scheme = $1
|
22
|
+
c.host = $2
|
23
|
+
c.port = $3.to_i if $3
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Output
|
3
|
+
class CMD < Out
|
4
|
+
def initialize(options={})
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
def print(connection)
|
8
|
+
case connection.scheme
|
9
|
+
when "tcp"
|
10
|
+
direct(connection)
|
11
|
+
when "http"
|
12
|
+
link(connection)
|
13
|
+
when "https"
|
14
|
+
link(connection)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def direct(connection)
|
19
|
+
color = connection.result == "open" ? :green : :red
|
20
|
+
puts (connection.host+" "+connection.port.to_s+" "+connection.scheme).foreground(color)
|
21
|
+
end
|
22
|
+
|
23
|
+
def link(connection)
|
24
|
+
codes = %w(403 302 200)
|
25
|
+
color = codes.include?(connection.result) ? :green : :red
|
26
|
+
puts (connection.scheme+"://"+connection.host+" "+connection.port.to_s+" via "+ connection.proxy).foreground(color)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Output
|
3
|
+
class HTML < Out
|
4
|
+
attr_accessor :html, :connections
|
5
|
+
def initialize(options={})
|
6
|
+
@html=""
|
7
|
+
@options = options
|
8
|
+
@connections = []
|
9
|
+
end
|
10
|
+
def print(connection)
|
11
|
+
@connections << connection
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate
|
15
|
+
File.open(file_name,"w+") do |file|
|
16
|
+
print_head
|
17
|
+
print_hosts
|
18
|
+
print_links
|
19
|
+
print_end
|
20
|
+
file << @html
|
21
|
+
@html
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def file_name
|
26
|
+
@options[:file_name].to_s+"_test_"+ Time.now.strftime("%d-%m-%y-%s")+".html"
|
27
|
+
end
|
28
|
+
|
29
|
+
def print_hosts
|
30
|
+
@html << "<h3>Conversation Map</h3>"
|
31
|
+
@html << "<table>"
|
32
|
+
@html << "<tr><th>Number</th><th> IP address</th><th> Port </th><th> Protocol </th><th> Result </th></tr>"
|
33
|
+
@connections.select{ |connection| connection.direct? }.each_with_index do |host, index|
|
34
|
+
@html << "<tr><td>#{index+1}</td><td>#{host.host}</td><td>#{host.port}</td><td>#{host.scheme}</td><td class='#{host.color}'>#{host.result}</td></tr>"
|
35
|
+
end
|
36
|
+
@html << "</table><br/><br/>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def print_links
|
40
|
+
@connections.select{ |connection| connection.link? }.group_by { |connection| connection.proxy}.each do |proxy, links|
|
41
|
+
print_links_table(proxy, links)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def print_links_table(proxy, links)
|
46
|
+
@html << "<h3>Intranet Access #{proxy}</h3>"
|
47
|
+
@html << "<table>"
|
48
|
+
@html << "<tr><th>Number</th><th> Link to page</th><th> Result </th></tr>"
|
49
|
+
links.each_with_index do |link, index|
|
50
|
+
@html << "<tr><td>#{index+1}</td><td><a href='#{link.scheme}://#{link.host}:#{link.port}'> #{link.scheme}://#{link.host}:#{link.port} </td><td class='#{link.color}'>#{link.result}</td></tr>"
|
51
|
+
end
|
52
|
+
@html << "</table>"
|
53
|
+
end
|
54
|
+
def print_head
|
55
|
+
@html << "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN'><html lang='en'>
|
56
|
+
<head>
|
57
|
+
<title>Connection Test Results</title>
|
58
|
+
<style type='text/css'>
|
59
|
+
.green{background-color:SeaGreen}
|
60
|
+
.red {background-color:Crimson}
|
61
|
+
</style>
|
62
|
+
</head><body>"
|
63
|
+
end
|
64
|
+
def print_end
|
65
|
+
@html << "</body></html>"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'socket'
|
3
|
+
module Schatz
|
4
|
+
module Schemes
|
5
|
+
module DirectTcp
|
6
|
+
def self.direct_test(host, port, timeout =0.1)
|
7
|
+
addr = Socket.pack_sockaddr_in(port, host)
|
8
|
+
s = Socket.new(:AF_INET, :SOCK_STREAM, 0)
|
9
|
+
begin
|
10
|
+
s.connect_nonblock(addr)
|
11
|
+
rescue Errno::EINPROGRESS
|
12
|
+
IO.select(nil, [s], nil, timeout) ? true : (raise Timeout::Error)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
module Schatz
|
4
|
+
module Schemes
|
5
|
+
module ProxyHttp
|
6
|
+
def self.http_test(link, proxy)
|
7
|
+
Proxy.connect(proxy).start(link.host, link.port, :proxy => proxy).get("/").code
|
8
|
+
end
|
9
|
+
end
|
10
|
+
module Proxy
|
11
|
+
def self.connect(proxy)
|
12
|
+
uri = URI(proxy)
|
13
|
+
Net::HTTP::Proxy(uri.host, uri.port)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'uri'
|
2
|
+
module Schatz
|
3
|
+
module Schemes
|
4
|
+
module ProxyHttps
|
5
|
+
def self.https_test(link, proxy)
|
6
|
+
response = Proxy.connect(proxy).start(link.host, link.port, :use_ssl => true, :verify_mode => OpenSSL::SSL::VERIFY_NONE, :open_timeout => 1.5).get("/")
|
7
|
+
case response
|
8
|
+
when Net::HTTPFound
|
9
|
+
"302" if response['location'] =~ /https\:\/\/login\-intranet\.isso\.db\.com/ ? "redirected to WebSSO" : "redirected to #{response['location']}"
|
10
|
+
when Net::HTTPOK
|
11
|
+
"200"
|
12
|
+
else
|
13
|
+
[response.code, response.msg].join(" ")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Schatz
|
2
|
+
module Testers
|
3
|
+
class IncrTest
|
4
|
+
attr_accessor :options, :output, :connections
|
5
|
+
def initialize(options={}, outputters=[])
|
6
|
+
@options = options
|
7
|
+
@outputters = outputters
|
8
|
+
end
|
9
|
+
|
10
|
+
def check_connections(connections)
|
11
|
+
@connections = connections
|
12
|
+
if @options[:direct_only]
|
13
|
+
direct_check
|
14
|
+
elsif @options[:proxy_only]
|
15
|
+
links_check
|
16
|
+
else
|
17
|
+
direct_check
|
18
|
+
links_check
|
19
|
+
end
|
20
|
+
@outputters.each { |outputter| outputter.generate }
|
21
|
+
end
|
22
|
+
|
23
|
+
def links_check
|
24
|
+
match_gcm_connections.select { |c| c.link? }.map do |connection|
|
25
|
+
proxies.map do |proxy|
|
26
|
+
@outputters.each { |out| out.print(Input::ConnectionResult.new(connection, proxy).check) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def direct_check
|
32
|
+
match_gcm_connections.select { |c| c.direct? }.map do |connection|
|
33
|
+
@outputters.each { |out| out.print(Input::ConnectionResult.new(connection).check) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def match_gcm_connections
|
38
|
+
@options[:gcm] ? @connections.select { |c| c.gcm == @options[:gcm] } : @connections
|
39
|
+
end
|
40
|
+
|
41
|
+
def proxies
|
42
|
+
@options[:proxies].values
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: schatz
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sergiy Shevchik
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-03 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Tool for checking the connectivity
|
15
|
+
email: berrouz@gmail.com
|
16
|
+
executables:
|
17
|
+
- schatz
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files:
|
20
|
+
- README.txt
|
21
|
+
files:
|
22
|
+
- lib/schatz.rb
|
23
|
+
- lib/schatz/input/connection.rb
|
24
|
+
- lib/schatz/input/connection_result.rb
|
25
|
+
- lib/schatz/input/export.rb
|
26
|
+
- lib/schatz/input/incr_export.rb
|
27
|
+
- lib/schatz/input/incr_line_parser.rb
|
28
|
+
- lib/schatz/input/parser.rb
|
29
|
+
- lib/schatz/input/result.rb
|
30
|
+
- lib/schatz/input/text_export.rb
|
31
|
+
- lib/schatz/input/txt_line_parser.rb
|
32
|
+
- lib/schatz/cli/runner.rb
|
33
|
+
- lib/schatz/cli/configuration.rb
|
34
|
+
- lib/schatz/output/html.rb
|
35
|
+
- lib/schatz/output/out.rb
|
36
|
+
- lib/schatz/output/cmd.rb
|
37
|
+
- lib/schatz/schemes/direct_tcp.rb
|
38
|
+
- lib/schatz/schemes/proxy_http.rb
|
39
|
+
- lib/schatz/schemes/proxy_https.rb
|
40
|
+
- lib/schatz/testers/incr_test.rb
|
41
|
+
- install.rb
|
42
|
+
- config/config.yml
|
43
|
+
- Gemfile
|
44
|
+
- Gemfile.lock
|
45
|
+
- README.txt
|
46
|
+
- bin/schatz
|
47
|
+
homepage: https://github.com/berrouz/schatz
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 1.9.3
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.8.11
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: TCP,UDP
|
71
|
+
test_files: []
|