且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何以及在哪里3 Kibana实现基本的身份验证

更新时间:2023-12-01 13:38:22

在Kibana,取代现有的弹性角client.js与可以发现最新的here.然后,在Kibana code替换的所有实例:

  $ scope.ejs = ejsResource(config.elasticsearch);

  $ scope.ejs = ejsResource({服务器:config.elasticsearch,标题:{访问控制请求报头:接受,产地,授权,授权 :基本+ Base64En code('用户名:密码')}});

这应该是所有你需要的。

更新:

就是Apache配置为CORS?请参见这个

 头始终设置访问控制,允许 - 方法GET,POST,DELETE,OPTIONS,PUT
头总是设置访问控制,允许 - 头内容类型,X-要求,随着X-HTTP的方法,覆盖,产地,接受,授权
头总是设置访问控制允许的凭据真
头总是设置缓存控制最大年龄= 0
头总是设置访问控制允许来源*

I have put my elasticsearch server behind a Apache reverse proxy that provides basic authentication.

Authenticating to Apache directly from the browser works fine. However, when I use Kibana 3 to access the server, I receive authentication errors.

Obviously because no auth headers are sent along with Kibana's Ajax calls.

I added the below to elastic-angular-client.js in the Kibana vendor directory to implement authentication quick and dirty. But for some reason it does not work.

$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');

What is the best approach and place to implement basic authentication in 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;
  };
}]);

UPDATE 1: I implemented Matts suggestion. However, the server returns a weird response. It seems that the authorization header is not working. Could it have to do with the fact, that I am running Kibana on port 81 and elasticsearch on 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

This is the response

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

UPDATE 2: Updated all instances with the modified headers in these Kibana files

root@localhost:/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=='}});

And modified my vhost conf for the reverse proxy like this

<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 sends back the new response headers but the request header still seems to be wrong somewhere. Authentication just doesn't work.

Request Headers

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

Response Headers

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

SOLUTION: After doing some more research, I found out that this is definitely a configuration issue with regard to CORS. There are quite a few posts available regarding that topic but it appears that in order to solve my problem, it would be necessary to to make some very granular configurations on apache and also make sure that the right stuff is sent from the browser.

So I reconsidered the strategy and found a much simpler solution. Just modify the vhost reverse proxy config to move the elastisearch server AND kibana on the same http port. This also adds even better security to Kibana.

This is what I did:

<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>

In Kibana, replace the existing elastic-angular-client.js with the latest which can be found here. Then, in the Kibana code replace all instances of:

$scope.ejs = ejsResource(config.elasticsearch);

with

$scope.ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'accept, origin, authorization', 'Authorization': 'Basic ' + Base64Encode('user:Password')}});

That should be all you need.

Update:

Is apache configured for for CORS? See this.

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 *