ES插件代碼的執行權限問題


一、問題描述

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異常,但是配置的權限卻沒有賦給此jar包,最終出現在jdk里配置才有效的錯覺。

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;
        }
    }

    // 省略后續代碼片段...
}

三、解決及總結

最終解決方式:

  1. 把ES_HOME下lib里的JDBC移動到當前插件目錄下
  2. 還原在jdk里配置的訪問策略(按需在各自模塊中配置權限更安全)
  3. 重啟ES后,問題解決

總結:
由於ES啟動后在程序里設置了自定義的Java權限策略,所以在各插件里必須配置用到的權限。JDBC的網絡權限配置不生效的原因是沒有按規范把JDBC的jar包放在插件目錄下,導致JDBC的訪問策略為空,最終在運行時報無權限的錯誤。所以在未知影響范圍的情況下,禁止往ES的lib目錄下放依賴Jar包,避免Jar包沖突和代碼權限等問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM