harbor/make/photon/prepare/utils/cert.py
DQ dcc6950af7 Feat: auto install ca in registry
Signed-off-by: DQ <dengq@vmware.com>
2020-03-18 19:22:09 +08:00

132 lines
4.8 KiB
Python

# Get or generate private key
import os, subprocess, shutil
from pathlib import Path
from subprocess import DEVNULL
from g import DEFAULT_GID, DEFAULT_UID, trust_ca_dir, storage_ca_bundle_filename
from .misc import (
mark_file,
generate_random_string,
check_permission,
stat_decorator,
get_realpath)
SSL_CERT_PATH = os.path.join("/etc/cert", "server.crt")
SSL_CERT_KEY_PATH = os.path.join("/etc/cert", "server.key")
def _get_secret(folder, filename, length=16):
key_file = os.path.join(folder, filename)
if os.path.isfile(key_file):
with open(key_file, 'r') as f:
key = f.read()
print("loaded secret from file: %s" % key_file)
mark_file(key_file)
return key
if not os.path.isdir(folder):
os.makedirs(folder)
key = generate_random_string(length)
with open(key_file, 'w') as f:
f.write(key)
print("Generated and saved secret to file: %s" % key_file)
mark_file(key_file)
return key
def get_secret_key(path):
secret_key = _get_secret(path, "secretkey")
if len(secret_key) != 16:
raise Exception("secret key's length has to be 16 chars, current length: %d" % len(secret_key))
return secret_key
def get_alias(path):
alias = _get_secret(path, "defaultalias", length=8)
return alias
@stat_decorator
def create_root_cert(subj, key_path="./k.key", cert_path="./cert.crt"):
rc = subprocess.call(["/usr/bin/openssl", "genrsa", "-out", key_path, "4096"], stdout=DEVNULL, stderr=subprocess.STDOUT)
if rc != 0:
return rc
return subprocess.call(["/usr/bin/openssl", "req", "-new", "-x509", "-key", key_path,\
"-out", cert_path, "-days", "3650", "-subj", subj], stdout=DEVNULL, stderr=subprocess.STDOUT)
@stat_decorator
def create_cert(subj, ca_key, ca_cert, key_path="./k.key", cert_path="./cert.crt"):
cert_dir = os.path.dirname(cert_path)
csr_path = os.path.join(cert_dir, "tmp.csr")
rc = subprocess.call(["/usr/bin/openssl", "req", "-newkey", "rsa:4096", "-nodes","-sha256","-keyout", key_path,\
"-out", csr_path, "-subj", subj], stdout=DEVNULL, stderr=subprocess.STDOUT)
if rc != 0:
return rc
return subprocess.call(["/usr/bin/openssl", "x509", "-req", "-days", "3650", "-in", csr_path, "-CA", \
ca_cert, "-CAkey", ca_key, "-CAcreateserial", "-out", cert_path], stdout=DEVNULL, stderr=subprocess.STDOUT)
def openssl_installed():
shell_stat = subprocess.check_call(["/usr/bin/which", "openssl"], stdout=DEVNULL, stderr=subprocess.STDOUT)
if shell_stat != 0:
print("Cannot find openssl installed in this computer\nUse default SSL certificate file")
return False
return True
def prepare_registry_ca(
private_key_pem_path: Path,
root_crt_path: Path,
old_private_key_pem_path: Path,
old_crt_path: Path):
if not ( private_key_pem_path.exists() and root_crt_path.exists() ):
# From version 1.8 the cert storage path is changed
# if old key paris not exist create new ones
# if old key pairs exist in old place copy it to new place
if not (old_crt_path.exists() and old_private_key_pem_path.exists()):
private_key_pem_path.parent.mkdir(parents=True, exist_ok=True)
root_crt_path.parent.mkdir(parents=True, exist_ok=True)
empty_subj = "/"
create_root_cert(empty_subj, key_path=private_key_pem_path, cert_path=root_crt_path)
mark_file(private_key_pem_path)
mark_file(root_crt_path)
else:
shutil.move(old_crt_path, root_crt_path)
shutil.move(old_private_key_pem_path, private_key_pem_path)
if not check_permission(root_crt_path, uid=DEFAULT_UID, gid=DEFAULT_GID):
os.chown(root_crt_path, DEFAULT_UID, DEFAULT_GID)
if not check_permission(private_key_pem_path, uid=DEFAULT_UID, gid=DEFAULT_GID):
os.chown(private_key_pem_path, DEFAULT_UID, DEFAULT_GID)
def prepare_trust_ca(**kwargs):
def f(path: str, file_name: str):
# check if source file valied
src_path = kwargs.get(path)
if not src_path:
return
real_path = get_realpath(src_path)
if not real_path.exists():
raise Exception('ca file {} is not exist'.format(real_path))
if not real_path.is_file():
raise Exception('{} is not file'.format(real_path))
dst_path = trust_ca_dir.joinpath(file_name)
# check destination dir exist
if not trust_ca_dir.exists():
trust_ca_dir.mkdir(parents=True)
else:
os.remove(dst_path)
# copy src to dst
shutil.copy(src_path, dst_path)
# change ownership and permission
mark_file(dst_path)
for p in (
('internal_https_ca_path', 'harbor_internal_ca.crt'),
('registry_custom_ca_bundle_path', storage_ca_bundle_filename)):
f(*p)