亚马逊AWS官方博客
在 AWS 中国区对 Amazon Elasticsearch Kibana 进行身份认证的解决方案
概述
Kibana 是一种流行的开源可视化工具,专为与 Elasticsearch 结合使用而设计。Amazon ES 为每个 Amazon ES 域默认安装 Kibana。目前ES内置的Kibana不支持IAM,对于Kibana的访问控制主要有两个方面:在VPC内访问可以通过安全组进行控制,在VPC外访问可以通过结合Amazon Cognito的User Pool和Identity Pool来进行身份验证或者使用基于IP的策略。
由于AWS中国区目前还不支持Cognito User Pool,因此需要在VPC外进行公开访问只能通过基于IP的策略来进行控制。当需要访问ES Kibana的员工发生变化或者人数变多时,基于IP的策略进行管理控制就显得不那么方便了。因此我们可以用一个Nginx服务器作为中间代理,将这台Nginx的IP加入Kibana的访问策略中,客户端通过Nginx的反向代理来访问Kibana,而关于身份验证的部分在Nginx上实现。
基于以上分析,关于中国区Amazon Elaticsearch Kibana身份验证问题,提出了用Nginx作为代理并且在Nginx做身份验证的三种解决方案。关于每个方案的具体架构和原理以及适用场景分析具体查看通篇博文。
- 方案一:使用 Nginx 作为代理,做 HTTP 基本认证,实现简单但是安全系数不高。
- 方案二:使用 Nginx 作为代理,做 OIDC 认证(这里以 Okta 为例),使用免费版本 Nginx 即可实现 OAuth 和 OIDC 后端认证。
- 方案三:使用 Nginx plus 作为代理,以 Okta 为 Idp 做 OIDC 认证,使用付费版本 Nginx Plus 实现 OIDC 后端认证。
前提条件
本博文下三个方案的演示都在AWS中国宁夏区域完成。在方案开始之前,请准备好以下AWS基本环境:
- 在AWS中国区创建一个 Elasticsearch 域,在步骤3“配置访问和安全”中的网络配置选择 “公有访问权限”,在访问配置中选择 “允许对域进行公开访问”,如下图所示。
- 在AWS中国区公有子网下启动一台带公有IP的 EC2 Linux,本博客起的是Amazon Linux 2,安全组的入站规则打开80端口(中国区需要备案才能使用80端口)。
方案一:在Nginx上做HTTP基本认证
利用Nginx的auth_basic模块,也就是HTTP Basic Authentication,是HTTP服务器对WEB浏览器进行基本身份认证的方法。
原理
当客户端向HTTP服务器进行数据请求时,如果客户端未被认证,则HTTP服务器将通过基本认证过程对客户端的用户名及密码进行验证,以决定用户是否合法。客户端在接收到HTTP服务器的身份验证要求后,会提示用户输入用户名密码,然后将用户名密码以BASE64加密,加密后的密文将附加于请求信息。并于每次请求数据时,将密文附加于请求头(Request Header)中。HTTP服务器在每次收到请求包后,根据协议取得客户端附加的用户信息(BASE64加密的用户名和密码),解开请求包,对用户名及密码进行验证。
优缺点
优点:提供简单的用户认证功能,其实现和认证过程都简单明了,适合于对安全要求不高的系统
缺点:
- 没有灵活可靠的认证策略,如无法提供域认证功能
- BASE64的加密强度非常低,可以说仅能防止搜索引擎将其搜到
- 没有统一可以进行用户管理的地方
实现过程
在EC2上安装Nginx
使用以下内容直接覆盖Nginx的配置文件/etc/nginx/nginx.conf
修改文件 /etc/nginx/conf.d/default.conf 为以下内容,主要修改两个参数:其中 “EC2_pulicDNS” 为EC2的公有DNS,可以在AWS EC2控制台中查看;“ES_Kibana_url” 为 Elasticsearch Service 中 Kibana 的 url,可以在 Elasticsearch Service 创建的域控制台上查看。
修改完配置文件后使用以下命令重启Nginx
如下图所示在AWS的Elasticsearch控制台修改 domain的访问策略,加上Nginx也就是EC2的公有IP
测试
直接访问EC2的公有DNS,会跳出HTTP基本认证的弹框,使用httpd-tools生成kibana-admin账号的密码登录后就会自动跳转到ES Kibana界面。
方案二:在Nginx上做OIDC认证(以Okta为例)
基础
- Nginx auth_request:模块位于Internet和Nginx将请求传递到的后端服务器之间,并且每当有请求进入时,它首先将请求转发到单独的服务器以检查用户是否已通过身份验证,并使用HTTP响应来决定是否允许请求继续到后端。
- Vouch:Nginx的auth_request模块没有用户或对任何人进行身份验证的概念,因此在这里我们还需要选择一个身份验证代理,开实际处理登录用户的内容,负责处理HTTP请求,并且根据用户是否登录来返回HTTP 200或者401,如果用户未登录,则需要知道如何让他们登录并且设置会话cookie。Vouch是用Go编写的,可以为Vouch配置OAuth和OpenID Connect后端对用户进行身份验证。
- Okta:Okta是一个符合OAuth和OIDC的标准身份认证服务,可以进行用户管理,实现SSO和MFA等,在这里作为一个标准的OIDC提供商
架构和原理
方案二的架构和原理如下图所示,在本实例中,kibana.stats.beckyhome.cn为Nginx服务器也就是用户访问Kibana的域名, kibana.login.beckyhome.cn 为Vouch服务器也就是中间做认证跳转的域名,在这里两个域名都指向EC2的公有IP。本博文使用Amazon Route53进行DNS管理。您需要将这两个域名替换成自己的域名,并使用Route53或者您自己的DNS服务将域名指向EC2的公有IP(测试情况下公开访问也需要指定)。
- 终端用户访问 http://kibana.stats.beckyhome.cn
- Nginx反向代理
- 收到用户对 kibana.stats.beckyhome.cn的请求
- 使用auth_request模块配置路径/vouch_validate
- /vouch_validate通过proxy_pass向http://kibana.stats.beckyhome.cn/validate请求验证
- 如果/vouch_validate为 200 OK,成功返回
- 如果/vouch_validate为 401 NotAuthorized,302重定向到http://kibana.login.beckyhome.cn/login?url=http://kibana.stats.beckyhome.cn
- vouch /vouch_validate验证过程
- 从Nginx的proxy_pass收到kibana.stats.beckyhome.cn的请求
- 寻找包含JWT的名为“oursitesSSO”的cookie
- cookie找到,并且JWT有效:返回200给Nginx,允许访问(用户无感知)
- cookie没找到,或者KWT无效:返回401 NotAuthorized给Nginx
- 请求转发给 https://kibana.login.beckyhome.cn/login?url=https://kibana.stats.beckyhome.cn
- 清除名为“oursitesSSO”的cookie(如果存在)
- 生成一个随机数并将其存储在会话变量$STATE中
- 将http://kibana.login.beckyhome.cn查询字符串中的url存储在会话变量$ requestedURL中
- 使用302重定向Okta的OIDC登录表单(包括$STATE随机数)回给用户
- Okta验证
- 用户在okta表单输入用户名和密码登录
- okat验证后,将用户重定向回$requestedURL
- 请求转发到ES Kibana
- 前面Nginx的auth_request验证通过后,请求重定向到Elasticsearch Kibana的url
优缺点
优点:
- 使用免费社区版Nginx即可
- 支持各个标准的OAuth和OIDC后端认证(包括Google,Facebook,Github,Amazon Cognito,Okta等)
- 可以灵活得进行用户和权限的控制
缺点:需要安装第三方开源工具Vouch,且配置过程较为复杂
配置Nginx
在EC2上安装Nginx后,检查是否安装了http_auth_request_module,高版本nginx(1.5.4+)下默认安装
如果没有auth_request模块,需要下载重新编译
在/etc/nginx/conf.d目录下新建文件nginx.conf,用以下配置替换内容。其中,“kibana.stats.beckyhome.cn” 和 “kibana.login.beckyhome.cn” 请换成您自己的域名。“ES_Kibana_url” 为 Elasticsearch Service 中 Kibana 的url,其他内容保持不变。
在/etc/nginx/conf.d目录下新建文件vouch.conf,用以下配置替换其内容。同样将“kibana.login.beckyhome.cn” 换成您自己的域名。
修改完配置文件后使用以下命令重启Nginx
配置Okta
注册后,在Develop Okta上创建Application选择WEB
填写Base URI和Login redirect URIs,同样将“kibana.login.beckyhome.cn” 换成您自己的域名。其他默认不变。
下载Client ID和Client secret
配置Vouch
在vouch_proxy/config文件夹下新建config.yml文件,用以下内容替换。其中 “client_id” 和 “client_secret” 为上一步下载的ClientID和Client secret,“yourOktaDomain”换成您个人账户的Okta域名(在Okta console中查看, 如”https://dev-123456.okta.com/,可以参考Okta帮助文档) ,将 “kibana.login.beckyhome.cn” 换成您自己的域名,“beckyhome.cn” 换成根域名。
注意:在中国区 EC2 上执行./do.sh goget 会报以下错误
解决办法:使用国内github的镜像库代替国外镜像库,手动下载完成后不需要再执行goget直接进入build阶段
测试
在Okta中创建一个用户,并attach到kibana的application
访问域名kibana.stats.beckyhome.cn跳转到okta的登录表单
登录之后跳转到Kibana界面
方案三:在Nginx plus上以Okta为Idp做OIDC认证
方案介绍
方案三的原理与方案二类似,只不过不需要安装第三方身份验证代理,Nginx plus上的nginx-plus-module-njs模块已经官方支持OIDC后端。
优缺点
优点:只需安装Nginx plus的官方模块即可,配并且配置过程简单
缺点:
- Nginx plus需付费
- 此方案只适用于OIDC 认证
配置过程
方案三由Nginx Plus官方支持,关于Okta以及更详细的配置可以直接参考Nginx Plus官方文档:https://docs.nginx.com/nginx/deployment-guides/single-sign-on/okta/
修改文件/etx/nginx/conf.d/frontend.conf的以下值
方案总结
以上提出的三个方案的优缺点总结如下所示。
A | 方案一 | 方案二 | 方案三 |
方案说明 | Nginx作为代理,做HTTP基本认证 |
Nginx作为代理,做OIDC认证(这里以Okta为例)
|
Nginx plus作为代理,以Okta为Idp做OIDC认证 |
优点 | 原理和配置过程都比较简单 | · 使用免费社区版Nginx即可; · 支持各个标准的OAuth和OIDC后端认证(包括Google,Facebook,Github,Amazon Cognito,Okta等); · 可以灵活得进行用户和权限的控制 |
只需安装Nginx plus的官方模块即可,配并且配置过程简单 |
缺点 | 安全程度低,不能灵活或者集中进行用户的管理和授权 |
需要安装第三方开源工具Vouch,且配置过程较为复杂
|
Nginx plus需付费,并且此方案只适用于OIDC 认证 |
适用场景 | 对安全要求不高的小型客户 | 对安全要求比较高,有多个OAuth和OIDC认证后端,又不想付费购买Nginx Plus的客户 | 对安全要求高,内部只有OIDC后端,不想安装第三方工具并且有经济实力的客户 |
参考资料
- Amazon Elasticsearch资料:https://docs.aws.amazon.com/zh_cn/elasticsearch-service/latest/developerguide/what-is-amazon-elasticsearch-service.html
- Vouch-proxy:https://github.com/vouch/vouch-proxy
- Nginx:http://nginx.org/en/docs/