proxes 0.9.2 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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 /usr/src/app
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
 
@@ -0,0 +1 @@
1
+ #react-dashboard{ 'data-elasticsearch-url' => '..'}
@@ -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
+ &copy; <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.2
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-02-06 00:00:00.000000000 Z
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.5
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
@@ -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