介绍

Elasticsearch

Kibana是Elasticsearch的开源数据可视化插件。 它在Elasticsearch集群上索引的内容之上提供可视化功能。 用户可以在大量数据之上创建条形图,折线图和散点图,或饼图和地图。

这两种产品在当今市场上广泛用于数据分析。 但是,安全性是产品最初并未内置的一个方面。 由于数据是当今任何组织的生命线,因此对“ Elasticsearch”和“ Kibana”进行“保护”至关重要。 在此博客文章中,我们将探讨可以为它们实施身份验证,授权和加密的一种方法。

假设条件

本教程假定以下内容:

  1. MapR沙箱正在运行
  2. Elasticsearch和Kibana已安装并正在运行

可用于保护Elasticsearch和Kibana的选项

下表中对保护Elasticsearch和Kibana的最受欢迎的选项进行了比较。

Shield是由开发Elasticsearch的同一家公司开发的安全插件。 它使您可以在简化架构的同时,使用用户名和密码轻松保护此数据。 在需要时,还可以使用高级安全功能,例如加密,基于角色的访问控制,IP过滤和审核。

NGINX是一个开源Web服务器。 它可以充当代理服务器并可以进行负载平衡。 与LUA和外部脚本结合使用,它可以用于保护Elasticsearch和Kibana。 在本教程中,我们将使用这种方法。

Searchguard是Shield的开源替代方案。 除了LDAP身份验证之类的功能外,它几乎提供与Shield相同的所有功能。 但是,这些功能在付费版本中可用。

屏蔽

NGINX

搜索引擎

Elasticsearch制作的适用于Elasticsearch和Kibana的安全插件。

NGINX

Search Guard是一个Elasticsearch插件,提供加密,身份验证和授权。

  1. 会话管理
  2. 加密通讯
  3. 基于角色的访问控制
  4. 审核记录

基于角色的访问控制在LUA模块的帮助下实现。LDAP身份验证可以通过使用外部程序来实现。

免费版本不支持基于LDAP的身份验证或审核日志记录。

$ 1600 /年/组

自由。

NGINX Plus是付费版本– 1900美元/实例

自由。 也提供商业版本。

安装NGINX

NGINX是一个开源Web服务器,专注于高性能,并发性和低内存占用。

NGINX在设计之初就考虑了代理角色,并支持许多相关的配置指令和选项。 我们将使用NGINX设置基于LDAP的身份验证和授权。

OpenResty™是一个完善的Web平台,它集成了标准NGINX内核,LuaJIT,许多精心编写的Lua库,许多高质量的第三方NGINX模块以及它们的大多数外部依赖项。

通过利用各种精心设计的NGINX功能,OpenResty有效地将NGINX服务器转变为功能强大的Web应用程序服务器。

脚步

  1. 从此处下载最新版本的“ OpenResty”:
    http://openresty.org/en/download.html
tar xvf openresty-.tar.gz

cd openresty-

./configure --prefix=/usr/local/openresty --with-luajit  
--with-http_auth_request_module 

gmake

gmake install

export PATH=/usr/local/openresty/bin:/usr/local/openresty/nginx/sbin:$PATH

认证方式

在本教程中,我们将研究以下两种身份验证方法:

  1. 基本HTTP验证
  2. LDAP验证

基本HTTP验证

第1步 -安装Apache工具

您将需要htpassword命令来配置密码,该密码将限制对Elasticsearch和Kibana的访问。 该命令是apache2-utils软件包的一部分,因此第一步是安装该软件包。

sudo apt-get install apache2-utils

第2步 -设置HTTP基本身份验证凭据

在此步骤中,您将为应该被允许访问Elasticsearch和Kibana的用户创建一个密码。 该密码和关联的用户名将存储在您指定的文件中。

密码将被加密,文件名可以是您喜欢的任何名称。 在这里,我们使用文件/opt/elk/.espasswd和用户名vikash

要创建密码,请运行以下命令。 您需要进行身份验证,然后指定并确认密码。

sudo htpasswd -c /opt/elk/.espasswd vikash

您可以检查新创建的文件的内容,以查看用户名和哈希密码。

cat /opt/elk/.espasswd

ES 安全问题_nginx

步骤3 —更新NGINX配置

现在,您已经创建了HTTP基本身份验证凭据,下一步是为Elasticsearch和Kibana更新NGINX配置以使用它。

可以通过auth_basicauth_basic_user_file伪指令实现HTTP基本认证。

auth_basic的值是任何字符串,并将显示在身份验证提示中。 auth_basic_user_file的值是在步骤2中创建的密码文件的路径。这两个指令都应添加在location部分下。

检查是否有任何NGINX进程正在运行并杀死它们:

cd /usr/local/openresty/nginx/
sbin/nginx -s stop

		(Or)

      ps –ef | grep nginx
kill -9 <pid1> <pid2> …. <pidn>

使用以下配置文件启动NGINX服务器:

cd /usr/local/openresty/nginx
sbin/nginx -p $PWD -c conf/nginx_basic_http_authentication.conf

配置文件的内容如下:

worker_processes  1;

error_log /usr/local/openresty/nginx/logs/lua.log debug;

events {
  worker_connections 1024;
}

http {
  upstream elasticsearch {
    server 127.0.0.1:9201;
    keepalive 15;
  }

  upstream kibana {
    server 127.0.0.1:5701;
    keepalive 15;
  }

  server {
    listen 8881;

    location / {
      auth_basic           "Protected Elasticsearch";<
      auth_basic_user_file /opt/elk/.espasswd;


      proxy_pass http://elasticsearch;
      proxy_redirect off;
      proxy_buffering off;

      proxy_http_version 1.1;
      proxy_set_header Connection "Keep-Alive";
      proxy_set_header Proxy-Connection "Keep-Alive";
    }

  }

  server {
    listen 8882;

    location / {
      auth_basic           "Protected Kibana";
      auth_basic_user_file /opt/elk/.espasswd;


      proxy_pass http://kibana;
      proxy_redirect off;
      proxy_buffering off;

      proxy_http_version 1.1;
      proxy_set_header Connection "Keep-Alive";
      proxy_set_header Proxy-Connection "Keep-Alive";
    }

  }

}

下面提供了用户尝试访问Elasticsearch时的屏幕截图。
注意:在此示例中,NGINX配置为侦听端口881以连接到Elasticsearch,并侦听端口8882以连接到Kibana。

屏幕截图显示“ evil_user”无法访问Elasticsearch

ES 安全问题_ES 安全问题_02

由于用户不在密码文件中,因此他/她已再次重定向到“登录”页面。

ES 安全问题_mysql_03

该屏幕快照显示用户“ vikash”有权访问Elasticsearch

ES 安全问题_nginx_04

ES 安全问题_nginx_05

LDAP验证

步骤1:如果LDAP服务器尚未运行,请安装并配置一个。 出于本示例的目的,请按照https://github.com/osixia/docker-openldap上的说明设置LDAP服务器。

由于LDAP服务器在Docker容器上运行,因此以下命令对于重新启动并执行其管理任务非常有用:

docker ps –a –列出所有正在运行的Docker进程

docker exec -it <Docker PID> bash –在Docker机器上打开bash shell

步骤2:就本示例而言,我们将运行一个用Python编写的后端服务器,该服务器提供一个Login页面,以及一个用Python编写的LDAP身份验证守护程序。 Python代码文件在以下GitHub存储库中可用:

https://github.com/nginxinc/nginx-ldap-auth

步骤3:在要运行ldap-auth守护程序的主机上,安装以下附加软件。 我们建议您使用操作系统随附的版本,而不是从开放源存储库下载软件。

  • Python版本2。不支持版本3。
  • python-ldap

步骤4:以下提供的是NGINX Plus配置文件。 重要的指令在这里讨论。

Filename - /usr/local/openresty/nginx/conf/conf/nginx-ldap-auth.conf

error_log logs/error.log debug;

error_log /usr/local/openresty/nginx/logs/lua.log notice;

events { }

http {
    proxy_cache_path cache/  keys_zone=auth_cache:10m;

    # The back-end daemon listens on port 9000 as implemented
    # in backend-sample-app.py.
    # Change the IP address if the daemon is not running on the
    # same host as NGINX/NGINX Plus.
    upstream backend {
        server 127.0.0.1:9000;
    }

    upstream elasticsearch {
        server 127.0.0.1:9200;
    }

    upstream kibana4 {
        server 127.0.0.1:5601;
    }

    # NGINX/NGINX Plus listen on port 8081 for requests that require
    # authentication. Change the port number as appropriate.
    

    server {
        listen 8881;

        # Protected application
        location / {

            auth_request /auth-proxy;

            # redirect 401 and 403 to login form
            error_page 401 403 =200 /login;

       	    auth_request_set $user $upstream_http_LDAPUser;
 
	    access_by_lua_file '/usr/local/openresty/nginx/authorize_es_ldap.lua';
 
	    proxy_pass http://elasticsearch/;
        }



        location /login {
            proxy_pass http://backend/login;
	    # Login service returns a redirect to the original URI
            # and sets the cookie for the ldap-auth daemon
            proxy_set_header X-Target $request_uri;
        }

        location = /auth-proxy {
            internal;

            # The ldap-auth daemon listens on port 8888, as set
            # in nginx-ldap-auth-daemon.py.
            # Change the IP address if the daemon is not running on
            # the same host as NGINX/NGINX Plus.
            proxy_pass http://127.0.0.1:8888;

            proxy_pass_request_body off;
            proxy_set_header X-Target 'http://localhost:9200/'; 
	    #proxy_set_header Content-Length "";
            proxy_cache auth_cache;
            proxy_cache_valid 200 403 10m;

            # The following directive adds the cookie to the cache key
            proxy_cache_key "$http_authorization$cookie_nginxauth";

            # As implemented in nginx-ldap-auth-daemon.py, the ldap-auth daemon
            # communicates with an OpenLDAP server, passing in the following
            # parameters to specify which user account to authenticate. To
            # eliminate the need to modify the Python code, this file contains
            # 'proxy_set_header' directives that set the values of the
            # parameters. Set or change them as instructed in the comments.
            #
            #    Parameter      Proxy header
            #    -----------    ----------------
            #    basedn         X-Ldap-BaseDN
            #    binddn         X-Ldap-BindDN
            #    bindpasswd     X-Ldap-BindPass
            #    cookiename     X-CookieName
            #    realm          X-Ldap-Realm
            #    template       X-Ldap-Template
            #    url            X-Ldap-URL

            # (Required) Set the URL and port for connecting to the LDAP server,
            # by replacing 'example.com' and '636'.
            proxy_set_header X-Ldap-URL      "ldap://172.17.0.1:389";

            # (Required) Set the Base DN, by replacing the value enclosed in
            # double quotes.
            proxy_set_header X-Ldap-BaseDN   "dc=example,dc=org";

            # (Required) Set the Bind DN, by replacing the value enclosed in
            # double quotes.
            proxy_set_header X-Ldap-BindDN   "cn=admin,dc=example,dc=org";

            # (Required) Set the Bind password, by replacing 'secret'.
            proxy_set_header X-Ldap-BindPass "admin";

            # (Required) The following directives set the cookie name and pass
            # it, respectively. They are required for cookie-based
            # authentication. Comment them out if using HTTP basic
            # authentication.
            proxy_set_header X-CookieName "nginxauth";
            proxy_set_header Cookie nginxauth=$cookie_nginxauth;

            # (Required if using Microsoft Active Directory as the LDAP server)
            # Set the LDAP template by uncommenting the following directive.
            #proxy_set_header X-Ldap-Template "(SAMAccountName=%(username)s)";

            # (Optional if using OpenLDAP as the LDAP server) Set the LDAP
            # template by uncommenting the following directive and replacing
            # '(cn=%(username)s)' which is the default set in
            # nginx-ldap-auth-daemon.py.
            #proxy_set_header X-Ldap-Template "(cn=%(username)s)";

            # (Optional) Set the realm name, by uncommenting the following
            # directive and replacing 'Restricted' which is the default set
            # in nginx-ldap-auth-daemon.py.
            #proxy_set_header X-Ldap-Realm    "Restricted";
            
	}
    }



    server {
        listen 8882;

        # Protected application
        location / {

            auth_request /auth-proxy;

            # redirect 401 and 403 to login form
            error_page 401 403 =200 /login;

       	    auth_request_set $user $upstream_http_LDAPUser;
 
	    access_by_lua_file '/usr/local/openresty/nginx/authorize_kibana4_ldap.lua';
 
	    proxy_pass http://kibana4/;
        }



        location /login {
            proxy_pass http://backend/login;
	    # Login service returns a redirect to the original URI
            # and sets the cookie for the ldap-auth daemon
            proxy_set_header X-Target $request_uri;
        }

        location = /auth-proxy {
            internal;

            # The ldap-auth daemon listens on port 8888, as set
            # in nginx-ldap-auth-daemon.py.
            # Change the IP address if the daemon is not running on
            # the same host as NGINX/NGINX Plus.
            proxy_pass http://127.0.0.1:8888;

            proxy_pass_request_body off;
            proxy_set_header X-Target 'http://localhost:5601/'; 
	    #proxy_set_header Content-Length "";
            proxy_cache auth_cache;
            proxy_cache_valid 200 403 10m;

            # The following directive adds the cookie to the cache key
            proxy_cache_key "$http_authorization$cookie_nginxauth";

            # As implemented in nginx-ldap-auth-daemon.py, the ldap-auth daemon
            # communicates with an OpenLDAP server, passing in the following
            # parameters to specify which user account to authenticate. To
            # eliminate the need to modify the Python code, this file contains
            # 'proxy_set_header' directives that set the values of the
            # parameters. Set or change them as instructed in the comments.
            #
            #    Parameter      Proxy header
            #    -----------    ----------------
            #    basedn         X-Ldap-BaseDN
            #    binddn         X-Ldap-BindDN
            #    bindpasswd     X-Ldap-BindPass
            #    cookiename     X-CookieName
            #    realm          X-Ldap-Realm
            #    template       X-Ldap-Template
            #    url            X-Ldap-URL

            # (Required) Set the URL and port for connecting to the LDAP server,
            # by replacing 'example.com' and '636'.
            proxy_set_header X-Ldap-URL      "ldap://172.17.0.1:389";

            # (Required) Set the Base DN, by replacing the value enclosed in
            # double quotes.
            proxy_set_header X-Ldap-BaseDN   "dc=example,dc=org";

            # (Required) Set the Bind DN, by replacing the value enclosed in
            # double quotes.
            proxy_set_header X-Ldap-BindDN   "cn=admin,dc=example,dc=org";

            # (Required) Set the Bind password, by replacing 'secret'.
            proxy_set_header X-Ldap-BindPass "admin";

            # (Required) The following directives set the cookie name and pass
            # it, respectively. They are required for cookie-based
            # authentication. Comment them out if using HTTP basic
            # authentication.
            proxy_set_header X-CookieName "nginxauth";
            proxy_set_header Cookie nginxauth=$cookie_nginxauth;

            # (Required if using Microsoft Active Directory as the LDAP server)
            # Set the LDAP template by uncommenting the following directive.
            #proxy_set_header X-Ldap-Template "(SAMAccountName=%(username)s)";

            # (Optional if using OpenLDAP as the LDAP server) Set the LDAP
            # template by uncommenting the following directive and replacing
            # '(cn=%(username)s)' which is the default set in
            # nginx-ldap-auth-daemon.py.
            #proxy_set_header X-Ldap-Template "(cn=%(username)s)";

            # (Optional) Set the realm name, by uncommenting the following
            # directive and replacing 'Restricted' which is the default set
            # in nginx-ldap-auth-daemon.py.
            #proxy_set_header X-Ldap-Realm    "Restricted";
            
	}
    }

}

LDAP设定

# URL and port for connecting to the LDAP server
# Use “ldaps://< IP Address of the LDAP Server >:636” if you are using secure LDAP
proxy_set_header X-Ldap-URL "ldap://< IP Address of the LDAP Server > ";

# Base DN
proxy_set_header X-Ldap-BaseDN "cn=admin,dc=example,dc=org";

# Bind DN
proxy_set_header X-Ldap-BindDN "cn=admin,dc=example,dc=org";

# Bind password
proxy_set_header X-Ldap-BindPass "admin";


IP Address for Backend Daemon

If the backend daemon is not running on the same host as NGINX Plus, change the IP address for it in the upstream configuration block:

upstream backend {
    server 127.0.0.1:9000;
 }

IP Address for ldap-auth Daemon

If the ldap-auth daemon is not running on the same host as NGINX Plus, change the IP address in this proxy_pass directive:

location = /auth-proxy {
    proxy_pass http://127.0.0.1:8888;
    ...
}

IP Address and Port on Which NGINX Listens

If the client is not running on the same host as NGINX Plus, change the IP address in this listen directive (or remove the address completely to accept traffic from any client). You can also change the port on which NGINX listens from 8081 if you wish:

server {
    listen 127.0.0.1:8081;         
    …
 }

注意:

步骤5:启动NGINX服务器,后端和LDAP身份验证守护程序:

检查是否有任何NGINX服务器进程已在运行并杀死它们:

cd /usr/local/openresty/nginx/
 sbin/nginx -s stop

		(Or)

 ps –ef | grep nginx
kill -9 <pid1> <pid2> …. <pidn>

使用相应的配置文件启动NGINX服务器:

cd  /usr/local/openresty/nginx/
sbin/nginx -p $PWD -c conf/nginx-ldap-auth.conf

启动后端服务器:

cd  /usr/local/openresty/nginx-ldap-auth
python backend-sample-app.py

启动LDAP认证守护程序:

cd  /usr/local/openresty/nginx-ldap-auth
python nginx-ldap-auth-daemon.py

下面的屏幕截图显示了后端,LDAP认证守护程序和尝试访问Elasticsearch的浏览器的输出。

  1. 尝试使用无效的凭证访问Elasticsearch
    ES 安全问题_linux_06
  2. LDAP身份验证守护程序显示身份验证失败(拖动图像在底角以获得更清晰的视图)。
    ES 安全问题_ES 安全问题_07
  3. 尝试通过提供有效的凭证来访问Elasticsearch
    ES 安全问题_linux_08
  4. 身份验证成功后,Web浏览器将重定向到Elasticsearch
    ES 安全问题_linux_09
  5. CURL请求的LDAP认证
    ES 安全问题_linux_10

授权书

我们将展示如何实现以下授权方法:

  1. 基于LUA脚本的访问控制
  2. 适用于不同Elasticsearch / Kibana实例的多级安全性

使用LUA脚本进行访问控制

“ access_by_lua_file”指令用于指定LUA文件的路径,该文件控制对Elasticsearch中特定资源的访问。

以下是一个示例LUA脚本,该脚本显示了如何仅允许用户“ vikash”访问索引“ traffic”并限制用户“ swapnil”。

-- authorization rules
 
local restrictions = {
  all  = {
    ["^/$"]                             = { "HEAD" }
  },
 
  swapnil = {
    ["^/$"]                             = { "GET" },
    ["^/?[^/]*/?[^/]*/_search"]         = { "GET", "POST" },
    ["^/?[^/]*/?[^/]*/_msearch"]        = { "GET", "POST" },
    ["^/?[^/]*/?[^/]*/_validate/query"] = { "GET", "POST" },
    ["/_aliases"]                       = { "GET" },
    ["/_cluster.*"]                     = { "GET" }
  },
  vikash = {
    ["^/$"]                             = { "GET" },
    ["^/?[^/]*/?[^/]*/_search"]         = { "GET", "POST" },
    ["^/?[^/]*/?[^/]*/_msearch"]        = { "GET", "POST" },
    ["^/?[^/]*/traffic*"]               = { "GET", "POST", "PUT", "DELETE" },
    ["^/?[^/]*/?[^/]*/_validate/query"] = { "GET", "POST" },
    ["/_aliases"]                       = { "GET" },
    ["/_cluster.*"]                     = { "GET" }
  },
 
  admin = {
    ["^/?[^/]*/?[^/]*/_bulk"]          = { "GET", "POST" },
    ["^/?[^/]*/?[^/]*/_refresh"]       = { "GET", "POST" },
    ["^/?[^/]*/?[^/]*/?[^/]*/_create"] = { "GET", "POST" },
    ["^/?[^/]*/?[^/]*/?[^/]*/_update"] = { "GET", "POST" },
    ["^/?[^/]*/?[^/]*/?.*"]            = { "GET", "POST", "PUT", "DELETE" },
    ["^/?[^/]*/?[^/]*$"]               = { "GET", "POST", "PUT", "DELETE" },
    ["/_aliases"]                      = { "GET", "POST" }
  }
}
 
-- get authenticated user as role
local role = ngx.var.remote_user
ngx.log(ngx.DEBUG, role)
 
-- exit 403 when no matching role has been found
if restrictions[role] == nil then
  ngx.header.content_type = 'text/plain'
  ngx.log(ngx.WARN, "Unknown role ["..role.."]")
  ngx.status = 403
  ngx.say("403 Forbidden: You don\'t have access to this resource.")
  return ngx.exit(403)
end
 
-- get URL
local uri = ngx.var.uri
ngx.log(ngx.DEBUG, uri)
 
-- get method
local method = ngx.req.get_method()
ngx.log(ngx.DEBUG, method)
 
local allowed  = false
 
for path, methods in pairs(restrictions[role]) do
 
  -- path matched rules?
  local p = string.match(uri, path)
 
  local m = nil
 
  -- method matched rules?
  for _, _method in pairs(methods) do
    m = m and m or string.match(method, _method)
  end
 
  if p and m then
    allowed = true
    ngx.log(ngx.NOTICE, method.." "..uri.." matched: "..tostring(m).." "..tostring(path).." for "..role)
    break
  end
end
 
if not allowed then
  ngx.header.content_type = 'text/plain'
  ngx.log(ngx.WARN, "Role ["..role.."] not allowed to access the resource ["..method.." "..uri.."]")
  ngx.status = 403
  ngx.say("403 Forbidden: You don\'t have access to this resource.")
  return ngx.exit(403)
end
cd /usr/local/openresty/nginx/
 sbin/nginx -s stop

		(Or)

 ps –ef | grep nginx
kill -9 <pid1> <pid2> …. <pidn>

使用以下配置启动NGINX服务:

cd /usr/local/openresty/nginx/
sbin/nginx -p $PWD -c conf/nginx_authorize_by_lua.conf

屏幕快照显示访问被拒绝访问用户“ swapnil”的“流量”索引

网址: http:// localhost:8881
ES 安全问题_nginx_11

ES 安全问题_linux_12

屏幕快照显示用户“ swapnil”能够访问“流量”以外的其他资源
ES 安全问题_mysql_13

屏幕快照显示用户“ vikash”有权访问“流量”索引
ES 安全问题_linux_14
ES 安全问题_ES 安全问题_15

多级安全(MLS)

上述方法的问题在于我们无法为Kibana复制该过程。 Kibana从Elasticsearch获取所有数据,并在内部重写所有URL,因此我们不再知道什么是URL,因此无法为其编写规则。

在这种情况下,最好使用MLS方法。 因此,我们将拥有三个不同的Elasticsearch和Kibana实例,每个实例对应不同的权限级别,从而解决了授权问题。 这些实例的身份验证可以是基本HTTP身份验证,也可以是基于LDAP的身份验证。

步骤1:设置多个Elasticsearch(ES)实例,并向最终用户公开一个公共URL。 在这种情况下,它被设置为http:// localhost:8081 。

在此实验中,设置了三个Elasticsearch实例,每个实例侦听本地计算机上的另一个端口。

ES Node 1 – http://localhost:9201
ES Node 2 – http://localhost:9202
ES Node 3 – http://localhost:9203

创建三个不同的Elasticsearch配置文件,每个这些实例一个,然后使用以下命令运行它们:

ES_HOME=/opt/elk/elasticsearch-1.4.4/

nohup $ES_HOME/bin/elasticsearch \
-Des.config=$ES_HOME/config/elasticsearch_node1.yml >>  /tmp/elasticsearch_node1.out \ 2>&1 &

nohup $ES_HOME/bin/elasticsearch \
-Des.config=$ES_HOME/config/elasticsearch_node2.yml >>  /tmp/elasticsearch_node2.out \ 2>&1 &

nohup $ES_HOME/bin/elasticsearch \
-Des.config=$ES_HOME/config/elasticsearch_node3.yml >>  /tmp/elasticsearch_node3.out \ 2>&1 &

在资源部分中提供了Elasticsearch的示例配置文件。 该文件的名称为:

/opt/elk/elasticsearch-1.4.4/config/elasticsearch_node1.yml

第2步:设置Kibana的多个实例,每个许可级别一个,并为最终用户公开一个URL; 在这种情况下,它设置为http:// localhost:8082 。

对于此实验,设置了三个Kibana实例,每个实例都侦听本地计算机上对应于不同清除级别的不同端口。

Kibana Node 1 – http://localhost:5701 - Top Secret – Connects to ES Node 1
Kibana Node 2 – http://localhost:5702 - Secret – Connects to ES Node 2
Kibana Node 3 – http://localhost:5703 - Public – Connects to ES Node 3

使用以下命令运行它们:

nohup /opt/elk/kibana_nodes/kibana_node1/bin/kibana > /tmp/kibana_node1.out 2>&1 &
nohup /opt/elk/kibana_nodes/kibana_node2/bin/kibana > /tmp/kibana_node2.out 2>&1 &
nohup /opt/elk/kibana_nodes/kibana_node3/bin/kibana > /tmp/kibana_node3.out 2>&1 &

参考资料部分提供了Kibana的示例配置文件。 该文件的名称为:

/opt/elk/kibana_nodes/kibana_node1/config/kibana.yml

步骤3:设置NGINX代理,以侦听与Elasticsearch(ES)或Kibana的连接(NGINX将在http:// localhost:8081侦听与ES的连接,而http:// localhost:8082侦听与Kibana的连接)。 请查看zip文件中的“ Installing NGINX and LDAP Authentication.docx”文件,以获取有关如何进行设置的逐步说明。

根据LDAP数据库对用户进行身份验证,并基于从数据库中读取的信息检查他/她具有的授权级别(在这种情况下,使用了包含用户列表和授权级别的本地文件),并将用户重定向到适当的Elasticsearch / Kibana服务器。

LDAP服务器–在Docker容器上运行( https://github.com/osixia/docker-openldap

用户角色数据库–该文件在资源部分中提供(文件名–“ user_authorization_level.dat”)

NGINX配置文件–该文件在资源部分中提供(文件名–“ nginx-ldap-auth-clusters.conf”)

Python守护程序来检查LDAP服务器(文件名“ nginx-ldap-auth-daemon.py”)

Python后端登录表单(文件名“ backend-sample-app.py”)

以上两个Python文件都可以在以下网址找到:https://github.com/nginxinc/nginx-ldap-auth

步骤4:如下所示启动NGINX服务器:

检查是否有任何NGINX服务器进程已在运行并杀死它们:

cd /usr/local/openresty/nginx/
 sbin/nginx -s stop

		(Or)

 ps –ef | grep nginx
kill -9 <pid1> <pid2> …. <pidn>

启动后端服务器:

cd  /usr/local/openresty/nginx-ldap-auth
python backend-sample-app.py

启动LDAP认证守护程序:

cd  /usr/local/openresty/nginx-ldap-auth
python nginx-ldap-auth-daemon.py

检查是否有任何NGINX服务器进程已在运行并杀死它们:

cd /usr/local/openresty/nginx/
sbin/nginx -s stop

		(Or)

ps –ef | grep nginx
kill -9 <pid1> <pid2> …. <pidn>

使用相应的配置文件启动NGINX服务器:

cd /usr/local/openresty/nginx/
sbin/nginx -p $PWD -c conf/nginx-ldap-auth-clusters.conf

屏幕截图:

用户“ admin”已登录,并且他具有“最高机密”清除级别。 与此对应的Kibana服务器是http:// localhost:5701 ,该服务器连接到Elasticsearch服务器http:// localhost:9201 ,其中只有索引“ shakespeare”。

ES 安全问题_ES 安全问题_16

Elasticsearch显示只有“莎士比亚”索引可用

ES 安全问题_mysql_17

ES 安全问题_java_18

ES 安全问题_nginx_19

管理员具有“ 最高机密

ES 安全问题_ES 安全问题_20

用户“ vikash”已登录,并且其权限级别为“秘密”。 与此对应的Kibana服务器是http:// localhost:5702 ,该服务器连接到其中具有索引“ logstash *”的Elasticsearch服务器http:// localhost:9202 。

ES 安全问题_nginx_21

Elasticsearch显示只有“ logstash *”索引可用

ES 安全问题_nginx_22

ES 安全问题_nginx_23

ES 安全问题_java_24

vikash仅具有秘密

ES 安全问题_java_25

用户“ swapnil”已登录,并且具有“公共”许可等级。 与此相对应的Kibana服务器是http:// localhost:5703 ,该服务器连接到其中只有索引“ bank”的Elasticsearch服务器http:// localhost:9203 。

ES 安全问题_java_26

Elasticsearch显示只有“银行”索引可用

ES 安全问题_nginx_27

ES 安全问题_nginx_28

ES 安全问题_mysql_29

swamnil仅具有公共

ES 安全问题_mysql_30
注意:所有索引映射和数据都是从以下位置下载的
https://www.elastic.co/guide/zh/kibana/current/getting-started.html

加密

如果您仔细地注意到,您可能会发现到目前为止我们只使用了“ http”。 在生产环境中,我们经常要使用“ https”,因为这会加密所有数据并防止攻击者窃取信息。 下面的教程将引导您完成使用“ https”协议所需的步骤。

步骤1:创建自签名SSL证书。

cd /usr/local/openresty/nginx

mkdir certs

cd certs

openssl genrsa 2048 > host.key

openssl req -new -x509 -nodes -sha1 -days 3650 -key host.key > host.cert

openssl x509 -noout -fingerprint -text < host.cert > host.info

cat host.cert host.key > host.pem

步骤2:将与证书相关的信息添加到NGINX配置文件中。

ssl on;
  ssl_certificate /usr/local/openresty/nginx/certs/host.cert;
  ssl_certificate_key /usr/local/openresty/nginx/certs/host.key;
  ssl_session_timeout 5m;
  ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  ssl_ciphers HIGH:!aNULL:!eNULL:!LOW:!MD5;
  ssl_prefer_server_ciphers on;

注意:以下提供了整个NGINX配置文件供您参考。


NGINX侦听端口8080以连接到ES,并实现基本HTTP身份验证

NGINX配置文件

worker_processes  1;

error_log /usr/local/openresty/nginx/logs/nginx_https.log debug;

events {
  worker_connections 1024;
}

http {

	upstream elasticsearch {
  		server 127.0.0.1:9200;
  		keepalive 15;
	}

	server {
  		listen 8080;
  		keepalive_timeout   60s;
  		ssl on;
  		ssl_certificate /usr/local/openresty/nginx/certs/host.cert;
  		ssl_certificate_key /usr/local/openresty/nginx/certs/host.key;
  		ssl_session_timeout 1m;
  		ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  		ssl_ciphers HIGH:!aNULL:!eNULL:!LOW:!MD5;
  		ssl_prefer_server_ciphers on;

  		auth_basic "ElasticSearch";
  		auth_basic_user_file /opt/elk/.espasswd;

  		location / {
    			proxy_pass http://elasticsearch;
    			proxy_http_version 1.1;
    			proxy_set_header Connection "Keep-Alive";
    			proxy_set_header Proxy-Connection "Keep-Alive";
  		}
	}
}

由于这是一个自签名证书,因此您将看到一个被划掉的“红色” https图标。 如果您使用来自受信任的第三方(如Verisign)的证书,则会看到它变成“绿色”图标。

在此博客文章中,您了解了可以为Elasticsearch和Kibana实施身份验证,授权和加密的一种方法。 如有任何疑问,请在下面的评论部分中提问。

翻译自: https://www.javacodegeeks.com/2016/09/secure-elasticsearch-kibana.html