proxes 0.9.2 → 0.9.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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/Dockerfile +1 -2
- data/Gemfile.deploy.lock +2 -2
- data/Gemfile.dev +4 -4
- data/config.ru +8 -2
- data/config/logger.yml +2 -0
- data/docker-compose.yml +5 -5
- data/lib/proxes/controllers/permissions.rb +1 -1
- data/lib/proxes/controllers/status.rb +18 -9
- data/lib/proxes/forwarder.rb +0 -11
- data/lib/proxes/helpers/indices.rb +17 -1
- data/lib/proxes/middleware/error_handling.rb +74 -0
- data/lib/proxes/middleware/metrics.rb +25 -0
- data/lib/proxes/middleware/security.rb +60 -0
- data/lib/proxes/models/permission.rb +6 -0
- data/lib/proxes/policies/request/bulk_policy.rb +5 -16
- data/lib/proxes/policies/request/cat_policy.rb +0 -8
- data/lib/proxes/policies/request/create_policy.rb +1 -6
- data/lib/proxes/policies/request/index_policy.rb +1 -7
- data/lib/proxes/policies/request/search_policy.rb +2 -8
- data/lib/proxes/policies/request/stats_policy.rb +0 -8
- data/lib/proxes/policies/request_policy.rb +6 -15
- data/lib/proxes/request.rb +45 -20
- data/lib/proxes/services/es.rb +2 -2
- data/lib/proxes/version.rb +1 -1
- data/public/js/bundle.js +422 -216
- data/startup.sh +3 -2
- data/views/index.haml +1 -0
- data/views/layout.haml +60 -0
- data/views/partials/navbar.haml +25 -0
- metadata +9 -4
- data/lib/proxes/security.rb +0 -89
data/startup.sh
CHANGED
@@ -4,14 +4,15 @@ set -e
|
|
4
4
|
echo "DATABASE_URL: $DATABASE_URL"
|
5
5
|
echo "ELASTICSEARCH_URL: $ELASTICSEARCH_URL"
|
6
6
|
echo "APP_ROOT: $APP_ROOT"
|
7
|
+
bundle show ditty
|
8
|
+
bundle show proxes
|
7
9
|
|
8
10
|
if [ "$1" = 'web-proxes' ]
|
9
11
|
then
|
10
|
-
cd
|
12
|
+
cd $APP_ROOT
|
11
13
|
bundle exec rake ditty:generate_tokens
|
12
14
|
bundle exec rake ditty:migrate
|
13
15
|
bundle exec rake ditty:seed
|
14
|
-
crond
|
15
16
|
exec bundle exec pumactl start "$@"
|
16
17
|
fi
|
17
18
|
|
data/views/index.haml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
#react-dashboard{ 'data-elasticsearch-url' => '..'}
|
data/views/layout.haml
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html{ lang: 'en' }
|
3
|
+
%head
|
4
|
+
%meta{ charset: 'utf-8' }
|
5
|
+
%meta{ 'http-equiv' => 'X-UA-Compatible', 'content' => 'IE=edge,chrome=1' }
|
6
|
+
%meta{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
7
|
+
%meta{ name: 'theme-color', content: '#ffffff' }
|
8
|
+
%link{ rel: 'manifest', href: '/_proxes/manifest.json' }
|
9
|
+
%link{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '/_proxes/images/favicon-32x32.png' }
|
10
|
+
%link{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '/_proxes/images/favicon-16x16.png' }
|
11
|
+
%link{ rel: 'apple-touch-icon', sizes: '76x76', href: '/_proxes/images/apple-icon.png' }
|
12
|
+
%link{ rel: 'mask-icon', href: '/_proxes/images/safari-pinned-tab.svg', color: '#5bbad5' }
|
13
|
+
|
14
|
+
%title
|
15
|
+
ProxES
|
16
|
+
- if defined? title
|
17
|
+
= "- #{title}"
|
18
|
+
|
19
|
+
%meta{ name: 'description', content: '' }
|
20
|
+
%meta{ name: 'author', content: '' }
|
21
|
+
|
22
|
+
/ Le styles
|
23
|
+
%link{ rel: 'stylesheet', href: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', media: 'screen' }
|
24
|
+
%link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/startbootstrap-sb-admin-2/3.3.7+1/css/sb-admin-2.min.css', media: 'screen' }
|
25
|
+
%link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/metisMenu/2.5.2/metisMenu.min.css', media: 'screen' }
|
26
|
+
%link{ rel: 'stylesheet', href: 'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css', media: 'screen' }
|
27
|
+
/[if lt IE 9] <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
|
28
|
+
/[if lt IE 9] <script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
|
29
|
+
|
30
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js' }
|
31
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/startbootstrap-sb-admin-2/3.3.7+1/js/sb-admin-2.min.js' }
|
32
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/metisMenu/2.5.2/metisMenu.min.js' }
|
33
|
+
%body
|
34
|
+
#wrapper
|
35
|
+
= haml :'partials/navbar', locals: { title: (defined?(title) ? title : 'ProxES') }
|
36
|
+
#page-wrapper{ style: 'opacity: 0.8' }
|
37
|
+
.row
|
38
|
+
.col-md-12
|
39
|
+
-if defined? title
|
40
|
+
%h1.page-header= title
|
41
|
+
= haml :'partials/notifications'
|
42
|
+
|
43
|
+
= yield
|
44
|
+
%footer.footer.text-muted.text-center
|
45
|
+
%hr
|
46
|
+
.copyright
|
47
|
+
:plain
|
48
|
+
© <script>document.write(new Date().getFullYear())</script>, DataTools.io
|
49
|
+
|
50
|
+
|
51
|
+
/ Placed at the end of the document so the pages load faster
|
52
|
+
%script{ type: 'text/javascript', src: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js' }
|
53
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.min.js' }
|
54
|
+
%script{ type: 'text/javascript', src: 'https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.min.js' }
|
55
|
+
%script{ type: 'text/javascript', src: '/_proxes/js/bundle.js' }
|
56
|
+
:javascript
|
57
|
+
$(function() {
|
58
|
+
$('.sidebar-nav').metisMenu();
|
59
|
+
});
|
60
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
.navbar.navbar-default.navbar-static-top{ role: 'navigation', style: 'margin-bottom: 0' }
|
2
|
+
.navbar-header
|
3
|
+
%button.navbar-toggle.collapsed{ 'type' => 'button', 'data-toggle' => 'collapse', 'data-target' => '.navbar-collapse' }
|
4
|
+
%span.sr-only Toggle navigation
|
5
|
+
%span.icon-bar
|
6
|
+
%span.icon-bar
|
7
|
+
%span.icon-bar
|
8
|
+
%span.navbar-brand
|
9
|
+
%a{ href: "#{settings.map_path}" }
|
10
|
+
ProxES
|
11
|
+
|
12
|
+
-if authenticated?
|
13
|
+
%form.nav.navbar-top-links.navbar-form.navbar-right{ action: "#{settings.map_path}/auth/identity", method: 'post' }
|
14
|
+
%a.btn.btn-default{ href: "#{settings.map_path}/users/profile" } My Account
|
15
|
+
%input{ name: '_method', value: 'DELETE', type: 'hidden' }
|
16
|
+
%button.btn.btn-default{ type: 'submit' }
|
17
|
+
/ %i.ti-panel
|
18
|
+
Logout
|
19
|
+
- else
|
20
|
+
%ul.nav.navbar-top-links.navbar-right
|
21
|
+
%li
|
22
|
+
%a.btn.btn-link{ href: "#{settings.map_path}/auth/identity" }
|
23
|
+
Log In
|
24
|
+
.navbar-default.sidebar{ role: 'navigation' }
|
25
|
+
= haml :'partials/sidebar'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proxes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jurgens du Toit
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -457,6 +457,9 @@ files:
|
|
457
457
|
- lib/proxes/forwarder.rb
|
458
458
|
- lib/proxes/helpers/indices.rb
|
459
459
|
- lib/proxes/loggers/elasticsearch.rb
|
460
|
+
- lib/proxes/middleware/error_handling.rb
|
461
|
+
- lib/proxes/middleware/metrics.rb
|
462
|
+
- lib/proxes/middleware/security.rb
|
460
463
|
- lib/proxes/models/permission.rb
|
461
464
|
- lib/proxes/policies/permission_policy.rb
|
462
465
|
- lib/proxes/policies/request/bulk_policy.rb
|
@@ -478,7 +481,6 @@ files:
|
|
478
481
|
- lib/proxes/request/search.rb
|
479
482
|
- lib/proxes/request/snapshot.rb
|
480
483
|
- lib/proxes/request/stats.rb
|
481
|
-
- lib/proxes/security.rb
|
482
484
|
- lib/proxes/services/es.rb
|
483
485
|
- lib/proxes/version.rb
|
484
486
|
- migrate/20170209_permissions.rb
|
@@ -499,6 +501,9 @@ files:
|
|
499
501
|
- public/manifest.json
|
500
502
|
- src/scripts/app.js
|
501
503
|
- startup.sh
|
504
|
+
- views/index.haml
|
505
|
+
- views/layout.haml
|
506
|
+
- views/partials/navbar.haml
|
502
507
|
- views/permissions/display.haml
|
503
508
|
- views/permissions/edit.haml
|
504
509
|
- views/permissions/form.haml
|
@@ -525,7 +530,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
525
530
|
version: '0'
|
526
531
|
requirements: []
|
527
532
|
rubyforge_project:
|
528
|
-
rubygems_version: 2.7.
|
533
|
+
rubygems_version: 2.7.6
|
529
534
|
signing_key:
|
530
535
|
specification_version: 4
|
531
536
|
summary: Rack wrapper around Elasticsearch to provide security and management features
|
data/lib/proxes/security.rb
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'proxes/request'
|
4
|
-
require 'proxes/policies/request_policy'
|
5
|
-
require 'ditty/services/logger'
|
6
|
-
require 'ditty/helpers/pundit'
|
7
|
-
require 'ditty/helpers/authentication'
|
8
|
-
require 'ditty/helpers/wisper'
|
9
|
-
|
10
|
-
module ProxES
|
11
|
-
class Security
|
12
|
-
attr_reader :env, :logger
|
13
|
-
|
14
|
-
include Ditty::Helpers::Authentication
|
15
|
-
include Ditty::Helpers::Pundit
|
16
|
-
include Ditty::Helpers::Wisper
|
17
|
-
include Wisper::Publisher
|
18
|
-
|
19
|
-
def initialize(app, logger = nil)
|
20
|
-
@app = app
|
21
|
-
@logger = logger || ::Ditty::Services::Logger.instance
|
22
|
-
end
|
23
|
-
|
24
|
-
def error(message, code = 500)
|
25
|
-
headers = { 'Content-Type' => 'application/json' }
|
26
|
-
headers['WWW-Authenticate'] = 'Basic realm="security"' if code == 401
|
27
|
-
[code, headers, ['{"error":"' + message + '"}']]
|
28
|
-
end
|
29
|
-
|
30
|
-
def redirect(destination, code = 302)
|
31
|
-
[code, { 'Location' => destination}, []]
|
32
|
-
end
|
33
|
-
|
34
|
-
def check(request)
|
35
|
-
check_basic request
|
36
|
-
authorize request, request.request_method.downcase
|
37
|
-
rescue Pundit::NotAuthorizedError
|
38
|
-
return redirect '/_proxes/' if request.get_header('HTTP_ACCEPT') && request.get_header('HTTP_ACCEPT').include?('text/html')
|
39
|
-
|
40
|
-
log_action(:es_request_denied, details: "#{request.request_method.upcase} #{request.fullpath} (#{request.class.name})")
|
41
|
-
logger.debug "Access denied for #{current_user ? current_user.email : 'Anonymous User'} by security layer: #{request.request_method.upcase} #{request.fullpath} (#{request.class.name})"
|
42
|
-
error 'Not Authorized', 401
|
43
|
-
rescue ::Ditty::Helpers::NotAuthenticated
|
44
|
-
logger.warn "Access denied for unauthenticated request by security layer: #{request.request_method.upcase} #{request.fullpath} (#{request.class.name})"
|
45
|
-
error 'Not Authenticated', 401
|
46
|
-
rescue StandardError => e
|
47
|
-
raise e if env['RACK_ENV'] != 'production'
|
48
|
-
logger.error "Access denied for #{current_user ? current_user.email : 'Anonymous User'} by security exception: #{request.request_method.upcase} #{request.fullpath} (#{request.class.name})"
|
49
|
-
logger.error e
|
50
|
-
error 'Forbidden', 403
|
51
|
-
end
|
52
|
-
|
53
|
-
def forward(request)
|
54
|
-
start = Time.now.to_f
|
55
|
-
result = @app.call request.env
|
56
|
-
broadcast(:call_completed, request, Time.now.to_f - start) if result[0].to_i >= 200 && result[0].to_i < 300
|
57
|
-
result
|
58
|
-
rescue Errno::EHOSTUNREACH
|
59
|
-
error 'Could not reach Elasticsearch at ' + ENV['ELASTICSEARCH_URL']
|
60
|
-
rescue Errno::ECONNREFUSED
|
61
|
-
error 'Elasticsearch not listening at ' + ENV['ELASTICSEARCH_URL']
|
62
|
-
end
|
63
|
-
|
64
|
-
def log(request, stage)
|
65
|
-
logger.debug '============' + stage.ljust(56) + '============'
|
66
|
-
logger.debug '= ' + "Request: #{request.request_method} #{request.fullpath} (#{request.class.name})".ljust(76) + ' ='
|
67
|
-
logger.debug '= ' + "Endpoint: #{request.endpoint}".ljust(76) + ' ='
|
68
|
-
logger.debug '================================================================================'
|
69
|
-
end
|
70
|
-
|
71
|
-
def call(env)
|
72
|
-
@env = env
|
73
|
-
|
74
|
-
request = Request.from_env(env)
|
75
|
-
broadcast(:call_started, request)
|
76
|
-
|
77
|
-
log(request, 'BEFORE')
|
78
|
-
unless env['PROXES_PASSTHROUGH']
|
79
|
-
result = check(request)
|
80
|
-
return result if result.is_a?(Array) # Rack Response
|
81
|
-
|
82
|
-
request.index = policy_scope(request) if request.indices?
|
83
|
-
log(request, 'AFTER')
|
84
|
-
end
|
85
|
-
|
86
|
-
forward request
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|