Как и где выполнить базовую аутентификацию в Kibana 3
Я поместил свой сервер elasticsearch за обратный прокси Apache, который обеспечивает базовую аутентификацию.
Проверка подлинности Apache непосредственно из браузера отлично работает. Однако, когда я использую Kibana 3 для доступа к серверу, я получаю ошибки аутентификации.
Очевидно, потому что никакие заголовки auth не отправляются вместе с вызовами Kibana Ajax.
Я добавил в каталог поставщиков продуктов Kibana для эластичности angular -client.js для быстрой и грязной аутентификации. Но по какой-то причине это не сработает.
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
Каков наилучший подход и место для реализации базовой аутентификации в Kibana?
/*! elastic.js - v1.1.1 - 2013-05-24
* https://github.com/fullscale/elastic.js
* Copyright (c) 2013 FullScale Labs, LLC; Licensed MIT */
/*jshint browser:true */
/*global angular:true */
'use strict';
/*
Angular.js service wrapping the elastic.js API. This module can simply
be injected into your angular controllers.
*/
angular.module('elasticjs.service', [])
.factory('ejsResource', ['$http', function ($http) {
return function (config) {
var
// use existing ejs object if it exists
ejs = window.ejs || {},
/* results are returned as a promise */
promiseThen = function (httpPromise, successcb, errorcb) {
return httpPromise.then(function (response) {
(successcb || angular.noop)(response.data);
return response.data;
}, function (response) {
(errorcb || angular.noop)(response.data);
return response.data;
});
};
// check if we have a config object
// if not, we have the server url so
// we convert it to a config object
if (config !== Object(config)) {
config = {server: config};
}
// set url to empty string if it was not specified
if (config.server == null) {
config.server = '';
}
/* implement the elastic.js client interface for angular */
ejs.client = {
server: function (s) {
if (s == null) {
return config.server;
}
config.server = s;
return this;
},
post: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
console.log($http.defaults.headers);
path = config.server + path;
var reqConfig = {url: path, data: data, method: 'POST'};
return promiseThen($http(angular.extend(reqConfig, config)), successcb, errorcb);
},
get: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
path = config.server + path;
// no body on get request, data will be request params
var reqConfig = {url: path, params: data, method: 'GET'};
return promiseThen($http(angular.extend(reqConfig, config)), successcb, errorcb);
},
put: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
path = config.server + path;
var reqConfig = {url: path, data: data, method: 'PUT'};
return promiseThen($http(angular.extend(reqConfig, config)), successcb, errorcb);
},
del: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
path = config.server + path;
var reqConfig = {url: path, data: data, method: 'DELETE'};
return promiseThen($http(angular.extend(reqConfig, config)), successcb, errorcb);
},
head: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
path = config.server + path;
// no body on HEAD request, data will be request params
var reqConfig = {url: path, params: data, method: 'HEAD'};
return $http(angular.extend(reqConfig, config))
.then(function (response) {
(successcb || angular.noop)(response.headers());
return response.headers();
}, function (response) {
(errorcb || angular.noop)(undefined);
return undefined;
});
}
};
return ejs;
};
}]);
ОБНОВЛЕНИЕ 1: Я реализовал предложение Matts. Однако сервер возвращает странный ответ. Кажется, что заголовок авторизации не работает. Может ли это иметь дело с тем, что я запускаю Kibana на порту 81 и elasticsearch на 8181?
OPTIONS /solar_vendor/_search HTTP/1.1
Host: 46.252.46.173:8181
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://46.252.46.173:81
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Это ответ
HTTP/1.1 401 Authorization Required
Date: Fri, 08 Nov 2013 23:47:02 GMT
WWW-Authenticate: Basic realm="Username/Password"
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 346
Connection: close
Content-Type: text/html; charset=iso-8859-1
ОБНОВЛЕНИЕ 2: Обновлены все экземпляры с измененными заголовками в этих файлах Kibana
[email protected]:/var/www/kibana# grep -r 'ejsResource(' .
./src/app/controllers/dash.js: $scope.ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'Accept, Origin, Authorization', 'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
./src/app/services/querySrv.js: var ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'Accept, Origin, Authorization', 'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
./src/app/services/filterSrv.js: var ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'Accept, Origin, Authorization', 'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
./src/app/services/dashboard.js: var ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'Accept, Origin, Authorization', 'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
И изменил мой vhost conf для обратного прокси, как это
<VirtualHost *:8181>
ProxyRequests Off
ProxyPass / http://127.0.0.1:9200/
ProxyPassReverse / https://127.0.0.1:9200/
<Location />
Order deny,allow
Allow from all
AuthType Basic
AuthName "Username/Password"
AuthUserFile /var/www/cake2.2.4/.htpasswd
Require valid-user
Header always set Access-Control-Allow-Methods "GET, POST, DELETE, OPTIONS, PUT"
Header always set Access-Control-Allow-Headers "Content-Type, X-Requested-With, X-HTTP-Method-Override, Origin, Accept, Authorization"
Header always set Access-Control-Allow-Credentials "true"
Header always set Cache-Control "max-age=0"
Header always set Access-Control-Allow-Origin *
</Location>
ErrorLog ${APACHE_LOG_DIR}/error.log
</VirtualHost>
Apache отправляет обратно новые заголовки ответов, но заголовок запроса все еще кажется неправильным. Аутентификация просто не работает.
Заголовок запроса
OPTIONS /solar_vendor/_search HTTP/1.1
Host: 46.252.26.173:8181
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://46.252.26.173:81
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Заголовки ответов
HTTP/1.1 401 Authorization Required
Date: Sat, 09 Nov 2013 08:48:48 GMT
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS, PUT
Access-Control-Allow-Headers: Content-Type, X-Requested-With, X-HTTP-Method-Override, Origin, Accept, Authorization
Access-Control-Allow-Credentials: true
Cache-Control: max-age=0
Access-Control-Allow-Origin: *
WWW-Authenticate: Basic realm="Username/Password"
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 346
Connection: close
Content-Type: text/html; charset=iso-8859-1
РЕШЕНИЕ:
Проведя еще несколько исследований, я узнал, что это определенно проблема конфигурации в отношении CORS. В этой теме имеется довольно много сообщений, но, похоже, для решения моей проблемы необходимо было сделать некоторые очень гранулярные конфигурации на apache, а также убедиться, что нужный материал отправлен из браузера.
Итак, я пересмотрел стратегию и нашел гораздо более простое решение. Просто измените конфигурацию обратного прокси vhost, чтобы переместить сервер elastisearch и kibana на тот же http-порт. Это также повышает безопасность Кибаны.
Это то, что я сделал:
<VirtualHost *:8181>
ProxyRequests Off
ProxyPass /bigdatadesk/ http://127.0.0.1:81/bigdatadesk/src/
ProxyPassReverse /bigdatadesk/ http://127.0.0.1:81/bigdatadesk/src/
ProxyPass / http://127.0.0.1:9200/
ProxyPassReverse / https://127.0.0.1:9200/
<Location />
Order deny,allow
Allow from all
AuthType Basic
AuthName "Username/Password"
AuthUserFile /var/www/.htpasswd
Require valid-user
</Location>
ErrorLog ${APACHE_LOG_DIR}/error.log
</VirtualHost>
Ответы
Ответ 1
В Кибане замените существующий эластичный angular -client.js последним, который можно найти здесь. Затем в коде Kibana замените все экземпляры:
$scope.ejs = ejsResource(config.elasticsearch);
с
$scope.ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'accept, origin, authorization', 'Authorization': 'Basic ' + Base64Encode('user:Password')}});
Это должно быть все, что вам нужно.
Update:
Установлен ли apache для CORS? См. .
Header always set Access-Control-Allow-Methods "GET, POST, DELETE, OPTIONS, PUT"
Header always set Access-Control-Allow-Headers "Content-Type, X-Requested-With, X-HTTP-Method-Override, Origin, Accept, Authorization"
Header always set Access-Control-Allow-Credentials "true"
Header always set Cache-Control "max-age=0"
Header always set Access-Control-Allow-Origin *
Ответ 2
Вот идеальное решение:
https://github.com/fangli/kibana-authentication-proxy
Поддержка не только basicAuth, но и GoogleOAuth и BasicAuth для клиента.
Если работает, пожалуйста, дайте звезду, спасибо.
Ответ 3
Вы правы в том, что это проблема CORS. Kibana 3 использует CORS для общения с ElasticSearch.
Чтобы включить заголовки и файлы cookie HTTP-аутентификации с запросами KBS в CORS, вам нужно сделать две вещи:
ONE: В файле config.js Kibana найдите параметр, в котором определяется ваш сервер ElasticSearch:
elasticsearch: "http://localhost:9200",
Это нужно изменить на:
elasticsearch: {server: "http://localhost:9200", withCredentials: true},
Это позволит Kibana отправить заголовки и файлы аутентификации, если сервер способен их получить.
TWO: Далее вам нужно войти в конфигурационный файл ElasticSearch (elasticsearch.yml на главном сервере, мой был расположен по адресу /etc/elasticsearch/elasticsearch.yml на сервере CentOS7). В этом файле вы найдете раздел "Сеть и HTTP". Вам нужно будет найти строку, которая гласит:
#http.port: 9200
Раскомментируйте эту строку и измените порт на порт, который вы хотите запустить ElasticSearch. Я выбрал 19200. Тогда сделайте то же самое для параметра #transport.tcp.port: 9300
. Опять я выбрал 19300.
Наконец, в конце этого раздела (просто для организационной структуры вы также можете просто добавить следующее в конец файла):
http.cors.allow-origin: http://localhost:8080
http.cors.allow-credentials: true
http.cors.enabled: true
Вы можете изменить указанный выше исходный адрес везде, где ваш веб-сервер обслуживает Kibana. В качестве альтернативы вы можете просто поместить /.*/
в соответствие со всем происхождением, но это не рекомендуется.
Теперь сохраните файл elasticsearch.yml и перезапустите сервер elasticsearch. Ваш обратный прокси должен быть настроен для работы на порту 9200 и указывать на 19200, если запрос аутентифицируется.
Слово предупреждения, если вы используете Cookies для аутентификации запросов, вы должны убедиться, что белый список использует метод HTTP OPTIONS в конфигурации обратного прокси-сервера, поскольку только запросы GET, PUT, POST и DELETE включают файлы cookie. Я не проверял, включают ли OPTIONS заголовок аутентификации, но это может быть та же ситуация, что и файлы cookie. Kibana не будет функционировать правильно, если запросы OPTIONS также не смогут пройти.
Также неплохо настроить обратный прокси-сервер для черного списка любого запроса, который заканчивается в _shutdown, поскольку в большинстве случаев эта команда не требуется в случае внешних запросов.