ip_auditor 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.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +64 -0
- data/Rakefile +2 -0
- data/bin/audit_ips +5 -0
- data/ip_auditor.gemspec +21 -0
- data/lib/ip_auditor.rb +284 -0
- data/lib/ip_auditor/version.rb +3 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
M2IxZmI1MzhmZGVhOWE0ZmE1MTNlNjMyYmM5NjdhNTdmNDQyNzlmZg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MjMwZjM3YmNiMGM4ZjE3Y2U4MGJjYzVmOGRjODY5ZjgyNmEyMDA4ZA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YmI1MmJiZDdkOGViY2ViMzZmMjBjMTUxN2E1ZjU2MGJkZDk4NzdmMTg5NmI4
|
10
|
+
MjMzYTFiYjRlYzViZThhZGIwNzcwODA2ZWQ3Y2VhZTY3YjdlNDBiZmJmZjNk
|
11
|
+
NjkwNWI3MGQ1MjczMWUzNDU2OWI2YmRhMDI5YWE4NmQzYWMxZWI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YjRiOTU2NGNiZTg0M2I4ZGRjOGI2ZjBjNGMxNjM1MDA5NmNhMWM5NWQxYTQ1
|
14
|
+
YmRhYjFkYTZiYjA0NTZjNzhkOTI3NzE0ZTdmMWZlNjc3YzE0YmI4MDk3NjVm
|
15
|
+
ZTBiZDE2OWFhZDI2N2FhZDlhNDI0MjFjOGIwZDc1ZmVmMDdjMjM=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 James Kurczodyna
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# IP Auditor
|
2
|
+
|
3
|
+
The IP Auditor looks through your Apache vhosts to compile a list of apps on the server, what domains are being listened for and what IP each domain is actually pointing to.
|
4
|
+
|
5
|
+
This allows you to quickly track which domains and apps are active and which are pointing elsewhere.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
* clone this repo
|
10
|
+
* cd into the repo
|
11
|
+
* run `bundle install`
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
To use the Auditor, cd into the cloned repo and run the following command:
|
16
|
+
|
17
|
+
ruby ./lib/ip_auditor.rb [server name/IP] [user] [options]
|
18
|
+
|
19
|
+
Example:
|
20
|
+
|
21
|
+
ruby ./lib/ip_auditor.rb someserver.com myuser
|
22
|
+
|
23
|
+
## Output
|
24
|
+
|
25
|
+
The Auditor will return a crude report for each VirtualHost in the following format.
|
26
|
+
|
27
|
+
============
|
28
|
+
/path/to/vhost/vhostname: <VirtualHost [IP]:[port]>
|
29
|
+
============
|
30
|
+
[domain-1]
|
31
|
+
[IP domain-1 is actually pointing to]
|
32
|
+
[domain-2]
|
33
|
+
[IP domain-2 is actually pointing to]
|
34
|
+
[/path/to/app/DocumentRoot]
|
35
|
+
|
36
|
+
## Options
|
37
|
+
|
38
|
+
* -p [PORT NUMBER] : Specify a port number (default is 22)
|
39
|
+
* -c [FILE NAME (optional)]: Output to .csv file instead of terminal (can specify a name)
|
40
|
+
* -v : Output more information as to what's happening
|
41
|
+
* -e [prod|stage|dev|etc.]: Specify an environment to output (defaults to 'all'; determined by passenger config files, so non-rails site will always return)
|
42
|
+
|
43
|
+
## License
|
44
|
+
|
45
|
+
MIT License
|
46
|
+
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
48
|
+
a copy of this software and associated documentation files (the
|
49
|
+
"Software"), to deal in the Software without restriction, including
|
50
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
51
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
52
|
+
permit persons to whom the Software is furnished to do so, subject to
|
53
|
+
the following conditions:
|
54
|
+
|
55
|
+
The above copyright notice and this permission notice shall be
|
56
|
+
included in all copies or substantial portions of the Software.
|
57
|
+
|
58
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
59
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
60
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
61
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
62
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
63
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
64
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/bin/audit_ips
ADDED
data/ip_auditor.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/ip_auditor/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "ip_auditor"
|
6
|
+
gem.version = IpAuditor::VERSION
|
7
|
+
gem.platform = Gem::Platform::RUBY
|
8
|
+
gem.authors = ["James Kurczodyna", "Kellen Hawley"]
|
9
|
+
gem.email = ["james@finedesigngroup.com"]
|
10
|
+
gem.description = "IP Auditor"
|
11
|
+
gem.summary = "Audits Apache vhosts and domain IPs"
|
12
|
+
gem.homepage = "https://github.com/jamesmkur/ip-auditor"
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($\)
|
15
|
+
gem.executables = ['audit_ips']
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
gem.bindir = 'bin'
|
19
|
+
|
20
|
+
gem.add_dependency "net-ssh", "~> 2.6.7"
|
21
|
+
end
|
data/lib/ip_auditor.rb
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
# require "ip_auditor/version"
|
2
|
+
require 'net/ssh'
|
3
|
+
require 'optparse'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'io/console'
|
9
|
+
rescue LoadError
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
module IpAuditor
|
14
|
+
|
15
|
+
def IpAuditor.set_options
|
16
|
+
@options = OpenStruct.new
|
17
|
+
|
18
|
+
@options.verbose = false
|
19
|
+
@options.environment = 'all'
|
20
|
+
|
21
|
+
# parse the options passed in through the terminal
|
22
|
+
OptionParser.new do |opts|
|
23
|
+
opts.banner = 'Usage: ip.auditor.rb [server name/IP] [username] [options]'
|
24
|
+
|
25
|
+
# get the port number
|
26
|
+
opts.on('-p', '--port [PORT NUMBER]', 'Port (default is 22)') do |p|
|
27
|
+
@options.port = p
|
28
|
+
end
|
29
|
+
|
30
|
+
# check whether to output data as csv, possibly get the name
|
31
|
+
opts.on('-c', '--csv [FILENAME]', 'Output data as CSV file') do |c|
|
32
|
+
@options.csv = true
|
33
|
+
@options.csv_name = c =~ /[^[:space:]]/ ? c : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
# check whether output more information
|
37
|
+
opts.on('-v', '--verbose', 'Print out more information about what\'s happening') do |v|
|
38
|
+
@options.verbose = true
|
39
|
+
end
|
40
|
+
|
41
|
+
# specify the environment we're checking
|
42
|
+
opts.on('-e', '--environment [prod|stage|dev|etc.]', 'Print only the sites that have environment specified in their passenger files (default is all)') do |e|
|
43
|
+
@options.environment = e
|
44
|
+
end
|
45
|
+
|
46
|
+
end.parse!
|
47
|
+
|
48
|
+
# prompt for password
|
49
|
+
@options.pass = IpAuditor.get_password
|
50
|
+
puts "\n"
|
51
|
+
|
52
|
+
# set the connection variables
|
53
|
+
@options.server = ARGV[0] || ''
|
54
|
+
@options.user = ARGV[1] || ''
|
55
|
+
@options.port = @options.port || 22
|
56
|
+
@options.pass = @options.pass || ''
|
57
|
+
@options.csv_name = @options.csv_name || @options.server
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
# prompt for and return password
|
62
|
+
def IpAuditor.get_password
|
63
|
+
if STDIN.respond_to?(:noecho)
|
64
|
+
puts "Password: "
|
65
|
+
STDIN.noecho(&:gets).chomp
|
66
|
+
else
|
67
|
+
`read -s -p "Password: " password; echo $password`.chomp
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# get and parse the yaml passenger config file if available, else return false
|
72
|
+
def IpAuditor.get_passenger_file(ssh,file_name)
|
73
|
+
|
74
|
+
puts "Getting passenger information for #{file_name}..." if @options.verbose
|
75
|
+
|
76
|
+
yaml_file = ssh.exec!("find /etc/passenger.d -name '#{file_name}.yml' -exec cat {} \\;")
|
77
|
+
|
78
|
+
# if blank, return false
|
79
|
+
if yaml_file !~ /[^[:space:]]/
|
80
|
+
return false
|
81
|
+
else
|
82
|
+
begin
|
83
|
+
content = YAML.load(yaml_file)
|
84
|
+
rescue ArgumentError
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
# get the rails version for the site, else return nil
|
92
|
+
def IpAuditor.get_rails_version(ssh,gemset)
|
93
|
+
|
94
|
+
puts "Getting the rails version..." if @options.verbose
|
95
|
+
rails_version = ssh.exec!("/usr/local/rvm/bin/rvm #{gemset} do gem list")[/\nrails \((.*?)\)\n/,1]
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
# get the rails information using passenger, or return false
|
101
|
+
def IpAuditor.get_rails_information(ssh,file_name)
|
102
|
+
|
103
|
+
rails_info = get_passenger_file(ssh,file_name)
|
104
|
+
|
105
|
+
# only return info if we're looking for this environment. Return false if rails info exists but
|
106
|
+
# we should ignore this environment, nil if there is no rails info
|
107
|
+
if rails_info && (rails_info['environment'][@options.environment] || @options.environment == 'all')
|
108
|
+
rails_info['rails_version'] = get_rails_version(ssh,rails_info['rvm'])
|
109
|
+
return rails_info
|
110
|
+
elsif rails_info
|
111
|
+
return false
|
112
|
+
else
|
113
|
+
return nil
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
# use nslookup to get the IP of a given domain
|
119
|
+
def IpAuditor.check_site_status(domain)
|
120
|
+
lookup = `nslookup #{domain}`
|
121
|
+
|
122
|
+
# strip output to IPs only
|
123
|
+
output = lookup[/Non-authoritative answer:(.*)/m,1]
|
124
|
+
ip = !output.nil? ? output[/Address: (.*)/m,1] : false
|
125
|
+
|
126
|
+
# output IP address or message saying lookup failed
|
127
|
+
if ip
|
128
|
+
return ip
|
129
|
+
else
|
130
|
+
return 'DOMAIN LOOKUP FAILED'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# get and compile information from /etc/apache2/sites-enabled
|
135
|
+
def IpAuditor.get_site_information(ssh)
|
136
|
+
data = []
|
137
|
+
current_file_path = '--'
|
138
|
+
current_file = nil
|
139
|
+
directory = ''
|
140
|
+
virtual_host = ''
|
141
|
+
domain_statuses = []
|
142
|
+
|
143
|
+
# get all relevant lines from vhost files
|
144
|
+
domain_text = ssh.exec!("grep -r '<VirtualHost\\|DocumentRoot\\|<Directory\\|ServerName\\|ServerAlias' /etc/apache2/sites-enabled")
|
145
|
+
|
146
|
+
# parse each line for relevant data
|
147
|
+
domain_text.each_line do |line|
|
148
|
+
|
149
|
+
# if we're still looking at the same file, get information
|
150
|
+
if line[current_file_path]
|
151
|
+
|
152
|
+
domain = nil
|
153
|
+
|
154
|
+
# if line contains a domain, get its status
|
155
|
+
if line[/(ServerName|ServerAlias)(.*)/]
|
156
|
+
domain = line[/(ServerName|ServerAlias)(.*)/,2].strip
|
157
|
+
domain_statuses << [domain,IpAuditor.check_site_status(domain)]
|
158
|
+
|
159
|
+
elsif line[/<VirtualHost/]
|
160
|
+
virtual_host = line[/<VirtualHost (.*)>/,1].strip.split(" ").join(", ")
|
161
|
+
|
162
|
+
elsif line[/DocumentRoot/]
|
163
|
+
directory = line[/DocumentRoot\s*?"?(.*)"?/,1]
|
164
|
+
end
|
165
|
+
|
166
|
+
else
|
167
|
+
# if this is a new file, get rails info and push into data array before resetting variables
|
168
|
+
if !(current_file.nil?)
|
169
|
+
rails_info = IpAuditor.get_rails_information(ssh,current_file)
|
170
|
+
|
171
|
+
# if it has rails info an dit's for the relavant domains
|
172
|
+
if rails_info
|
173
|
+
data << [current_file, rails_info['environment'], rails_info['cwd'], rails_info['rvm'], rails_info['rails_version'], virtual_host,domain_statuses].flatten
|
174
|
+
elsif rails_info.nil?
|
175
|
+
data << [current_file,'',directory,'','',virtual_host,domain_statuses].flatten
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# reset the per-file variables
|
180
|
+
current_file_path = line[/(.*?):/,1]
|
181
|
+
current_file = current_file_path[/.*\/(.*?\.com$)/,1]
|
182
|
+
virtual_host = line[/<VirtualHost/] ? line[/<VirtualHost (.*)>/,1].strip.split(" ").join(", ") : ''
|
183
|
+
directory = ''
|
184
|
+
domain_statuses = []
|
185
|
+
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
data
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
def IpAuditor.write_to_csv(headers,csv_data)
|
195
|
+
require 'csv'
|
196
|
+
CSV.open("IP Audit - #{@options.csv_name}.csv", "w") do |csv|
|
197
|
+
csv << headers
|
198
|
+
csv_data.each do |line|
|
199
|
+
csv << line
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def IpAuditor.write_to_terminal(headers,site_data)
|
205
|
+
last_header_index = headers.length - 1
|
206
|
+
|
207
|
+
site_data.each do |site|
|
208
|
+
|
209
|
+
puts "\n\n============\n#{site[0]}\n============"
|
210
|
+
|
211
|
+
|
212
|
+
(1...site.length).each do |index|
|
213
|
+
if site[index] =~ /[^[:space:]]/
|
214
|
+
|
215
|
+
if !headers[index].nil? && index < last_header_index
|
216
|
+
puts "#{headers[index]}: #{site[index]}"
|
217
|
+
|
218
|
+
elsif index == last_header_index
|
219
|
+
puts "------------\n#{headers[index]}\n------------"
|
220
|
+
puts site[index]
|
221
|
+
else
|
222
|
+
puts site[index]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
def IpAuditor.audit
|
232
|
+
|
233
|
+
# set the options for this instance
|
234
|
+
IpAuditor.set_options
|
235
|
+
|
236
|
+
puts "Opening SSH connection to #{@options.server}..."
|
237
|
+
|
238
|
+
begin
|
239
|
+
|
240
|
+
# open an ssh connection
|
241
|
+
Net::SSH.start(@options.server, @options.user, {port: @options.port, password: @options.pass}) do |ssh|
|
242
|
+
|
243
|
+
puts "Connection opened! Finding and parsing apache/passenger files (this may take a while)..."
|
244
|
+
|
245
|
+
# find lines of interest in vhosts, assumes location is /etc/apache2/sites-enabled
|
246
|
+
domain_text = ssh.exec!("grep -r '<VirtualHost\\|DocumentRoot\\|<Directory\\|ServerName\\|ServerAlias' /etc/apache2/sites-enabled")
|
247
|
+
|
248
|
+
headers = ['Site','Environment','Directory','Gemset','Rails Version','Virtual Host','Site Statuses']
|
249
|
+
|
250
|
+
puts "Parsing the vhosts files ..." if @options.verbose
|
251
|
+
site_data = IpAuditor.get_site_information(ssh)
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
|
256
|
+
# output to .csv file
|
257
|
+
if !@options.csv.nil? && @options.csv
|
258
|
+
|
259
|
+
puts "Writing to .csv file..." if @options.verbose
|
260
|
+
IpAuditor.write_to_csv(headers,site_data)
|
261
|
+
|
262
|
+
puts "File saved to ./IP Audit - #{@options.csv_name}.csv!"
|
263
|
+
|
264
|
+
|
265
|
+
# output to terminal
|
266
|
+
else
|
267
|
+
IpAuditor.write_to_terminal(headers,site_data)
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
end
|
272
|
+
|
273
|
+
# catch the basic errors
|
274
|
+
rescue SocketError => e
|
275
|
+
puts "Socket Error! Is your domain name correct?"
|
276
|
+
rescue Net::SSH::AuthenticationFailed
|
277
|
+
puts "Authentication Error! Did you correctly type in your username and password?"
|
278
|
+
rescue Exception => e
|
279
|
+
puts "Error! Have you specified the correct port? Or maybe there's a problem with the code..."
|
280
|
+
end
|
281
|
+
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ip_auditor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Kurczodyna
|
8
|
+
- Kellen Hawley
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-05-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: net-ssh
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 2.6.7
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 2.6.7
|
28
|
+
description: IP Auditor
|
29
|
+
email:
|
30
|
+
- james@finedesigngroup.com
|
31
|
+
executables:
|
32
|
+
- audit_ips
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- .gitignore
|
37
|
+
- Gemfile
|
38
|
+
- LICENSE
|
39
|
+
- README.md
|
40
|
+
- Rakefile
|
41
|
+
- ip_auditor.gemspec
|
42
|
+
- lib/ip_auditor.rb
|
43
|
+
- lib/ip_auditor/version.rb
|
44
|
+
- bin/audit_ips
|
45
|
+
homepage: https://github.com/jamesmkur/ip-auditor
|
46
|
+
licenses: []
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.1.3
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: Audits Apache vhosts and domain IPs
|
68
|
+
test_files: []
|