@@ -68,6 +68,7 @@ def __init__(self, orchestrator_config_filename: Path, **kwargs: Any) -> None:
6868 self .usb_path = None
6969 # The path on the workstation to the certificate authorities directory
7070 self .local_ca_path = None
71+ self .ca_cert_files_in_repo = []
7172
7273 def get_openssl_cnf_config (self ) -> None :
7374 """Parse the OpenSSL configuration (.cnf) file.
@@ -116,6 +117,43 @@ def get_openssl_cnf_config(self) -> None:
116117 "" , inline_comment
117118 )
118119
120+ def get_ca_cert_filename_on_usb (self ) -> str :
121+ """Identify which file on USB stick is the CA cert
122+
123+ Compare files on the USB stick with CA certificate files in the repo
124+ to identify which one is the CA certificate
125+
126+ :returns: The filename of the CA certificate on the USB stick
127+ """
128+ for private_key_directory in [
129+ x
130+ for x in Path (self .repo_dir / "certificate-authorities" ).iterdir ()
131+ if x .is_dir ()
132+ ]:
133+ for certificate_authority_directory in private_key_directory .iterdir ():
134+ for certificate_file in certificate_authority_directory .iterdir ():
135+ self .ca_cert_files_in_repo .append (certificate_file )
136+ crt_filenames_on_usb = set (x .name for x in self .usb_path .glob ("*.crt" ))
137+ ca_cert_filenames_on_usb = (
138+ set (x .name for x in self .ca_cert_files_in_repo ) & crt_filenames_on_usb
139+ )
140+ if len (ca_cert_filenames_on_usb ) == 0 :
141+ print (
142+ "No .crt files were found on the USB stick with names that match CA"
143+ " certificate files.We would expect there to be one CA certificate file"
144+ " on the USB stick."
145+ )
146+ exit (1 )
147+ if len (ca_cert_filenames_on_usb ) > 1 :
148+ print (
149+ "There are multiple .crt files on the USB stick with names that match"
150+ " CA certificate files.We would only expect there to be one CA"
151+ " certificate file on the USB stick."
152+ )
153+ exit (1 )
154+ ca_cert_filename_on_usb = next (iter (ca_cert_filenames_on_usb ))
155+ return ca_cert_filename_on_usb
156+
119157 def check_update_private_key (self ) -> None :
120158 """Validate and update the OpenSSL 'private_key' value.
121159
@@ -329,6 +367,27 @@ def check_ca_files(self) -> None:
329367 )
330368 exit (1 )
331369
370+ def check_for_matching_issued_cert (self ):
371+ """Check to see if there is an existing cert which matches the .cnf/.csr
372+
373+ To prevent issuing a duplicate cert with the same name as an existing
374+ issued cert, compare the .cnf/.csr filenames with the existing certs
375+ in the certs_issued directory.
376+ """
377+ issued_cert_map = {
378+ x .name : x for x in Path (self .repo_dir / "certs_issued" ).glob ("**/*.crt" )
379+ }
380+ if self .csr_file .with_suffix (".crt" ).name in issued_cert_map .keys ():
381+ print (
382+ f"The .csr file { self .csr_file } , were it to be used to create a .crt"
383+ f" file, would create { self .csr_file .with_suffix ('.crt' ).name } which"
384+ " has the same name as the existing issued cert"
385+ f" { issued_cert_map [self .csr_file .with_suffix ('.crt' ).name ]} . This"
386+ f" could cause a collision. Please change the name of { self .csr_file } "
387+ f" and { self .cnf_file } to something distinct."
388+ )
389+ exit (1 )
390+
332391 def check_update_cnf_file (self ) -> None :
333392 """Perform validation and update of the OpenSSL .cnf file.
334393
@@ -355,7 +414,6 @@ def check_update_cnf_file(self) -> None:
355414 self .check_update_ca_crt ()
356415 self .check_update_unique_subject ()
357416 self .check_ca_files ()
358- print ("Check completed." )
359417
360418 def check_environment (self , skip_git_fetch : bool ) -> None :
361419 """Validate the git environment and prepare for CSR processing.
@@ -642,7 +700,8 @@ def process_usb_files(self, actions):
642700 elif issubclass (type (actions [filename ]), PurePath ):
643701 destination = Path (actions [filename ] / filename .name )
644702 shutil .copy2 (filename , destination )
645- # We only need to ensure that the execute bit isn't set because that's all that git records
703+ # We only need to ensure that the execute bit isn't set because
704+ # that's all that git records
646705 # https://github.com/git/git/commit/e447947
647706 destination .chmod (
648707 destination .stat ().st_mode
@@ -814,36 +873,16 @@ def pull_from_stick(
814873 """
815874 orchestrator = HsmOrchestrator (orchestrator_config_filename , repo_dir = repo_dir )
816875 orchestrator .choose_usb_disk ()
876+
817877 actions = {} # Key is the file and value is the action to perform on that file
818- ca_cert_files_in_repo = {}
819- for private_key_directory in [
820- x
821- for x in Path (orchestrator .repo_dir / "certificate-authorities" ).iterdir ()
822- if x .is_dir ()
823- ]:
824- for certificate_authority_directory in private_key_directory .iterdir ():
825- for certificate_file in certificate_authority_directory .iterdir ():
826- ca_cert_files_in_repo [certificate_file .name ] = certificate_file
827- crt_filenames_on_usb = set (x .name for x in orchestrator .usb_path .glob ("*.crt" ))
828- ca_cert_filenames_on_usb = ca_cert_files_in_repo .keys () & crt_filenames_on_usb
829- if len (ca_cert_filenames_on_usb ) == 0 :
830- print (
831- "No .crt files were found on the USB stick with names that match CA"
832- " certificate files.We would expect there to be one CA certificate file on"
833- " the USB stick."
834- )
835- exit (1 )
836- if len (ca_cert_filenames_on_usb ) > 1 :
837- print (
838- "There are multiple .crt files on the USB stick with names that match CA"
839- " certificate files.We would only expect there to be one CA certificate"
840- " file on the USB stick."
841- )
842- exit (1 )
843- ca_cert_filename_on_usb = next (iter (ca_cert_filenames_on_usb ))
844- certificate_authority_directory = ca_cert_files_in_repo [
845- ca_cert_filename_on_usb
846- ].parent
878+ ca_cert_filename_on_usb = orchestrator .get_ca_cert_filename_on_usb ()
879+ certificate_authority_directory = next (
880+ iter ([
881+ x
882+ for x in orchestrator .ca_cert_files_in_repo
883+ if x .name == ca_cert_filename_on_usb
884+ ])
885+ ).parent
847886 # Delete the CA crt file on the USB stick
848887 actions [Path (orchestrator .usb_path / ca_cert_filename_on_usb )] = "delete"
849888
@@ -925,6 +964,8 @@ def check(
925964 orchestrator .check_environment (skip_git_fetch )
926965 orchestrator .get_openssl_cnf_config ()
927966 orchestrator .check_update_cnf_file ()
967+ orchestrator .check_for_matching_issued_cert ()
968+ print ("Check completed." )
928969
929970
930971if __name__ == "__main__" :
0 commit comments