1. 程式人生 > >在Ignite中自定義身份認證安全外掛

在Ignite中自定義身份認證安全外掛

Ignite叢集搭建完成之後,應用就可以接入叢集進行各種操作了,但是預設的叢集,沒有安全保護機制,任何應用、支援JDBC的客戶端,只要知道叢集節點的IP地址,都可以接入叢集,這造成了一定的安全風險,這對於持有敏感資料的使用者,顯然是無法接受的。

Ignite本身有一個簡單的安全模組,提供了一個基於使用者名稱/密碼的認證機制,但是在實際業務場景中,需求往往更復雜,本文以白名單認證方式為例,講述如何通過自定義安全外掛的方式,滿足自己的業務需求。

外掛

Ignite有一個設計良好的模組化架構和外掛機制,可以配置不同的模組,也可以自定義自己的外掛。本文會介紹如何替換掉預設的安全實現。

第一步是在IgniteConfiguration

中注入一個外掛,本示例採用基於XML的配置,配置如下:

<bean id="ignite" class="org.apache.ignite.configuration.IgniteConfiguration"
      p:gridName="mygrid">

    <property name="pluginConfigurations">
        <bean class="ignite.WhiteListPluginConfiguration"/>
    </property>
</bean>

這個配置類的實現沒什麼特別的,只是建立一個外掛提供者:

public class WhiteListPluginConfiguration implements PluginConfiguration {
    @Override
    public Class<? extends PluginProvider> providerClass() {
        return WhiteListPluginProvider.class;
    }
}

外掛提供者類將在啟動時由IgniteKernal初始化,可以建立支援不同介面的外掛。本文對安全外掛感興趣,所以會建立GridSecurityProcessor

的實現:

public class WhiteListPluginProvider
                  implements PluginProvider<WhiteListPluginConfiguration> {

    @Override
    public String name() {
        return "WhiteListSecurity";
    }

    @Override
    public String version() {
        return "1.0.0";
    }

    @Nullable
    @Override
    public Object createComponent(PluginContext ctx, Class cls) {
        if (cls.isAssignableFrom(GridSecurityProcessor.class)) {
            return new WhiteListSecurityProcessor();
        } else {
            return null;
        }
    }

    @Override
    public IgnitePlugin plugin() {
        return new WhiteListAuthenticator();
    }

    //all other methods are no-op
}

注意這裡的createComponent方法和plugin方法。

這個類上的其它方法,大部分都是空實現。

WhiteListSecurityProcessor

到此為止,已經在Ignite中建立和安裝了安全外掛,剩下的就是實現具體的認證和授權邏輯,本文只關注認證,認證通過之後會授予所有的許可權。

以下是主要的程式碼段:

public class WhiteListSecurityProcessor
                          implements DiscoverySpiNodeAuthenticator,
                                     GridSecurityProcessor,
                                     IgnitePlugin {

    //the hosts that will be allowed to join the cluster
    private Set<String> whitelist = new HashSet<>();

    private boolean isAddressOk(Collection<String> addresses) {
        //return true if the address is in the whitelist
    }

    @Override
    public SecurityContext authenticateNode(ClusterNode node,
                                                SecurityCredentials cred)
                                                throws IgniteException {

        return new SecurityContext(new SecuritySubject() {

            @Override
            public SecurityPermissionSet permissions() {
                if (isAddressOk(node.addresses())) {
                    return WhiteListPermissionSets.ALLOW_ALL;
                } else {
                    return WhiteListPermissionSets.ALLOW_NONE;
                }
            }

            //all other methods are noop

        });
    }

    @Override
    public boolean isGlobalNodeAuthentication() {
        //allow any node to perform the authentication
        return true;
    }

    @Override
    public void start() throws IgniteCheckedException {
        //load the whitelist
        //check that this process is running on a white listed server
        //if there's a problem throw new IgniteCheckedException
    }

    @Nullable
    @Override
    public IgniteSpiNodeValidationResult validateNode(ClusterNode node) {
        if (!isAddressOk(node.addresses())) {
            return new IgniteSpiNodeValidationResult(node.id(),
                                                     "Access denied",
                                                     "Access denied");
        } else {
            return null;
        }
    }

    //all other methods are noop

}

這個只是一段虛擬碼,具體的實現需要開發者根據自身的需求進行發揮。

start方法會在Ignite啟動時呼叫,因此這裡是載入白名單IP地址的合適位置。這裡還可以用於校驗此程序是否在列出白名單的伺服器上執行,如果有任何問題,都可以丟擲IgniteCheckedException異常,這會導致程序終止並輸出錯誤資訊。

當新的節點啟動並嘗試接入時,將按順序呼叫authenticateNodevalidateNode方法。呼叫authenticateNode需要返回一個安全上下文,該安全上下文標識授予該程序的許可權。為安全起見,如果IP地址不在白名單上,會返回一個ALLOW_NONE策略。然後呼叫validateNode,在這裡可以獲取連線節點的IP地址,並確定它是否可以加入叢集。

至於有關如何建立策略列表的示例,請檢視Ignite的GridOsSecurityProcessor類。

同樣,有許多需要實現的無操作方法,但是與本文的主題無關。

最後

這個只是一個簡單的示例,講述瞭如何定製Ignite的外掛,尤其是身份認證外掛。如果用於處理身份認證的節點故障,則會選擇一個新的節