Files
samba-pki-tools/root_module.py
T
2024-05-17 17:29:47 +02:00

170 lines
7.7 KiB
Python

#!/usr/bin/python3
#-------------------------------------------------------------------------------
# Name: Samba PKI Tools
# Purpose:
#
# Author: kguerineau-adm
#
# Created: 10/05/2024
# Copyright: (c) kguerineau-adm 2024
# Licence: <your licence>
#-------------------------------------------------------------------------------
# Manage Root CA
from common import Printing, TisPKI, check_directories, config
import subprocess
import jinja2
import os
import configparser
import sys
from colorama import Fore, Style
import shutil
import time
def create_openssl_config(force=False,verbose=False):
if force:
Printing.error("Do you realy want to remove ALL you PKI ? This will destroy ALL YOUR CERTIFICATES AND PRIVATE KEY")
Printing.error("After that, you MUST REGENERATE YOUR PKI with NEW certificates and private key for ALL YOUR DOMAIN CONTROLLERS AND USERS")
destroy = input('If you are realy sure, please enter : "I want to remove all my PKI" : ')
if destroy == 'I want to remove all my PKI':
Printing.information('OK, too late ! Destroying your PKI !')
time.sleep(1)
shutil.rmtree(TisPKI.pki_dir(), ignore_errors=True)
Printing.information('Check Root CA OpenSSL Config')
if config.get('general','pki_dir'):
check_directories(path=config.get('general','pki_dir'),verbose=verbose)
else:
Printing.error('No pki_dir set in samba-pki-tools.ini')
sys.exit(1)
root_ca_config = os.path.join(TisPKI.pki_dir(),'config','openssl_root_ca.ini')
if not os.path.isfile(root_ca_config):
Printing.information('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'),
'default_crl_duration' : config.get('openssl_config','default_crl_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):
Printing.success('Root CA OpenSSL config file is correctly generated !')
else:
Printing.warning('Root CA OpenSSL config already exist. Skip.')
# 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')
if gen_root_ca.returncode == 0:
if verbose:
subprocess.run(f'openssl x509 -in {TisPKI.root_ca_certfile()} -text', shell=True, check=True, executable='/bin/bash')
Printing.information(f'Root CA Certfile is stored in {TisPKI.root_ca_certfile()}')
else:
Printing.error('Error on generating Root CA private key')
retry = input('If you want to retry, press Y : ')
if retry == "y" or retry == 'Y':
os.remove(TisPKI.root_ca_keyfile())
create_openssl_config(force,verbose)
else:
Printing.warning('Root CA private key and certificate already exist. Skip.')
def revoke_intermediate_cert(name):
Printing.information(f'Revoke {name} CA Intermediate certificate')
Printing.error(f'Are you realy sure to revoke {name} CA Intermediate certificate ?')
Printing.error('If you revoke the CA Intermediate, you revoke also all users and servers certificate signed by this CA')
destroy = input('If you are realy sure, please enter : "I want to revoke CA Intermediate" : ')
if destroy == 'I want to revoke CA Intermediate':
Printing.information('OK, too late ! Revoking your CA Intermediate certificate !')
revoke_cmd = subprocess.run(f"/usr/bin/openssl ca -config {os.path.join(TisPKI.root_config_path(),'openssl_root_ca_sign_intermediate.ini')} -revoke {TisPKI.intermediate_ca_certfile(name)}",
shell=True, check=False, executable='/bin/bash')
if revoke_cmd.returncode == 0:
Printing.information('Regenerate Root CRL')
generate_root_crl()
else:
Printing.error('Unable to revoke CA Intermediate certificate')
def generate_root_crl(verbose=False):
Printing.information('Generate CRL for Root CA')
root_ca_sign_intermediate = os.path.join(TisPKI.root_config_path(),'openssl_root_ca_sign_intermediate.ini')
gen_crl = subprocess.run(f'openssl ca -config {root_ca_sign_intermediate} -gencrl -out {TisPKI.root_ca_crlfile()}',shell=True)
if gen_crl.returncode == 0:
Printing.success(f'CRL successfuly generated in : {TisPKI.root_ca_crlfile()}')
else:
Printing.error('Unable to generate CRL')
def list_root_certificates():
Printing.information('List certificates issued of Root CA')
certs_list = []
with open(os.path.join('/opt','pki','index.txt'),'r') as index:
for line in index.readlines():
if line.split('\t')[0] == 'R':
status = 'Revoked'
elif line.split('\t')[0] == 'V':
status = 'Valid '
elif line.split('\t')[0] == 'E':
status = 'Expired'
else:
status = line.split('\t')[0]
serial_number = line.split('\t')[3]
exp_date = line.split('\t')[1]
expiration_date = '20' + exp_date[0:2] + '/' + exp_date[2:4] + '/' + exp_date[4:6] + ' ' + exp_date[6:8] + ':' + exp_date[8:10] +':'+ exp_date[10:12]
rev_date = line.split('\t')[2]
if rev_date != '':
revocation_date = '20' + rev_date[0:2] + '/' + rev_date[2:4] + '/' + rev_date[4:6] + ' ' + rev_date[6:8] + ':' + rev_date[8:10] +':'+ rev_date[10:12]
else:
revocation_date = ' '
cn = line.split('\t')[5].split('CN')[1].replace('=','').replace('\n','')
cn_len = 20
if len(cn) < cn_len:
diff = cn_len - len(cn)
space = ''
for i in range(0, diff):
space = space + ' '
commonName = cn + space
commonName_full = ''
else:
commonName = cn[0:20]
commonName_full = cn
certs_list.append(commonName + ' | ' + status + ' | ' + serial_number + ' | ' + expiration_date + ' | ' + revocation_date + ' | ' + commonName_full)
print(' CommonName | Status | Serial Number | Expiration date | Revocation date |')
print('---------------------|---------|------------------------------------------|---------------------|---------------------|')
for cert in certs_list:
print(cert)