commit ed35ce72903d9b903c97eed7176b891fefd62524
Author: David Friesecký <frieseck@students.zcu.cz>
Date:   Mon Apr 26 12:02:06 2021 +0200

    Re #8570 - Rotating file settings

diff --git a/src/config/configuration.py b/src/config/configuration.py
index 981d874..f723cd2 100644
--- a/src/config/configuration.py
+++ b/src/config/configuration.py
@@ -2,9 +2,12 @@ import os
 
 import configparser
 import logging
+from logging import handlers
+
 from injector import singleton
 
-from src.constants import DEFAULT_CONNECTION_STRING, TEST_DATABASE_FILE, DEFAULT_SERVER_BASE_URL
+from src.constants import DEFAULT_CONNECTION_STRING, TEST_DATABASE_FILE, DEFAULT_SERVER_BASE_URL, LOG_NAME, \
+    LOG_DIR_LOCATION
 from src.constants import LOG_FILE_LOCATION, LOG_FORMAT
 from src.utils.logger import Logger
 
@@ -70,10 +73,18 @@ def configure_env_variable(binder):
 
 
 def configure_logging():
-    logging.basicConfig(filename=LOG_FILE_LOCATION.shortest_relative_path(),
-                        filemode='a+',
-                        format=LOG_FORMAT,
-                        level=logging.DEBUG)
+    if not os.path.exists(LOG_DIR_LOCATION.shortest_relative_path()):
+        os.makedirs(LOG_DIR_LOCATION.shortest_relative_path())
+
+    handler = logging.handlers.TimedRotatingFileHandler(
+        LOG_FILE_LOCATION.shortest_relative_path(),
+        when='H', interval=1)
+    formatter = logging.Formatter(LOG_FORMAT)
+    handler.setFormatter(formatter)
+
+    app_logger = logging.getLogger(LOG_NAME)
+    app_logger.setLevel(logging.DEBUG)
+    app_logger.addHandler(handler)
 
     # TODO check is 'valid'
     log = logging.getLogger('werkzeug')
diff --git a/src/constants.py b/src/constants.py
index ad8f0ec..0d7cc8f 100644
--- a/src/constants.py
+++ b/src/constants.py
@@ -6,9 +6,12 @@ DATABASE_FILE = "db/database_sqlite.db"
 DATABASE_FILE_LOCATION = FileAnchor("aswi2021jmsd", DATABASE_FILE)
 DATETIME_FORMAT = "%d.%m.%Y %H:%M:%S"
 
-LOG_FILE = "log/application.log"
+LOG_DIR = "logs"
+LOG_DIR_LOCATION = FileAnchor("aswi2021jmsd", LOG_DIR)
+LOG_FILE = f"{LOG_DIR}/application.log"
 LOG_FILE_LOCATION = FileAnchor("aswi2021jmsd", LOG_FILE)
 LOG_FORMAT = "%(levelname)-8s %(asctime)s - %(message)s"
+LOG_NAME = "app_logger"
 
 REV_REASON_UNSPECIFIED = "unspecified"
 
diff --git a/src/services/crl_ocsp/ca_index_file_line_generator.py b/src/services/crl_ocsp/ca_index_file_line_generator.py
index 8804ce3..a21207f 100644
--- a/src/services/crl_ocsp/ca_index_file_line_generator.py
+++ b/src/services/crl_ocsp/ca_index_file_line_generator.py
@@ -3,6 +3,7 @@ from time import struct_time
 
 from src.model.certificate import Certificate
 from src.model.subject import Subject
+from src.utils.logger import Logger
 
 SRL_LEN = 8  # number of hex digits in serial number
 TAB_CHAR = "\t"
@@ -11,11 +12,17 @@ INDEX_FILE_DATE_ENTRY_FORMAT = "%y%m%d%H%M%SZ"
 
 def get_index_file_time_entry(date: struct_time):
     # convert the time to the format of openssl CA index file
+
+    Logger.debug("Function launched.")
+
     return time.strftime(INDEX_FILE_DATE_ENTRY_FORMAT, date)
 
 
 def get_distinguished_name(subject: Subject):
     # convert subject class instance to the distinguished name in the openssl CA index file format
+
+    Logger.debug("Function launched.")
+
     return "".join([f"/{key}={value}" if value is not None else "" for key, value in subject.to_dict().items()])
 
 
@@ -23,6 +30,9 @@ def create_index_file_revoked_line(revoked_certificate: Certificate, subject: Su
                                    valid_to: struct_time) -> str:
     # converts the given certificate as well as the subject and revocation / valid_to dates to a line of openssl CA
     # index file format
+
+    Logger.debug("Function launched.")
+
     items = [
         # certificate status flag (R stands for revoked)
         "R",
@@ -43,6 +53,9 @@ def create_index_file_revoked_line(revoked_certificate: Certificate, subject: Su
 def create_index_file_valid_line(certificate: Certificate, subject: Subject, valid_to: struct_time) -> str:
     # converts the given certificate as well as the subject and revocation / valid_to dates to a line of openssl CA
     # index file format
+
+    Logger.debug("Function launched.")
+
     items = [
         # certificate status flag (R stands for revoked)
         "V",
@@ -61,6 +74,9 @@ def create_index_file_valid_line(certificate: Certificate, subject: Subject, val
     return TAB_CHAR.join(items)
 
 def __get_serial(cert_id) -> str:
+
+    Logger.debug("Function launched.")
+
     srl = hex(cert_id).replace("0x", "")
     srl = "0"*(SRL_LEN - len(srl)) + srl  # generate exactly SRL_LEN digits
     return srl.upper()
diff --git a/src/services/crl_ocsp/crl_ocsp_service.py b/src/services/crl_ocsp/crl_ocsp_service.py
index e88c50c..a860c99 100644
--- a/src/services/crl_ocsp/crl_ocsp_service.py
+++ b/src/services/crl_ocsp/crl_ocsp_service.py
@@ -8,6 +8,7 @@ from src.exceptions.certificate_not_found_exception import CertificateNotFoundEx
 from src.exceptions.unknown_exception import UnknownException
 from src.services.crl_ocsp.ca_index_file_line_generator import create_index_file_revoked_line, create_index_file_valid_line
 from src.services.cryptography import CryptographyService
+from src.utils.logger import Logger
 from src.utils.temporary_file import TemporaryFile
 
 
@@ -30,9 +31,13 @@ class CrlOcspService:
         :param ca_id: ID of the CA whose revoked certificates should be put into the index file
         :return: a str representing the content of a CA index file
         """
+
+        Logger.debug("Function launched.")
+
         # get issuing certificate
         certificate = self.certificate_repository.read(ca_id)
         if certificate is None:
+            Logger.error(f"No such certificate found 'ID = {ca_id}'.")
             raise CertificateNotFoundException(ca_id)
 
         # get subject and notAfter of the issuer
@@ -64,9 +69,13 @@ class CrlOcspService:
         :param ca_id: ID of the CA whose issued (=child) certificates should be put into the index file
         :return: a str representing the content of a CA index file
         """
+
+        Logger.debug("Function launched.")
+
         # get issuing certificate
         certificate = self.certificate_repository.read(ca_id)
         if certificate is None:
+            Logger.error(f"No such certificate found 'ID = {ca_id}'.")
             raise CertificateNotFoundException(ca_id)
 
         # get subject and notAfter of the issuer
@@ -101,6 +110,9 @@ class CrlOcspService:
         :param ca_id: ID of a CA whose CRL shall be generated
         :return: CRL in PEM format
         """
+
+        Logger.debug("Function launched.")
+
         # get cert and check if the requested CA exists and if not throw an exception
         cert, key = self.check_ca_and_key(ca_id)
 
@@ -117,6 +129,9 @@ class CrlOcspService:
         :param der_ocsp_request: DER encoded OCSP Request
         :return: DER encoded OCSP Response
         """
+
+        Logger.debug("Function launched.")
+
         cert, key = self.check_ca_and_key(ca_id)
 
         # Create an index file and call cryptography service to generate the OCSP response
@@ -132,6 +147,9 @@ class CrlOcspService:
         :param ca_id: certificate authority ID
         :return: certificate data & associated key
         """
+
+        Logger.debug("Function launched.")
+
         # get cert and check if the requested CA exists and if not throw an exception
         cert = self.certificate_repository.read(ca_id)
         if cert is None:
@@ -139,6 +157,6 @@ class CrlOcspService:
         # get key and check if it exists
         key = self.key_repository.read(cert.private_key_id)
         if key is None:
+            Logger.error("Corrupted database, expected PrivateKey not found.")
             raise UnknownException("Corrupted database, expected PrivateKey not found.")
-            # TODO log this
         return cert, key
\ No newline at end of file
diff --git a/src/utils/logger.py b/src/utils/logger.py
index 19419c1..496ab05 100644
--- a/src/utils/logger.py
+++ b/src/utils/logger.py
@@ -2,6 +2,8 @@ import inspect
 import logging
 from pathlib import Path
 
+from src.constants import LOG_NAME
+
 
 class Logger:
 
@@ -20,24 +22,29 @@ class Logger:
     @staticmethod
     def debug(message: str):
         names = Logger.get_names()
-        logging.debug(f'{Path(names[0]).name}[{names[1]}{names[2]}()]: {message}')
+        app_logger = logging.getLogger(LOG_NAME)
+        app_logger.debug(f'{Path(names[0]).name}[{names[1]}{names[2]}()]: {message}')
 
     @staticmethod
     def info(message: str):
         names = Logger.get_names()
-        logging.info(f'{Path(names[0]).name}[{names[1]}{names[2]}()]: {message}')
+        app_logger = logging.getLogger(LOG_NAME)
+        app_logger.info(f'{Path(names[0]).name}[{names[1]}{names[2]}()]: {message}')
 
     @staticmethod
     def warning(message: str):
         names = Logger.get_names()
-        logging.warning(f'{Path(names[0]).name}[{names[1]}{names[2]}()]: {message}')
+        app_logger = logging.getLogger(LOG_NAME)
+        app_logger.warning(f'{Path(names[0]).name}[{names[1]}{names[2]}()]: {message}')
 
     @staticmethod
     def error(message: str):
         names = Logger.get_names()
-        logging.error(f'{Path(names[0]).name}[{names[1]}.{names[2]}()]: {message}')
+        app_logger = logging.getLogger(LOG_NAME)
+        app_logger.error(f'{Path(names[0]).name}[{names[1]}.{names[2]}()]: {message}')
 
     @staticmethod
     def critical(message: str):
         names = Logger.get_names()
-        logging.critical(f'{Path(names[0]).name}[{names[1]}.{names[2]}()]: {message}')
+        app_logger = logging.getLogger(LOG_NAME)
+        app_logger.critical(f'{Path(names[0]).name}[{names[1]}.{names[2]}()]: {message}')
