使用Cookie进行iFraming Kibana仪表板时出现TOO_MANY_REDIRECTS错误

时间:2019-02-10 16:00:36

标签: node.js express elasticsearch kibana elasticsearch-x-pack

我正在根据this thread中的信息,尝试将受密码保护的Kibana仪表板嵌入到iNode中的Node Express Express应用程序中。 Kibana受X-Pack保护,要求用户登录才能查看其可视化数据。

当前,这要求用户登录两次,一次登录到应用程序,再一次访问Kibana仪表板,这不是目标。

根据该线程中的信息,我实现了一些代码,向https://elk-stack.my.domain:5601/api/security/v1/login发出飞行前POST请求以获取Cookie

此客户端请求...

function preFlightKibanaAuth () {
    ...
    $.ajax({
      type: 'POST',
      url: '/kibana-auth',
      datatype: 'json',
      success: function (response) {
        if (response && response.authenticated) {
          $('iframe#kibana-dashboard').prop('src', 'https://elk-stack.my.domain:5601/s/spacename/app/kibana#/dashboards?_g=()')
        }
      },
      error: function (err) {
        console.log(err)
      }
    })
  }

已路由到此路线...

router
  .route('/kibana-auth')
  .post((req, res, next) => {
    ... 
    if (authorised) {
      ...
      authenticateKibana(req)
          .then(cookie => {
            if (cookie && cookie.name && cookie.value) {
              res.set('Set-Cookie', `${cookie.name}=${cookie.value}; Domain=my.domain; Path=/; Secure; HttpOnly`)
              res.send({ 'authenticated': true })
            } else {
              res.send({ 'authenticated': false })
            }
          })
          .catch((err) => {
            logger.error(err)
            res.send({ 'authenticated': false })
          })
    }
    ...
  })

此功能的实现方式,实际上是在其中获取并解析Cookie的...

authenticateKibana () {
    return new Promise((resolve, reject) => {
      ...
      request({
        method: 'POST',
        uri: `https://elk-stack.my.domain:5601/api/security/v1/login`,
        headers: {
          'kibana-version': '6.5.4',
          'kibana-xsrf': 'xsrftoken',    
        },
        type: 'JSON',
        form: {
          password: 'validPassword',
          username: 'validUsername'
        }
      }, function (error, res, body) {
        if (!error) {
          let cookies = cookieParser.parse(res)
          cookies.forEach(function (cookie) {
            if (cookie.name.startsWith('kibana')) {
              // Got Kibana Cookie
              return resolve(cookie)
            }
          })
        } 
        ... 
      })
    })
  }

这很好用,我可以通过Kibana成功进行身份验证,获取cookie并在客户端浏览器中进行设置(请参见下面的屏幕截图)。

enter image description here

我看到的问题是在src请求的成功回调中更新iFrame的preFlightKibanaAuth()时。我可以短暂看到已认证的Kibana仪表板加载(因此cookie 允许客户端查看其已认证的仪表板),但是,随后我看到对/login?next=%2Fs%2Fspacename%2Fapp%2Fkibana的多个GET请求,结果是TOO_MANY_REDIRECTS错误。

我在GitHub issues page中找到了以下注释,我认为这可能是我遇到的问题,因为我在日志中看到了此问题(请参阅底部):"message":"Found 2 auth sessions when we were only expecting 1." 。我只是想不通!

  

通常是什么原因导致相同的多个Cookie   “域”和“名称”,但“路径”具有不同的值。如果你打开   Chrome中的开发人员工具,然后单击“应用程序”标签,然后   展开Cookies部分,然后单击域,您是否   多个名称为“ sid”的cookie?如果是这样,您可以通过以下方式解决此问题:   清除所有这些。

我将cookie名称从“ sid”更改为“ kibana”,但在“应用程序”选项卡中看不到其中的两个,只有在调用/kibana-auth之后设置的一个。

然后将iFrame加载到https://elk-stack.my.domain:5601/s/spacename/app/kibana#/dashboards?_g=()中,并出现问题。清除我的cookie只会导致获取并设置另一个cookie(如果我们还没有),这是必需的,因此这并不能解决问题。

当我将Set-Cookie标头发送回客户端时,我正在将Domain设置为主域my.domain,其最终为.my.domain。 Kibana实例位于一个子域elk-stack.my.domain上,如果我登录到Kibana前端,则可以看到返回的cookie it Domain设置为{{ 1}}。我不确定那是否应该重要。

任何人都可以对此进行说明或向我指出方向吗?

预先感谢

以下是elk-stack.my.domain发出请求时的日志信息。那里仍然有一些垃圾,但您仍然可以看到发生了什么。

/var/log/kibana/kibana.stdout

下面的内容一遍又一遍地重复...

{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["debug","security","basic"],"pid":7857,"message":"Trying to authenticate user request to /api/security/v1/login."}
{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["debug","security","basic"],"pid":7857,"message":"Trying to authenticate via header."}
{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["debug","security","basic"],"pid":7857,"message":"Request has been authenticated via header."}
{"type":"response","@timestamp":"2019-02-12T19:47:44Z","tags":[],"pid":7857,"method":"post","statusCode":204,"req":{"url":"/api/security/v1/login","method":"post","headers":{"kibana-version":"6.5.4","kbn-xsrf":"6.5.4","host":"10.30.10.30:5601","content-type":"application/
x-www-form-urlencoded","content-length":"35","connection":"close"},"remoteAddress":"192.168.56.102","userAgent":"192.168.56.102"},"res":{"statusCode":204,"responseTime":109,"contentLength":9},"message":"POST /api/security/v1/login 204 109ms - 9.0B"}
{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["debug","legacy","proxy"],"pid":7857,"message":"Event is being forwarded: connection"}
{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["trace","legacy","service"],"pid":7857,"message":"Request will be handled by proxy GET:/s/spacename/app/kibana."}
{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["warning","security","auth","session"],"pid":7857,"message":"Found 2 auth sessions when we were only expecting 1."}
{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["debug","security","basic"],"pid":7857,"message":"Trying to authenticate user request to /app/kibana."}
{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["debug","security","basic"],"pid":7857,"message":"Trying to authenticate via header."}
{"type":"log","@timestamp":"2019-02-12T19:47:44Z","tags":["debug","security","basic"],"pid":7857,"message":"Authorization header is not presented."}
{"type":"response","@timestamp":"2019-02-12T19:47:44Z","tags":[],"pid":7857,"method":"get","statusCode":302,"req":{"url":"/app/kibana","method":"get","headers":{"host":"elk-stack.my.domain:5601","connection":"keep-alive","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8","referer":"https://local.local.my.domain/fortigate/reporting/dashboard","accept-encoding":"gzip, deflate, br","accept-language":"en-GB,en;q=0.9,en-US;q=0.8,la;q=0.7,fr;q=0.6"},"remoteAddress":"192.168.56.102","userAgent":"192.168.56.102","referer":"https://local.local.my.domain/fortigate/reporting/dashboard"},"res":{"statusCode":302,"responseTime":3,"contentLength":9},"message":"GET /app/kibana 302 3ms - 9.0B"}
{"type":"log","@timestamp":"2019-02-12T19:47:45Z","tags":["debug","legacy","proxy"],"pid":7857,"message":"Event is being forwarded: connection"}
{"type":"log","@timestamp":"2019-02-12T19:47:45Z","tags":["debug","legacy","proxy"],"pid":7857,"message":"\"getConnections\" has been called."}
{"type":"ops","@timestamp":"2019-02-12T19:47:45Z","tags":[],"pid":7857,"os":{"load":[0.2568359375,0.31640625,0.3173828125],"mem":{"total":33567580160,"free":346796032},"uptime":1585351},"proc":{"uptime":33636.577,"mem":{"rss":322772992,"heapTotal":225566720,"heapUsed":184707176,"external":2052484},"delay":6.417333126068115},"load":{"requests":{"5601":{"total":2,"disconnects":0,"statusCodes":{"204":1,"302":1}}},"concurrents":{"5601":1},"responseTimes":{"5601":{"avg":56,"max":109}},"sockets":{"http":{"total":0},"https":{"total":0}}},"message":"memory: 176.2MB uptime: 9:20:37 load: [0.26 0.32 0.32] delay: 6.417"}
{"type":"log","@timestamp":"2019-02-12T19:47:45Z","tags":["debug","monitoring-ui","kibana-monitoring"],"pid":7857,"message":"Received Kibana Ops event data"}
{"type":"log","@timestamp":"2019-02-12T19:47:45Z","tags":["debug","monitoring-ui","kibana-monitoring"],"pid":7857,"message":"Received Kibana Ops event data"}
{"type":"log","@timestamp":"2019-02-12T19:47:45Z","tags":["trace","legacy","service"],"pid":7857,"message":"Request will be handled by proxy GET:/login?next=%2Fs%2Fspacename%2Fapp%2Fkibana."}
{"type":"response","@timestamp":"2019-02-12T19:47:45Z","tags":[],"pid":7857,"method":"get","statusCode":302,"req":{"url":"/login?next=%2Fs%2Fspacename%2Fapp%2Fkibana","method":"get","headers":{"host":"elk-stack.my.domain:5601","connection":"keep-alive","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8","referer":"https://local.local.my.domain/fortigate/reporting/dashboard","accept-encoding":"gzip, deflate, br","accept-language":"en-GB,en;q=0.9,en-US;q=0.8,la;q=0.7,fr;q=0.6"},"remoteAddress":"192.168.56.102","userAgent":"192.168.56.102","referer":"https://local.local.my.domain/fortigate/reporting/dashboard"},"res":{"statusCode":302,"responseTime":2,"contentLength":9},"message":"GET /login?next=%2Fs%2Fspacename%2Fapp%2Fkibana 302 2ms - 9.0B"}
{"type":"log","@timestamp":"2019-02-12T19:47:45Z","tags":["debug","legacy","proxy"],"pid":7857,"message":"Event is being forwarded: connection"}

Kibana版本:6.5.4

Elasticsearch:6.5.4

1 个答案:

答案 0 :(得分:0)

起初,我以为这一切都是因为Cookie属性不匹配,,,不是!

从Elastic团队那里收到了一些信息...

  

Kibana回复的Cookie通常设置httpOnly标志,   和安全标志(通过https托管时),以及   域。如果您所使用的Cookie的任何设置不同   试图强迫Kibana使用,您会看到2个Cookie正在提交   和行为与您所看到的类似。

以为我为cookie设置了不同的属性,但是并没有...最终使用了一个插件来解决这个问题:https://readonlyrest.com/