搭建mongodb副本叢集,keyfile和ssl方式,使用者認證模式
阿新 • • 發佈:2019-02-04
環境:
Microsoft Windows [版本 10.0.10586]
mongod 版本:
db version v3.2.1
git version: a14d55980c2cdc565d4704a7e3ad37e4e535c1b2
OpenSSL version: OpenSSL 1.0.1p-fips 9 Jul 2015
allocator: tcmalloc
modules: none
build environment:
distmod: 2008plus-ssl
distarch: x86_64
target_arch: x86_64
1.建立3個資料夾1、2、3分別為主、備、備伺服器
2.使用keyFile進行授權連線replica sets
#隨機生成keyFile或者手動寫入,key的長度必須是6-1024的base64字元,unix下必須相同組許可權,windows下不需要
openssl rand -base64 1024 > mongodb.key
chmod 600 mongodb.key
3.配置檔案
{ "storage": { "dbPath": "D:/MongoDB3/1/db" }, "net": { "port": 27001, "http": { "enabled":true } }, "replication": { "replSetName":"s1" }, "security": { "authorization": "enabled", "clusterAuthMode":"keyFile", "keyFile":"D:/MongoDB3/settings/mongodb.key" } }
4.啟動mongo
mongod --config="D:\MongoDB3\1\mongodb.cfg"
mongod --config="D:\MongoDB3\2\mongodb.cfg"
mongod --config="D:\MongoDB3\3\mongodb.cfg"
5.連線主Mongo
mongo 127.0.0.1:27001
use admin
rs.initiate()
#確認
rs.conf()
#新增從庫,使用本機區域網ip地址,使用127.0.0.1會出錯
rs.add('192.168.10.105:27002')
rs.add('192.168.10.105:27003')
#或者一次性新增 rs.initiate({_id:"s1",members:[ {_id:0,host:"192.168.10.105:27001",priority:100}, {_id:1,host:"192.168.10.105:27002",priority:99}, {_id:2,host:"192.168.10.105:27003",priority:98}, ]})
#檢視配置資訊
rs.status()
#移除庫
rs.remove('192.168.10.105:27002')
6.新增使用者及授權認證
db.createUser(
{
user:"any",
pwd:"password",
roles:[{role:"userAdminAnyDatabase",db:"admin"}]
}
);
db.auth("any","password")
7.連線副本
mongo 127.0.0.1:27001
#show dbs不可用
#設定可讀
rs.slaveOk() #Deprecated.
設定讀寫方式
#Primary #從主的讀,預設
#primaryPreferred #基本上從主的讀,主不可用時,從從的讀
#secondary #從從的讀
#secondaryPreferred #基本上從從的讀,從不可用時,從主的讀
#nearest #從網路延遲最小的讀
db.getMongo().setReadPref('secondaryPreferred')
8.使用x509進行授權連線replica sets
9.生成CA證書和使用者證書
#建立CA目錄
mkdir -p ./demoCA/{private,newcerts}
touch ./demoCA/index.txt
echo 01 > ./demoCA/serial
#生成CA金鑰對
openssl genrsa -des3 -out ./demoCA/private/cakey.pem 2048
#生成證書請求和證書
openssl req -new -x509 -days 3650 -key ./demoCA/private/cakey.pem -out ./demoCA/cacert.pem
#生成使用者金鑰對,userkey設定密碼userpempassword,clusterkey設定密碼clusterempassword
#生成user證書Common Name必須為127.0.0.1
openssl genrsa -des3 -out ./demoCA/private/userkey.pem 2048
openssl genrsa -des3 -out ./demoCA/private/clusterkey.pem 2048
#生成使用者證書請求
openssl req -new -key ./demoCA/private/userkey.pem -out userreq.req
openssl req -new -key ./demoCA/private/clusterkey.pem -out clusterreq1.req
#使用 CA 簽發使用者證書
openssl ca -in userreq.req -out usercert.pem -days 3650
openssl ca -in clusterreq1.req -out clustercert1.pem -days 3650
#將key和cer打包成pem
cat ./demoCA/private/userkey.pem usercert.pem > user.pem
cat ./demoCA/private/clusterkey.pem clustercert1.pem > cluster1.pem
openssl pkcs12 -export -clcerts -in usercert.pem -inkey ./demoCA/private/userkey.pem -out user.p12
10.上述生成的可能要用到檔案有:cacert.pem可重新命名為ca-cert.crt,user.pem,user.p12,cluster1.pem(參照生成cluster2.pem,cluster3.pem)
11.windows下ca證書管理,點選證書ca-cert.crt,安裝證書->將證書放入"受信任的根證書頒發機構",檢視windows下證書可執行certmgr.msc
12.配置檔案
{
"storage":
{
"dbPath": "D:/MongoDB3/1/db"
},
"net":
{
"port": 27001,
"http":
{
"enabled":false
},
"ssl":
{
"mode":"requireSSL",
"CAFile":"D:/MongoDB3/settings/keys/ca-cert.crt",
"PEMKeyFile":"D:/MongoDB3/settings/keys/user.pem",
"PEMKeyPassword":"userpempassword",
"clusterFile":"D:/MongoDB3/settings/keys/cluster1.pem",
"clusterPassword":"clusterpempassword",
"allowInvalidHostnames":true
}
},
"replication":
{
"replSetName":"s1"
},
"security":
{
"authorization": "enabled",
"clusterAuthMode":"x509"
}
}
userpempassword為使用者金鑰對密碼, clusterpempassword為副本金鑰對密碼
13.啟動mongodb
mongod --config="D:\MongoDB3\1\mongodbs.cfg"
mongod --config="D:\MongoDB3\2\mongodbs.cfg"
mongod --config="D:\MongoDB3\3\mongodbs.cfg"
14.連線mongo
mongo 127.0.0.1:27001 --ssl --sslPEMKeyFile "D:/MongoDB3/settings/keys/user.pem" --sslPEMKeyPassword "userpempassword" --sslAllowInvalidCertificates
15.剩下步驟與keyfile設定一致
16.java驅動連線
import java.io.*;
import java.net.Socket;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import javax.net.ssl.*;
import org.bson.Document;
import com.mongodb.*;
import com.mongodb.MongoClientOptions.*;
import com.mongodb.client.*;
import xiaogen.util.Logger;
/**
* @author zhg
* 創建於 2015年12月3日 上午11:14:07
*/
/**
* @author zhg
*
*/
public class Mains implements MongoDBHelper
{
private static SSLSocketFactory sss;
private static void initSSL() throws Exception
{
// 服務端證書
TrustManager[] trust = new TrustManager[] { new EmptyX509TrustManager() };
// 客戶端證書
KeyManager[] key = createKeyManager(new FileInputStream("D:/MongoDB3/settings/keys/user.p12"), "sssss",
null);
SSLContext ssl = SSLContext.getInstance("SSL");
ssl.init(key, trust, new java.security.SecureRandom());
sss = ssl.getSocketFactory();
}
/**
* 服務端要求證書
*
* @param stream
* @param password
* @param alias
* @return
*/
public static KeyManager[] createKeyManager(InputStream stream, String password, String alias)
{
try
{
if (stream != null)
{
// String type = KeyStore.getDefaultType();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(stream, password.toCharArray());
if (alias != null)
{
return new KeyManager[] { new AliasKeyManager(ks, alias, password) };
} else
{
KeyManagerFactory trustManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ks, password.toCharArray());
return trustManagerFactory.getKeyManagers();
}
}
} catch (Exception e)
{
// TODO
e.printStackTrace();
}
return null;
}
/**
* 檢驗伺服器
*
* @param stream
* @param password
* @return
*/
public static TrustManager[] createTrustManager(InputStream stream, String password)
{
try
{
if (stream != null)
{
// String type = KeyStore.getDefaultType();
// System.out.println(type);
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(stream, password.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ks);
// Logger.d("Provider : " + ks.getProvider().getName());
// Logger.d("Type : " + ks.getType());
// Logger.d("Size : " + ks.size());
//
// Enumeration<String> en = ks.aliases();
// while (en.hasMoreElements())
// {
// Logger.d("Alias: " + en.nextElement());
// }
return trustManagerFactory.getTrustManagers();
} else
{
return new TrustManager[] { new EmptyX509TrustManager() };
}
} catch (Exception e)
{
// TODO
e.printStackTrace();
}
return null;
}
private static class MyHostnameVerifier implements HostnameVerifier
{
@Override
public boolean verify(String host, SSLSession arg1)
{
// Logger.d(host);
return true;
}
}
private static class EmptyX509TrustManager implements X509TrustManager
{
public EmptyX509TrustManager()
{
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException
{
// Logger.d(authType);
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
{
// Logger.d(Arrays.asList(chain)+"");
}
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
}
private static class AliasKeyManager implements X509KeyManager
{
private KeyStore _ks;
private String _alias;
private String _password;
public AliasKeyManager(KeyStore ks, String alias, String password)
{
_ks = ks;
_alias = alias;
_password = password;
}
public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2)
{
return _alias;
}
public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2)
{
return _alias;
}
public String[] getClientAliases(String arg0, Principal[] arg1)
{
return new String[] { _alias };
}
public String[] getServerAliases(String arg0, Principal[] arg1)
{
return new String[] { _alias };
}
public X509Certificate[] getCertificateChain(String arg0)
{
try
{
java.security.cert.Certificate[] certificates = this._ks.getCertificateChain(_alias);
X509Certificate[] x509Certificates = new X509Certificate[certificates.length];
System.arraycopy(certificates, 0, x509Certificates, 0, certificates.length);
return x509Certificates;
} catch (Exception e)
{
e.printStackTrace();
return null;
}
}
public PrivateKey getPrivateKey(String arg0)
{
try
{
return (PrivateKey) _ks.getKey(_alias, _password == null ? null : _password.toCharArray());
} catch (Exception e)
{
e.printStackTrace();
return null;
}
}
}
final static String user = "all";
final static char[] password = "xxxxxx".toCharArray();
final static String auth = "admin";
public static final String url = "192.168.10.105";
public static MongoClient getClients()
{
try
{
initSSL();
} catch (Exception e)
{
e.printStackTrace();
}
Builder build = new MongoClientOptions.Builder();
build.sslEnabled(true);
build.sslInvalidHostNameAllowed(true);
build.socketFactory(sss);
MongoClient client = new MongoClient(Arrays.asList(new ServerAddress(url, 27001)),
Arrays.asList(MongoCredential.createCredential(user, auth, password)), build.build());
return client;
}
Mains()
{
//關閉Mongodb除錯輸出
java.util.logging.Logger.getLogger("").setLevel(java.util.logging.Level.OFF);
try (MongoClient client = getClients())
{
showDBs(client);
MongoDatabase db = client.getDatabase("admin");
showCollections(db);
// getRoles(db);
db = client.getDatabase("my");
MongoCollection<Document> col = db.getCollection("logs");
ArrayList<Document> list = col.find().into(new ArrayList<Document>());
if (list.isEmpty())
{
ArrayList<Document> documents = new ArrayList<>();
for (int i = 0; i < 10; i++)
{
documents.add(new Document("index", i).append("uid", UUID.randomUUID().toString()));
}
col.insertMany(documents);
} else
{
Logger.d("list size=" + list.size());
Logger.d(new Document("res", list).toJson());
if (list.size() < 10)
{
col.drop();
}
}
}
}
/**
* @param args
*/
public static void main(String[] args)
{
new Mains();
}
}