elasticsearch's basic auth plugin "Jetty"

Elasticsearch本身是沒有安全性的功能, 我們得透過plugin來安裝, 這次我選擇了elasticsearch-jetty,此外也有人用nginx反向代理來進行控制.

首先我們得先注意到Elasticsearch與Jetty Plugin的版本號對應, 在這裡可以查看, 如果版本號沒對應上就無法正常工作了.

這次範例是用1.2.1版本(Elasticsearch & Jetty Plugin), 到es的bin目錄下執行

plugin -url https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-1.2.1.zip -install elasticsearch-jetty-1.2.1

接下來我們要取代es原來的Jetty, 請到es目錄下的config文件夾下面打開 elasticsearch.yml 檔案,接這找出http:type這個section,找不到就直接添加, 改如下(注意冒號後面有個空格)

http.type: com.sonian.elasticsearch.http.jetty.JettyHttpServerTransportModule

接下來我們用curl來測試一下,es的http server的jetty版本是否正確

$ curl -I "http://localhost:9200/"
HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
Access-Control-Allow-Origin: *
Content-Length: 0
Server: Jetty(8.1.14.v20131031)

接下來我們要開始配置jetty了, jetty配置文件會使用jetty-*.xml檔名來存放配置內容, 而且是可以配置多個檔案的, 其好處是讓我們可以做些分類. 此配置同樣在 elasticsearch.yml 檔案內

sonian.elasticsearch.http.jetty.config: jetty.xml, jetty-hash-auth.xml,jetty-restrict-all.xml

請勿盲目的複製以上代碼, 後面所出現的3個檔案名jetty.xml, jetty-hash-auth.xml,jetty-restrict-all.xml是實際存在檔案, 而且是存在es目錄下的config, 請確保你的檔案位置與名稱是否正確, 注意配置檔案名稱順序不要調換.

這個檔案的sample可以在es目錄下的\plugins\jetty-1.2.1找到, 接著把他們複製到es目錄下的config.

接下來我們要把焦點放到Jertty的xml配置檔上面, 這裡主要關心的是jetty-hash-auth.xml,jetty-restrict-all.xml這兩個檔案, 也可參考官方文檔的說明.

首先來看jetty-hash-auth.xml, 我們可以發現文件內有一串字/realm.properties,其實這是一個檔案, 我們必須在es目錄下的config下新增realm.properties檔案, 這裡面擺放的就是basic_auth的帳號密碼.

superuser: Adm1n,admin,readwrite
user: Passw0rd,readwrite
me: CRYPT:meyvITIbcrTAY,readwrite
read: 1234,readonly
guest: 1111

上面我列了一些範例, 配置格式為 username: password,role1,role2 這個配置是最基礎的密碼是明碼(有時候並不想給人直接看到).

me: CRYPT:meyvITIbcrTAY,readwrite 這個範例的密碼是被混淆過的,逗號分個開來的仍然是role, 只是密碼是CRYPT:meyvITIbcrTAY這種格式.

這裡順便也來給出如何產生密碼的方法, 執行java -cp lib/jetty-util-xxx.jar org.eclipse.jetty.util.security.Password username password, XXX是版本號.

下面範例我是用es目錄下的\plugins\jetty-1.2.1的jetty-util-8.1.14.v20131031.jar.

java -cp jetty-util-8.1.14.v20131031.jar org.eclipse.jetty.util.security.Password guest guestPwd
guestPwd
OBF:20771x1b206z
MD5:639bae9ac6b3e1a84cebb7b403297b79
CRYPT:guest/ks90E221EY
我們可以選其中一個作為realm.properties檔案內文的帳號密碼
guest: CRYPT:guest/ks90E221EY或guest: MD5:639bae9ac6b3e1a84cebb7b403297b79, 關於basic_auth跟用戶名與密碼有關的說明就到這裡.
 
關於Role的控制才是比較複雜的, 我們可以達到很多角色來限制訪問與操握es的功能, 例如不可以刪除, 只讀, 數據隔離, es的系統配置權限..等等. 注意, 以下所有配置都圍繞在jetty-restrict-all.xml檔案裡面
先來看這個section
<New class="org.eclipse.jetty.util.security.Constraint"
         id="DefaultSecurityConstraint">
        <Set name="authenticate">true</Set>
        <Set name="name">BASIC</Set>
        <Set name="roles">
            <Array type="java.lang.String">
                <Item>readwrite</Item>
            </Array>
        </Set>
</New>

<New class="org.eclipse.jetty.util.security.Constraint"
     id="NoneSecurityConstraint">
      <Set name="authenticate">false</Set>
</New>

根據我的理解這是在創建一個實例,id類似於變量名(DefaultSecurityConstraint), 根據名稱來看這是一個約束class, 開啟authenticate, 設置驗證方式BASIC,我們可以在roles段添加一些語意性的名子(這邊是readwrite),  另一個是沒有權限控制的約束(NoneSecurityConstraint).

注意到readwrite這個字串, 這跟我們在配置realm.properties裡面的角色是對應的.

接下來這段, 有關handler的部分尚未研究, 我們先關注到Call元素的method, pathSpec, constraint.

下面的範例是指: GET http://127.0.0.1:9200, GET http://127.0.0.1:9200/_search?q=*  都可以不需要通過basic_auth驗證就可以訪問, 其他例如: GET http://127.0.0.1:9200/_plugin/marvel 則需要權限.

<Set name="handler">
        <New class="com.sonian.elasticsearch.http.jetty.security.RestConstraintSecurityHandler"
             id="DefaultSecurityHandler">

            <Set name="handler"><Ref id="OldHandler"/></Set>

            <Set name="loginService">
                <!-- from jetty-es-auth.xml or jetty-hash-auth.xml -->
                <Ref id="DefaultLoginService"/>
            </Set>

            <Set name="realmName">DefaultRealm</Set>
            <Call name="addConstraintMapping">
                <Arg>
                    <New class="org.eclipse.jetty.security.ConstraintMapping">
                        <Set name="pathSpec">*</Set>
                        <Set name="constraint">
                            <Ref id="DefaultSecurityConstraint"/>
                        </Set>
                    </New>
                </Arg>
            </Call>

            <Call name="addConstraintMapping">
                <Arg>
                    <New class="org.eclipse.jetty.security.ConstraintMapping">
                        <Set name="method">GET</Set>
                        <Set name="pathSpec">
                            /,/_search
                        </Set>
                        <Set name="constraint">
                            <Ref id="NoneSecurityConstraint"/>
                        </Set>
                    </New>
                </Arg>
            </Call>
        </New>
</Set>

pathSpec主要是配置可以分訪問的uri, 分別用逗號隔開. 注意這個Set Setion需要段行那怕只有一個url規則, 下面是針對rui根的配置

<Set name="pathSpec">
  /
</Set>

method是指允許的http的動詞, GET, PUT, POST...是否可以設置多個尚未研究.

constraint配置之前的角色約束.

以上的配置目前都需要重新啟動es, 關於這樣的方案有待研究, 或者是我們要正確的去使用uri約束, 而不是把所有的業務相關過濾行為都放在這個配置檔案.

posted @ 2014-06-24 16:12  Henry JAO  阅读(534)  评论(0编辑  收藏  举报