summaryrefslogtreecommitdiff
path: root/etoolkit/__main__.py
diff options
context:
space:
mode:
Diffstat (limited to 'etoolkit/__main__.py')
-rw-r--r--etoolkit/__main__.py79
1 files changed, 72 insertions, 7 deletions
diff --git a/etoolkit/__main__.py b/etoolkit/__main__.py
index 8c4245d..603bb2e 100644
--- a/etoolkit/__main__.py
+++ b/etoolkit/__main__.py
@@ -1,5 +1,5 @@
1# etoolkit 1# etoolkit
2# Copyright (C) 2021 Simeon Simeonov 2# Copyright (C) 2021-2022 Simeon Simeonov
3 3
4# This program is free software: you can redistribute it and/or modify 4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by 5# it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ python -m etoolkit -p
24import argparse 24import argparse
25import errno 25import errno
26import getpass 26import getpass
27import io
27import json 28import json
28import logging 29import logging
29import os 30import os
@@ -52,11 +53,29 @@ def decrypt_value(args: argparse.Namespace, config: dict):
52 :type config: dict 53 :type config: dict
53 """ 54 """
54 password_hash = None 55 password_hash = None
56 pipe_input = None
57 if not os.isatty(sys.stdin.fileno()):
58 pipe_input = sys.stdin.read().strip()
55 if 'general' in config: 59 if 'general' in config:
56 password_hash = config['general'].get('MASTER_PASSWORD_HASH') 60 password_hash = config['general'].get('MASTER_PASSWORD_HASH')
57 password = etoolkit.EtoolkitInstance.confirm_password_prompt( 61
58 password_hash, False 62 if (
59 ) 63 args.master_password_prompt
64 or os.environ.get('ETOOLKIT_MASTER_PASSWORD') is None
65 ):
66 password = etoolkit.EtoolkitInstance.confirm_password_prompt(
67 password_hash, False
68 )
69 else:
70 password = os.environ.get('ETOOLKIT_MASTER_PASSWORD')
71
72 if pipe_input:
73 # the input came from stdin. No need to prompt
74 print(
75 'Decrypted value: '
76 f'{etoolkit.EtoolkitInstance.decrypt(password, pipe_input)}'
77 )
78 return
60 while True: 79 while True:
61 try: 80 try:
62 value = input('Value: ') 81 value = input('Value: ')
@@ -69,6 +88,7 @@ def decrypt_value(args: argparse.Namespace, config: dict):
69 except KeyboardInterrupt: 88 except KeyboardInterrupt:
70 print(os.linesep) 89 print(os.linesep)
71 break 90 break
91 return
72 92
73 93
74def encrypt_value(args: argparse.Namespace, config: dict): 94def encrypt_value(args: argparse.Namespace, config: dict):
@@ -86,9 +106,29 @@ def encrypt_value(args: argparse.Namespace, config: dict):
86 :type config: dict 106 :type config: dict
87 """ 107 """
88 password_hash = None 108 password_hash = None
109 pipe_input = None
110 if not os.isatty(sys.stdin.fileno()):
111 pipe_input = sys.stdin.read().strip()
89 if 'general' in config: 112 if 'general' in config:
90 password_hash = config['general'].get('MASTER_PASSWORD_HASH') 113 password_hash = config['general'].get('MASTER_PASSWORD_HASH')
91 password = etoolkit.EtoolkitInstance.confirm_password_prompt(password_hash) 114
115 if (
116 args.master_password_prompt
117 or os.environ.get('ETOOLKIT_MASTER_PASSWORD') is None
118 ):
119 password = etoolkit.EtoolkitInstance.confirm_password_prompt(
120 password_hash
121 )
122 else:
123 password = os.environ.get('ETOOLKIT_MASTER_PASSWORD')
124
125 if pipe_input:
126 # the input came from stdin. No need to prompt
127 print(
128 'Encrypted value: '
129 f'{etoolkit.EtoolkitInstance.encrypt(password, pipe_input)}'
130 )
131 return
92 while True: 132 while True:
93 try: 133 try:
94 if args.echo: 134 if args.echo:
@@ -104,6 +144,7 @@ def encrypt_value(args: argparse.Namespace, config: dict):
104 except KeyboardInterrupt: 144 except KeyboardInterrupt:
105 print(os.linesep) 145 print(os.linesep)
106 break 146 break
147 return
107 148
108 149
109def main(inargs=None): 150def main(inargs=None):
@@ -192,6 +233,16 @@ def main(inargs=None):
192 ), 233 ),
193 ) 234 )
194 parser.add_argument( 235 parser.add_argument(
236 '-P',
237 '--master-password-prompt',
238 dest='master_password_prompt',
239 action='store_true',
240 help=(
241 'Force prompt for the master password even if the env. variable '
242 '"ETOOLKIT_MASTER_PASSWORD" is set'
243 ),
244 )
245 parser.add_argument(
195 '-q', 246 '-q',
196 '--no-output', 247 '--no-output',
197 dest='dump_output', 248 dest='dump_output',
@@ -217,12 +268,26 @@ def main(inargs=None):
217 ) 268 )
218 args = parser.parse_args(inargs) 269 args = parser.parse_args(inargs)
219 try: 270 try:
220 with open(args.config_file, 'r', encoding='utf-8') as fp: 271 with io.open(args.config_file, 'r', encoding='utf-8') as fp:
221 config_dict = json.load(fp) 272 config_dict = json.load(fp)
273 except FileNotFoundError as e:
274 # do not raise exception if config-file is missing for:
275 # - decrypting value
276 # - encrypting value
277 # - password hash generation
278 if args.password_hash or args.decrypt_value or args.encrypt_value:
279 logger.warning(
280 "Configuration file %s is missing, although not required "
281 "by the provided parameters",
282 args.config_file,
283 )
284 config_dict = {}
285 else:
286 logger.error("Configuration file %s is missing", args.config_file)
287 raise SystemExit(errno.EIO) from e
222 except Exception as e: 288 except Exception as e:
223 logger.error("Unable to parse %r: %s", args.config_file, e) 289 logger.error("Unable to parse %r: %s", args.config_file, e)
224 raise SystemExit(errno.EIO) from e 290 raise SystemExit(errno.EIO) from e
225
226 try: 291 try:
227 if args.decrypt_value: 292 if args.decrypt_value:
228 decrypt_value(args, config_dict) 293 decrypt_value(args, config_dict)