ES外掛程式碼的執行許可權問題
阿新 • • 發佈:2021-10-27
一、問題描述
es的ik外掛需要使用jdbc訪問資料庫,所以需要在plugin-security.policy
裡配置SocketPermission
,但是配置好並重啟es卻依然出現了下列錯誤:
Caused by: java.security.AccessControlException: access denied ("java.net.SocketPermission" "172.16.20.213:3306" "connect,resolve") at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) ~[?:?] at java.security.AccessController.checkPermission(AccessController.java:1036) ~[?:?] at java.lang.SecurityManager.checkPermission(SecurityManager.java:408) ~[?:?] at java.lang.SecurityManager.checkConnect(SecurityManager.java:910) ~[?:?] at java.net.Socket.connect(Socket.java:599) ~[?:?] at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:213) ~[mysql-connector-java-5.1.34.jar:5.1.34]
看樣子配置是沒有起作用,多次重啟後還是這個錯誤,在網上搜索相關解決方案,臨時在es自帶的jdk裡修改jdk/conf/security/java.policy
後才解決。
二、原因分析
可能的原因:
- es讀取的外掛許可權策略不適用於外掛的依賴包?
- 依賴包裡有httpclient依賴包,且網路請求都正常,不可能只針對jdbc做特殊限制
- 檢視許可權校驗的相關程式碼得知,許可權策略適用於本外掛目錄下的所有jar包,所以排除此猜測
- mysql的依賴包不在本外掛目錄下,導致許可權策略沒載入上?
- 仔細查詢jdbc的依賴包,在本外掛目錄下確實不存在,最後發現放在了es的lib目錄下(官方安裝包裡並沒有此JDBC依賴),雖然啟動時不會報
ClassNotFoundException
- 仔細查詢jdbc的依賴包,在本外掛目錄下確實不存在,最後發現放在了es的lib目錄下(官方安裝包裡並沒有此JDBC依賴),雖然啟動時不會報
ES外掛的許可權配置及許可權校驗的大致流程:
- 首先在
org.elasticsearch.bootstrap.Bootstrap
的setup方法裡會呼叫org.elasticsearch.bootstrap.Security.configure
方法 - 例項化
ESPolicy
替換Java的安全策略。過程中呼叫getPluginAndModulePermissions
方法獲取各外掛和模組中jar包的訪問策略,最終ESPolicy.plugins
裡儲存的KV:<外掛或模組目錄下的每個Jar包路徑, Jar包所屬外掛或模組目錄下配置的策略 - 執行時會通過
ESPolicy.implies
方法校驗目的碼是否有許可權,原始碼如下:
// 程式碼位置:org.elasticsearch.bootstrap.ESPolicy
public boolean implies(ProtectionDomain domain, Permission permission) {
CodeSource codeSource = domain.getCodeSource();
// codesource can be null when reducing privileges via doPrivileged()
if (codeSource == null) {
return false;
}
URL location = codeSource.getLocation();
// https://bugs.openjdk.java.net/browse/JDK-8129972
if (location != null) {
// run scripts with limited permissions
if (BootstrapInfo.UNTRUSTED_CODEBASE.equals(location.getFile())) {
return untrusted.implies(domain, permission);
}
// plugins已經儲存了每個Jar包路徑對應的Policy
// 這裡根據目的碼所屬的Jar包路徑,找到對應的Policy進行許可權校驗
Policy plugin = plugins.get(location.getFile());
if (plugin != null && plugin.implies(domain, permission)) {
return true;
}
}
// 省略後續程式碼片段...
}
三、解決及總結
最終解決方式:
- 把ES_HOME下lib裡的JDBC移動到當前外掛目錄下
- 還原在jdk裡配置的訪問策略(按需在各自模組中配置許可權更安全)
- 重啟ES後,問題解決
總結:
由於ES啟動後在程式裡設定了自定義的Java許可權策略,所以在各外掛裡必須配置用到的許可權。JDBC的網路許可權配置不生效的原因是沒有按規範把JDBC的jar包放在外掛目錄下,導致JDBC的訪問策略為空,最終在執行時報無許可權的錯誤。所以在未知影響範圍的情況下,禁止往ES的lib目錄下放依賴Jar包,避免Jar包衝突和程式碼許可權等問題。