proxes 0.1.0
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 +7 -0
- data/.codeclimate.yml +24 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.rubocop.yml +12 -0
- data/.ruby-version +1 -0
- data/.travis.yml +18 -0
- data/Gemfile +4 -0
- data/Gemfile.ci +15 -0
- data/Gemfile.dev +10 -0
- data/Gemfile.dev.lock +155 -0
- data/LICENSE.txt +8 -0
- data/README.md +83 -0
- data/Rakefile +9 -0
- data/Vagrantfile +46 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/config.ru +64 -0
- data/config/logger.yml +3 -0
- data/gulpfile.js +80 -0
- data/lib/proxes.rb +3 -0
- data/lib/proxes/app.rb +48 -0
- data/lib/proxes/controllers/application.rb +53 -0
- data/lib/proxes/controllers/audit_logs.rb +34 -0
- data/lib/proxes/controllers/auth_identity.rb +21 -0
- data/lib/proxes/controllers/component.rb +108 -0
- data/lib/proxes/controllers/permissions.rb +10 -0
- data/lib/proxes/controllers/roles.rb +10 -0
- data/lib/proxes/controllers/users.rb +119 -0
- data/lib/proxes/db.rb +17 -0
- data/lib/proxes/helpers/authentication.rb +45 -0
- data/lib/proxes/helpers/component.rb +40 -0
- data/lib/proxes/helpers/indices.rb +16 -0
- data/lib/proxes/helpers/pundit.rb +39 -0
- data/lib/proxes/helpers/views.rb +41 -0
- data/lib/proxes/loggers/elasticsearch.rb +9 -0
- data/lib/proxes/models/audit_log.rb +12 -0
- data/lib/proxes/models/identity.rb +67 -0
- data/lib/proxes/models/permission.rb +17 -0
- data/lib/proxes/models/role.rb +14 -0
- data/lib/proxes/models/user.rb +57 -0
- data/lib/proxes/policies/application_policy.rb +20 -0
- data/lib/proxes/policies/audit_log_policy.rb +40 -0
- data/lib/proxes/policies/identity_policy.rb +24 -0
- data/lib/proxes/policies/permission_policy.rb +40 -0
- data/lib/proxes/policies/request/root_policy.rb +12 -0
- data/lib/proxes/policies/request/search_policy.rb +15 -0
- data/lib/proxes/policies/request/snapshot_policy.rb +12 -0
- data/lib/proxes/policies/request/stats_policy.rb +15 -0
- data/lib/proxes/policies/request_policy.rb +69 -0
- data/lib/proxes/policies/role_policy.rb +40 -0
- data/lib/proxes/policies/token_policy.rb +46 -0
- data/lib/proxes/policies/user_policy.rb +46 -0
- data/lib/proxes/rake_tasks.rb +59 -0
- data/lib/proxes/request.rb +51 -0
- data/lib/proxes/request/root.rb +10 -0
- data/lib/proxes/request/search.rb +37 -0
- data/lib/proxes/request/snapshot.rb +16 -0
- data/lib/proxes/request/stats.rb +30 -0
- data/lib/proxes/security.rb +59 -0
- data/lib/proxes/seed.rb +10 -0
- data/lib/proxes/services/logger.rb +50 -0
- data/lib/proxes/version.rb +4 -0
- data/migrate/001_tables.rb +47 -0
- data/migrate/002_audit_log.rb +11 -0
- data/package.json +34 -0
- data/proxes.gemspec +44 -0
- data/public/js/bundle.js +28988 -0
- data/src/scripts/app.js +10 -0
- data/views/404.haml +1 -0
- data/views/audit_logs/index.haml +18 -0
- data/views/error.haml +4 -0
- data/views/getting_started.haml +16 -0
- data/views/identity/login.haml +19 -0
- data/views/identity/register.haml +17 -0
- data/views/index.haml +3 -0
- data/views/layout.haml +48 -0
- data/views/partials/delete_form.haml +4 -0
- data/views/partials/form_control.haml +21 -0
- data/views/partials/navbar.haml +25 -0
- data/views/partials/notifications.haml +24 -0
- data/views/partials/pager.haml +19 -0
- data/views/partials/sidebar.haml +32 -0
- data/views/permissions/display.haml +24 -0
- data/views/permissions/edit.haml +11 -0
- data/views/permissions/form.haml +3 -0
- data/views/permissions/index.haml +14 -0
- data/views/permissions/new.haml +10 -0
- data/views/roles/display.haml +33 -0
- data/views/roles/edit.haml +11 -0
- data/views/roles/form.haml +1 -0
- data/views/roles/index.haml +17 -0
- data/views/roles/new.haml +10 -0
- data/views/users/display.haml +32 -0
- data/views/users/edit.haml +11 -0
- data/views/users/identity.haml +3 -0
- data/views/users/index.haml +20 -0
- data/views/users/new.haml +11 -0
- data/views/users/profile.haml +37 -0
- data/views/users/user.haml +3 -0
- metadata +424 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/tasklib'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
class Tasks < ::Rake::TaskLib
|
7
|
+
include ::Rake::DSL if defined?(::Rake::DSL)
|
8
|
+
|
9
|
+
def install_tasks
|
10
|
+
namespace :proxes do
|
11
|
+
desc 'Generate the needed tokens'
|
12
|
+
task :generate_tokens do
|
13
|
+
require 'securerandom'
|
14
|
+
File.write('.session_secret', SecureRandom.random_bytes(40))
|
15
|
+
File.write('.token_secret', SecureRandom.random_bytes(40))
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Seed the database'
|
19
|
+
task :seed do
|
20
|
+
require 'proxes/seed'
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Migrate ProxES database to latest version'
|
24
|
+
task :migrate do
|
25
|
+
Rake::Task['proxes:migrate:up'].invoke
|
26
|
+
end
|
27
|
+
|
28
|
+
namespace :migrate do
|
29
|
+
require_relative './db'
|
30
|
+
Sequel.extension :migration
|
31
|
+
folder = File.expand_path(File.dirname(__FILE__) + '/../../migrate')
|
32
|
+
|
33
|
+
desc 'Check if the migration is current'
|
34
|
+
task :check do
|
35
|
+
Sequel::Migrator.check_current(DB, folder)
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'Migrate ProxES database to latest version'
|
39
|
+
task :up do
|
40
|
+
Sequel::Migrator.apply(DB, folder)
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'Roll back the ProxES database'
|
44
|
+
task :down do
|
45
|
+
Sequel::Migrator.apply(DB, folder, 0)
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'Reset the ProxES database'
|
49
|
+
task :bounce do
|
50
|
+
Sequel::Migrator.apply(DB, folder, 0)
|
51
|
+
Sequel::Migrator.apply(DB, folder)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
ProxES::Tasks.new.install_tasks
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module ProxES
|
5
|
+
class Request < Rack::Request
|
6
|
+
def self.from_env(env)
|
7
|
+
request = Rack::Request.new(env)
|
8
|
+
splits = request.path.split('/')
|
9
|
+
endpoint = if splits[1] && splits[1][0] == '_'
|
10
|
+
splits[1][1..-1].titlecase
|
11
|
+
else
|
12
|
+
splits.count > 0 ? splits[-1][1..-1].titlecase : 'Root'
|
13
|
+
end
|
14
|
+
begin
|
15
|
+
require 'proxes/request/' + endpoint.downcase
|
16
|
+
ProxES::Request.const_get(endpoint).new(env)
|
17
|
+
rescue LoadError
|
18
|
+
self.new(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(env)
|
23
|
+
super
|
24
|
+
parse
|
25
|
+
end
|
26
|
+
|
27
|
+
def endpoint
|
28
|
+
path_parts[0]
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse
|
32
|
+
path_parts
|
33
|
+
end
|
34
|
+
|
35
|
+
def indices?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def path_parts
|
42
|
+
@path_parts ||= path[1..-1].split('/')
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_part(val)
|
46
|
+
return val if val.nil?
|
47
|
+
return [] if [endpoint, '_all'].include? val
|
48
|
+
val.split(',')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rack'
|
3
|
+
require 'proxes/request'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
class Request
|
7
|
+
class Search < ProxES::Request
|
8
|
+
attr_reader :index, :type
|
9
|
+
attr_reader :type
|
10
|
+
|
11
|
+
def index=(idx)
|
12
|
+
@index = idx
|
13
|
+
self.path_info = '/' + [ index, type, id, endpoint ]
|
14
|
+
.map { |v| v.is_a?(Array) ? v.join(',') : v }
|
15
|
+
.select { |v| !v.nil? && v != '' }.join('/')
|
16
|
+
end
|
17
|
+
|
18
|
+
def endpoint
|
19
|
+
'_search'
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse
|
23
|
+
@index ||= check_part(path_parts[0])
|
24
|
+
@type ||= check_part(path_parts[1])
|
25
|
+
@id ||= check_part(path_parts[2])
|
26
|
+
end
|
27
|
+
|
28
|
+
def id
|
29
|
+
@id == [] ? nil : @id
|
30
|
+
end
|
31
|
+
|
32
|
+
def indices?
|
33
|
+
true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rack'
|
3
|
+
require 'proxes/request'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
class Request
|
7
|
+
class Snapshot < ProxES::Request
|
8
|
+
attr_reader :repository
|
9
|
+
|
10
|
+
def parse
|
11
|
+
@repository ||= check_part(path_parts[1])
|
12
|
+
@repository = [] if repository.nil?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'rack'
|
3
|
+
require 'proxes/request'
|
4
|
+
|
5
|
+
module ProxES
|
6
|
+
class Request
|
7
|
+
class Stats < ProxES::Request
|
8
|
+
attr_reader :index
|
9
|
+
|
10
|
+
def index=(idx)
|
11
|
+
@index = idx
|
12
|
+
self.path_info = '/' + [ index, endpoint ]
|
13
|
+
.map { |v| v.is_a?(Array) ? v.join(',') : v }
|
14
|
+
.select { |v| !v.nil? && v != '' }.join('/')
|
15
|
+
end
|
16
|
+
|
17
|
+
def endpoint
|
18
|
+
'_stats'
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse
|
22
|
+
@index ||= check_part(path_parts[0])
|
23
|
+
end
|
24
|
+
|
25
|
+
def indices?
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'proxes/services/logger'
|
3
|
+
require 'rack-proxy'
|
4
|
+
require 'proxes/request'
|
5
|
+
require 'proxes/policies/request_policy'
|
6
|
+
require 'proxes/helpers/pundit'
|
7
|
+
require 'proxes/helpers/authentication'
|
8
|
+
require 'proxes/services/logger'
|
9
|
+
|
10
|
+
module ProxES
|
11
|
+
class Security
|
12
|
+
attr_reader :env, :logger
|
13
|
+
|
14
|
+
include ProxES::Helpers::Authentication
|
15
|
+
include ProxES::Helpers::Pundit
|
16
|
+
|
17
|
+
def initialize(app, logger = nil)
|
18
|
+
@app = app
|
19
|
+
@logger = logger || ProxES::Services::Logger.instance
|
20
|
+
end
|
21
|
+
|
22
|
+
def error(message, code = 500)
|
23
|
+
[code, { 'Content-Type' => 'application/json' }, ['{"error":"' + message + '}']]
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(env)
|
27
|
+
@env = env
|
28
|
+
|
29
|
+
request = ProxES::Request.from_env(env)
|
30
|
+
|
31
|
+
logger.debug '==========================BEFORE================================================'
|
32
|
+
logger.debug '= ' + "Request: #{request.fullpath}".ljust(76) + ' ='
|
33
|
+
logger.debug '= ' + "Endpoint: #{request.endpoint}".ljust(76) + ' ='
|
34
|
+
logger.debug '================================================================================'
|
35
|
+
|
36
|
+
begin
|
37
|
+
check_basic
|
38
|
+
authorize request
|
39
|
+
rescue StandardError => e
|
40
|
+
logger.debug "Access denied by security layer: #{e.message}"
|
41
|
+
return error 'Forbidden', 403
|
42
|
+
end
|
43
|
+
request.index = policy_scope(request) if request.indices?
|
44
|
+
|
45
|
+
logger.debug '==========================AFTER================================================='
|
46
|
+
logger.debug '= ' + "Request: #{request.fullpath}".ljust(76) + ' ='
|
47
|
+
logger.debug '= ' + "Endpoint: #{request.endpoint}".ljust(76) + ' ='
|
48
|
+
logger.debug '================================================================================'
|
49
|
+
|
50
|
+
begin
|
51
|
+
@app.call request.env
|
52
|
+
rescue Errno::EHOSTUNREACH
|
53
|
+
error 'Could not reach Elasticsearch at ' + ENV['ELASTICSEARCH_URL']
|
54
|
+
rescue Errno::ECONNREFUSED
|
55
|
+
error 'Elasticsearch not listening at ' + ENV['ELASTICSEARCH_URL']
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/proxes/seed.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'proxes/db'
|
2
|
+
require 'proxes/models/role'
|
3
|
+
require 'proxes/models/permission'
|
4
|
+
|
5
|
+
ProxES::Role.find_or_create(name: 'user')
|
6
|
+
ProxES::Role.find_or_create(name: 'admin')
|
7
|
+
sa = ProxES::Role.find_or_create(name: 'super_admin')
|
8
|
+
%w(GET POST PUT DELETE HEAD OPTIONS).each do |verb|
|
9
|
+
ProxES::Permission.find_or_create(role: sa, verb: verb, pattern: '.*')
|
10
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'logger'
|
3
|
+
require 'yaml'
|
4
|
+
require 'singleton'
|
5
|
+
require 'active_support/inflector'
|
6
|
+
require 'proxes/loggers/elasticsearch'
|
7
|
+
|
8
|
+
# ProxES::Services::Logger.instance
|
9
|
+
|
10
|
+
module ProxES
|
11
|
+
module Services
|
12
|
+
class Logger
|
13
|
+
include Singleton
|
14
|
+
|
15
|
+
CONFIG = './config/logger.yml'
|
16
|
+
attr_reader :loggers
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@loggers = []
|
20
|
+
config.each do |values|
|
21
|
+
klass = values['class'].constantize
|
22
|
+
opts = values['options'] || nil
|
23
|
+
logger = klass.new(opts)
|
24
|
+
if values['level']
|
25
|
+
logger.level = klass.const_get(values['level'].to_sym)
|
26
|
+
end
|
27
|
+
@loggers << logger
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(method, *args, &block)
|
32
|
+
loggers.each { |logger| logger.send(method, *args, &block) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def respond_to_missing?(method, include_private = false)
|
36
|
+
loggers.any? { |logger| logger.respond_to?(method) }
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def config
|
42
|
+
@config ||= File.exist?(CONFIG) ? YAML.load_file(CONFIG) : default
|
43
|
+
end
|
44
|
+
|
45
|
+
def default
|
46
|
+
[{ 'name' => 'default', 'class' => 'Logger' }]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
Sequel.migration do
|
3
|
+
change do
|
4
|
+
create_table :users do
|
5
|
+
primary_key :id
|
6
|
+
String :name
|
7
|
+
String :surname
|
8
|
+
String :email
|
9
|
+
DateTime :created_at
|
10
|
+
DateTime :updated_at
|
11
|
+
unique [:email]
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table :identities do
|
15
|
+
primary_key :id
|
16
|
+
foreign_key :user_id, :users
|
17
|
+
String :username
|
18
|
+
String :crypted_password
|
19
|
+
DateTime :created_at
|
20
|
+
DateTime :updated_at
|
21
|
+
unique [:username]
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :roles do
|
25
|
+
primary_key :id
|
26
|
+
String :name
|
27
|
+
DateTime :created_at
|
28
|
+
DateTime :updated_at
|
29
|
+
unique [:name]
|
30
|
+
end
|
31
|
+
|
32
|
+
create_table :permissions do
|
33
|
+
primary_key :id
|
34
|
+
String :verb
|
35
|
+
String :pattern
|
36
|
+
DateTime :created_at
|
37
|
+
foreign_key :role_id, :roles
|
38
|
+
end
|
39
|
+
|
40
|
+
create_table :roles_users do
|
41
|
+
DateTime :created_at
|
42
|
+
foreign_key :user_id, :users
|
43
|
+
foreign_key :role_id, :roles
|
44
|
+
unique [:user_id, :role_id]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/package.json
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
{
|
2
|
+
"name": "proxes",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"description": "Elasticsearch Management System",
|
5
|
+
"repository": {
|
6
|
+
"type": "git",
|
7
|
+
"url": "git+https://github.com/EagerELK/proxes.git"
|
8
|
+
},
|
9
|
+
"author": "Jurgens du Toit",
|
10
|
+
"license": "LGPL-3.0",
|
11
|
+
"bugs": {
|
12
|
+
"url": "https://github.com/EagerELK/proxes/issues"
|
13
|
+
},
|
14
|
+
"homepage": "https://github.com/EagerELK/proxes#readme",
|
15
|
+
"dependencies": {
|
16
|
+
"body-parser": "^1.4.3",
|
17
|
+
"express": "^4.4.5",
|
18
|
+
"gulp-connect": "^5.0.0",
|
19
|
+
"jquery": "^3.1.0",
|
20
|
+
"numeral": "^1.5.3",
|
21
|
+
"react": "^15.2.1",
|
22
|
+
"react-dom": "^15.2.1",
|
23
|
+
"react-proxes-components": "^0.2.2"
|
24
|
+
},
|
25
|
+
"devDependencies": {
|
26
|
+
"babel-preset-es2015": "^6.9.0",
|
27
|
+
"babel-preset-react": "^6.11.1",
|
28
|
+
"babelify": "^7.3.0",
|
29
|
+
"browserify": "^13.1.0",
|
30
|
+
"gulp": "^3.9.1",
|
31
|
+
"gulp-util": "^3.0.7",
|
32
|
+
"vinyl-source-stream": "^1.1.0"
|
33
|
+
}
|
34
|
+
}
|
data/proxes.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'proxes/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'proxes'
|
9
|
+
spec.version = ProxES::VERSION
|
10
|
+
spec.authors = ['Jurgens du Toit']
|
11
|
+
spec.email = ['jrgns@jadeit.co.za']
|
12
|
+
|
13
|
+
spec.summary = 'Rack wrapper around Elasticsearch to provide security and management features'
|
14
|
+
spec.description = 'Rack wrapper around Elasticsearch to provide security and management features'
|
15
|
+
spec.homepage = 'https://github.com/eagerelk/proxes'
|
16
|
+
spec.license = 'LGPLv3'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
|
+
spec.add_development_dependency 'racksh'
|
27
|
+
spec.add_development_dependency 'rack-test'
|
28
|
+
spec.add_development_dependency 'database_cleaner'
|
29
|
+
spec.add_development_dependency 'factory_girl'
|
30
|
+
|
31
|
+
spec.add_dependency 'rack-proxy'
|
32
|
+
spec.add_dependency 'sinatra'
|
33
|
+
spec.add_dependency 'sinatra-flash'
|
34
|
+
spec.add_dependency 'sinatra-contrib'
|
35
|
+
spec.add_dependency 'elasticsearch'
|
36
|
+
spec.add_dependency 'logger'
|
37
|
+
spec.add_dependency 'pundit'
|
38
|
+
spec.add_dependency 'sequel'
|
39
|
+
spec.add_dependency 'bcrypt'
|
40
|
+
spec.add_dependency 'omniauth'
|
41
|
+
spec.add_dependency 'omniauth-identity'
|
42
|
+
spec.add_dependency 'haml'
|
43
|
+
spec.add_dependency 'tilt', '>= 2'
|
44
|
+
end
|