在Ignite中自定義身份認證安全外掛
Ignite叢集搭建完成之後,應用就可以接入叢集進行各種操作了,但是預設的叢集,沒有安全保護機制,任何應用、支援JDBC的客戶端,只要知道叢集節點的IP地址,都可以接入叢集,這造成了一定的安全風險,這對於持有敏感資料的使用者,顯然是無法接受的。
Ignite本身有一個簡單的安全模組,提供了一個基於使用者名稱/密碼的認證機制,但是在實際業務場景中,需求往往更復雜,本文以白名單認證方式為例,講述如何通過自定義安全外掛的方式,滿足自己的業務需求。
外掛
Ignite有一個設計良好的模組化架構和外掛機制,可以配置不同的模組,也可以自定義自己的外掛。本文會介紹如何替換掉預設的安全實現。
第一步是在IgniteConfiguration
<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
異常,這會導致程序終止並輸出錯誤資訊。
當新的節點啟動並嘗試接入時,將按順序呼叫authenticateNode
和validateNode
方法。呼叫authenticateNode
需要返回一個安全上下文,該安全上下文標識授予該程序的許可權。為安全起見,如果IP地址不在白名單上,會返回一個ALLOW_NONE
策略。然後呼叫validateNode
,在這裡可以獲取連線節點的IP地址,並確定它是否可以加入叢集。
至於有關如何建立策略列表的示例,請檢視Ignite的GridOsSecurityProcessor
類。
同樣,有許多需要實現的無操作方法,但是與本文的主題無關。
最後
這個只是一個簡單的示例,講述瞭如何定製Ignite的外掛,尤其是身份認證外掛。如果用於處理身份認證的節點故障,則會選擇一個新的節