Skip to content

Commit

Permalink
Merge pull request #19 from Kwaizer/logging
Browse files Browse the repository at this point in the history
Implement logging for albs-sign-file
  • Loading branch information
anfimovdm authored Dec 9, 2024
2 parents 1d3dd3e + e22a017 commit 681428a
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 2 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ SF_HOST_GNUPG="~/.gnupg"
# (see below)
SF_ROOT_URL=""
# The service that will use sign-file
# default "albs-sign-service"
TARGET_SERVICE="albs-sign-service"
```

### Database initialization
Expand All @@ -110,7 +114,7 @@ Create database and user with `db_manage.py` script


### Service startup
Start service using `startup.py` script
Start service using `start.py` script

```bash
(.venv) % python3 start.py
Expand Down
5 changes: 5 additions & 0 deletions sign/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
JWT_EXPIRE_MINUTES_DEFAULT = 30
JWT_ALGORITHM_DEFAULT = "HS256"
ROOT_URL_DEFAULT = ''
SERVICE_DEFAULT='albs-sign-service'

class Settings(BaseSettings):
gpg_binary: str = Field(default=GPG_BINARY_DEFAULT,
Expand Down Expand Up @@ -50,6 +51,10 @@ class Settings(BaseSettings):
Field(default= ROOT_URL_DEFAULT,
description="root url for api calls",
env="SF_ROOT_URL")
service: str = \
Field(default=SERVICE_DEFAULT,
description="name of the service that will use sign-file",
env="TARGET_SERVICE")

class Config:
case_sensitive = False
Expand Down
34 changes: 34 additions & 0 deletions sign/log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import logging
import logging.handlers

class SysLog:

def __init__(self, tag_name: str, level: int = logging.INFO):
self._tag_name = tag_name
self._logger = logging.getLogger()
self._level = level
self._logger.setLevel(self._level)
formatter = logging.Formatter(self._tag_name + ': %(message)s')
handler = logging.handlers.SysLogHandler(address='/dev/log')
handler.setFormatter(formatter)
self.logger.addHandler(handler)

def sign_log(
self,
file_name: str,
hash_before: str,
hash_after: str,
pgp_keyid: str,
):
self._logger.info(
'Filename: %s. Hash before: %s. '
'Hash after: %s. Sign key ID: %s',
file_name,
hash_before,
hash_after,
pgp_keyid,
)

@property
def logger(self) -> logging.Logger:
return self._logger
25 changes: 24 additions & 1 deletion sign/pgp/pgp.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import os
import aiofiles
from aiofiles.os import remove
from fastapi import UploadFile
import gnupg
import logging
import plumbum
import pexpect

from sign.config import settings
from sign.log import SysLog
from sign.pgp.pgp_password_db import PGPPasswordDB
from sign.errors import FileTooBigError
from sign.utils.hashing import get_hasher, hash_file


class PGP:
Expand All @@ -25,6 +30,7 @@ def __init__(self,
self.max_upload_bytes = max_upload_bytes
self.tmp_dir = tmp_dir
self.__pass_db.ask_for_passwords()
self.__syslog = SysLog(tag_name=settings.service)

def list_keys(self):
return self.__gpg.list_keys()
Expand All @@ -49,7 +55,12 @@ async def sign(
await fd.write(content)
await fd.flush()
file.file.close()


hash_before = hash_file(
fd.name,
hasher=get_hasher('sha256'),
)

# signing tmp file with gpg binary
# using pgp.sign_file() will result in wrong signature
password = self.__pass_db.get_password(keyid)
Expand All @@ -68,6 +79,18 @@ async def sign(
timeout=1200,
withexitstatus=1,
)
hash_after = hash_file(
fd.name,
hasher=get_hasher('sha256'),
)

# it would be nice if we could know the platform too
self.__syslog.sign_log(
os.path.basename(fd.name),
hash_before,
hash_after,
keyid,
)
if status != 0:
message = f'gpg failed to sign file, error: {out}'
logging.error(message)
Expand Down
Empty file added sign/utils/__init__.py
Empty file.
52 changes: 52 additions & 0 deletions sign/utils/hashing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import hashlib


def hash_file(file_path, hasher=None, buff_size=1048576):
"""
Returns checksum (hexadecimal digest) of the file.
Parameters
----------
file_path : str or file-like
File to hash. It could be either a path or a file descriptor.
hasher : hashlib.Hasher
Any hash algorithm from hashlib.
buff_size : int
Number of bytes to read at once.
Returns
-------
str
Checksum (hexadecimal digest) of the file.
"""
if hasher is None:
hasher = get_hasher()

def feed_hasher(_fd):
buff = _fd.read(buff_size)
while len(buff):
if not isinstance(buff, bytes):
buff = buff.encode('utf')
hasher.update(buff)
buff = _fd.read(buff_size)

if isinstance(file_path, str):
with open(file_path, "rb") as fd:
feed_hasher(fd)
else:
file_path.seek(0)
feed_hasher(file_path)
return hasher.hexdigest()


def get_hasher():
"""
Returns a corresponding hashlib hashing function for the specified checksum
type.
Returns
-------
_hashlib.HASH
Hashlib hashing function.
"""
return hashlib.new('sha256')

0 comments on commit 681428a

Please sign in to comment.