proxes 0.9.13 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ditty/components/proxes.rb +61 -16
- data/lib/proxes/controllers/permissions.rb +1 -6
- data/lib/proxes/controllers/search.rb +12 -10
- data/lib/proxes/controllers/status.rb +23 -86
- data/lib/proxes/controllers/status_checks.rb +18 -0
- data/lib/proxes/forwarder.rb +44 -20
- data/lib/proxes/middleware/error_handling.rb +5 -3
- data/lib/proxes/middleware/security.rb +4 -3
- data/lib/proxes/models/permission.rb +47 -3
- data/lib/proxes/models/status_check.rb +76 -0
- data/lib/proxes/models/status_checks/cluster_health_status_check.rb +19 -0
- data/lib/proxes/models/status_checks/cpu_status_check.rb +29 -0
- data/lib/proxes/models/status_checks/file_system_status_check.rb +32 -0
- data/lib/proxes/models/status_checks/jvm_heap_status_check.rb +28 -0
- data/lib/proxes/models/status_checks/memory_status_check.rb +29 -0
- data/lib/proxes/models/status_checks/nodes_status_check.rb +53 -0
- data/lib/proxes/policies/permission_policy.rb +3 -3
- data/lib/proxes/policies/request/bulk_policy.rb +0 -12
- data/lib/proxes/policies/request/create_policy.rb +0 -3
- data/lib/proxes/policies/request/index_policy.rb +0 -5
- data/lib/proxes/policies/request/mget_policy.rb +12 -0
- data/lib/proxes/policies/request/msearch_policy.rb +12 -0
- data/lib/proxes/policies/request/root_policy.rb +0 -3
- data/lib/proxes/policies/request/snapshot_policy.rb +0 -3
- data/lib/proxes/policies/request_policy.rb +24 -25
- data/lib/proxes/policies/search_policy.rb +6 -2
- data/lib/proxes/policies/status_check_policy.rb +37 -0
- data/lib/proxes/request.rb +19 -5
- data/lib/proxes/request/bulk.rb +8 -24
- data/lib/proxes/request/cat.rb +6 -0
- data/lib/proxes/request/create.rb +4 -0
- data/lib/proxes/request/index.rb +4 -0
- data/lib/proxes/request/mget.rb +24 -0
- data/lib/proxes/request/msearch.rb +24 -0
- data/lib/proxes/request/multi.rb +40 -0
- data/lib/proxes/request/search.rb +4 -0
- data/lib/proxes/request/stats.rb +4 -0
- data/lib/proxes/services/es.rb +5 -1
- data/lib/proxes/services/listener.rb +29 -6
- data/lib/proxes/services/search.rb +4 -1
- data/lib/proxes/version.rb +1 -1
- data/migrate/20180908_index_specific_permissions.rb +9 -0
- data/migrate/20190109_add_status_checks_table.rb +17 -0
- data/views/layout.haml +17 -6
- metadata +81 -25
- data/lib/proxes/helpers/indices.rb +0 -35
@@ -8,11 +8,6 @@ module ProxES
|
|
8
8
|
class Request
|
9
9
|
class IndexPolicy < RequestPolicy
|
10
10
|
class Scope < RequestPolicy::Scope
|
11
|
-
def resolve
|
12
|
-
result = super
|
13
|
-
return [] unless result.count > 0
|
14
|
-
%w[POST PUT].include?(request.request_method) ? request.index : result
|
15
|
-
end
|
16
11
|
end
|
17
12
|
end
|
18
13
|
end
|
@@ -4,60 +4,59 @@ require 'active_support'
|
|
4
4
|
require 'active_support/core_ext/object/blank'
|
5
5
|
require 'ditty/services/logger'
|
6
6
|
require 'proxes/models/permission'
|
7
|
-
require 'proxes/helpers/indices'
|
8
7
|
|
9
8
|
module ProxES
|
10
9
|
class RequestPolicy
|
11
|
-
include Helpers::Indices
|
12
|
-
|
13
10
|
attr_reader :user, :record
|
14
11
|
alias request record
|
15
12
|
|
16
13
|
def initialize(user, record)
|
17
|
-
@user = user
|
14
|
+
@user = user || Ditty::User.anonymous_user
|
18
15
|
@record = record
|
19
16
|
end
|
20
17
|
|
21
18
|
def method_missing(method_sym, *arguments, &block)
|
22
|
-
return super
|
19
|
+
return super unless respond_to_missing? method_sym
|
20
|
+
|
21
|
+
return false if permissions.empty?
|
22
|
+
|
23
|
+
return permissions.count.positive? unless request.indices?
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
# Only allow if all the indices match the given permissions
|
26
|
+
request.indices.find do |idx|
|
27
|
+
idx = idx[1..-1] if idx[0] == '-'
|
28
|
+
permissions.find { |perm| perm.index_regex.match idx }.nil?
|
29
|
+
end.nil?
|
27
30
|
end
|
28
31
|
|
29
32
|
def respond_to_missing?(name, _include_private = false)
|
30
33
|
name[-1] == '?'
|
31
34
|
end
|
32
35
|
|
33
|
-
def
|
34
|
-
|
35
|
-
return nil if permission.pattern.blank?
|
36
|
-
permission.pattern.gsub(/\{user.(.*)\}/) { |_match| user.send(Regexp.last_match[1].to_sym) }
|
37
|
-
end.compact
|
38
|
-
filter(request.index, patterns).count > 0
|
39
|
-
end
|
40
|
-
|
41
|
-
def action_allowed?(action)
|
42
|
-
# Give me all the user's permissions that match the verb
|
43
|
-
!!patterns_for(action).find { |permission| (request.path =~ /#{permission.pattern}/) }
|
36
|
+
def permissions
|
37
|
+
@permissions ||= Permission.for_user(user).for_request(request)
|
44
38
|
end
|
45
39
|
|
46
40
|
class Scope
|
47
|
-
include Helpers::Indices
|
48
|
-
|
49
41
|
attr_reader :user, :scope
|
50
42
|
alias request scope
|
51
43
|
|
52
44
|
def initialize(user, scope)
|
53
|
-
@user = user
|
45
|
+
@user = user || Ditty::User.anonymous_user
|
54
46
|
@scope = scope
|
55
47
|
end
|
56
48
|
|
57
49
|
def resolve
|
58
|
-
|
59
|
-
|
60
|
-
|
50
|
+
return permissions.map(&:index) if request.indices == ['*'] || request.indices == ['_all'] || request.indices.blank?
|
51
|
+
|
52
|
+
request.indices.select do |idx|
|
53
|
+
idx = idx[1..-1] if idx[0] == '-'
|
54
|
+
permissions.find { |perm| perm.index_regex.match idx }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def permissions
|
59
|
+
@permissions ||= Permission.for_user(user).for_request(request)
|
61
60
|
end
|
62
61
|
end
|
63
62
|
end
|
@@ -4,8 +4,12 @@ require 'ditty/policies/application_policy'
|
|
4
4
|
|
5
5
|
module ProxES
|
6
6
|
class SearchPolicy < Ditty::ApplicationPolicy
|
7
|
+
def list?
|
8
|
+
search?
|
9
|
+
end
|
10
|
+
|
7
11
|
def search?
|
8
|
-
user
|
12
|
+
user
|
9
13
|
end
|
10
14
|
|
11
15
|
def fields?
|
@@ -22,7 +26,7 @@ module ProxES
|
|
22
26
|
|
23
27
|
class Scope < Ditty::ApplicationPolicy::Scope
|
24
28
|
def resolve
|
25
|
-
user
|
29
|
+
user&.super_admin? ? scope : scope.where(id: -1)
|
26
30
|
end
|
27
31
|
end
|
28
32
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ditty/policies/application_policy'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
class StatusCheckPolicy < Ditty::ApplicationPolicy
|
7
|
+
def create?
|
8
|
+
user && (user.super_admin? || user.admin?)
|
9
|
+
end
|
10
|
+
|
11
|
+
def list?
|
12
|
+
user && (user.super_admin? || user.admin?)
|
13
|
+
end
|
14
|
+
|
15
|
+
def read?
|
16
|
+
create?
|
17
|
+
end
|
18
|
+
|
19
|
+
def update?
|
20
|
+
read?
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete?
|
24
|
+
create?
|
25
|
+
end
|
26
|
+
|
27
|
+
def permitted_attributes
|
28
|
+
%i[type name source required_value order]
|
29
|
+
end
|
30
|
+
|
31
|
+
class Scope < Ditty::ApplicationPolicy::Scope
|
32
|
+
def resolve
|
33
|
+
user&.super_admin? ? scope : scope.where(id: -1)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/proxes/request.rb
CHANGED
@@ -21,12 +21,18 @@ module ProxES
|
|
21
21
|
path_parts
|
22
22
|
end
|
23
23
|
|
24
|
+
# Indicate whether or not the request is index specific
|
24
25
|
def indices?
|
25
26
|
false
|
26
27
|
end
|
27
28
|
|
29
|
+
# Return the indices associated with the request as an array. [] if `#indices?` is false
|
30
|
+
def indices
|
31
|
+
[]
|
32
|
+
end
|
33
|
+
|
28
34
|
def html?
|
29
|
-
get_header('HTTP_ACCEPT')
|
35
|
+
get_header('HTTP_ACCEPT')&.include?('text/html')
|
30
36
|
end
|
31
37
|
|
32
38
|
def duration
|
@@ -34,17 +40,22 @@ module ProxES
|
|
34
40
|
end
|
35
41
|
|
36
42
|
def user_id
|
37
|
-
return
|
38
|
-
|
43
|
+
return session['user_id'] if session['user_id']
|
44
|
+
|
45
|
+
env['omniauth.auth']&.uid
|
39
46
|
end
|
40
47
|
|
41
48
|
def user
|
42
49
|
return nil if user_id.nil?
|
50
|
+
|
43
51
|
@user ||= Ditty::User[user_id]
|
44
52
|
end
|
45
53
|
|
46
54
|
def detail
|
47
|
-
"#{request_method.upcase} #{fullpath} (#{self.class.name})"
|
55
|
+
detail = "#{request_method.upcase} #{fullpath} (#{self.class.name})"
|
56
|
+
return detail unless indices?
|
57
|
+
|
58
|
+
"#{detail} #{indices.join(',')}"
|
48
59
|
end
|
49
60
|
|
50
61
|
private
|
@@ -56,6 +67,7 @@ module ProxES
|
|
56
67
|
def check_part(val)
|
57
68
|
return val if val.nil?
|
58
69
|
return [] if [endpoint, '_all'].include?(val) && !WRITE_METHODS.include?(request_method)
|
70
|
+
|
59
71
|
val.split(',')
|
60
72
|
end
|
61
73
|
|
@@ -73,11 +85,13 @@ module ProxES
|
|
73
85
|
|
74
86
|
def path_endpoint(path)
|
75
87
|
return '_root' if ['', nil, '/'].include? path
|
88
|
+
|
76
89
|
path_parts = path[1..-1].split('/')
|
77
90
|
return path_parts[-1] if ID_ENDPOINTS.include? path_parts[-1]
|
78
91
|
return path_parts[-2] if path_parts[-1] == 'count' && path_parts[-2] == '_percolate'
|
79
92
|
return path_parts[-2] if path_parts[-1] == 'scroll' && path_parts[-2] == '_search'
|
80
|
-
|
93
|
+
|
94
|
+
path_parts.find { |part| part[0] == '_' && part != '_all' }
|
81
95
|
end
|
82
96
|
end
|
83
97
|
end
|
data/lib/proxes/request/bulk.rb
CHANGED
@@ -1,39 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'proxes/request'
|
3
|
+
require 'proxes/request/multi'
|
4
4
|
require 'proxes/policies/request/bulk_policy'
|
5
5
|
|
6
6
|
module ProxES
|
7
7
|
class Request
|
8
|
-
class Bulk <
|
9
|
-
|
10
|
-
|
11
|
-
REGEX = /"(index|delete|create|update)".*"_index"\s*:\s*"(.*?)"/
|
12
|
-
|
13
|
-
def bulk_indices
|
14
|
-
@bulk_indices ||= begin
|
15
|
-
body.read.scan(REGEX).tap { |_r| body.rewind }
|
16
|
-
end.map { |e| e[1] }.uniq
|
17
|
-
end
|
8
|
+
class Bulk < Multi
|
9
|
+
INDICES_REGEX = /"(index|delete|create|update)".*"_index"\s*:\s*"(.*?)"/
|
18
10
|
|
19
|
-
|
20
|
-
@index = idx
|
21
|
-
self.path_info = '/' + [index, type, endpoint].compact
|
22
|
-
.map { |v| v.is_a?(Array) ? v.join(',') : v }
|
23
|
-
.select { |v| !v.nil? && v != '' }.join('/')
|
24
|
-
end
|
11
|
+
attr_reader :index, :type
|
25
12
|
|
26
13
|
def endpoint
|
27
14
|
'_bulk'
|
28
15
|
end
|
29
16
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
def indices?
|
36
|
-
!@index.nil?
|
17
|
+
class << self
|
18
|
+
def indices_regex
|
19
|
+
INDICES_REGEX
|
20
|
+
end
|
37
21
|
end
|
38
22
|
end
|
39
23
|
end
|
data/lib/proxes/request/cat.rb
CHANGED
data/lib/proxes/request/index.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'proxes/request/multi'
|
4
|
+
require 'proxes/policies/request/mget_policy'
|
5
|
+
|
6
|
+
module ProxES
|
7
|
+
class Request
|
8
|
+
class Mget < Multi
|
9
|
+
INDICES_REGEX = /"(_index)"\s*:\s*"(.*?)"/
|
10
|
+
|
11
|
+
attr_reader :index, :type
|
12
|
+
|
13
|
+
def endpoint
|
14
|
+
'_mget'
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def indices_regex
|
19
|
+
INDICES_REGEX
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'proxes/request/multi'
|
4
|
+
require 'proxes/policies/request/msearch_policy'
|
5
|
+
|
6
|
+
module ProxES
|
7
|
+
class Request
|
8
|
+
class Msearch < Multi
|
9
|
+
INDICES_REGEX = /"(index)"\s*:\s*"(.*?)"/
|
10
|
+
|
11
|
+
attr_reader :index, :type
|
12
|
+
|
13
|
+
def endpoint
|
14
|
+
'_msearch'
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def indices_regex
|
19
|
+
INDICES_REGEX
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'proxes/request'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
class Request
|
7
|
+
class Multi < Request
|
8
|
+
# Read up on URL-based access control - https://www.elastic.co/guide/en/elasticsearch/reference/current/url-access-control.html
|
9
|
+
# Setting `rest.action.multi.allow_explicit_index` to false will not allow the user to send an index in the request body
|
10
|
+
# which negates this. Depending on your needs, you can enable / disable this
|
11
|
+
def body_indices
|
12
|
+
# TODO: Do / Don't do this depending on rest.action.multi.allow_explicit_index
|
13
|
+
@body_indices ||= begin
|
14
|
+
body.read.scan(self.class.indices_regex).tap { |_r| body.rewind }
|
15
|
+
end.map { |e| e[1] }.compact.uniq
|
16
|
+
end
|
17
|
+
|
18
|
+
def index=(idx)
|
19
|
+
@body_indices = []
|
20
|
+
@index = idx
|
21
|
+
self.path_info = '/' + [index, type, endpoint].compact
|
22
|
+
.map { |v| v.is_a?(Array) ? v.join(',') : v }
|
23
|
+
.select { |v| !v.nil? && v != '' }.join('/')
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse
|
27
|
+
@index ||= check_part(path_parts[0]) unless path_parts[0] == endpoint
|
28
|
+
@type ||= check_part(path_parts[1]) unless path_parts[1] == endpoint
|
29
|
+
end
|
30
|
+
|
31
|
+
def indices?
|
32
|
+
indices.blank? == false
|
33
|
+
end
|
34
|
+
|
35
|
+
def indices
|
36
|
+
body_indices + (@index || [])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|