!72 创建ssl所需相关文件

Merge pull request !72 from 薛蒙恩/split_ssl
This commit is contained in:
opengauss-bot 2022-12-06 08:34:40 +00:00 committed by Gitee
commit 4d28a8cfea
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
5 changed files with 224 additions and 11 deletions

View File

@ -61,14 +61,12 @@ def checkXMLFile(xmlFile):
if not os.access(xmlFile, os.R_OK):
CMLog.exitWithError(ErrorCode.GAUSS_501["GAUSS_50100"] % (xmlFile, "current user"))
def checkHostsTrust(hosts, localhost = ""):
def checkHostsTrust(hosts):
"""
check trust between current host and the given hosts
"""
hostsWithoutTrust = []
for host in hosts:
if host == localhost:
continue
checkTrustCmd = "ssh -o ConnectTimeout=3 -o ConnectionAttempts=5 -o PasswordAuthentication=no " \
"-o StrictHostKeyChecking=no %s 'pwd > /dev/null'" % host
status, output = subprocess.getstatusoutput(checkTrustCmd)

82
tool/cm_tool/CreateCMCACert.sh Executable file
View File

@ -0,0 +1,82 @@
#!/bin/bash
#############################################################################
# Copyright (c) 2022 Huawei Technologies Co.,Ltd.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms
# and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# ----------------------------------------------------------------------------
# Description : CreateCMCACert.sh
#############################################################################
set -e
envfile=$1
if [ "$envfile" = "" ]; then
echo "Envfile is needed."
exit 1
fi
activePeriod=$2
if [ "$activePeriod" == "" ]; then
activePeriod=10950
fi
read -s passwd
source $envfile
certPath=$GAUSSHOME/share/sslcert/cm
if [ ! -f "$certPath/openssl.cnf" ]; then
echo "CM ssl conf does not exist."
exit 1
fi
export OPENSSL_CONF=$GAUSSHOME/share/sslcert/gsql/openssl.cnf
if [ ! -f "$OPENSSL_CONF" ]; then
echo "ssl config file does not exist."
exit 1
fi
# generate root cert
## cakey.pem
echo "$passwd" | openssl genrsa -aes256 -f4 -passout stdin -out $certPath/cakey.pem 2048
## cacert.pem
echo "$passwd" | openssl req -new -x509 -passin stdin -days $activePeriod -key $certPath/cakey.pem -out $certPath/cacert.pem -subj "/C=CN/ST=NULL/L=NULL/O=NULL/OU=NULL/CN=CA"
# generate server and client cert
for role in "server" "client";
do
## key
echo "$passwd" | openssl genrsa -aes256 -passout stdin -out $certPath/$role.key 2048
## csr
echo "$passwd" | openssl req -new -key $certPath/$role.key -passin stdin -out $certPath/$role.csr -subj "/C=CN/ST=NULL/L=NULL/O=NULL/OU=NULL/CN=$role"
## crt
echo "$passwd" | openssl x509 -req -days $activePeriod -in $certPath/$role.csr -CA $certPath/cacert.pem -CAkey $certPath/cakey.pem -passin stdin -CAcreateserial -out $certPath/$role.crt -extfile $certPath/openssl.cnf
done
# generate server cipher and rand
expect -c "
spawn cm_ctl encrypt -M server -D $certPath;
expect {
\"*password*\" { send \"$passwd\r\"; exp_continue }
}
"
# generate client cipher and rand
expect -c "
spawn cm_ctl encrypt -M client -D $certPath;
expect {
\"*password*\" { send \"$passwd\r\"; exp_continue }
}
"
# set the password to null and unset it
passwd=""
unset passwd
# change to readonly
chmod 400 $certPath/*

View File

@ -18,13 +18,13 @@
# Description : InstallImpl.py
#############################################################################
from curses.ascii import isdigit, islower, isupper
import os
import re
import subprocess
import xml.etree.cElementTree as ETree
import getpass
from ErrorCode import ErrorCode
from Common import executeCmdOnHost
from CMLog import CMLog
class InstallImpl:
def __init__(self, install):
@ -139,7 +139,6 @@ class InstallImpl:
cmd = """
cp {gaussHome}/share/config/cm_server.conf.sample {cmdir}/cm_server/cm_server.conf
sed 's#log_dir = .*#log_dir = {gaussLog}/cm/cm_server#' {cmdir}/cm_server/cm_server.conf -i
sed 's/enable_ssl.*=.*on/enable_ssl = off/g' {cmdir}/cm_server/cm_server.conf -i
""".format(gaussHome=self.gaussHome, gaussLog=self.gaussLog, cmdir=cmdir)
status, output = self.executeCmdOnHost(host, cmd)
if status != 0:
@ -154,7 +153,6 @@ class InstallImpl:
cp {gaussHome}/share/config/cm_agent.conf.sample {cmdir}/cm_agent/cm_agent.conf &&
sed 's#log_dir = .*#log_dir = {gaussLog}/cm/cm_agent#' {cmdir}/cm_agent/cm_agent.conf -i &&
sed 's#unix_socket_directory = .*#unix_socket_directory = {gaussHome}#' {cmdir}/cm_agent/cm_agent.conf -i
sed 's/enable_ssl.*=.*on/enable_ssl = off/g' {cmdir}/cm_agent/cm_agent.conf -i
""".format(gaussHome=self.gaussHome, gaussLog=self.gaussLog, cmdir=cmdir)
status, output = self.executeCmdOnHost(host, cmd)
if status != 0:
@ -201,7 +199,6 @@ class InstallImpl:
# set crontab on other hosts
setCronCmd = "crontab %s" % cronContentTmpFile
cleanTmpFileCmd = "rm %s -f" % cronContentTmpFile
import getpass
username = getpass.getuser()
killMonitorCmd = "pkill om_monitor -u %s; " % username
for host in self.hostnames:
@ -299,6 +296,139 @@ class InstallImpl:
if status != 0:
self.logger.logExit("Failed to refresh static file." + output)
@staticmethod
def checkPassword(passwordCA):
minPasswordLen = 8
maxPasswordLen = 15
kinds = [0, 0, 0, 0]
specLetters = "~!@#$%^&*()-_=+\\|[{}];:,<.>/?"
if len(passwordCA) < minPasswordLen:
print("Invalid password, it must contain at least eight characters.")
return False
if len(passwordCA) > maxPasswordLen:
print("Invalid password, it must contain at most fifteen characters.")
return False
for c in passwordCA:
if isdigit(c):
kinds[0] += 1
elif isupper(c):
kinds[1] += 1
elif islower(c):
kinds[2] += 1
elif c in specLetters:
kinds[3] += 1
else:
print("The password contains illegal character: %s." % c)
return False
kindsNum = 0
for k in kinds:
if k > 0:
kindsNum += 1
if kindsNum < 3:
print("The password must contain at least three kinds of characters.")
return False
return True
def _getPassword(self):
passwordCA = ""
passwordCA2 = ""
tryCount = 0
while tryCount < 3:
passwordCA = getpass.getpass("Please input the password for ca cert:")
passwordCA2 = getpass.getpass("Please input the password for ca cert again:")
if passwordCA != passwordCA2:
tryCount += 1
self.logger.printMessage("The password enterd twice do not match.")
continue
if not InstallImpl.checkPassword(passwordCA):
tryCount += 1
continue
break
if tryCount == 3:
self.logger.logExit("Maximum number of attempts has been reached.")
return passwordCA
def _createCMSslConf(self, certPath):
"""
Generate config file.
"""
self.logger.debug("OPENSSL: Create config file.")
v3CaL = [
"[ v3_ca ]",
"subjectKeyIdentifier=hash",
"authorityKeyIdentifier=keyid:always,issuer:always",
"basicConstraints = CA:true",
"keyUsage = keyCertSign,cRLSign",
]
v3Ca = os.linesep.join(v3CaL)
# Create config file.
with open(os.path.join(certPath, "openssl.cnf"), "w") as fp:
# Write config item of Signature
fp.write(v3Ca)
self.logger.debug("OPENSSL: Successfully create config file.")
def _cleanUselessFile(self):
"""
Clean useless files
:return: NA
"""
certPath = os.path.join(self.gaussHome, "share/sslcert/cm")
keyFiles = ["cacert.pem", "server.crt", "server.key", "client.crt", "client.key",
"server.key.cipher", "server.key.rand", "client.key.cipher", "client.key.rand"]
for fileName in os.listdir(certPath):
filePath = os.path.join(certPath, fileName)
if fileName not in keyFiles:
os.remove(filePath)
def _createCMCALocal(self):
self.logger.debug("Creating Cm ca files locally.")
certPath = os.path.join(self.gaussHome, "share/sslcert/cm")
mkdirCmd = "rm %s -rf; mkdir %s" % (certPath, certPath)
status, output = subprocess.getstatusoutput(mkdirCmd)
if status != 0:
self.logger.debug("Command: %s\nStatus: %sOutput: %s" % (mkdirCmd, status, output))
self.logger.logExit("Failed to create cert path.")
self._createCMSslConf(certPath)
curPath = os.path.split(os.path.realpath(__file__))[0]
createCMCACert = os.path.realpath(os.path.join(curPath, "CreateCMCACert.sh"))
passwd = self._getPassword()
cmd = "echo \"%s\" | sh %s %s" % (passwd, createCMCACert, self.envFile)
# once used, set password to null and release it
passwd = ""
del passwd
status, output = subprocess.getstatusoutput(cmd)
cmd = ""
del cmd
if status != 0:
self.logger.logExit("Failed to create cm ca cert file.\n" + output)
self._cleanUselessFile()
def _distributeCA(self):
self.logger.debug("Distributing CM ca files to other hosts.")
certPath = os.path.join(self.gaussHome, "share/sslcert/cm")
createCertPathCmd = "rm {certPath} -rf; mkdir {certPath}; chmod 700 {certPath}".format(
certPath=certPath)
for host in self.hostnames:
if host == self.localhostName:
continue
status, output = self.executeCmdOnHost(host, createCertPathCmd)
if status != 0:
errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" (createCertPathCmd, status, output)
self.logger.debug(errorDetail)
self.logger.logExit("Failed to create path of CA for CM on host %s." % host)
scpCmd = "scp {certPath}/* {host}:{certPath}".format(certPath=certPath, host=host)
status, output = subprocess.getstatusoutput(scpCmd)
if status != 0:
errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" (scpCmd, status, output)
self.logger.debug(errorDetail)
self.logger.logExit("Failed to create CA for CM.")
def createCMCA(self):
self.logger.log("Creating CM ca files.")
self._createCMCALocal()
self._distributeCA()
def run(self):
self.logger.log("Start to install cm tool.")
self.prepareCMPath()
@ -306,6 +436,7 @@ class InstallImpl:
self.createManualStartFile()
self.initCMServer()
self.initCMAgent()
self.createCMCA()
self._refreshStaticFile()
self.setMonitorCrontab()
self.startCluster()

View File

@ -114,6 +114,8 @@ General options:
CMLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] % '-cmpkg' + ".")
if not os.path.exists(self.cmpkg):
CMLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50201"] % self.cmpkg)
if not os.path.isfile(self.cmpkg):
CMLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50210"] % ("cmpkg " + self.cmpkg))
if self.envFile == "":
self.envFile = os.path.join(os.environ['HOME'], ".bashrc")
@ -235,7 +237,7 @@ General options:
self.logger.logExit("\"cmDir\" of all nodes must be provided.")
def checkHostTrust(self):
checkHostsTrust(self.hostnames, self.localhostName)
checkHostsTrust(self.hostnames)
def initLogger(self):
logPath = os.path.join(self.gaussLog, "cm", "cm_tool")

View File

@ -249,7 +249,7 @@ General options:
if host == self.localhostName:
isLocal = True
cmd = "source %s; cd $GAUSSHOME/bin; rm -f om_monitor* cm_agent* cm_server* " \
"cm_ctl* cm_persist* *manual*start*; cd -" % self.envFile
"cm_ctl* cm_persist* *manual*start* promote_mode_cms; cd -" % self.envFile
status, output = executeCmdOnHost(host, cmd, isLocal)
if status != 0:
errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" % (cmd, status, output)
@ -267,7 +267,7 @@ General options:
CMLog.exitWithError(ErrorCode.GAUSS_501["GAUSS_50105"])
def checkHostTrust(self):
checkHostsTrust(self.hostnames, self.localhostName)
checkHostsTrust(self.hostnames)
def run(self):
self.checkExeUser()