diff --git a/models/authority.py b/models/authority.py index 1198aa2..666e37c 100755 --- a/models/authority.py +++ b/models/authority.py @@ -35,165 +35,3 @@ class Authority(Model): def __repr__(self): return ( "%s %s" % ( self.__class__.__name__, self.ca_id ) ) - -class SSHAuthority(Authority): - - request_allowed = [ UserSSHRequest, HostSSHRequest, ] - - key_algorithm = 'ed25519' - - user_validity = '+52w' - host_validity = '+52w' - - def __init__(self, ca_id): - ssh_ca_dir = os.path.join(MANAGER_PATH, 'ssh_cas') - - super(SSHAuthority, self).__init__(ca_id, ssh_ca_dir) - - def __bool__(self): - """ - For a SSH Authority we only need a private-public key couple, - moreover we request to have the next serial number - """ - keys_couple_exist = os.path.exists(self.path) and os.path.exists(self.path + '.pub') - serial_exist = os.path.exists(self.path + '.serial') - - return keys_couple_exist and serial_exist - - def generate(self): - """ - Generate a SSHAuthority if the files associated - do not exists - """ - # check if the public key exists - if not self: - # let ssh-keygen do its job - subprocess.check_output(['ssh-keygen', - '-f', self.path, - '-t', self.key_algorithm, - '-C', self.name]) - - # write the serial file with a value of - # 0 for first certificate - with open(self.path + '.serial', 'w') as stream: - stream.write(str(0)) - - super(SSHAuthority, self).generate() - - - else: - raise ValueError('A CA with the same id and type already exists') - - - def sign(self, request): - - assert type(request) in self.request_allowed - - pub_key_path = request.destination - cert_path = Certificate(request.req_id).path - - 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)) - - with open(request.destination, 'w') as stream: - stream.write(request.key_data) - - ca_private_key = self.path - - if type(request) == UserSSHRequest: - login_names = [ request.user_name, ] - if request.root_requested: - login_names.append('root') - - subprocess.check_output(['ssh-keygen', - '-s', ca_private_key, - '-I', 'user_%s' % request.user_name, - '-n', ','.join(login_names), - '-V', self.user_validity, - '-z', str(next_serial), - pub_key_path]) - elif type(request) == HostSSHRequest: - subprocess.check_output(['ssh-keygen', - '-s', ca_private_key, - '-I', 'host_%s' % request.host_name.replace('.', '_'), - '-h', - '-n', request.host_name, - '-V', self.host_validity, - '-z', str(next_serial), - pub_key_path]) - - return cert_path - -class SSLAuthority(Authority): - request_allowed = [ HostSSLRequest, ] - - ca_key_algorithm = 'des3' - key_length = '4096' - - key_algorithm = 'sha256' - ca_validity = '365' - cert_validity = '365' - - def __init__(self, ca_id): - ssl_ca_dir = os.path.join(MANAGER_PATH, 'ssl_ca') - - super(SSLAuthority, self).__init__(ca_id, ssl_ca_dir) - - def generate(self): - if os.path.exists(self.path): - raise ValueError("A CA with the same id and type already exists") - - subprocess.check_output(['openssl', - 'genrsa', - '-%s'%self.ca_key_algorithm, - '-out', '%s'%(self.path), - self.key_length]) - - subprocess.check_output(['openssl', - 'req', - '-new', - '-x509', - '-days', self.ca_validity, - '-key', self.path, - # '-extensions', 'v3_ca' - '-out', "%s.pub"%self.path, - # '-config', "%s.conf"%self.path - ]) - - with open(self.path + '.serial', 'w') as stream: - stream.write(str(0)) - - - def sign(self, request): - OUTPUT_PATH - - 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)) - - 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', - '-days', self.ca_validity, - '-in', pub_key_path, - '-CA', "%s.pub"%self.path, - '-CAkey', self.path, - '-CAcreateserial', - '-out', cert_path, - '-%s'%self.key_algorithm]) - - return cert_path diff --git a/models/request.py b/models/request.py index 5d5c4c3..4a1fac9 100755 --- a/models/request.py +++ b/models/request.py @@ -100,52 +100,6 @@ class RequestLoader(object): print(exc_type, exc_value) print(traceback) -class UserSSHRequest(SignRequest, object): - def __init__(self, req_id, user_name, root_requested, key_data): - super(UserSSHRequest, self).__init__(req_id) - - self.user_name = user_name - self.root_requested = root_requested - self.key_data = key_data - - @property - def name(self): - return "User: %s [R:%d]" % (self.user_name, int(self.root_requested)) - - @property - def fields(self): - return [ - ("User name", self.user_name), - ("Root access requested", 'yes' if self.root_requested else 'no') - ] - -class HostSSLRequest(SignRequest, object): - def __init__(self, req_id, host_name, key_data): - super(HostSSLRequest, self).__init__(req_id) - - self.host_name = host_name - self.key_data = key_data - - @property - def name(self): - return "Hostname: %s" % self.host_name - - @property - def fields(self): - return [ - ("Hostname", self.host_name) - ] - -class HostSSHRequest(SignRequest, object): - def __init__(self, req_id, host_name, key_data): - super(HostSSHRequest, self).__init__(req_id) - - self.host_name = host_name - self.key_data = key_data - - @property - def name(self): - return "Hostname: %s" % self.host_name @property def fields(self): diff --git a/models/ssh.py b/models/ssh.py new file mode 100644 index 0000000..81e87ae --- /dev/null +++ b/models/ssh.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from peewee import * + +from datetime import datetime +import os.path +import subprocess + +from models.authority import Authority +from models.certificate import Certificate +from models.request import SignRequest +from paths import * + + +class UserSSHRequest(SignRequest): + def __init__(self, req_id, user_name, root_requested, key_data): + super(UserSSHRequest, self).__init__(req_id) + + self.user_name = user_name + self.root_requested = root_requested + self.key_data = key_data + + @property + def name(self): + return "User: %s [R:%d]" % (self.user_name, int(self.root_requested)) + + @property + def fields(self): + return [ + ("User name", self.user_name), + ("Root access requested", 'yes' if self.root_requested else 'no') + ] + + @property + def receiver(self): + return self.user_name + + +class HostSSHRequest(SignRequest): + def __init__(self, req_id, host_name, key_data): + super(HostSSHRequest, self).__init__(req_id) + + self.host_name = host_name + self.key_data = key_data + + @property + def name(self): + return "Hostname: %s" % self.host_name + + @property + def fields(self): + return [ + ("Hostname", self.host_name) + ] + + @property + def receiver(self): + return self.host_name + + +class SSHAuthority(Authority): + + request_allowed = [ UserSSHRequest, HostSSHRequest, ] + + key_algorithm = 'ed25519' + + cert_validity = '+52w' + + def __bool__(self): + """ + Check if key pair already exists + """ + keys_pair_exist = os.path.exists(self.path) and os.path.exists(self.path + '.pub') + + return keys_couple_exist + + def generate(self): + """ + Generate a SSHAuthority if the files associated + do not exists + """ + # check if the public key exists + if not self: + # let ssh-keygen do its job + subprocess.check_output(['ssh-keygen', + '-f', self.path, + '-t', self.key_algorithm, + '-C', self.name]) + + # write the serial file with a value of + # 0 for first certificate + with open(self.path + '.serial', 'w') as stream: + stream.write(str(0)) + + super(SSHAuthority, self).generate() + + else: + raise ValueError('A CA with the same id already exists') + + + def sign(self, request): + """ + Sign a *SSHRequest with this certification authority + """ + + assert type(request) in self.request_allowed + + pub_key_path = request.destination + + cert = Certificate( + signed_by = self, + cert_id = request.req_id, + date_issued = datetime.now(), + receiver = self.receiver, + serial_number = self.serial, + validity_interval = self.user_validity, + ) + + # write the key data from the request into + # the output folder + with open(request.destination, 'w') as stream: + stream.write(request.key_data) + + ca_private_key = self.path + + if type(request) == UserSSHRequest: + login_names = [ request.user_name, ] + if request.root_requested: + login_names.append('root') + + subprocess.check_output(['ssh-keygen', + '-s', ca_private_key, + '-I', 'user_%s' % request.user_name, + '-n', ','.join(login_names), + '-V', self.user_validity, + '-z', str(self.serial), + pub_key_path]) + + + elif type(request) == HostSSHRequest: + subprocess.check_output(['ssh-keygen', + '-s', ca_private_key, + '-I', 'host_%s' % request.host_name.replace('.', '_'), + '-h', + '-n', request.host_name, + '-V', self.host_validity, + '-z', str(self.serial), + pub_key_path]) + + self.serial += 1 + + cert.save() + + return cert.path + + diff --git a/models/ssl.py b/models/ssl.py new file mode 100644 index 0000000..17047a7 --- /dev/null +++ b/models/ssl.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from peewee import * + +import os +import os.path +import subprocess + +from models.authority import Authority +from models.certificate import Certificate +from models.request import SignRequest +from paths import * + +class HostSSLRequest(SignRequest): + def __init__(self, req_id, host_name, key_data): + super(HostSSLRequest, self).__init__(req_id) + + self.host_name = host_name + self.key_data = key_data + + @property + def name(self): + return "Hostname: %s" % self.host_name + + @property + def fields(self): + return [ + ("Hostname", self.host_name) + ] + + +class SSLAuthority(Authority): + request_allowed = [ HostSSLRequest, ] + + ca_key_algorithm = 'des3' + key_length = '4096' + + key_algorithm = 'sha256' + ca_validity = '365' + cert_validity = '365' + + def __init__(self, ca_id): + ssl_ca_dir = os.path.join(MANAGER_PATH, 'ssl_ca') + + super(SSLAuthority, self).__init__(ca_id, ssl_ca_dir) + + def generate(self): + if os.path.exists(self.path): + raise ValueError("A CA with the same id and type already exists") + + subprocess.check_output(['openssl', + 'genrsa', + '-%s'%self.ca_key_algorithm, + '-out', '%s'%(self.path), + self.key_length]) + + subprocess.check_output(['openssl', + 'req', + '-new', + '-x509', + '-days', self.ca_validity, + '-key', self.path, + # '-extensions', 'v3_ca' + '-out', "%s.pub"%self.path, + # '-config', "%s.conf"%self.path + ]) + + with open(self.path + '.serial', 'w') as stream: + stream.write(str(0)) + + + def sign(self, request): + OUTPUT_PATH + + 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)) + + 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', + '-days', self.ca_validity, + '-in', pub_key_path, + '-CA', "%s.pub"%self.path, + '-CAkey', self.path, + '-CAcreateserial', + '-out', cert_path, + '-%s'%self.key_algorithm]) + + return cert_path +