From 79ca16c13928f4ef632d813e7c2780a0750f3858 Mon Sep 17 00:00:00 2001 From: Kevin Guerineau Date: Tue, 7 May 2024 20:54:20 +0200 Subject: [PATCH] [IMP] Generate dc certificates --- common.py | 145 ++++++++++++++++++++++++++------------------------ manage_pki.py | 12 +++++ 2 files changed, 87 insertions(+), 70 deletions(-) diff --git a/common.py b/common.py index 2f0826a..c4fbcfa 100644 --- a/common.py +++ b/common.py @@ -175,7 +175,9 @@ def create_openssl_config(force=False,verbose=False): # Generate privkey and cert for Root CA if not os.path.isfile(TisPKI.root_ca_keyfile()) or not os.path.isfile(TisPKI.root_ca_certfile()): Printing.information('Generate Root 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 {TisPKI.root_ca_keyfile()} -out {TisPKI.root_ca_certfile()}', shell=True, check=False, executable='/bin/bash') + gen_root_ca = subprocess.run(f'/usr/bin/openssl req -x509 -new -sha512 -config {root_ca_config} \ + -days 3650 -extensions v3_ca -keyout {TisPKI.root_ca_keyfile()} -out {TisPKI.root_ca_certfile()}', + shell=True, check=False, executable='/bin/bash') if gen_root_ca.returncode == 0: if verbose: @@ -253,98 +255,101 @@ def create_openssl_intermediate(name, force=False,verbose=False): else: Printing.information('Intermediate CA OpenSSL config already exist. Skip.') - if not os.path.isfile(TisPKI.intermediate_ca_keyfile()) and not os.path.isfile(TisPKI.intermediate_ca_certfile(name)): + if not os.path.isfile(TisPKI.intermediate_ca_keyfile(name)) and not os.path.isfile(TisPKI.intermediate_ca_certfile(name)): Printing.information('Generate Intermediate CA private key and CSR') - gen_intermediate_ca = subprocess.run(f'/usr/bin/openssl req -config {intermediate_ca_config} -new -sha512 -keyout {TisPKI.intermediate_ca_keyfile()} -out {TisPKI.intermediate_csr_path(name)}/{name}_intermediate_ca.csr', shell=True, check=True, executable='/bin/bash') + gen_intermediate_ca = subprocess.run(f"/usr/bin/openssl req -config {intermediate_ca_config} -new -sha512 -keyout {TisPKI.intermediate_ca_keyfile(name)} \ + -out {TisPKI.intermediate_csr_path(name)}/{name.replace(' ','_')}_intermediate_ca.csr", shell=True, check=True, executable='/bin/bash') + Printing.information('Sign Intermediate CA with Root CA') - sign_intermediate_ca = subprocess.run(f"/usr/bin/openssl ca -config {os.path.join(TisPKI.pki_dir(),'config','openssl_root_ca_sign_intermediate.ini')} -extensions v3_intermediate_ca -days 1825 -notext -md sha512 -create_serial -in {TisPKI.intermediate_csr_path(name)}/{name}_intermediate_ca.csr -out {TisPKI.intermediate_ca_certfile(name)}", shell=True, check=True, executable='/bin/bash' ) + sign_intermediate_ca = subprocess.run(f"/usr/bin/openssl ca -config {os.path.join(TisPKI.root_config_path(),'openssl_root_ca_sign_intermediate.ini')} \ + -extensions v3_intermediate_ca -days 1825 -notext -md sha512 -create_serial -in {TisPKI.intermediate_csr_path(name)}/{name.replace(' ','_')}_intermediate_ca.csr \ + -out {TisPKI.intermediate_ca_certfile(name)}", shell=True, check=True, executable='/bin/bash') + if sign_intermediate_ca.returncode == 0: if verbose: subprocess.run(f'openssl x509 -in {TisPKI.intermediate_ca_certfile(name)} -text', shell=True, check=True, executable='/bin/bash') Printing.success(f'Intermediate CA Certfile is stored in : {TisPKI.intermediate_ca_certfile(name)}') - input("Press Enter to continue...") else: Printing.error('Error on generating Intermediate CA private key') sys.exit(1) else: Printing.warning('Intermediate CA private key and certificate already exist. Skip.') -## if not os.path.isfile(intermediate_crl_file): -## print('Generate CRL') -## subprocess.run(f'openssl ca -config {intermediate_ca_config} -gencrl -out {intermediate_crl_file}',shell=True) +def generate_dc_certificate(dc_name=None, ca_name=None, force=False, verbose=False): -def generate_dc_certificate(): - dc_list = config.get('samba_ad','dc_list') + if ca_name != "Root": + dc_certfile = os.path.join(TisPKI.intermediate_cert_path(ca_name),f'{dc_name}.crt') + dc_keyfile = os.path.join(TisPKI.intermediate_keyout_path(ca_name),f'{dc_name}.key') + dc_csrfile = os.path.join(TisPKI.intermediate_csr_path(ca_name),f'{dc_name}.csr') + dc_openssl_configfile = os.path.join(TisPKI.intermediate_config_path(ca_name),f'openssl_{dc_name}.ini') + crl_file = os.path.join(TisPKI.intermediate_crl_path(ca_name),'intermediate_ca.crl') + dc_ca_keyfile = TisPKI.intermediate_ca_keyfile(ca_name) + dc_ca_certfile = TisPKI.intermediate_cert_path(ca_name) + crl_uri = config.get('openssl_config','intermediate_crl_uri') + pki_dir = TisPKI.pki_intermediate_dir() + else: + dc_certfile = os.path.join(TisPKI.root_cert_path(),f'{dc_name}.crt') + dc_keyfile = os.path.join(TisPKI.root_keyout_path(),f'{dc_name}.key') + dc_csrfile = os.path.join(TisPKI.root_csr_path(),f'{dc_name}.csr') + dc_openssl_configfile = os.path.join(TisPKI.root_config_path(),f'openssl_{dc_name}.ini') + crl_file = os.path.join(TisPKI.root_crl_path(),'root_ca.crl') + dc_ca_keyfile = os.path.join(TisPKI.root_keyout_path(),'root_ca.key') + dc_ca_certfile = os.path.join(TisPKI.root_cert_path(),'root_ca.crt') + crl_uri = config.get('openssl_config','crl_uri') + pki_dir = TisPKI.pki_dir() - for dc in dc_list.split(','): - if TisPKI.intermediate_ca: - dc_certfile = os.path.join(TisPKI.intermediate_cert_path(),f'{dc}.crt') - dc_keyfile = os.path.join(TisPKI.intermediate_keyout_path(),f'{dc}.key') - dc_csrfile = os.path.join(TisPKI.intermediate_csr_path(),f'{dc}.csr') - dc_openssl_configfile = os.path.join(TisPKI.intermediate_config_path(),f'openssl_{dc}.ini') - crl_file = os.path.join(TisPKI.intermediate_crl_path(),'intermediate_ca.crl') - dc_ca_keyfile = os.path.join(TisPKI.intermediate_keyout_path(),'intermediate_ca.key') - dc_ca_certfile = os.path.join(TisPKI.intermediate_cert_path(),'intermediate_ca.crt') - crl_uri = config.get('openssl_config','intermediate_crl_uri') - pki_dir = TisPKI.pki_intermediate_dir() + if not os.path.isfile(dc_certfile) and not os.path.isfile(dc_keyfile): + Printing.information(f'Generate certificate for {dc_name}') + + dc_guid = subprocess.run('/bin/bash get_guid.sh',shell=True, check=True, executable='/bin/bash') + if dc_guid.returncode != 0: + Printing.error('Unable to find dc_guid') + sys.exit(1) else: - dc_certfile = os.path.join(TisPKI.root_cert_path(),f'{dc}.crt') - dc_keyfile = os.path.join(TisPKI.root_keyout_path(),f'{dc}.key') - dc_csrfile = os.path.join(TisPKI.root_csr_path(),f'{dc}.csr') - dc_openssl_configfile = os.path.join(TisPKI.root_config_path(),f'openssl_{dc}.ini') - crl_file = os.path.join(TisPKI.root_crl_path(),'root_ca.crl') - dc_ca_keyfile = os.path.join(TisPKI.root_keyout_path(),'root_ca.key') - dc_ca_certfile = os.path.join(TisPKI.root_cert_path(),'root_ca.crt') - crl_uri = config.get('openssl_config','crl_uri') - pki_dir = TisPKI.pki_dir() + dc_guid = str(subprocess.check_output(f'/bin/bash get_guid.sh',shell=True).decode("utf-8")).strip() - if not os.path.isfile(dc_certfile) and not os.path.isfile(dc_keyfile): - print(f'Generate certificate for {dc}') - input("Press Enter to continue...") - dc_guid = subprocess.run('/bin/bash get_guid.sh',shell=True, check=True, executable='/bin/bash') - if dc_guid.returncode != 0: - print('Unable to find dc_guid') - sys.exit(1) - else: - dc_guid = str(subprocess.check_output(f'/bin/bash get_guid.sh',shell=True).decode("utf-8")).strip() - print(str(dc_guid).strip()) - 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': str(dc_guid), - 'crl_uri': crl_uri, - 'pki_dir': 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'), - 'dc_ca_keyfile': dc_ca_keyfile, - 'dc_ca_certfile': dc_ca_certfile - } + if verbose: + Printing.information(f'{dc_name} GUID is : ', str(dc_guid).strip()) - config_string = dc_tmpl.render(dc_tmpl_var) - with open(dc_openssl_configfile,'wt') as file: - file.write(config_string) + 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_name}", + 'dc_guid': str(dc_guid), + 'crl_uri': crl_uri, + 'pki_dir': 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'), + 'dc_ca_keyfile': dc_ca_keyfile, + 'dc_ca_certfile': dc_ca_certfile + } - if os.path.isfile(dc_openssl_configfile): - print(f'{dc} OpenSSL configfile is correctly generated !') + config_string = dc_tmpl.render(dc_tmpl_var) + with open(dc_openssl_configfile,'wt') as file: + file.write(config_string) - 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}" , shell=True, check=True, executable='/bin/bash')) + if os.path.isfile(dc_openssl_configfile): + Printing.information(f'{dc_name} OpenSSL configfile is correctly generated !') - 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')) + Printing.information(f'Generate private key and CSR for {dc_name}') + print(subprocess.run(f"openssl req -new -addext 'subjectAltName = email:copy' -newkey rsa:4096 -keyout {dc_keyfile} \ + -out {dc_csrfile} -config {dc_openssl_configfile}" , 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) + if os.path.isfile(dc_csrfile): + print(f'Sign certificate for {dc_name}') + 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) def generate_user_certificate(): diff --git a/manage_pki.py b/manage_pki.py index b42bb0e..aef2a59 100644 --- a/manage_pki.py +++ b/manage_pki.py @@ -34,6 +34,12 @@ def main(): intermediate_group.add_argument('--crl', dest='intermediate_crl', help='Regenerate CRL for intermediate CA') intermediate_group.add_argument('--show-certs', '--show-certificates', dest='intermediate_list', help='List all certificates issues of intermediate CA') + dc_cert = parser.add_argument_group('Domain Controler options', 'Manage DC certificates') + dc_cert.add_argument('--dc-cert', dest="dc_cert", action="store_true", help="Create a DC certificate. Specify intermediate CA name with --name option. \ + If you want to use Root ca, set \"Root\" for name value. ") + dc_cert.add_argument('--dc-name', dest='dc_name', help='Specity the FQDN of DC.') + + dangerous_group = parser.add_argument_group('Dangerous options', "Caution: use these options at your own risk.") dangerous_group.add_argument('-f', '--force', dest="force", action="store_true", help="Force reinitialize PKI. VERY DANGEROUS") @@ -51,6 +57,12 @@ def main(): else: create_openssl_intermediate(args.intermediate_name,args.force,args.verbose) + if args.dc_cert: + if not args.dc_name or args.intermediate_name: + print('Add --dc-name or --name with this command') + else: + generate_dc_certificate(dc_name=args.dc_name, ca_name=args.intermediate_name, force=args.force, verbose=args.verbose) + if __name__ == '__main__': main()