#!/usr/bin/python3 import subprocess import jinja2 import os import configparser import sys config = configparser.ConfigParser() config.read('samba-pki-tools.ini') # # write config file # jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_3cx)) # template = jinja_env.get_template("3CXVoipPhone.j2") # template_variables = { # "name": "TIS (%s)" % get_current_user(), } class TisPKI: def pki_dir(): return config.get('general','pki_dir') def root_ca_certfile(): return os.path.join(TisPKI.pki_dir(),'certs','root_ca.crt') def keyout_path(): return os.path.join(TisPKI.pki_dir(),'private') def csr_path(): return os.path.join(TisPKI.pki_dir(),'csr') def cert_path(): return os.path.join(TisPKI.pki_dir(),'certs') def p12_path(): return os.path.join(TisPKI.pki_dir(),'p12') def check_directories(): print('Check directories') directories_list = ['certs','config','crl','newcerts','private','csr','crl','p12'] if not os.path.isdir(TisPKI.pki_dir()): print(f'Create { TisPKI.pki_dir() } directory') os.makedirs(TisPKI.pki_dir()) for directory in directories_list: directory_path = os.path.join(TisPKI.pki_dir(),directory) if not os.path.isdir(directory_path): print(f'Create { directory_path } directory') os.makedirs(directory_path) if not os.path.isfile(os.path.join(TisPKI.pki_dir(),'index.txt')): with open(os.path.join(TisPKI.pki_dir(),'index.txt'),'w') as file: pass def create_openssl_config(): print('Check Root CA OpenSSL Config') root_ca_config = os.path.join(TisPKI.pki_dir(),'config','openssl_root_ca.ini') root_ca_keyfile = os.path.join(TisPKI.pki_dir(),'private','root_ca.key') if not os.path.isfile(root_ca_config): print('Root CA OpenSSL configfile not exist. Creating...') template_dir = os.path.join('templates') jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir)) root_ca_tmpl = jinja_env.get_template('openssl_root_ca.tmpl') root_ca_tmpl_var = { 'organization_ou': config.get('openssl_config','organization_name') + 'CA', 'default_cert_duration': config.get('openssl_config','default_cert_duration'), 'pki_dir': TisPKI.pki_dir(), 'country': config.get('openssl_config','country'), 'state': config.get('openssl_config','state'), 'city': config.get('openssl_config','city'), 'organization_name': config.get('openssl_config','organization_name'), 'organization_ou': config.get('openssl_config','organization_ou'), 'organization_cn': config.get('openssl_config','organization_cn'), 'crl_uri': config.get('openssl_config','crl_uri') } config_string = root_ca_tmpl.render(root_ca_tmpl_var) with open(root_ca_config,'wt') as file: file.write(config_string) if os.path.isfile(root_ca_config): print('Root CA OpenSSL config file is correctly generated !') else: print('Root CA OpenSSL config already exist. Skip.') # Generate privkey and cert for Root CA if not os.path.isfile(root_ca_keyfile) and not os.path.isfile(TisPKI.root_ca_certfile()): print('Generate CA private key') gen_root_ca = subprocess.run(f'/usr/bin/openssl req -x509 -new -sha512 -config {root_ca_config} -days 3650 -extensions v3_ca -keyout {root_ca_keyfile} -out {TisPKI.root_ca_certfile()} -passout pass:calimero', shell=True, check=True, executable='/bin/bash') if gen_root_ca.returncode == 0: print(subprocess.run(f'openssl x509 -in {TisPKI.root_ca_certfile()} -text -noout', shell=True, check=True, executable='/bin/bash')) else: print('Error on generating Root CA private key') sys.exit(1) else: print('Root CA private key and certificate already exist. Skip.') def generate_dc_certificate(): dc_list = config.get('samba_ad','dc_list') for dc in dc_list.split(','): dc_certfile = os.path.join(TisPKI.pki_dir(),'certs',f'{dc}.crt') dc_keyfile = os.path.join(TisPKI.pki_dir(),'private',f'{dc}.key') dc_csrfile = os.path.join(TisPKI.pki_dir(),'csr',f'{dc}.csr') dc_openssl_configfile = os.path.join(TisPKI.pki_dir(),'config',f'openssl_{dc}.ini') crl_file = os.path.join(TisPKI.pki_dir(),'crl','root_ca.crl') if not os.path.isfile(dc_certfile) and not os.path.isfile(dc_keyfile): print(f'Generate certificate for {dc}') #dc_guid = subprocess.run(f'get_guid.sh {dc}',shell=True) dc_guid = '51a10f19f84f8d4abda4dee35fe096c6' print(dc_guid) template_dir = ('templates') jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir)) dc_tmpl = jinja_env.get_template('openssl_server_cert.tmpl') dc_tmpl_var = { 'dc_name': f"{dc}", 'dc_guid': dc_guid, 'crl_uri': config.get('openssl_config','crl_uri'), 'pki_dir': TisPKI.pki_dir(), 'default_cert_duration': config.get('openssl_config','default_cert_duration'), 'country': config.get('openssl_config','country'), 'state': config.get('openssl_config','state'), 'city': config.get('openssl_config','city'), 'organization_name': config.get('openssl_config','organization_name'), 'organization_ou': config.get('openssl_config','organization_ou') } config_string = dc_tmpl.render(dc_tmpl_var) with open(dc_openssl_configfile,'wt') as file: file.write(config_string) if os.path.isfile(dc_openssl_configfile): print(f'{dc} OpenSSL configfile is correctly generated !') print(f'Generate private key and CSR for {dc}') print(subprocess.run(f"openssl req -new -addext 'subjectAltName = email:copy' -newkey rsa:4096 -keyout {dc_keyfile} -out {dc_csrfile} -config {dc_openssl_configfile} -passout pass:calimero" , shell=True, check=True, executable='/bin/bash')) if os.path.isfile(dc_csrfile): print(f'Sign certificate for {dc}') print(subprocess.run(f'openssl ca -config {dc_openssl_configfile} -extensions usr_cert_mskdc -days 3650 -notext -md sha512 -create_serial -in {dc_csrfile} -out {dc_certfile}', shell=True, check=True, executable='/bin/bash')) if os.path.isfile(dc_certfile): print('Concatenation of DC and Root cert') subprocess.run(f'cat {dc_certfile} {TisPKI.root_ca_certfile()} > {dc_certfile}_full',shell=True) else: print(f'{dc} private key and certificate already exist ! Revoke certificate before regenerate') print('Generate CRL') subprocess.run(f'openssl ca -config {dc_openssl_configfile} -gencrl -out {crl_file}',shell=True) def generate_user_certificate(): openssl_user_file = os.path.join(TisPKI.pki_dir(),'config','openssl_user.ini') template_dir = ('templates') jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir)) user_tmpl = jinja_env.get_template('openssl_user_cert.tmpl') user_tmpl_var = { 'crl_uri': config.get('openssl_config','crl_uri'), 'pki_dir': TisPKI.pki_dir(), 'default_cert_duration': config.get('openssl_config','default_cert_duration'), 'country': config.get('openssl_config','country'), 'state': config.get('openssl_config','state'), 'city': config.get('openssl_config','city'), 'organization_name': config.get('openssl_config','organization_name'), 'organization_ou': config.get('openssl_config','organization_ou') } config_string = user_tmpl.render(user_tmpl_var) with open(openssl_user_file,'wt') as file: file.write(config_string) if os.path.isfile(openssl_user_file): print(f'User OpenSSL configfile is correctly generated !') print('Enter username') username = input() upn = f'{username}@kg.tranquil.it' print(f'Generate private key for {upn}') print(subprocess.run(f"openssl req -new -newkey rsa:4096 -keyout {TisPKI.keyout_path()}/{username}.key -out {TisPKI.csr_path()}/{username}.csr -config <(cat {openssl_user_file} <(cat <<-EOF\n[ sanuser ]\notherName=msUPN;UTF8:{upn}\nemail=copy\nEOF\n)\n)",shell=True,check=True, executable='/bin/bash')) print(f'Sign certificate') print(subprocess.run(f'openssl ca -extensions usr_cert_scarduser -days 730 -notext -md sha512 -create_serial -in {TisPKI.csr_path()}/{username}.csr -out {TisPKI.cert_path()}/{username}.crt -config <(cat {openssl_user_file} <(cat <<-EOF\n[ sanuser ]\notherName=msUPN;UTF8:{upn}\nemail=copy\nEOF\n)\n)',shell=True,check=True, executable='/bin/bash')) print('Remove password in rsa key') print(subprocess.run(f'openssl rsa -in {TisPKI.keyout_path()}/{username}.key -out {TisPKI.keyout_path()}/{username}-nopasswd.key',shell=True,check=True, executable='/bin/bash')) print('Create p12') print(subprocess.run(f'openssl pkcs12 -export -inkey {TisPKI.keyout_path()}/{username}-nopasswd.key -in {TisPKI.cert_path()}/{username}.crt -out {TisPKI.p12_path()}/{username}.p12', shell=True,check=True, executable='/bin/bash')) def main(): if config.get('general','pki_dir'): check_directories() else: print('No pki_dir set in samba-pki-tools.ini') sys.exit(1) if config.get('openssl_config','root_name'): create_openssl_config() else: print('No root_name set in samba-pki-tools.ini') sys.exit(1) if config.get('samba_ad','dc_list'): generate_dc_certificate() else: print('No dc_list set in samba-pki-tools.ini') sys.exit(1) generate_user_certificate() if __name__ == '__main__': main()