Skip to content

Commit

Permalink
Add support of IPA client
Browse files Browse the repository at this point in the history
Add support of IPA client

A lot of work is done in the setup of the environment, support of IPA clients (used for testing as Kerberos users). Most of Bash scripts are replaced with python code. Add unit tests.
  • Loading branch information
x00Pavel authored Sep 9, 2021
2 parents d1457b7 + 5584856 commit 24fa16e
Show file tree
Hide file tree
Showing 25 changed files with 2,271 additions and 989 deletions.
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,9 @@ src/env/keys*
.idea/
.vscode/
src/env/krb-server-client-setup-rhel8.sh
src/env/conf*
*.yml
*.yaml
/src/.env
/conf/*
*original*
*backup*
33 changes: 19 additions & 14 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import logging
from sys import stdout
import colorlog


handler = logging.StreamHandler(stdout)
handler.setLevel(logging.DEBUG)

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt="%H:%M:%S")
handler = colorlog.StreamHandler()
formatter = colorlog.ColoredFormatter(
'%(log_color)s%(module)s.%(funcName)s.%(lineno)d [%(levelname)s] %(message)s',
log_colors={
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red,bg_white'})
handler.setFormatter(formatter)

# Basic logger
log = logging.getLogger("base")
log.setLevel(logging.DEBUG)

log.addHandler(handler)
base_logger = colorlog.getLogger("base")
base_logger.addHandler(handler)
base_logger.setLevel(colorlog.DEBUG)

# Logger for environment events
env_logger = logging.getLogger("env")
env_logger.setLevel(logging.DEBUG)

env_logger = colorlog.getLogger("env")
env_logger.addHandler(handler)
env_logger.setLevel(colorlog.DEBUG)


def hello():
print("Hello. Just check that SCAutolib is imported")
92 changes: 92 additions & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from os.path import (dirname, abspath, join)

import yaml
from SCAutolib import env_logger
from decouple import config

DIR_PATH = dirname(abspath(__file__))
SETUP_IPA_SERVER = f"{DIR_PATH}/env/ipa-install-server.sh"


def load_env(conf_file: str) -> str:
"""
Create .env near source files of the library. In .env file following
variables expected to be present: CA_DIR, TMP, KEYS, CERTS, BACKUP.
Deployment process would relay on this variables.
Args:
conf_file: path to YAML configuration fil
Returns:
Path to .env file.
"""

env_file = f"{DIR_PATH}/.env"
with open(conf_file, "r") as f:
env_logger.debug(f"Reading configurations from {conf_file}")
data = yaml.load(f, Loader=yaml.FullLoader)
ca_dir = data["ca_dir"]
data["restore"] = []

with open(conf_file, "w") as f:
yaml.dump(data, f)
env_logger.debug("restore section is added to te configuration file")

with open(env_file, "w") as f:
f.write(f"TMP={join(ca_dir, 'tmp')}\n")
f.write(f"KEYS={join(ca_dir, 'tmp', 'keys')}\n")
f.write(f"CERTS={join(ca_dir, 'tmp', 'certs')}\n")
f.write(f"BACKUP={join(ca_dir, 'tmp', 'backup')}\n")
f.write(f"CONF={abspath(conf_file)}\n")
f.write(f"CA_DIR={ca_dir}\n")
env_logger.debug(f"File {env_file} is created")
return env_file


def read_env(item: str, *args, **kwargs):
"""Just for unifying with read_conf function. Accepts all arguments that
decouple.config() function takes.
Args:
item: variable to read from the .env file
"""
return config(item, *args, **kwargs)


def read_config(*items) -> list or object:
"""
Read data from the configuration file and return require items or full
content.
Args:
items: list of items to extracrt from the configuration file.
If None, full contant would be returned
Returns:
list with required items
"""
try:
with open(read_env("CONF"), "r") as file:
config_data = yaml.load(file, Loader=yaml.FullLoader)
assert config_data, "Data are not loaded correctly."
except FileNotFoundError as e:
env_logger.error(".env file is not present. Try to rerun command"
"with --conf </path/to/conf.yaml> parameter")
raise e

if items is None:
return config_data

return_list = []
for item in items:
parts = item.split(".")
value = config_data
for part in parts:
if value is None:
env_logger.warning(
f"Key {part} not present in the configuration file. Skip.")
return None

value = value.get(part)
if part == parts[-1]:
return_list.append(value)

return return_list if len(items) > 1 else return_list[0]
34 changes: 14 additions & 20 deletions src/authselect.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from SCAutolib import log
import subprocess as subp
from subprocess import check_output, PIPE
from traceback import format_exc

from SCAutolib import base_logger


class Authselect:
Expand Down Expand Up @@ -38,36 +40,28 @@ def _set(self):
args.append("with-mkhomedir")
args.append("--force")

rc = subp.run(args, stdout=subp.DEVNULL, stderr=subp.STDOUT)
msg = f"Authselect command failed. Return code: {rc.returncode}"
assert rc.returncode == 0, msg
log.debug(f"SSSD is set to: {' '.join(args)}")
log.debug(f"Backupfile: {self.backup_name}")
check_output(args, stderr=PIPE, encoding="utf=8")
base_logger.debug(f"SSSD is set to: {' '.join(args)}")
base_logger.debug(f"Backupfile: {self.backup_name}")

def _reset(self):
"""
Restore the previous configuration of authselect.
"""
rc = subp.run(["authselect", "backup-restore", self.backup_name,
"--debug"], stdout=subp.DEVNULL, stderr=subp.STDOUT)
msg = f"Authselect backup-restore failed. Output: {rc.returncode}"
assert rc.returncode == 0, msg
check_output(["authselect", "backup-restore", self.backup_name,
"--debug"], stderr=PIPE, encoding="utf=8")

rc = subp.run(["authselect", "backup-remove", self.backup_name,
"--debug"], stdout=subp.DEVNULL, stderr=subp.STDOUT)
msg = f"Authselect backup-remove failed. Output: {rc.returncode}"
assert rc.returncode == 0, msg
check_output(["authselect", "backup-remove", self.backup_name,
"--debug"], stderr=PIPE, encoding="utf=8")

log.debug("Authselect backup file is restored")
base_logger.debug("Authselect backup file is restored")

def __enter__(self):
self._set()
return self

def __exit__(self, ext_type, ext_value, ext_traceback):
if ext_type is not None:
log.error("Exception in virtual smart card context")
log.error(f"Exception type: {ext_type}")
log.error(f"Exception value: {ext_value}")
log.error(f"Exception traceback: {ext_traceback}")
base_logger.error("Exception in authselect context")
base_logger.error(format_exc())
self._reset()
Loading

0 comments on commit 24fa16e

Please sign in to comment.