mikrotik check cert

This commit is contained in:
Mateusz Gruszczyński
2025-10-27 09:21:24 +01:00
parent dccad5d7a4
commit 81d13e44eb

View File

@@ -269,8 +269,12 @@ class MikroTikManager(SSHManager):
self.cert_name = "letsencrypt" self.cert_name = "letsencrypt"
self.key_name = "letsencrypt-key" self.key_name = "letsencrypt-key"
def check_certificate_expiry(self, source_cert: x509.Certificate) -> bool: def check_certificate_expiry(self, source_cert: x509.Certificate, services: List[str]) -> bool:
"""Check if certificate on MikroTik needs update""" """
Check if certificate on MikroTik needs update
Also verifies that services are properly configured
Returns True if upload needed, False if everything is OK
"""
try: try:
logger.info("Checking MikroTik certificate") logger.info("Checking MikroTik certificate")
@@ -311,129 +315,173 @@ class MikroTikManager(SSHManager):
time_diff = abs((source_expiry - mikrotik_expiry).total_seconds()) time_diff = abs((source_expiry - mikrotik_expiry).total_seconds())
if time_diff < 86400: if time_diff >= 86400:
logger.info("✓ Certificate is current. Skipping.")
return False
else:
logger.info(f"Certificate differs. Upload needed.") logger.info(f"Certificate differs. Upload needed.")
return True return True
# Certificate is current, but check if services are properly configured
logger.info("Certificate is current. Verifying services configuration...")
cert_name = "letsencrypt.pem_0"
services_need_update = False
for service in services:
success, stdout, stderr = self.execute_command(
f'/ip service print where name="{service}"',
ignore_error=True
)
if success and stdout:
# Check if certificate is set correctly
if f'certificate={cert_name}' not in stdout and 'certificate=letsencrypt' not in stdout:
logger.warning(f"Service {service} not using correct certificate")
services_need_update = True
else:
logger.info(f"✓ Service {service} properly configured")
else:
logger.warning(f"Could not check service {service}")
services_need_update = True
if services_need_update:
logger.info("Services need reconfiguration. Updating...")
self.configure_services(services, cert_name)
return False # Don't need to upload cert, just reconfigure
logger.info("✓ Certificate and services are current. Skipping.")
return False
except Exception as e: except Exception as e:
logger.warning(f"Error checking: {e}") logger.warning(f"Error checking: {e}")
return True return True
def upload_certificate(self, cert_path: str, key_path: str, check_first: bool, def configure_services(self, services: List[str], cert_name: str):
source_cert: x509.Certificate, services: List[str] = None) -> Tuple[bool, bool]: """Configure services to use certificate without re-uploading"""
"""Upload certificate to MikroTik"""
try:
if check_first and source_cert:
if not self.check_certificate_expiry(source_cert):
return True, False
if not services:
services = ['www-ssl']
logger.info(f"Deploying certificate for: {', '.join(services)}")
# Disable services
for service in services:
logger.info(f"Disabling {service}")
self.execute_command(f'/ip service disable {service}', ignore_error=True)
import time
time.sleep(1)
# Cleanup
logger.info("Cleaning up old certificates")
cleanup = [
'/certificate remove [find name~"letsencrypt"]',
'/file remove "letsencrypt.pem"',
'/file remove "letsencrypt-key.pem"',
]
for cmd in cleanup:
self.execute_command(cmd, ignore_error=True)
time.sleep(1)
# Upload
logger.info("Uploading certificate")
try: try:
with SCPClient(self.ssh_client.get_transport(), progress=None) as scp: for service in services:
scp.put(cert_path, 'letsencrypt.pem') logger.info(f"Configuring {service}")
logger.info("✓ Certificate uploaded")
# Set certificate
success, _, stderr = self.execute_command(
f'/ip service set {service} certificate="{cert_name}"',
ignore_error=True
)
if success:
logger.info(f"{service} configured")
else:
logger.warning(f"Failed to configure {service}: {stderr}")
# Ensure service is enabled
success, stdout, _ = self.execute_command(
f'/ip service print where name="{service}"',
ignore_error=True
)
if 'disabled=yes' in stdout:
logger.info(f"Enabling {service}")
self.execute_command(f'/ip service enable {service}')
except Exception as e: except Exception as e:
logger.error(f"Upload failed: {e}") logger.error(f"Service configuration failed: {e}")
return False, False
def upload_certificate(self, cert_path: str, key_path: str, check_first: bool,
if key_path: source_cert: x509.Certificate, services: List[str] = None) -> Tuple[bool, bool]:
logger.info("Uploading key") """Upload certificate to MikroTik"""
try:
if not services:
services = ['www-ssl']
if check_first and source_cert:
if not self.check_certificate_expiry(source_cert, services):
return True, False # Certificate and services are OK
logger.info(f"Deploying certificate for: {', '.join(services)}")
# Disable services
for service in services:
logger.info(f"Disabling {service}")
self.execute_command(f'/ip service disable {service}', ignore_error=True)
import time
time.sleep(1)
# Cleanup
logger.info("Cleaning up old certificates")
cleanup = [
'/certificate remove [find name~"letsencrypt"]',
'/file remove "letsencrypt.pem"',
'/file remove "letsencrypt-key.pem"',
]
for cmd in cleanup:
self.execute_command(cmd, ignore_error=True)
time.sleep(1)
# Upload
logger.info("Uploading certificate")
try: try:
with SCPClient(self.ssh_client.get_transport(), progress=None) as scp: with SCPClient(self.ssh_client.get_transport(), progress=None) as scp:
scp.put(key_path, 'letsencrypt-key.pem') scp.put(cert_path, 'letsencrypt.pem')
logger.info("Key uploaded") logger.info("Certificate uploaded")
except Exception as e: except Exception as e:
logger.error(f"Key upload failed: {e}") logger.error(f"Upload failed: {e}")
return False, False return False, False
time.sleep(2) if key_path:
logger.info("Uploading key")
# Verify try:
success, stdout, stderr = self.execute_command( with SCPClient(self.ssh_client.get_transport(), progress=None) as scp:
'/file print where name~"letsencrypt"', scp.put(key_path, 'letsencrypt-key.pem')
ignore_error=True logger.info("✓ Key uploaded")
) except Exception as e:
logger.error(f"Key upload failed: {e}")
if not success or 'letsencrypt.pem' not in stdout: return False, False
logger.error("Files not found on MikroTik!")
return False, False time.sleep(2)
logger.info("✓ Files verified") # Verify
success, stdout, stderr = self.execute_command(
# Import '/file print where name~"letsencrypt"',
logger.info("Importing certificate") ignore_error=True
success, stdout, stderr = self.execute_command( )
'/certificate import file-name=letsencrypt.pem passphrase=""',
timeout=30 if not success or 'letsencrypt.pem' not in stdout:
) logger.error("Files not found on MikroTik!")
return False, False
if not success:
logger.error(f"Import failed: {stderr}") logger.info("✓ Files verified")
return False, False
# Import
logger.info("✓ Certificate imported") logger.info("Importing certificate")
success, stdout, stderr = self.execute_command(
time.sleep(2) '/certificate import file-name=letsencrypt.pem passphrase=""',
timeout=30
# Use predictable name
imported_cert_name = "letsencrypt.pem_0"
logger.info(f"Using certificate: {imported_cert_name}")
# Configure services
for service in services:
logger.info(f"Configuring {service}")
success, _, stderr = self.execute_command(
f'/ip service set {service} certificate="{imported_cert_name}"'
) )
if not success: if not success:
logger.error(f"Failed to configure {service}: {stderr}") logger.error(f"Import failed: {stderr}")
else: return False, False
logger.info(f"{service} configured")
logger.info("✓ Certificate imported")
# Enable services
for service in services: time.sleep(2)
logger.info(f"Enabling {service}")
self.execute_command(f'/ip service enable {service}') # Use predictable name
imported_cert_name = "letsencrypt.pem_0"
time.sleep(1) logger.info(f"Using certificate: {imported_cert_name}")
logger.info(f"✓ MikroTik deployment completed") # Configure services using the new method
return True, True self.configure_services(services, imported_cert_name)
except Exception as e: time.sleep(1)
logger.error(f"MikroTik deployment failed: {e}")
return False, False logger.info(f"✓ MikroTik deployment completed")
return True, True
except Exception as e:
logger.error(f"MikroTik deployment failed: {e}")
return False, False
class ProxmoxManager(SSHManager): class ProxmoxManager(SSHManager):