mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-26 01:48:45 +00:00
Initial commit of kibana security plugin
Original commit: elastic/x-pack-elasticsearch@bb6a86866c
This commit is contained in:
parent
28326a2c4c
commit
b4aa90b104
shield/kibana
20
shield/kibana/.gitignore
vendored
Normal file
20
shield/kibana/.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
work
|
||||
.idea
|
||||
agent/logs
|
||||
agent/data
|
||||
agent/target
|
||||
agent/.project
|
||||
agent/.classpath
|
||||
agent/.settings
|
||||
agent/config
|
||||
agent/lib
|
||||
agent/.local-execution-hints.log
|
||||
.DS_Store
|
||||
*.iml
|
||||
*.log
|
||||
node_modules
|
||||
esvm
|
||||
build
|
||||
.aws-config.json
|
||||
html_docs
|
||||
target
|
63
shield/kibana/index.js
Normal file
63
shield/kibana/index.js
Normal file
@ -0,0 +1,63 @@
|
||||
const _ = require('lodash');
|
||||
const hapiAuthCookie = require('hapi-auth-cookie');
|
||||
const getAuthHeader = require('./server/lib/get_auth_header');
|
||||
|
||||
module.exports = (kibana) => new kibana.Plugin({
|
||||
name: 'security',
|
||||
require: ['elasticsearch'],
|
||||
|
||||
config(Joi) {
|
||||
return Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
encryptionKey: Joi.string().default('secret'),
|
||||
sessionTimeout: Joi.number().default(30 * 60 * 1000)
|
||||
}).default()
|
||||
},
|
||||
|
||||
uiExports: {
|
||||
apps: [{
|
||||
id: 'login',
|
||||
title: 'Login',
|
||||
main: 'plugins/security/login',
|
||||
hidden: true,
|
||||
autoload: kibana.autoload.styles
|
||||
}, {
|
||||
id: 'logout',
|
||||
title: 'Logout',
|
||||
main: 'plugins/security/login/logout',
|
||||
hidden: false,
|
||||
autoload: kibana.autoload.styles
|
||||
}]
|
||||
},
|
||||
|
||||
init(server, options) {
|
||||
const isValidUser = require('./server/lib/is_valid_user')(server.plugins.elasticsearch.client);
|
||||
const config = server.config();
|
||||
|
||||
server.register(hapiAuthCookie, (error) => {
|
||||
if (error != null) throw error;
|
||||
|
||||
server.auth.strategy('session', 'cookie', 'required', {
|
||||
cookie: 'sid',
|
||||
password: config.get('security.encryptionKey'),
|
||||
ttl: config.get('security.sessionTimeout'),
|
||||
clearInvalid: true,
|
||||
keepAlive: true,
|
||||
isSecure: false, // TODO: Remove this
|
||||
redirectTo: '/login',
|
||||
validateFunc(request, session, callback) {
|
||||
const {username, password} = session;
|
||||
|
||||
return isValidUser(username, password).then(() => {
|
||||
_.assign(request.headers, getAuthHeader(username, password));
|
||||
return callback(null, true);
|
||||
}, (error) => {
|
||||
return callback(error, false);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
require('./server/routes/authentication')(server, this);
|
||||
}
|
||||
});
|
25
shield/kibana/package.json
Normal file
25
shield/kibana/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"author": {
|
||||
"name": "Elasticsearch",
|
||||
"company": "Elasticsearch BV"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"precommit": "gulp lint"
|
||||
},
|
||||
"name": "security",
|
||||
"version": "0.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/elastic/x-plugins"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"dependencies": {
|
||||
"bluebird": "^3.0.0",
|
||||
"boom": "^2.10.0",
|
||||
"hapi": "^11.0.2",
|
||||
"hapi-auth-cookie": "^3.1.0",
|
||||
"joi": "^6.9.1",
|
||||
"lodash": "^3.10.1"
|
||||
}
|
||||
}
|
17
shield/kibana/public/login/login.html
Normal file
17
shield/kibana/public/login/login.html
Normal file
@ -0,0 +1,17 @@
|
||||
<div class="container">
|
||||
<h1><img src="{{login.kibanaLogoUrl}}" /></h1>
|
||||
|
||||
<form id="login-form" ng-submit="login.submit(username, password)" class="animated infinite bounce">
|
||||
<div class="form-group inner-addon left-addon">
|
||||
<i class="fa fa-user fa-lg fa-fw"></i>
|
||||
<input type="text" ng-model="username" class="form-control" id="username" name="username" placeholder="Username" />
|
||||
</div>
|
||||
<div class="form-group inner-addon left-addon">
|
||||
<i class="fa fa-lock fa-lg fa-fw"></i>
|
||||
<input type="password" ng-model="password" class="form-control" id="password" name="password" placeholder="Password" />
|
||||
</div>
|
||||
<div ng-show="login.error" class="form-group has-error">Oops! That is an invalid username/password combination.</div>
|
||||
<button type="submit" ng-disabled="!username || !password" class="btn btn-default login">LOG IN</button>
|
||||
<!--<span ng-show="login.loading" class="fa fa-spinner fa-spin"></span>-->
|
||||
</form>
|
||||
</div>
|
27
shield/kibana/public/login/login.js
Normal file
27
shield/kibana/public/login/login.js
Normal file
@ -0,0 +1,27 @@
|
||||
require('plugins/security/login/login.less');
|
||||
|
||||
const kibanaLogoUrl = require('ui/images/kibana-transparent-white.svg');
|
||||
|
||||
require('ui/chrome')
|
||||
.setVisible(false)
|
||||
.setRootTemplate(require('plugins/security/login/login.html'))
|
||||
.setRootController('login', ($http) => {
|
||||
var login = {
|
||||
loading: false,
|
||||
kibanaLogoUrl
|
||||
};
|
||||
|
||||
login.submit = (username, password) => {
|
||||
login.loading = true;
|
||||
|
||||
$http.post('/login', {
|
||||
username: username,
|
||||
password: password
|
||||
}).then(
|
||||
(response) => window.location.href = '/', // TODO: Redirect more intelligently
|
||||
(error) => login.error = true
|
||||
).finally(() => login.loading = false);
|
||||
};
|
||||
|
||||
return login;
|
||||
});
|
54
shield/kibana/public/login/login.less
Normal file
54
shield/kibana/public/login/login.less
Normal file
@ -0,0 +1,54 @@
|
||||
body {
|
||||
background: #222222;
|
||||
}
|
||||
|
||||
.inner-addon {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.inner-addon .fa {
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
pointer-events: none;
|
||||
color: #A2A4AC;
|
||||
}
|
||||
|
||||
.left-addon .fa { left: 0px;}
|
||||
.right-addon .fa { right: 0px;}
|
||||
|
||||
.left-addon input { padding-left: 30px !important; }
|
||||
.right-addon input { padding-right: 30px !important; }
|
||||
|
||||
.container {
|
||||
width: 350px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
|
||||
h1, button {
|
||||
margin: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.has-error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.login {
|
||||
background-color: #94C63D;
|
||||
color: white;
|
||||
width: 200px;
|
||||
font-size: 1.5em;
|
||||
border: none;
|
||||
|
||||
&:disabled {
|
||||
background-color: #44532A;
|
||||
color: #636464;
|
||||
}
|
||||
}
|
||||
|
||||
input.form-control {
|
||||
border: none;
|
||||
font-size: 1.25em;
|
||||
height: auto;
|
||||
padding: 0.5em;
|
||||
}
|
0
shield/kibana/public/login/logout.js
Normal file
0
shield/kibana/public/login/logout.js
Normal file
4
shield/kibana/server/lib/get_auth_header.js
Normal file
4
shield/kibana/server/lib/get_auth_header.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = (username, password) => {
|
||||
const auth = new Buffer(`${username}:${password}`, 'utf8').toString('base64');
|
||||
return {'Authorization': `Basic ${auth}`};
|
||||
};
|
5
shield/kibana/server/lib/is_valid_user.js
Normal file
5
shield/kibana/server/lib/is_valid_user.js
Normal file
@ -0,0 +1,5 @@
|
||||
const getAuthHeader = require('./get_auth_header');
|
||||
|
||||
module.exports = (client) => (username, password) => client.info({
|
||||
headers: getAuthHeader(username, password)
|
||||
});
|
53
shield/kibana/server/routes/authentication.js
Normal file
53
shield/kibana/server/routes/authentication.js
Normal file
@ -0,0 +1,53 @@
|
||||
const Boom = require('boom');
|
||||
const Joi = require('joi');
|
||||
|
||||
module.exports = (server, uiExports) => {
|
||||
const login = uiExports.apps.byId.login;
|
||||
const isValidUser = require('../lib/is_valid_user')(server.plugins.elasticsearch.client);
|
||||
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: '/login',
|
||||
handler(request, reply) {
|
||||
return reply.renderApp(login);
|
||||
},
|
||||
config: {
|
||||
auth: false
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: 'POST',
|
||||
path: '/login',
|
||||
handler(request, reply) {
|
||||
return isValidUser(request.payload.username, request.payload.password).then(() => {
|
||||
request.auth.session.set({username: request.payload.username, password: request.payload.password});
|
||||
return reply({
|
||||
statusCode: 200,
|
||||
payload: 'success'
|
||||
});
|
||||
}, (error) => {
|
||||
request.auth.session.clear();
|
||||
return reply(Boom.unauthorized(error));
|
||||
})
|
||||
},
|
||||
config: {
|
||||
auth: false,
|
||||
validate: {
|
||||
payload: {
|
||||
username: Joi.string().required(),
|
||||
password: Joi.string().required()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: '/app/logout', // TODO: Change to /logout
|
||||
handler(request, reply) {
|
||||
request.auth.session.clear();
|
||||
return reply.redirect('/');
|
||||
}
|
||||
});
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user