package org.ovirt.engine.core.bll; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.inject.Singleton; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.BackendService; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogable; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableImpl; import org.ovirt.engine.core.dao.VdsDao; import org.ovirt.engine.core.utils.EngineLocalConfig; import org.ovirt.engine.core.utils.crypt.EngineEncryptionUtils; import org.ovirt.engine.core.utils.timer.OnTimerMethodAnnotation; import org.ovirt.engine.core.utils.timer.SchedulerUtilQuartzImpl; import org.ovirt.engine.core.vdsbroker.ResourceManager; import org.ovirt.engine.core.vdsbroker.VdsManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton public class CertificationValidityChecker implements BackendService { private static Logger log = LoggerFactory.getLogger(CertificationValidityChecker.class); @Inject private SchedulerUtilQuartzImpl scheduler; @Inject private AuditLogDirector auditLogDirector; @Inject private VdsDao hostDao; @Inject private ResourceManager resourceManager; @PostConstruct public void scheduleJob() { double interval = Config.<Double>getValue(ConfigValues.CertificationValidityCheckTimeInHours); final int HOURS_TO_MINUTES = 60; long intervalInMinutes = Math.round(interval * HOURS_TO_MINUTES); scheduler.scheduleAFixedDelayJob( this, "checkCertificationValidity", new Class[0], new Object[0], 10, intervalInMinutes, TimeUnit.MINUTES); } @OnTimerMethodAnnotation("checkCertificationValidity") public void checkCertificationValidity() { try { if (!checkCertificate(EngineEncryptionUtils.getCertificate(EngineLocalConfig.getInstance().getPKICACert()), AuditLogType.ENGINE_CA_CERTIFICATION_HAS_EXPIRED, AuditLogType.ENGINE_CA_CERTIFICATION_IS_ABOUT_TO_EXPIRE_ALERT, AuditLogType.ENGINE_CA_CERTIFICATION_IS_ABOUT_TO_EXPIRE, null) ^ !checkCertificate((X509Certificate) EngineEncryptionUtils.getCertificate(), AuditLogType.ENGINE_CERTIFICATION_HAS_EXPIRED, AuditLogType.ENGINE_CERTIFICATION_IS_ABOUT_TO_EXPIRE_ALERT, AuditLogType.ENGINE_CERTIFICATION_IS_ABOUT_TO_EXPIRE, null)) { return; } if (!Config.<Boolean>getValue(ConfigValues.EncryptHostCommunication)) { return; } hostDao.getAll() .stream() .filter(host -> host.getStatus() == VDSStatus.Up || host.getStatus() == VDSStatus.NonOperational) .forEach(this::checkHostCertificateValidity); } catch (Exception e) { log.error("Failed to check certification validity: {}", e.getMessage()); log.error("Exception", e); } } private void checkHostCertificateValidity(VDS host) { VdsManager hostManager = resourceManager.getVdsManager(host.getId()); List<Certificate> peerCertificates = hostManager.getVdsProxy().getPeerCertificates(); if (peerCertificates == null || peerCertificates.isEmpty()) { log.error("Failed to retrieve peer certifications for host '{}'", host.getName()); } else { checkCertificate((X509Certificate) peerCertificates.get(0), AuditLogType.HOST_CERTIFICATION_HAS_EXPIRED, AuditLogType.HOST_CERTIFICATION_IS_ABOUT_TO_EXPIRE_ALERT, AuditLogType.HOST_CERTIFICATION_IS_ABOUT_TO_EXPIRE, host); } } private boolean checkCertificate(X509Certificate cert, AuditLogType alertExpirationEventType, AuditLogType alertAboutToExpireEventType, AuditLogType warnAboutToExpireEventType, VDS host) { Date expirationDate = cert.getNotAfter(); Date certWarnTime = getExpirationDate(expirationDate, ConfigValues.CertExpirationWarnPeriodInDays); Date certAlertTime = getExpirationDate(expirationDate, ConfigValues.CertExpirationAlertPeriodInDays); Date now = new Date(); AuditLogType eventType = null; if (now.compareTo(expirationDate) > 0) { eventType = alertExpirationEventType; } else if (now.compareTo(certAlertTime) > 0) { eventType = alertAboutToExpireEventType; } else if (now.compareTo(certWarnTime) > 0) { eventType = warnAboutToExpireEventType; } if (eventType != null) { AuditLogable event = new AuditLogableImpl(); event.addCustomValue("ExpirationDate", new SimpleDateFormat("yyyy-MM-dd").format(expirationDate)); if (host != null) { event.setVdsName(host.getName()); event.setVdsId(host.getId()); } auditLogDirector.log(event, eventType); return false; } return true; } private Date getExpirationDate(Date expirationDate, ConfigValues daysBeforeExpiration) { Calendar expirationTime = Calendar.getInstance(); expirationTime.setTime(expirationDate); expirationTime.add(Calendar.DAY_OF_MONTH, -1 * Config.<Integer> getValue(daysBeforeExpiration)); return expirationTime.getTime(); } }