jira_scan 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/bin/jira-scan +21 -5
- data/lib/jira_scan.rb +86 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
N2U3MTgzNjZlMDY0N2Q5MzJiMTJhYjFlZjA3ODg4Njg3YmNmYzVlOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTBmYmNhMmQ0MDQ0MTdmY2Q4MWRiYzQ1MzUxMWNmOWJmNmQwZjljOQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZTg1NzllMDk0MWNlNWRjZDEwNTcyMTc0YWJlMmMzYjUzYjk3ZjUzMjkyYWIw
|
10
|
+
M2U2YmI5MjllMTEzNTc0NGE4YWVkMzE0Y2I2MzVkOWY3NDAyYjc1MTVkZjQ2
|
11
|
+
YTJjMGZiYTcyYWFjMjRmZmI2YzdkMDAwMTVkMTVjYzRlODVmNDE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NDc1ODc0MjIzMGY1YzlkMGYzMGY4Y2Q1ZmI3MDkwNjczNzI4ZDE5NDdhYmQ1
|
14
|
+
NzgwMTZiOGU3N2Y3MGVkYTQxMGE1ODMxMTVkNTBjNTIwOTQxMjI2OTJkZTg0
|
15
|
+
YmExYzZlOWFkNGUyODZkYTA0M2QwYWJhZTI1YmQwZGM5N2UxNmQ=
|
data/bin/jira-scan
CHANGED
@@ -17,7 +17,7 @@ def banner
|
|
17
17
|
_ | | | '__/ _` |\\___ \\ / __/ _` | '_ \\
|
18
18
|
| |__| | | | | (_| |____) | (_| (_| | | | |
|
19
19
|
\\____/|_|_| \\__,_|_____/ \\___\\__,_|_| |_|
|
20
|
-
version 0.0.
|
20
|
+
version 0.0.3"
|
21
21
|
puts
|
22
22
|
puts '-' * 60
|
23
23
|
end
|
@@ -39,6 +39,10 @@ opts = OptionParser.new do |o|
|
|
39
39
|
options[:skip] = true
|
40
40
|
end
|
41
41
|
|
42
|
+
o.on('-i', '--insecure', 'Skip SSL/TLS validation') do
|
43
|
+
options[:insecure] = true
|
44
|
+
end
|
45
|
+
|
42
46
|
o.on('-v', '--verbose', 'Enable verbose output') do
|
43
47
|
options[:verbose] = true
|
44
48
|
end
|
@@ -53,6 +57,7 @@ opts.parse!
|
|
53
57
|
|
54
58
|
$VERBOSE = true unless options[:verbose].nil?
|
55
59
|
@check = true unless options[:skip]
|
60
|
+
@insecure = false unless options[:insecure]
|
56
61
|
|
57
62
|
if options[:url].nil?
|
58
63
|
puts opts
|
@@ -85,7 +90,9 @@ def scan(url)
|
|
85
90
|
|
86
91
|
# Check if the URL is Jira
|
87
92
|
if @check
|
88
|
-
|
93
|
+
is_jira = JiraScan::detectJiraDashboard(url)
|
94
|
+
is_jira = JiraScan::detectJiraLogin(url) unless is_jira
|
95
|
+
unless is_jira
|
89
96
|
puts '- Jira not found'
|
90
97
|
exit(1)
|
91
98
|
end
|
@@ -93,7 +100,8 @@ def scan(url)
|
|
93
100
|
end
|
94
101
|
|
95
102
|
# Get Jira version
|
96
|
-
version = JiraScan::
|
103
|
+
version = JiraScan::getVersionFromDashboard(url)
|
104
|
+
version = JiraScan::getVersionFromLogin(url) unless version
|
97
105
|
puts "+ Version: #{version}" if version
|
98
106
|
|
99
107
|
# Dev mode enabled
|
@@ -109,7 +117,7 @@ def scan(url)
|
|
109
117
|
if user_picker
|
110
118
|
puts '+ User Picker Browser is available'
|
111
119
|
# Retrieve list of first 1,000 users
|
112
|
-
users = JiraScan::
|
120
|
+
users = JiraScan::getUsersFromUserPickerBrowser(url)
|
113
121
|
unless users.empty?
|
114
122
|
puts "+ Found users (#{users.length}):"
|
115
123
|
table = Terminal::Table.new :headings => ['Username', 'Full Name', 'Email'], :rows => users
|
@@ -150,7 +158,15 @@ def scan(url)
|
|
150
158
|
end
|
151
159
|
|
152
160
|
# Retrieve list of field names
|
153
|
-
field_names = JiraScan::
|
161
|
+
field_names = JiraScan::getFieldNamesQueryComponentDefault(url)
|
162
|
+
unless field_names.empty?
|
163
|
+
puts "+ Found field names (#{field_names.length}):"
|
164
|
+
table = Terminal::Table.new :headings => ['Name', 'ID', 'Key', 'IsShown', 'Last Viewed'], :rows => field_names
|
165
|
+
puts table
|
166
|
+
end
|
167
|
+
|
168
|
+
# Retrieve list of field names
|
169
|
+
field_names = JiraScan::getFieldNamesQueryComponentJql(url)
|
154
170
|
unless field_names.empty?
|
155
171
|
puts "+ Found field names (#{field_names.length}):"
|
156
172
|
table = Terminal::Table.new :headings => ['Name', 'ID', 'Key', 'IsShown', 'Last Viewed'], :rows => field_names
|
data/lib/jira_scan.rb
CHANGED
@@ -10,16 +10,33 @@ require 'net/http'
|
|
10
10
|
require 'openssl'
|
11
11
|
|
12
12
|
class JiraScan
|
13
|
-
VERSION = '0.0.
|
13
|
+
VERSION = '0.0.3'.freeze
|
14
14
|
|
15
15
|
#
|
16
|
-
# Check if Jira
|
16
|
+
# Check if URL is running Jira using Login page
|
17
17
|
#
|
18
18
|
# @param [String] URL
|
19
19
|
#
|
20
20
|
# @return [Boolean]
|
21
21
|
#
|
22
|
-
def self.
|
22
|
+
def self.detectJiraLogin(url)
|
23
|
+
url += '/' unless url.to_s.end_with? '/'
|
24
|
+
res = sendHttpRequest("#{url}login.jsp")
|
25
|
+
|
26
|
+
return false unless res
|
27
|
+
return false unless res.code.to_i == 200
|
28
|
+
|
29
|
+
res.body.to_s.include?('JIRA')
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Check if URL is running Jira using Dashboard page
|
34
|
+
#
|
35
|
+
# @param [String] URL
|
36
|
+
#
|
37
|
+
# @return [Boolean]
|
38
|
+
#
|
39
|
+
def self.detectJiraDashboard(url)
|
23
40
|
url += '/' unless url.to_s.end_with? '/'
|
24
41
|
res = sendHttpRequest("#{url}secure/Dashboard.jspa")
|
25
42
|
|
@@ -30,13 +47,13 @@ class JiraScan
|
|
30
47
|
end
|
31
48
|
|
32
49
|
#
|
33
|
-
# Get Jira version
|
50
|
+
# Get Jira version from Dashboard page
|
34
51
|
#
|
35
52
|
# @param [String] URL
|
36
53
|
#
|
37
54
|
# @return [String] Jira version
|
38
55
|
#
|
39
|
-
def self.
|
56
|
+
def self.getVersionFromDashboard(url)
|
40
57
|
url += '/' unless url.to_s.end_with? '/'
|
41
58
|
res = sendHttpRequest("#{url}secure/Dashboard.jspa")
|
42
59
|
|
@@ -58,6 +75,35 @@ class JiraScan
|
|
58
75
|
"#{version}-##{build}"
|
59
76
|
end
|
60
77
|
|
78
|
+
#
|
79
|
+
# Get Jira version from Login page
|
80
|
+
#
|
81
|
+
# @param [String] URL
|
82
|
+
#
|
83
|
+
# @return [String] Jira version
|
84
|
+
#
|
85
|
+
def self.getVersionFromLogin(url)
|
86
|
+
url += '/' unless url.to_s.end_with? '/'
|
87
|
+
res = sendHttpRequest("#{url}login.jsp")
|
88
|
+
|
89
|
+
return unless res
|
90
|
+
return unless res.code.to_i == 200
|
91
|
+
|
92
|
+
version = res.body.to_s.scan(%r{<meta name="ajs-version-number" content="([\d\.]+)">}).flatten.first
|
93
|
+
build = res.body.to_s.scan(%r{<meta name="ajs-build-number" content="(\d+)">}).flatten.first
|
94
|
+
|
95
|
+
unless version && build
|
96
|
+
if res.body.to_s =~ /Version: ([\d\.]+)-#(\d+)/
|
97
|
+
version = $1
|
98
|
+
build = $2
|
99
|
+
else
|
100
|
+
return
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
"#{version}-##{build}"
|
105
|
+
end
|
106
|
+
|
61
107
|
#
|
62
108
|
# Check if dev mode is enabled
|
63
109
|
#
|
@@ -258,7 +304,7 @@ class JiraScan
|
|
258
304
|
#
|
259
305
|
# @return [Array] list of field names
|
260
306
|
#
|
261
|
-
def self.
|
307
|
+
def self.getFieldNamesQueryComponentDefault(url)
|
262
308
|
url += '/' unless url.to_s.end_with? '/'
|
263
309
|
res = sendHttpRequest("#{url}secure/QueryComponent!Default.jspa")
|
264
310
|
|
@@ -284,6 +330,39 @@ class JiraScan
|
|
284
330
|
[]
|
285
331
|
end
|
286
332
|
|
333
|
+
#
|
334
|
+
# Retrieve list of field names from QueryComponent!Jql.jspa (EDB-49924)
|
335
|
+
#
|
336
|
+
# @param [String] URL
|
337
|
+
#
|
338
|
+
# @return [Array] list of field names
|
339
|
+
#
|
340
|
+
def self.getFieldNamesQueryComponentJql(url)
|
341
|
+
url += '/' unless url.to_s.end_with? '/'
|
342
|
+
res = sendHttpRequest("#{url}secure/QueryComponent!Jql.jspa?jql=")
|
343
|
+
|
344
|
+
return [] unless res
|
345
|
+
return [] unless res.code.to_i == 200
|
346
|
+
return [] unless res.body.to_s.start_with?('{"searchers"')
|
347
|
+
|
348
|
+
searchers = JSON.parse(res.body.to_s)["searchers"]
|
349
|
+
return [] if searchers.empty?
|
350
|
+
|
351
|
+
groups = searchers['groups']
|
352
|
+
return [] if groups.empty?
|
353
|
+
|
354
|
+
field_names = []
|
355
|
+
groups.each do |g|
|
356
|
+
g['searchers'].each do |s|
|
357
|
+
field_names << s
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
JSON.parse(field_names.to_json, symbolize_names: true).map {|f| [f[:name], f[:id], f[:key], f[:isShown].to_s, f[:lastViewed]] }
|
362
|
+
rescue
|
363
|
+
[]
|
364
|
+
end
|
365
|
+
|
287
366
|
private
|
288
367
|
|
289
368
|
#
|
@@ -299,8 +378,7 @@ class JiraScan
|
|
299
378
|
http = Net::HTTP.new(target.host, target.port)
|
300
379
|
if target.scheme.to_s.eql?('https')
|
301
380
|
http.use_ssl = true
|
302
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
303
|
-
# http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
381
|
+
http.verify_mode = @insecure ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
304
382
|
end
|
305
383
|
http.open_timeout = 20
|
306
384
|
http.read_timeout = 20
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jira_scan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brendan Coles
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A simple remote scanner for Atlassian Jira
|
14
14
|
email: bcoles@gmail.com
|