在kibana V6.5.1上开发认证插件的踩坑记录

之前在6.0.0版本上做过一次,那时是用template-kibana-plugin也就是sao来生成开发插件的模板的。需要自己去下载npm install -g sao然后再跑起来。还是想用这个方法的可以浏览这些文章:

  1. kibana-plugin-development-tutorial——kibana5版本的插件开发教程
  2. template-kibana-plugin文档——sao使用文档

到了kibana6.3版本之后,你就可以用kibana自带的插件模板生成器(Kibana Plugin Generator)去生成模板。其实整个elastic stack基本上也是从6.3版本之后开始大跨步的走,版本发布之快,变动之大,让二次开发变得更加困难。

做认证插件的思路整理一下:

  • 在服务器端(kibana用的是hapi,在node下,类似的有express,python有flask, django等)对所有的链接进行拦截。确认请求中是否包含cookie,如果没有,跳到登录页面
  • hapi里面有一个memory cache,在服务器启动时候自动创建。当用户通过登录页面登录成功后,返回一个cookie给浏览器,里面包含经过加密当用户信息,并且把该cookie的session保存到cache当中
  • 用户继续访问kibana,每次请求当中都会带有该cookie。服务器每次都会检验该cookie的值是否合法。如果不合法,跳转到登录页面

代码看起来大概是这样的:

	const Cookie = require('hapi-auth-cookie');

    server.register([Cookie], (err) => {
          if (err) {
              server.log(['status', 'error', 'kibana-auth-plugin'], 'Failed to register Cookie plugin');
              throw err;
          }
          const cache = server.cache({
              segment: 'sessions',
              expiresIn: eval(Config.expiration)
          });
          server.app.cache = cache;
          server.auth.strategy('session', 'cookie', 'required', {
              password: Config.secret,
              cookie: 'kibana-cookie',
              redirectTo: '/login',
              appendNext: true,
              isSecure: false,
              validateFunc: (request, session, callback) => {
                  cache.get(session.sid, (err, cached) => {
                      if (err) {
                          server.log(['status', 'error', 'kibana-auth-plugin'], 'failed to access session cache');
                          return callback(err, false);
                      }
                      if (!cached) {
                          server.log(['status', 'info', 'kibana-auth-plugin'], 'failed to find session ' + session.sid + ' from cache');
                          return callback(null, false);
                      }
                      server.log(['status', 'info', 'kibana-auth-plugin'], 'load session ' + session.sid + ' from cache');
                      if(!validateCacheInfo(cache)){
                      	return callback(null, false);
                      }
                      return callback(null, true, null);
                  });
              }
          });
      });

在V6.0.0当中,cache在创建之后,cache是被初始化过的,可以直接使用get和set方法。

const cache = server.cache({
              segment: 'sessions',
              expiresIn: eval(Config.expiration)
          });

但是当我把这个代码移植到V6.5.0之后,该cache变成了一个未初始化的对象。当代码尝试将session保存在cache的时候抛出如下异常:

{ Error: Disconnected
    at module.exports.internals.Client.internals.Client.set (/Users/caishichao/Code/kibana/node_modules/hapi/node_modules/catbox/lib/client.js:113:30)
    at module.exports.internals.Policy.internals.Policy.set (/Users/caishichao/Code/kibana/node_modules/hapi/node_modules/catbox/lib/policy.js:274:17)
    at Plugin.init [as externalInit] (/Users/caishichao/Code/kibana-extra/system_portal/index.js:39:13)
    at asyncRegister (/Users/caishichao/Code/kibana/src/server/plugins/lib/plugin.js:84:20)
    at Object.register (/Users/caishichao/Code/kibana/src/server/plugins/lib/plugin.js:89:7)
    at Object.target [as register] (/Users/caishichao/Code/kibana/node_modules/hapi/node_modules/joi/lib/object.js:77:34)
    at each (/Users/caishichao/Code/kibana/node_modules/hapi/lib/plugin.js:317:14)
    at iterate (/Users/caishichao/Code/kibana/node_modules/items/lib/index.js:36:13)
    at Object.exports.serial (/Users/caishichao/Code/kibana/node_modules/items/lib/index.js:39:9)
    at module.exports.internals.Server.internals.Plugin.register (/Users/caishichao/Code/kibana/node_modules/hapi/lib/plugin.js:320:11)
    at Promise (/Users/caishichao/Code/kibana/node_modules/hapi/lib/promises.js:24:16)
    at new Promise (<anonymous>)
    at Object.exports.wrap (/Users/caishichao/Code/kibana/node_modules/hapi/lib/promises.js:13:12)
    at module.exports.internals.Server.internals.Plugin.register (/Users/caishichao/Code/kibana/node_modules/hapi/lib/plugin.js:164:25)
    at Plugin.init (/Users/caishichao/Code/kibana/src/server/plugins/lib/plugin.js:95:28)
    at Plugin.init (/Users/caishichao/Code/kibana/node_modules/lodash/index.js:7407:25)
    at callPluginHook (/Users/caishichao/Code/kibana/src/server/plugins/lib/call_plugin_hook.js:49:9)
    at <anonymous>
  data: undefined,
  isBoom: true,
  isServer: true,
  output: 
   { statusCode: 500,
     payload: 
      { statusCode: 500,
        error: 'Internal Server Error',
        message: 'An internal server error occurred' },
     headers: {} },
  reformat: [Function],
  typeof: [Function] }

肯定是因为版本的变动,导致server.cache()创建出来的cache对象没有初始化。
比较一下kibana的源码变动:

git diff v6.0.0 v6.5.0 --stat

有点疯狂:

 x-pack/test_utils/mocks/intl.js                                                                                               |    18 +
 x-pack/tsconfig.json                                                                                                          |    31 +
 x-pack/tslint.yaml                                                                                                            |    11 +
 x-pack/webpackShims/jquery-flot.js                                                                                            |    16 +
 x-pack/yarn.lock                                                                                                              | 12109 ++++++++++++++++
 yarn.lock                                                                                                                     | 18017 +++++++++++++++++++++++
 13238 files changed, 1009808 insertions(+), 139517 deletions(-)

13238个文件。导出diff到文件当中,没有搜索到可以的删除cache初始化的代码。
比较两个版本的库:

git diff v6.0.0 v6.5.0 package.json

结果(只看dependencies):

   "dependencies": {
-    "@elastic/datemath": "2.3.0",
+    "@elastic/eui": "4.5.1-logos-tooltip-betabadge",
     "@elastic/filesaver": "1.1.2",
-    "@elastic/numeral": "2.2.1",
-    "@elastic/test-subj-selector": "0.2.1",
+    "@elastic/numeral": "2.3.2",
     "@elastic/ui-ace": "0.2.3",
-    "@elastic/webpack-directory-name-as-main": "2.0.2",
+    "@kbn/babel-preset": "link:packages/kbn-babel-preset",
+    "@kbn/config-schema": "link:packages/kbn-config-schema",
+    "@kbn/datemath": "link:packages/kbn-datemath",
+    "@kbn/i18n": "link:packages/kbn-i18n",
+    "@kbn/pm": "link:packages/kbn-pm",
+    "@kbn/test-subj-selector": "link:packages/kbn-test-subj-selector",
+    "@kbn/ui-framework": "link:packages/kbn-ui-framework",
     "JSONStream": "1.1.1",
-    "accept-language-parser": "1.2.0",
-    "angular": "1.6.5",
-    "angular-bootstrap-colorpicker": "3.0.19",
+    "abortcontroller-polyfill": "^1.1.9",
+    "angular": "1.6.9",
+    "angular-aria": "1.6.6",
     "angular-elastic": "2.5.0",
+    "angular-recursion": "^1.0.5",
     "angular-route": "1.4.7",
     "angular-sanitize": "1.5.7",
     "angular-sortable-view": "0.0.15",
-    "angular-translate": "2.13.1",
     "ansicolors": "0.3.2",
-    "autoprefixer": "6.5.4",
-    "autoprefixer-loader": "2.0.0",
+    "autoprefixer": "^9.1.0",
     "babel-core": "6.21.0",
-    "babel-jest": "20.0.3",
-    "babel-loader": "6.2.10",
-    "babel-plugin-add-module-exports": "0.2.1",
-    "babel-plugin-transform-async-generator-functions": "6.24.1",
-    "babel-plugin-transform-class-properties": "6.24.1",
-    "babel-plugin-transform-define": "1.3.0",
-    "babel-plugin-transform-object-rest-spread": "6.23.0",
+    "babel-loader": "7.1.2",
     "babel-polyfill": "6.20.0",
-    "babel-preset-env": "1.4.0",
-    "babel-preset-react": "6.22.0",
     "babel-register": "6.18.0",
     "bluebird": "2.9.34",
-    "body-parser": "1.12.0",
     "boom": "5.2.0",
-    "brace": "0.5.1",
-    "bunyan": "1.7.1",
-    "check-hash": "1.0.1",
+    "brace": "0.11.1",
+    "cache-loader": "1.0.3",
+    "chalk": "^2.4.1",
     "color": "1.0.3",
     "commander": "2.8.1",
-    "css-loader": "0.28.1",
+    "compare-versions": "3.1.0",
+    "css-loader": "0.28.7",
+    "custom-event-polyfill": "^0.3.0",
     "d3": "3.5.6",
     "d3-cloud": "1.2.1",
+    "del": "^3.0.0",
     "dragula": "3.7.0",
-    "elasticsearch": "13.0.1",
-    "elasticsearch-browser": "13.0.1",
+    "elasticsearch": "^15.2.0",
+    "elasticsearch-browser": "^15.2.0",
     "encode-uri-query": "1.0.0",
     "even-better": "7.0.2",
+    "execa": "^0.10.0",
     "expiry-js": "0.1.7",
-    "exports-loader": "0.6.2",
-    "expose-loader": "0.7.0",
-    "extract-text-webpack-plugin": "0.8.2",
-    "file-loader": "0.8.4",
-    "flot-charts": "0.8.3",
+    "extract-text-webpack-plugin": "3.0.1",
+    "file-loader": "1.1.4",
     "font-awesome": "4.4.0",
-    "glob": "5.0.13",
-    "glob-all": "3.0.1",
+    "getos": "^3.1.0",
+    "glob": "^7.1.2",
+    "glob-all": "^3.1.0",
     "good-squeeze": "2.1.0",
-    "gridster": "0.5.6",
     "h2o2": "5.1.1",
+    "h2o2-latest": "npm:h2o2@8.1.2",
     "handlebars": "4.0.5",
     "hapi": "14.2.0",
-    "imports-loader": "0.6.4",
+    "hapi-latest": "npm:hapi@17.5.0",
+    "hjson": "3.1.0",
+    "http-proxy-agent": "^2.1.0",
+    "https-proxy-agent": "^2.2.1",
     "inert": "4.0.2",
-    "jade": "1.11.0",
-    "jade-loader": "0.7.1",
     "joi": "10.4.1",
-    "jquery": "2.2.4",
+    "jquery": "^3.3.1",
     "js-yaml": "3.4.1",
-    "json-loader": "0.5.3",
+    "json-stringify-pretty-compact": "1.0.4",
     "json-stringify-safe": "5.0.1",
     "jstimezonedetect": "1.0.5",
     "leaflet": "1.0.3",
     "leaflet-draw": "0.4.10",
     "leaflet-responsive-popup": "0.2.0",
+    "leaflet-vega": "^0.8.6",
     "leaflet.heat": "0.2.0",
     "less": "2.7.1",
-    "less-loader": "2.2.3",
-    "lodash": "3.10.1",
-    "markdown-it": "8.3.2",
-    "minimatch": "2.0.10",
+    "less-loader": "4.0.5",
+    "lodash": "npm:@elastic/lodash@3.10.1-kibana1",
+    "lru-cache": "4.1.1",
+    "markdown-it": "^8.4.1",
+    "minimatch": "^3.0.4",
     "mkdirp": "0.5.1",
-    "moment": "2.13.0",
-    "moment-timezone": "0.5.4",
-    "ngreact": "0.3.0",
+    "moment": "^2.20.1",
+    "moment-timezone": "^0.5.14",
+    "mustache": "2.3.0",
+    "ngreact": "0.5.1",
     "no-ui-slider": "1.2.0",
     "node-fetch": "1.3.2",
+    "opn": "^5.4.0",
     "pegjs": "0.9.0",
-    "postcss-loader": "1.3.3",
+    "postcss-loader": "2.0.6",
     "prop-types": "15.5.8",
     "proxy-from-env": "1.0.0",
-    "pui-react-overlay-trigger": "7.5.4",
-    "pui-react-tooltip": "7.5.4",
+    "pug": "^2.0.3",
     "querystring-browser": "1.0.4",
     "raw-loader": "0.5.1",
-    "react": "15.4.2",
-    "react-ace": "3.7.0",
-    "react-addons-test-utils": "15.4.2",
-    "react-anything-sortable": "1.6.1",
-    "react-color": "2.11.1",
-    "react-dom": "15.4.2",
-    "react-input-autosize": "1.1.0",
-    "react-markdown": "2.4.2",
-    "react-redux": "4.4.5",
-    "react-router": "2.0.0",
-    "react-router-redux": "4.0.4",
-    "react-select": "1.0.0-rc.1",
-    "react-sortable": "1.1.0",
-    "react-toggle": "3.0.1",
-    "reactcss": "1.0.7",
-    "redux": "3.0.0",
-    "redux-thunk": "0.1.0",
-    "request": "2.61.0",
+    "react": "^16.3.0",
+    "react-addons-shallow-compare": "15.6.2",
+    "react-anything-sortable": "^1.7.4",
+    "react-color": "^2.13.8",
+    "react-dom": "^16.3.0",
+    "react-grid-layout": "^0.16.2",
+    "react-input-range": "^1.3.0",
+    "react-markdown": "^3.1.4",
+    "react-markdown": "^3.1.4",
+    "react-redux": "^5.0.7",
+    "react-router-dom": "^4.3.1",
+    "react-sizeme": "^2.3.6",
+    "react-toggle": "4.0.2",
+    "reactcss": "1.2.3",
+    "redux": "4.0.0",
+    "redux-actions": "2.2.1",
+    "redux-thunk": "2.3.0",
+    "regression": "2.0.0",
+    "request": "^2.85.0",
+    "reselect": "^3.0.1",
     "resize-observer-polyfill": "1.2.1",
     "rimraf": "2.4.3",
     "rison-node": "1.0.0",
-    "rjs-repack-loader": "1.0.6",
-    "script-loader": "0.6.1",
-    "semver": "5.1.0",
-    "style-loader": "0.12.3",
+    "rxjs": "^6.2.1",
+    "script-loader": "0.7.2",
+    "semver": "^5.5.0",
+    "style-loader": "0.19.0",
+    "symbol-observable": "^1.2.0",
     "tar": "2.2.0",
     "tinygradient": "0.3.0",
+    "tinymath": "1.1.0",
+    "topojson-client": "3.0.0",
     "trunc-html": "1.0.2",
     "trunc-text": "1.0.2",
+    "ts-optchain": "^0.1.1",
+    "tslib": "^1.9.3",
+    "type-detect": "^4.0.8",
+    "uglifyjs-webpack-plugin": "^1.2.7",
     "ui-select": "0.19.6",
-    "url-loader": "0.5.6",
+    "url-loader": "0.5.9",
     "uuid": "3.0.1",
+    "val-loader": "^1.1.0",
     "validate-npm-package-name": "2.2.2",
+    "vega-lib": "^3.3.1",
+    "vega-lite": "^2.4.0",
+    "vega-schema-url-parser": "1.0.0",
+    "vega-tooltip": "^0.9.14",
     "vision": "4.1.0",
-    "webpack": "github:elastic/webpack#fix/query-params-for-aliased-loaders",
+    "webpack": "3.6.0",
+    "webpack-merge": "4.1.0",
+    "whatwg-fetch": "^2.0.3",
     "wreck": "12.4.0",
+    "x-pack": "link:x-pack",
     "yauzl": "2.7.0"
   },

版本貌似没有变化。。。

那只有在创建的时候手动初始化了:

cache._cache.start(()=>{})

因为不常写node.js,所以来不及深究。本篇只作为一个记录。
但elastic stack现在给我的直观感受是,其代码修改太过自由奔放,换言之就是缺少管制,离一个成熟的商业产品还有不少的路要走。。。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页