diff --git a/certpusher.py b/certpusher.py index b720ce5..cb160a3 100644 --- a/certpusher.py +++ b/certpusher.py @@ -292,42 +292,116 @@ class MikroTikManager(SSHManager): try: logger.info("Checking MikroTik certificate") + # First, check what certificates exist success, stdout, stderr = self.execute_command( - f'/certificate print detail where name~"{self.cert_name}"', + '/certificate print', ignore_error=True ) - if not success or not stdout: - logger.info("No certificate found. Upload needed.") + if success and stdout: + logger.debug(f"Certificates on MikroTik:\n{stdout}") + + # Get detailed info about our certificate + # Try multiple patterns to find our cert + patterns = [ + f'name~"{self.cert_name}"', # ssl-cert + f'name~"{self.cert_name}_0"', # ssl-cert_0 + 'common-name~".*"', # Any cert + ] + + cert_output = None + used_pattern = None + + for pattern in patterns: + success, stdout, stderr = self.execute_command( + f'/certificate print detail where {pattern}', + ignore_error=True + ) + + if success and stdout and 'invalid-after' in stdout.lower(): + cert_output = stdout + used_pattern = pattern + logger.debug(f"Found certificate using pattern: {pattern}") + break + + if not cert_output: + logger.info("No certificate found on MikroTik. Upload needed.") return True - invalid_after_match = re.search(r'invalid-after:\s+([a-zA-Z]{3}/\d{2}/\d{4}\s+\d{2}:\d{2}:\d{2})', stdout) + # Show raw output for debugging + logger.debug(f"Certificate details:\n{cert_output}") + + # Try multiple date formats + invalid_after_match = re.search( + r'invalid-after[:\s=]+([a-zA-Z]{3}[/\s]\d{1,2}[/\s]\d{4}\s+\d{2}:\d{2}:\d{2})', + cert_output, + re.IGNORECASE + ) if not invalid_after_match: - logger.warning("Could not parse expiry. Proceeding with upload.") + invalid_after_match = re.search( + r'invalid-after[:\s=]+(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})', + cert_output, + re.IGNORECASE + ) + + if not invalid_after_match: + # Try to find ANY date pattern + invalid_after_match = re.search( + r'(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[/\s-]\d{1,2}[/\s-]\d{4}\s+\d{2}:\d{2}:\d{2}', + cert_output, + re.IGNORECASE + ) + + if not invalid_after_match: + logger.warning(f"Could not parse expiry date") + logger.info(f"Raw output to help debug:") + logger.info(cert_output[:500]) # First 500 chars + logger.info("Cannot verify - proceeding with upload for safety.") return True mikrotik_expiry_str = invalid_after_match.group(1) + logger.info(f"Found expiry: {mikrotik_expiry_str}") - try: - mikrotik_expiry = datetime.strptime(mikrotik_expiry_str, '%b/%d/%Y %H:%M:%S') - mikrotik_expiry = mikrotik_expiry.replace(tzinfo=timezone.utc) - except Exception: + # Parse with flexible format + mikrotik_expiry = None + date_formats = [ + '%b/%d/%Y %H:%M:%S', + '%b %d %Y %H:%M:%S', + '%Y-%m-%d %H:%M:%S', + ] + + for fmt in date_formats: + try: + mikrotik_expiry = datetime.strptime(mikrotik_expiry_str, fmt) + mikrotik_expiry = mikrotik_expiry.replace(tzinfo=timezone.utc) + break + except ValueError: + continue + + if not mikrotik_expiry: + logger.warning(f"Could not parse date: {mikrotik_expiry_str}") return True source_expiry = source_cert.not_valid_after_utc time_diff = abs((source_expiry - mikrotik_expiry).total_seconds()) + logger.info(f"Source expires: {source_expiry}") + logger.info(f"MikroTik expires: {mikrotik_expiry}") + if time_diff < 86400: logger.info("✓ MikroTik certificate is current. Skipping.") return False else: - logger.info(f"MikroTik certificate differs. Upload needed.") + logger.info(f"Certificate differs (diff: {time_diff/86400:.1f} days). Upload needed.") return True except Exception as e: - logger.warning(f"Error checking: {e}. Proceeding with upload.") + logger.warning(f"Error checking: {e}") + import traceback + logger.debug(traceback.format_exc()) return True + def upload_certificate(self, cert_path: str, key_path: str, check_first: bool, source_cert: x509.Certificate) -> Tuple[bool, bool]: """