Ambari 使用 Knox 進行 LDAP 身份認(rèn)證
Knox有如下兩種認(rèn)證方式:
- ShiroProvider 對于LDAP/AD身份驗證,使用用戶名和密碼。沒有SPNEGO/Kerberos支持。
- HadoopAuth 對于SPNEGO/Kerberos身份驗證,使用委派令牌。沒有LDAP/AD支持。
下面我們主要介紹下LDAP認(rèn)證方式:
一 配置LDAP認(rèn)證
用ambari安裝的knox,默認(rèn)安裝目錄是 /usr/hdp/current/knox-server 。默認(rèn)cluster-name是default,對應(yīng)的拓?fù)渑渲梦募牵?code style="color:rgb(150,84,181);font-size:14px;font-family:'Operator Mono', Consolas, Monaco, Menlo, monospace;">/usr/hdp/current/knox-server/conf/topologies/default.xml
有兩種方式創(chuàng)建LDAP服務(wù)器,一是手工安裝OpenLDAP;二是使用Knox自帶的Demo LDAP:
- 如果要手工安裝OpenLDAP,參考 Centos7 下 OpenLDAP 安裝。
- 如果要使用Knox自帶的DemoLDAP服務(wù)器,則在Ambari中前往 Services -> Knox -> Service Actions -> Start Demo LDAP。
下面的測試使用手工部署OpenLDAP,并在LDAP上創(chuàng)建了一個測試用戶test(dn: cn=test,ou=users,dc=hdp,dc=com),該用戶的密碼是test。初學(xué)者可以安裝一個JXplorer來鏈接LDAP服務(wù)器查看其中的數(shù)據(jù)。
為了修改Knox的默認(rèn)集群拓?fù)湮募?default.xml),前往 Services -> Knox -> Configs -> Advanced topology,將第一個xml的第一個provider元素替換為下列內(nèi)容:
<topology>
<gateway>
<provider>
<role>authentication</role>
<name>ShiroProvider</name>
<enabled>true</enabled>
<param>
<name>sessionTimeout</name>
<value>30</value>
</param>
<param>
<name>main.ldapRealm</name>
<value>org.apache.hadoop.gateway.shirorealm.KnoxLdapRealm</value>
</param>
<param>
<name>main.ldapRealm.userDnTemplate</name>
<value>uid={0},ou=users,dc=hdp,dc=com</value>
</param>
<param>
<name>main.ldapRealm.contextFactory.url</name>
<value>ldap://{{knox_host_name}}</value>
</param>
<param>
<name>main.ldapRealm.contextFactory.authenticationMechanism</name>
<value>simple</value>
</param>
<param>
<name>urls./**</name>
<value>authcBasic</value>
</param>
</provider>
......
</topology>
相對于默認(rèn)配置,只修改了兩個參數(shù):
<param>
<name>main.ldapRealm.userDnTemplate</name>
<value>>cn={0},ou=users,dc=hdp,dc=com</value>
</param>
<param>
<name>main.ldapRealm.contextFactory.url</name>
<value>ldap://freeipa.testing.com</value>
</param>
- main.ldapRealm.userDnTemplate
You would use LDAP configuration as documented above to authenticate against Active Directory as well.
Some Active Directory specific things to keep in mind:
Typical AD main.ldapRealm.userDnTemplate value looks slightly different, such as
cn={0},cn=users,DC=lab,DC=sample,dc=com
Please compare this with a typical Apache DS main.ldapRealm.userDnTemplate value and make note of the difference:
uid={0},ou=people,dc=hadoop,dc=apache,dc=org
If your AD is configured to authenticate based on just the cn and password and does not require user DN, you do not have to specify value for main.ldapRealm.userDnTemplate.
- main.ldapRealm.contextFactory.url
你自己ldap的url,LDAP沒有啟用TLS,使用默認(rèn)端口389。
我使用apacheds的ldap, ldap://ldap_host:10389
在ambari界面中點擊Save按鈕保存,并通過橙黃色按鈕重啟相關(guān)服務(wù)。之后會發(fā)現(xiàn)/usr/hdp/current/knox-server/conf/topologies/目錄下的default.xml修改更新了。
二 驗證Knox網(wǎng)關(guān)
作為一個代理網(wǎng)關(guān),Knox將所有支持代理的RESTful服務(wù)和頁面進行了一層地址映射
https://knox.apache.org/books/knox-1-6-0/user-guide.html#URL+Mapping
Service HA配置文檔:
https://knox.apache.org/books/knox-1-6-0/user-guide.html#Default+Service+HA+support
2.1 Yarn RESTfull
現(xiàn)在我們來測試一下YARN的RESTful服務(wù),打開瀏覽器輸入https://knox_host_name:8443/gateway/default/resourcemanager/v1/cluster/apps。這是YARN查看集群運行任務(wù)的RESTful服務(wù)接口。如圖下圖所示,Knox網(wǎng)關(guān)要求進行登錄認(rèn)證。
輸入用戶名和密碼進行登錄認(rèn)證,認(rèn)證通過之后我們?nèi)缭冈L問到數(shù)據(jù)了,如圖下圖所示。
2.2 Yarn UI
接下來我們嘗試訪問YARN的Web UI控制臺,Knox網(wǎng)關(guān)的默認(rèn)配置中只代理了RESTful接口,所以我們需要修改它的配置文件,添加想要代理的Web UI控制臺。打開Ambari找到Knox網(wǎng)關(guān)的配置頁面,選擇Advanced topology配置項,在末尾增加YARN UI的配置,保存之后需要重啟Knox網(wǎng)關(guān)服務(wù)。
YARNUI HA配置:
<provider>
<role>ha</role>
<name>HaProvider</name>
<enabled>true</enabled>
<param>
<name>WEBHDFS</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>HDFSUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>YARNUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
</provider>
<service>
<role>YARNUI</role>
<url>http://hdp.test.col10:8088</url>
<url>http://hdp.test.col09:8088</url>
</service>
現(xiàn)在我們再次打開瀏覽器輸入https://knox_host_name:8443/gateway/default/yarn,就能看到Y(jié)ARN的Web UI管理控制臺了。
報錯如下:
查看Knox服務(wù)日志,報錯如下:
2023-01-04 17:20:28,759 INFO knox.gateway (AclsAuthorizationFilter.java:doFilter(104)) - Access Granted: true
2023-01-04 17:20:28,760 ERROR knox.gateway (GatewayDispatchFilter.java:isDispatchAllowed(155)) - The dispatch to http://hdp.test.col09:8088/cluster was disallowed because it fails the dispatch whitelist validation. See documentation for dispatch whitelisting.
需要修改一下gateway.dispatch.whitelist.services屬性,內(nèi)容里刪掉YARNUI,如果不刪除,則會報錯:
再次訪問 https://knox_host_name:8443/gateway/default/yarn ,輸入用戶名和密碼后,訪問正常
2.3 Hdfs RESTfull
配置如下:
<provider>
<role>ha</role>
<name>HaProvider</name>
<enabled>true</enabled>
<param>
<name>WEBHDFS</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>HDFSUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>YARNUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
</provider>
<service>
<role>WEBHDFS</role>
<url>http://hdp.test.col09:50070/webhdfs</url>
<url>http://hdp.test.col10:50070/webhdfs</url>
</service>
測試:
curl -i -k -u gust:gust-password -X GET \
'https://localhost:8443/gateway/default/webhdfs/v1/?op=LISTSTATUS'
2.4 HDFSUI
配置如下:
<provider>
<role>ha</role>
<name>HaProvider</name>
<enabled>true</enabled>
<param>
<name>WEBHDFS</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>HDFSUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>YARNUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
</provider>
<service>
<role>HDFSUI</role>
<url>http://hdp.test.col09:50070</url>
<url>http://hdp.test.col10:50070</url>
</service>
需要修改一下gateway.dispatch.whitelist.services屬性,內(nèi)容里刪掉HDFSUI,如果不刪除,則會報錯:
測試:
訪問https://hdp.test.col10:8443/gateway/default/hdfs 輸入用戶名和密碼后,后臺報如下錯誤:
Caused by: java.io.IOException: java.io.IOException: Service connectivity error.
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.failoverRequest(DefaultHaDispatch.java:125)
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.executeRequest(DefaultHaDispatch.java:94)
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.failoverRequest(DefaultHaDispatch.java:119)
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.executeRequest(DefaultHaDispatch.java:94)
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.failoverRequest(DefaultHaDispatch.java:119)
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.executeRequest(DefaultHaDispatch.java:94)
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.failoverRequest(DefaultHaDispatch.java:119)
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.executeRequest(DefaultHaDispatch.java:94)
at org.apache.knox.gateway.dispatch.DefaultDispatch.doGet(DefaultDispatch.java:278)
at org.apache.knox.gateway.dispatch.GatewayDispatchFilter$GetAdapter.doMethod(GatewayDispatchFilter.java:170)
at org.apache.knox.gateway.dispatch.GatewayDispatchFilter.doFilter(GatewayDispatchFilter.java:122)
at org.apache.knox.gateway.filter.AbstractGatewayFilter.doFilter(AbstractGatewayFilter.java:61)
at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
at org.apache.knox.gateway.filter.AclsAuthorizationFilter.doFilter(AclsAuthorizationFilter.java:108)
at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
at org.apache.knox.gateway.identityasserter.common.filter.AbstractIdentityAssertionFilter.doFilterInternal(AbstractIdentityAssertionFilter.java:196)
at org.apache.knox.gateway.identityasserter.common.filter.AbstractIdentityAssertionFilter.continueChainAsPrincipal(AbstractIdentityAssertionFilter.java:153)
at org.apache.knox.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter.doFilter(CommonIdentityAssertionFilter.java:90)
at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
at org.apache.knox.gateway.filter.rewrite.api.UrlRewriteServletFilter.doFilter(UrlRewriteServletFilter.java:60)
at org.apache.knox.gateway.filter.AbstractGatewayFilter.doFilter(AbstractGatewayFilter.java:61)
at org.apache.knox.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:372)
at org.apache.knox.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:272)
at org.apache.knox.gateway.filter.ShiroSubjectIdentityAdapter$CallableChain$1.run(ShiroSubjectIdentityAdapter.java:91)
at org.apache.knox.gateway.filter.ShiroSubjectIdentityAdapter$CallableChain$1.run(ShiroSubjectIdentityAdapter.java:88)
... 82 more
Caused by: java.io.IOException: Service connectivity error.
at org.apache.knox.gateway.dispatch.DefaultDispatch.executeOutboundRequest(DefaultDispatch.java:148)
at org.apache.knox.gateway.ha.dispatch.DefaultHaDispatch.executeRequest(DefaultHaDispatch.java:90)
... 108 more
23/01/10 14:47:28 ||91d91611-27bc-4c0f-84f0-ece1497d461e|audit|10.252.xx.xx|HDFSUI||||access|uri|/gateway/default/hdfs|unavailable|Request method: GET
23/01/10 14:47:28 ||91d91611-27bc-4c0f-84f0-ece1497d461e|audit|10.252.xx.xx|HDFSUI|test|||authentication|uri|/gateway/default/hdfs|success|
23/01/10 14:47:28 ||91d91611-27bc-4c0f-84f0-ece1497d461e|audit|10.252.xx.xx|HDFSUI|test|||authentication|uri|/gateway/default/hdfs|success|Groups: []
23/01/10 14:47:28 ||91d91611-27bc-4c0f-84f0-ece1497d461e|audit|10.252.xx.xx|HDFSUI|test|||authorization|uri|/gateway/default/hdfs|success|
23/01/10 14:47:28 ||91d91611-27bc-4c0f-84f0-ece1497d461e|audit|10.252.xx.xx|HDFSUI|test|||dispatch|uri|https://hdp.test.col10:8443/gateway/default/hdfs?user.name=test|unavailable|Request method: GET
23/01/10 14:47:28 ||91d91611-27bc-4c0f-84f0-ece1497d461e|audit|10.252.xx.xx|HDFSUI|test|||dispatch|uri|https://hdp.test.col10:8443/gateway/default/hdfs?user.name=test|failure|
23/01/10 14:47:28 ||91d91611-27bc-4c0f-84f0-ece1497d461e|audit|10.252.xx.xx|HDFSUI|test|||access|uri|/gateway/default/hdfs|failure|
問題原因:HDP 3.1.0 - Knox proxy HDFSUI - HTTP 401 Error
this seems to be a known bug in Knox-1.0 used in HDP-3.1. One solution is to modify the URL used to access HDFS UI:
https://<knox-host>:8443/gateway/default/hdfs?host=http://<namenode-host>:50070
Admittedly not a great solution but it worked for me. Another solution which I haven't tried is to insert the following line in the HDFSUI service definition in Knox topology file.
<version>2.7.0</version>
This will use an older, bug-free version of HDFSUI service. More details here.
增加配置如下:
<service>
<role>HDFSUI</role>
<version>2.7.0</version>
<url>http://hdp.test.col09:50070</url>
<url>http://hdp.test.col10:50070</url>
</service>
再次訪問https://hdp.test.col10:8443/gateway/default/hdfs,可以正常訪問。
后臺日志正常:
23/01/10 15:18:23 ||e042d675-f027-4175-9dbf-12fcbe7d4a23|audit|10.252.169.246|HDFSUI||||access|uri|/gateway/default/hdfs|unavailable|Request method: GET
23/01/10 15:18:23 ||e042d675-f027-4175-9dbf-12fcbe7d4a23|audit|10.252.169.246|HDFSUI|test|||authentication|uri|/gateway/default/hdfs|success|
23/01/10 15:18:23 ||e042d675-f027-4175-9dbf-12fcbe7d4a23|audit|10.252.169.246|HDFSUI|test|||authentication|uri|/gateway/default/hdfs|success|Groups: []
23/01/10 15:18:23 ||e042d675-f027-4175-9dbf-12fcbe7d4a23|audit|10.252.169.246|HDFSUI|test|||authorization|uri|/gateway/default/hdfs|success|
23/01/10 15:18:23 ||e042d675-f027-4175-9dbf-12fcbe7d4a23|audit|10.252.169.246|HDFSUI|test|||dispatch|uri|http://hdp.test.col09:50070/?user.name=test|unavailable|Request method: GET
23/01/10 15:18:23 ||e042d675-f027-4175-9dbf-12fcbe7d4a23|audit|10.252.169.246|HDFSUI|test|||dispatch|uri|http://hdp.test.col09:50070/?user.name=test|success|Response status: 200
23/01/10 15:18:23 |||audit|10.252.169.246|HDFSUI|test|||access|uri|/gateway/default/hdfs|success|Response status: 200
2.5 HBASEUI
配置如下:
<provider>
<role>ha</role>
<name>HaProvider</name>
<enabled>true</enabled>
<param>
<name>WEBHDFS</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>HDFSUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>YARNUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
<param>
<name>HBASEUI</name>
<value>maxFailoverAttempts=3;failoverSleep=1000;enabled=true</value>
</param>
</provider>
<service>
<role>HBASEUI</role>
<url>http://hdp.test.col10:16010</url>
<url>http://hdp.test.col09:16010</url>
</service>
需要修改一下gateway.dispatch.whitelist.services屬性,內(nèi)容里刪掉HBASEUI,如果不刪除,則會報錯:
訪問https://hdp.test.col10:8443/gateway/default/hbase/webui 輸入用戶名密碼即可跳到HBASE UI界面
