Merge pull request #1062 from YunoHost/move-local-ca-mangement-to-regenconf

Refactor local CA management for more consistency and simpler postinstall
This commit is contained in:
Alexandre Aubin 2021-01-31 16:17:20 +01:00 committed by GitHub
commit 68e24c986a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 116 deletions

View file

@ -3,71 +3,81 @@
set -e
ssl_dir="/usr/share/yunohost/yunohost-config/ssl/yunoCA"
ynh_ca="/etc/yunohost/certs/yunohost.org/ca.pem"
ynh_crt="/etc/yunohost/certs/yunohost.org/crt.pem"
ynh_key="/etc/yunohost/certs/yunohost.org/key.pem"
openssl_conf="/usr/share/yunohost/templates/ssl/openssl.cnf"
regen_local_ca() {
domain="$1"
echo -e "\n# Creating local certification authority with domain=$domain\n"
# create certs and SSL directories
mkdir -p "/etc/yunohost/certs/yunohost.org"
mkdir -p "${ssl_dir}/"{ca,certs,crl,newcerts}
pushd ${ssl_dir}
# (Update the serial so that it's specific to this very instance)
# N.B. : the weird RANDFILE thing comes from:
# https://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean
RANDFILE=.rnd openssl rand -hex 19 > serial
rm -f index.txt
touch index.txt
cp /usr/share/yunohost/templates/ssl/openssl.cnf openssl.ca.cnf
sed -i s/yunohost.org/${domain}/g openssl.ca.cnf
openssl req -x509 \
-new \
-config openssl.ca.cnf \
-days 3650 \
-out ca/cacert.pem \
-keyout ca/cakey.pem \
-nodes \
-batch \
-subj /CN=${domain}/O=${domain%.*} 2>&1
chmod 640 ca/cacert.pem
chmod 640 ca/cakey.pem
cp ca/cacert.pem $ynh_ca
ln -sf "$ynh_ca" /etc/ssl/certs/ca-yunohost_crt.pem
update-ca-certificates
popd
}
do_init_regen() {
if [[ $EUID -ne 0 ]]; then
echo "You must be root to run this script" 1>&2
exit 1
fi
LOGFILE="/tmp/yunohost-ssl-init"
echo "Initializing a local SSL certification authority ..."
echo "(logs available in $LOGFILE)"
rm -f $LOGFILE
touch $LOGFILE
# create certs and SSL directories
mkdir -p "/etc/yunohost/certs/yunohost.org"
mkdir -p "${ssl_dir}/"{ca,certs,crl,newcerts}
# initialize some files
# N.B. : the weird RANDFILE thing comes from:
# https://stackoverflow.com/questions/94445/using-openssl-what-does-unable-to-write-random-state-mean
[[ -f "${ssl_dir}/serial" ]] \
|| RANDFILE=.rnd openssl rand -hex 19 > "${ssl_dir}/serial"
[[ -f "${ssl_dir}/index.txt" ]] \
|| touch "${ssl_dir}/index.txt"
openssl_conf="/usr/share/yunohost/templates/ssl/openssl.cnf"
ynh_ca="/etc/yunohost/certs/yunohost.org/ca.pem"
ynh_crt="/etc/yunohost/certs/yunohost.org/crt.pem"
ynh_key="/etc/yunohost/certs/yunohost.org/key.pem"
LOGFILE=/tmp/yunohost-ssl-init
echo "" > $LOGFILE
chown root:root $LOGFILE
chmod 640 $LOGFILE
# create default certificates
if [[ ! -f "$ynh_ca" ]]; then
echo -e "\n# Creating the CA key (?)\n" >>$LOGFILE
openssl req -x509 \
-new \
-config "$openssl_conf" \
-days 3650 \
-out "${ssl_dir}/ca/cacert.pem" \
-keyout "${ssl_dir}/ca/cakey.pem" \
-nodes -batch >>$LOGFILE 2>&1
cp "${ssl_dir}/ca/cacert.pem" "$ynh_ca"
ln -sf "$ynh_ca" /etc/ssl/certs/ca-yunohost_crt.pem
update-ca-certificates
regen_local_ca yunohost.org >>$LOGFILE
fi
if [[ ! -f "$ynh_crt" ]]; then
echo -e "\n# Creating initial key and certificate (?)\n" >>$LOGFILE
echo -e "\n# Creating initial key and certificate \n" >>$LOGFILE
openssl req -new \
-config "$openssl_conf" \
-days 730 \
-out "${ssl_dir}/certs/yunohost_csr.pem" \
-keyout "${ssl_dir}/certs/yunohost_key.pem" \
-nodes -batch >>$LOGFILE 2>&1
-nodes -batch &>>$LOGFILE
openssl ca \
-config "$openssl_conf" \
-days 730 \
-in "${ssl_dir}/certs/yunohost_csr.pem" \
-out "${ssl_dir}/certs/yunohost_crt.pem" \
-batch >>$LOGFILE 2>&1
-batch &>>$LOGFILE
chmod 640 "${ssl_dir}/certs/yunohost_key.pem"
chmod 640 "${ssl_dir}/certs/yunohost_crt.pem"
@ -80,6 +90,8 @@ do_init_regen() {
chown -R root:ssl-cert /etc/yunohost/certs/yunohost.org/
chmod o-rwx /etc/yunohost/certs/yunohost.org/
install -D -m 644 $openssl_conf "${ssl_dir}/openssl.cnf"
}
do_pre_regen() {
@ -93,22 +105,16 @@ do_pre_regen() {
do_post_regen() {
regen_conf_files=$1
# Ensure that index.txt exists
index_txt=/usr/share/yunohost/yunohost-config/ssl/yunoCA/index.txt
[[ -f "${index_txt}" ]] || {
if [[ -f "${index_txt}.saved" ]]; then
# use saved database from 2.2
cp "${index_txt}.saved" "${index_txt}"
elif [[ -f "${index_txt}.old" ]]; then
# ... or use the state-1 database
cp "${index_txt}.old" "${index_txt}"
else
# ... or create an empty one
touch "${index_txt}"
fi
}
current_local_ca_domain=$(openssl x509 -in $ynh_ca -text | tr ',' '\n' | grep Issuer | awk '{print $4}')
main_domain=$(cat /etc/yunohost/current_host)
# TODO: regenerate certificates if conf changed?
if [[ "$current_local_ca_domain" != "$main_domain" ]]
then
regen_local_ca $main_domain
# Idk how useful this is, but this was in the previous python code (domain.main_domain())
ln -sf /etc/yunohost/certs/$domain/crt.pem /etc/ssl/certs/yunohost_crt.pem
ln -sf /etc/yunohost/certs/$domain/key.pem /etc/ssl/private/yunohost_key.pem
fi
}
FORCE=${2:-0}

View file

@ -627,8 +627,6 @@
"user_update_failed": "Could not update user {user}: {error}",
"user_updated": "User info changed",
"yunohost_already_installed": "YunoHost is already installed",
"yunohost_ca_creation_failed": "Could not create certificate authority",
"yunohost_ca_creation_success": "Local certification authority created.",
"yunohost_configured": "YunoHost is now configured",
"yunohost_installing": "Installing YunoHost...",
"yunohost_not_installed": "YunoHost is not correctly installed. Please run 'yunohost tools postinstall'",

View file

@ -30,6 +30,7 @@ from moulinette import m18n, msettings
from moulinette.core import MoulinetteError
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import write_to_file
from yunohost.app import app_ssowatconf, _installed_apps, _get_app_settings, _get_conflicting_apps
from yunohost.regenconf import regen_conf, _force_clear_hashes, _process_regen_conf
@ -318,36 +319,20 @@ def domain_main_domain(operation_logger, new_main_domain=None):
operation_logger.start()
# Apply changes to ssl certs
ssl_key = "/etc/ssl/private/yunohost_key.pem"
ssl_crt = "/etc/ssl/private/yunohost_crt.pem"
new_ssl_key = "/etc/yunohost/certs/%s/key.pem" % new_main_domain
new_ssl_crt = "/etc/yunohost/certs/%s/crt.pem" % new_main_domain
try:
if os.path.exists(ssl_key) or os.path.lexists(ssl_key):
os.remove(ssl_key)
if os.path.exists(ssl_crt) or os.path.lexists(ssl_crt):
os.remove(ssl_crt)
write_to_file('/etc/yunohost/current_host', new_main_domain)
os.symlink(new_ssl_key, ssl_key)
os.symlink(new_ssl_crt, ssl_crt)
_set_maindomain(new_main_domain)
_set_hostname(new_main_domain)
except Exception as e:
logger.warning("%s" % e, exc_info=1)
raise YunohostError('main_domain_change_failed')
_set_hostname(new_main_domain)
# Generate SSOwat configuration file
app_ssowatconf()
# Regen configurations
try:
with open('/etc/yunohost/installed', 'r'):
regen_conf()
except IOError:
pass
if os.path.exists('/etc/yunohost/installed'):
regen_conf()
logger.success(m18n.n('main_domain_changed'))
@ -385,11 +370,6 @@ def _get_maindomain():
return maindomain
def _set_maindomain(domain):
with open('/etc/yunohost/current_host', 'w') as f:
f.write(domain)
def _build_dns_conf(domain, ttl=3600, include_empty_AAAA_if_no_ipv6=False):
"""
Internal function that will returns a data structure containing the needed

View file

@ -327,37 +327,7 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False,
os.system('chmod 644 /etc/ssowat/conf.json.persistent')
# Create SSL CA
regen_conf(['ssl'], force=True)
ssl_dir = '/usr/share/yunohost/yunohost-config/ssl/yunoCA'
# (Update the serial so that it's specific to this very instance)
os.system("openssl rand -hex 19 > %s/serial" % ssl_dir)
commands = [
'rm %s/index.txt' % ssl_dir,
'touch %s/index.txt' % ssl_dir,
'cp %s/openssl.cnf %s/openssl.ca.cnf' % (ssl_dir, ssl_dir),
'sed -i s/yunohost.org/%s/g %s/openssl.ca.cnf ' % (domain, ssl_dir),
'openssl req -x509 -new -config %s/openssl.ca.cnf -days 3650 -out %s/ca/cacert.pem -keyout %s/ca/cakey.pem -nodes -batch -subj /CN=%s/O=%s' % (ssl_dir, ssl_dir, ssl_dir, domain, os.path.splitext(domain)[0]),
'cp %s/ca/cacert.pem /etc/ssl/certs/ca-yunohost_crt.pem' % ssl_dir,
'update-ca-certificates'
]
for command in commands:
p = subprocess.Popen(
command.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = p.communicate()
if p.returncode != 0:
logger.warning(out)
raise YunohostError('yunohost_ca_creation_failed')
else:
logger.debug(out)
logger.success(m18n.n('yunohost_ca_creation_success'))
# New domain config
regen_conf(['nsswitch'], force=True)
domain_add(domain, dyndns)
domain_main_domain(domain)