From faf537f1cf4e2f0da2cdc7887f0b629383114c6a Mon Sep 17 00:00:00 2001 From: Andrea Cimbalo Date: Thu, 9 Mar 2017 22:30:23 +0100 Subject: [PATCH] move common certificate generation code to Authority --- lookup.py | 6 ------ manager.py | 16 ++++++---------- models/authority.py | 24 ++++++++++++++++++++++++ models/certificate.py | 2 +- models/request.py | 8 ++------ models/ssh.py | 30 +++++------------------------- models/ssl.py | 21 +++++++-------------- shell.py | 21 ++++++++++----------- 8 files changed, 55 insertions(+), 73 deletions(-) diff --git a/lookup.py b/lookup.py index 7338cc1..58c0da9 100755 --- a/lookup.py +++ b/lookup.py @@ -1,16 +1,10 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import cmd -import hashlib from itertools import chain import json import os import os.path -import pickle -import shutil -import sqlite3 -import tempfile from models.ssh import SSHAuthority, UserSSHRequest, HostSSHRequest from models.ssl import SSLAuthority, HostSSLRequest diff --git a/manager.py b/manager.py index 590fdc5..f0d6014 100755 --- a/manager.py +++ b/manager.py @@ -1,15 +1,11 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - -import cmd import hashlib -import json import os import os.path import shutil -import tempfile -from peewee import * +from playhouse.gfk import * from lookup import CALookup, RequestLookup, CertificateLookup @@ -19,7 +15,7 @@ from models.certificate import Certificate from paths import * -__doc__= """ +__doc__ = """ Define classes to interact with certificate requests and Certification Authority """ @@ -36,9 +32,9 @@ class CAManager(object): self.certificate = CertificateLookup() # Create tables - SSHAuthority.create_table(fail_silently = True) - SSLAuthority.create_table(fail_silently = True) - Certificate.create_table(fail_silently = True) + SSHAuthority.create_table(fail_silently=True) + SSLAuthority.create_table(fail_silently=True) + Certificate.create_table(fail_silently=True) @property def ssh_ca_dir(self): @@ -90,7 +86,7 @@ def sign_request(ca_manager, request_id, authority_id): h.update(request.key_data.encode('utf-8')) print("Request hash: %s" % h.hexdigest()) - print("You are about to sign this request with the following CA: %s"%authority) + print("You are about to sign the following request:\n %s\nwith the following CA:\n %s"%(request, authority)) confirm = input('Proceed? (type yes)> ') if confirm != 'yes': print ("user abort") diff --git a/models/authority.py b/models/authority.py index 8b9cc14..a334428 100755 --- a/models/authority.py +++ b/models/authority.py @@ -3,6 +3,8 @@ from playhouse.gfk import * +from datetime import datetime + import os import os.path @@ -53,6 +55,28 @@ class Authority(customModel.CustomModel): raise NotImplementedError() def sign(self, request): + assert type(request) in self.request_allowed + + # write the key data from the request into + # the output folder + with open(request.destination + '.pub', 'w') as stream: + stream.write(request.key_data) + + cert = Certificate( + authority = self, + cert_id = request.req_id, + date_issued = datetime.now(), + receiver = request.receiver, + serial_number = self.serial, + ) + + cert.validity_interval = self.generate_certificate(request) + + cert.save() + + return cert.path + + def generate_certificate(self, request): raise NotImplementedError() def __repr__(self): diff --git a/models/certificate.py b/models/certificate.py index aebbc69..46a4589 100755 --- a/models/certificate.py +++ b/models/certificate.py @@ -42,7 +42,7 @@ class Certificate(customModel.CustomModel): ) def __repr__(self): - return ( "%s %s for %s on %s" % (self.__class__.__name__, self.cert_id, self.receiver, self.date_issued)) + return ( "%s %s for %s on %s issued by %s"%(self.__class__.__name__, self.cert_id, self.receiver, self.date_issued, self.authority)) def __bool__(self): return os.path.exists(self.path) diff --git a/models/request.py b/models/request.py index a8740fd..ca19254 100755 --- a/models/request.py +++ b/models/request.py @@ -1,11 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import os import os.path -import sqlite3 -import subprocess -import json from paths import * @@ -18,7 +14,7 @@ class SignRequest(object): self.req_id = req_id def __repr__(self): - return ( "%s %s with fileds: %s" % (self.__class__.__name__, self.req_id, self.fields)) + return ( "%s %s with fields: %s" % (self.__class__.__name__, self.req_id, self.fields)) def __bool__(self): return os.path.exists(self.path) @@ -37,7 +33,7 @@ class SignRequest(object): @property def destination(self): - return os.path.join(OUTPUT_PATH, self.req_id + '.pub') + return os.path.join(OUTPUT_PATH, self.req_id) @property def fields(self): diff --git a/models/ssh.py b/models/ssh.py index e3e64fa..ea77d15 100644 --- a/models/ssh.py +++ b/models/ssh.py @@ -3,7 +3,6 @@ from playhouse.gfk import * -from datetime import datetime import os.path import subprocess @@ -93,27 +92,12 @@ class SSHAuthority(Authority): raise ValueError('A CA with the same id already exists') - def sign(self, request): + def generate_certificate(self, request): """ Sign a *SSHRequest with this certification authority """ - assert type(request) in self.request_allowed - - pub_key_path = request.destination - - cert = Certificate( - authority = self, - cert_id = request.req_id, - date_issued = datetime.now(), - receiver = request.receiver, - serial_number = self.serial, - ) - - # write the key data from the request into - # the output folder - with open(request.destination, 'w') as stream: - stream.write(request.key_data) + pub_key_path = request.destination + '.pub' ca_private_key = self.path @@ -129,7 +113,7 @@ class SSHAuthority(Authority): '-V', self.user_validity, '-z', str(self.serial), pub_key_path]) - cert.validity_interval = self.user_validity + validity_interval = self.user_validity elif type(request) == HostSSHRequest: @@ -141,12 +125,8 @@ class SSHAuthority(Authority): '-V', self.host_validity, '-z', str(self.serial), pub_key_path]) - cert.validity_interval = self.host_validity - - self.serial += 1 - - cert.save() + validity_interval = self.host_validity - return cert.path + return validity_interval diff --git a/models/ssl.py b/models/ssl.py index cbcb328..539c8d2 100644 --- a/models/ssl.py +++ b/models/ssl.py @@ -29,6 +29,9 @@ class HostSSLRequest(SignRequest): ("Hostname", self.host_name) ] + @property + def receiver(self): + return self.host_name class SSLAuthority(Authority): request_allowed = [ HostSSLRequest, ] @@ -65,27 +68,17 @@ class SSLAuthority(Authority): stream.write(str(0)) - def sign(self, request): + def generate_certificate(self, request): """ Sign a *SSLRequest with this certification authority """ - assert type(request) in self.request_allowed - - pub_key_path = os.path.join(OUTPUT_PATH, request.req_id + '.pub') - cert_path = os.path.join(OUTPUT_PATH, request.req_id + '-cert.pub') - - with open(self.path + '.serial', 'r') as stream: - next_serial = int(stream.read()) - with open(self.path + '.serial', 'w') as stream: - stream.write(str(next_serial + 1)) + pub_key_path = request.destination + '.pub' + cert_path = request.destination + '-cert.pub' with open(pub_key_path, 'w') as stream: stream.write(request.key_data) - ca_private_key = self.path - - # openssl x509 -req -days 360 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt # print() subprocess.check_output(['openssl', 'x509', '-req', @@ -97,5 +90,5 @@ class SSLAuthority(Authority): '-out', cert_path, '-%s'%self.key_algorithm]) - return cert_path + return self.ca_validity diff --git a/shell.py b/shell.py index a735f5a..be3169a 100755 --- a/shell.py +++ b/shell.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - import cmd import sys from datetime import datetime @@ -10,16 +9,16 @@ from models.ssl import SSLAuthority from manager import sign_request -__doc__= """ - Class to make a shell and interact with the user - """ +__doc__ = """ +Class to make a shell and interact with the user +""" class CAManagerShell(cmd.Cmd): - intro= """# LILiK CA Manager # + intro = """# LILiK CA Manager # Welcome to the certification authority shell. Type help or ? to list commands. """ - prompt= "(CA Manager)> " + prompt = "(CA Manager)> " def __init__(self, ca_manager): super(CAManagerShell, self).__init__() @@ -28,12 +27,12 @@ class CAManagerShell(cmd.Cmd): def do_ls_cas(self, l): 'List the available certification authorities: LS_CA' for i, authority in enumerate(self.ca_manager.ca): - print('- %d - %s' % (i, authority)) + print(authority) def do_ls_certificates(self, l): 'List the issued certificates: LS_CERTIFICATES' for i, cert in enumerate(self.ca_manager.certificate): - print('- %d - %s' % (i, cert)) + print(cert) def do_ls_requests(self, l): 'List the available certification requests: LS_REQUESTS' @@ -275,9 +274,9 @@ class CAManagerShell(cmd.Cmd): def print_available_authorities(ca_manager): - for i, ca_item in enumerate(ca_manager.ca): - print("- %d : %s" % (i , ca_item)) + for i, ca in enumerate(ca_manager.ca): + print(ca) def print_available_requests(ca_manager): for i, request in enumerate(ca_manager.request): - print("- %d : %s" % (i, request)) + print(request)