jira_scan 0.0.2 → 0.0.3
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 +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
|