From 05af5b14ba1edde0e03c027b92281c5e6fbf35d1 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sat, 22 May 2021 16:39:42 +0200 Subject: [PATCH] add ouputter --- provisioning_example.sh | 5 +- scripts/cucchiaiata-cli | 21 +++++-- setup.py | 2 +- src/cucchiaiata/common.py | 21 ++++--- src/cucchiaiata/output/__init__.py | 0 src/cucchiaiata/output/interactive.py | 86 +++++++++++++++++++++++++++ src/cucchiaiata/output/json.py | 10 ++++ 7 files changed, 131 insertions(+), 14 deletions(-) create mode 100644 src/cucchiaiata/output/__init__.py create mode 100644 src/cucchiaiata/output/interactive.py create mode 100644 src/cucchiaiata/output/json.py diff --git a/provisioning_example.sh b/provisioning_example.sh index c5301b0..938675f 100755 --- a/provisioning_example.sh +++ b/provisioning_example.sh @@ -106,8 +106,9 @@ cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save # Servermodel unbound S=$(get_id "cucchiaiata-cli v1.setting.session.servermodel.start --servermodel_name unbound") -cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.serveur_dns.unbound_local_zones cadoles.com \ - --configuration.serveur_dns.unbound_allowed_client_cidr 192.168.0.0/24 +cucchiaiata-cli v1.setting.session.configure --session_id "$S" --configuration.dns_server.unbound_role autorité \ + --configuration.dns_server.unbound_allowed_client_cidr 192.168.0.0/24 \ + --configuration.dns_zone.unbound_local_zones cadoles.com cucchiaiata-cli v1.setting.session.stop --session_id "$S" --save # Servermodel unbound_etab1 diff --git a/scripts/cucchiaiata-cli b/scripts/cucchiaiata-cli index 810eeaf..f09a1d8 100755 --- a/scripts/cucchiaiata-cli +++ b/scripts/cucchiaiata-cli @@ -1,22 +1,35 @@ #!/usr/bin/python3 """Zephir-cmd-input script """ +from os import environ from sys import exit, argv -from json import dumps from traceback import print_exc +from json import dumps from cucchiaiata import Parser, config, Configuration, JsonError from cucchiaiata.i18n import _ +from cucchiaiata.output.interactive import get as interactive_get +from cucchiaiata.output.json import get as json_get def main(): + dico = {'interactive': interactive_get, + 'json': json_get, + } + default_outputs = ','.join(dico.keys()) + outputs = [dico[output] for output in environ.get('RISOTTO_OUTPUT', default_outputs).split(',')] try: if len(argv) > 2 and argv[1] == 'v1.setting.session.configure': Configuration().get() else: parser = Parser() - print(dumps(parser.get(), - indent=config.indent), - ) + message = parser.remote_config.option('message').value.get() + for output in outputs: + func = output(message) + if func: + func(parser.get(), + config, + ) + break except KeyboardInterrupt: pass except JsonError as err: diff --git a/setup.py b/setup.py index bafe9fa..ddf2263 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,6 @@ from setuptools import setup, find_packages setup( name='cucchiaiata', version='0.1', - packages=['cucchiaiata' ], + packages=['cucchiaiata', 'cucchiaiata.output'], package_dir={"": "src"}, ) diff --git a/src/cucchiaiata/common.py b/src/cucchiaiata/common.py index d4eeeee..03166d2 100644 --- a/src/cucchiaiata/common.py +++ b/src/cucchiaiata/common.py @@ -1,3 +1,4 @@ +from os import environ from os.path import isfile from requests import get, post from json import dumps @@ -23,11 +24,6 @@ class Common: def __init__(self): self.cucchiaiata_config = config - def get_token(self): - if isfile(self.cucchiaiata_config.token_file): - return open(self.cucchiaiata_config.token_file).read() - return '' - def get_error_from_http(self, req): try: @@ -42,8 +38,7 @@ class Common: config_type=Config, ): "retrieves the remote config from the distant api description" - token = self.get_token() - headers = {'Authorization':'Bearer {}'.format(token)} + headers = get_headers() req = get(url, headers=headers, verify=config.allow_insecure_https, @@ -91,6 +86,17 @@ class Common: raise err from err +def get_headers(): + headers = {} + if isfile(config.token_file): + with open(config.token_file) as token_file: + token = token_file.read() + headers['Authorization'] = f'Bearer {token}' + if 'FORCE_RISOTTO_USER' in environ: + headers['username'] = environ['FORCE_RISOTTO_USER'] + return headers + + def send_data(uri: str, payload: Dict, ): @@ -101,6 +107,7 @@ def send_data(uri: str, ) ret = post(final_url, data=dumps(payload), + headers=get_headers(), verify=config.allow_insecure_https) try: response = ret.json() diff --git a/src/cucchiaiata/output/__init__.py b/src/cucchiaiata/output/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/cucchiaiata/output/interactive.py b/src/cucchiaiata/output/interactive.py new file mode 100644 index 0000000..2518979 --- /dev/null +++ b/src/cucchiaiata/output/interactive.py @@ -0,0 +1,86 @@ +from paramiko.config import SSHConfig +from os.path import expandvars, isdir, isfile, join +from os import open as os_open, write, close, truncate, makedirs, O_WRONLY, O_CREAT + + +def setting_pki_openssh_client(dico, config): + config_dir = expandvars('$HOME/.ssh') + config_file = join(config_dir, 'config') + identityfile = join(expandvars('$HOME/.ssh'), f'risotto_{dico["organization_name"]}') + known_hosts = expandvars('$HOME/.ssh/known_hosts') + hostname = f'*.{dico["organization_name"]}' + new_data = {'identityfile': [identityfile], + 'stricthostkeychecking': 'yes', + 'hostname': hostname, + 'user': dico['cn'], + } + ssh = SSHConfig() + if isfile(config_file): + ssh.parse(open(config_file)) + if hostname not in ssh.get_hostnames(): + print(f'\n\nIl faudrait ajouter dans le fichier "{config_file}" :') + print(f'Host {hostname}') + for key, value in new_data.items(): + if key == 'hostname': + continue + print(f' {key} {value}') + print('\n') + else: + current_data = dict(ssh.lookup(hostname)) + if current_data != new_data: + current = set(current_data) + new = set(new_data) + add = new - current + modify = [key for key in new if key in current and current_data[key] != new_data[key]] + if add or modify: + print(f'\n\nModifications suggérées de la section "Host {hostname}"du fichier "{config_file}" :') + for line in add: + value = new_data[line] + if isinstance(value, list): + value = ','.join(value) + print(f' - ajouter "{line} {value}"') + for line in modify: + value = new_data[line] + if isinstance(value, list): + value = ','.join(value) + print(f' - modifier "{line} {value}"') + print('\n') + else: + print(f'\n\nIl faudrait créer le fichier "{config_file}" :') + print(f'Host {hostname}') + for key, value in new_data.items(): + if key == 'hostname': + continue + print(f' {key} {value}') + if not isdir(config_dir): + makedirs(config_dir, 0o700) + fh = os_open(f'{identityfile}.pub', O_WRONLY | O_CREAT, 0o400) + truncate(fh, 0) + write(fh, dico['certificate'].encode()) + write(fh, b'\n') + close(fh) + if 'private_key' in dico: + fh = os_open(identityfile, O_WRONLY | O_CREAT, 0o400) + truncate(fh, 0) + write(fh, dico['private_key'].encode()) + write(fh, b'\n') + close(fh, ) + content = [f'@cert-authority *.cadoles.com {dico["chain"]}'] + if isfile(known_hosts): + with open(known_hosts) as fh: + old = fh.read().strip() + for line in old.split('\n'): + if line.startswith(f'@cert-authority {hostname} '): + continue + content.append(line) + fh = os_open(known_hosts, O_WRONLY | O_CREAT, 0o400) + truncate(fh, 0) + for line in content: + write(fh, f'{line}\n'.encode()) + close(fh) + print('Certificat mise à jour') + + +def get(message): + if message == 'v1.setting.pki.openssh.client.get': + return setting_pki_openssh_client diff --git a/src/cucchiaiata/output/json.py b/src/cucchiaiata/output/json.py new file mode 100644 index 0000000..6a8485e --- /dev/null +++ b/src/cucchiaiata/output/json.py @@ -0,0 +1,10 @@ +from json import dumps + + +def print_json(dico, config): + indent = config.indent + print(dumps(dico, indent = indent)) + + +def get(message): + return print_json