diff options
author | jerome provensal <552382+jeromegit@users.noreply.github.com> | 2021-03-01 08:54:15 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-01 19:54:15 +0300 |
commit | 05c87d8f29d3caaf6a437db336feb0735d4d085e (patch) | |
tree | 59dd467abd12b6590ff242965d63ef6a1d037703 | |
parent | 695ce02f52a67310baa4cc1a51dcc37faa1be0d4 (diff) |
Allow to pass file instead of password (#913)
* allow to pass a file or FIFO as password with --password /my/file/path as suggested in this best-practice https://www.netmeister.org/blog/passing-passwords.html article
* allow to pass a file or FIFO as password with --password /my/file/path as suggested in this best-practice https://www.netmeister.org/blog/passing-passwords.html article (including change to changelog and AUTHORS)
* A few changes based on input received after the pull request
Co-authored-by: Georgy Frolov <gosha@fro.lv>
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | changelog.md | 1 | ||||
-rw-r--r-- | mycli/AUTHORS | 1 | ||||
-rwxr-xr-x | mycli/main.py | 33 | ||||
-rw-r--r-- | mycli/packages/parseutils.py | 3 |
5 files changed, 34 insertions, 7 deletions
@@ -2,7 +2,6 @@ [![Build Status](https://github.com/dbcli/mycli/workflows/mycli/badge.svg)](https://github.com/dbcli/mycli/actions?query=workflow%3Amycli) [![PyPI](https://img.shields.io/pypi/v/mycli.svg?style=plastic)](https://pypi.python.org/pypi/mycli) -[![LGTM](https://img.shields.io/lgtm/grade/python/github/dbcli/mycli.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/dbcli/mycli/context:python) A command line client for MySQL that can do auto-completion and syntax highlighting. @@ -109,6 +108,8 @@ $ sudo apt-get install mycli # Only on debian or ubuntu -e, --execute TEXT Execute command and quit. --init-command TEXT SQL statement to execute after connecting. --charset TEXT Character set for MySQL session. + --password-file PATH File or FIFO path containing the password + to connect to the db if not specified otherwise --help Show this message and exit. diff --git a/changelog.md b/changelog.md index 5aff432..965ef97 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,7 @@ Features: --------- * Add `-g` shortcut to option `--login-path`. * Alt-Enter dispatches the command in multi-line mode. +* Allow to pass a file or FIFO path with --password-file when password is not specified or is failing (as suggested in this best-practice https://www.netmeister.org/blog/passing-passwords.html) Internal: --------- diff --git a/mycli/AUTHORS b/mycli/AUTHORS index c871f51..8cdea91 100644 --- a/mycli/AUTHORS +++ b/mycli/AUTHORS @@ -84,6 +84,7 @@ Contributors: * xeron * 0xflotus * Seamile + * Jerome Provensal Creator: -------- diff --git a/mycli/main.py b/mycli/main.py index 2e2b842..3f08e9c 100755 --- a/mycli/main.py +++ b/mycli/main.py @@ -6,6 +6,8 @@ import traceback import logging import threading import re +import stat +import fileinput from collections import namedtuple try: from pwd import getpwuid @@ -387,7 +389,7 @@ class MyCli(object): def connect(self, database='', user='', passwd='', host='', port='', socket='', charset='', local_infile='', ssl='', ssh_user='', ssh_host='', ssh_port='', - ssh_password='', ssh_key_filename='', init_command=''): + ssh_password='', ssh_key_filename='', init_command='', password_file=''): cnf = {'database': None, 'user': None, @@ -443,6 +445,10 @@ class MyCli(object): if not any(v for v in ssl.values()): ssl = None + # if the passwd is not specfied try to set it using the password_file option + password_from_file = self.get_password_from_file(password_file) + passwd = passwd or password_from_file + # Connect to the database. def _connect(): @@ -454,8 +460,11 @@ class MyCli(object): ) except OperationalError as e: if e.args[0] == ERROR_CODE_ACCESS_DENIED: - new_passwd = click.prompt('Password', hide_input=True, - show_default=False, type=str, err=True) + if password_from_file: + new_passwd = password_from_file + else: + new_passwd = click.prompt('Password', hide_input=True, + show_default=False, type=str, err=True) self.sqlexecute = SQLExecute( database, user, new_passwd, host, port, socket, charset, local_infile, ssl, ssh_user, ssh_host, @@ -510,6 +519,17 @@ class MyCli(object): self.echo(str(e), err=True, fg='red') exit(1) + def get_password_from_file(self, password_file): + password_from_file = None + if password_file: + if (os.path.isfile(password_file) or stat.S_ISFIFO(os.stat(password_file).st_mode)) \ + and os.access(password_file, os.R_OK): + with open(password_file) as fp: + password_from_file = fp.readline() + password_from_file = password_from_file.rstrip().lstrip() + + return password_from_file + def handle_editor_command(self, text): r"""Editor command is any query that is prefixed or suffixed by a '\e'. The reason for a while loop is because a user might edit a query @@ -1112,6 +1132,8 @@ class MyCli(object): help='SQL statement to execute after connecting.') @click.option('--charset', type=str, help='Character set for MySQL session.') +@click.option('--password-file', type=click.Path(), + help='File or FIFO path containing the password to connect to the db if not specified otherwise.') @click.argument('database', default='', nargs=1) def cli(database, user, host, port, socket, password, dbname, version, verbose, prompt, logfile, defaults_group_suffix, @@ -1120,7 +1142,7 @@ def cli(database, user, host, port, socket, password, dbname, ssl_verify_server_cert, table, csv, warn, execute, myclirc, dsn, list_dsn, ssh_user, ssh_host, ssh_port, ssh_password, ssh_key_filename, list_ssh_config, ssh_config_path, ssh_config_host, - init_command, charset): + init_command, charset, password_file): """A MySQL terminal client with auto-completion and syntax highlighting. \b @@ -1246,7 +1268,8 @@ def cli(database, user, host, port, socket, password, dbname, ssh_password=ssh_password, ssh_key_filename=ssh_key_filename, init_command=init_command, - charset=charset + charset=charset, + password_file=password_file ) mycli.logger.debug('Launch Params: \n' diff --git a/mycli/packages/parseutils.py b/mycli/packages/parseutils.py index 90a868e..fa5f2c9 100644 --- a/mycli/packages/parseutils.py +++ b/mycli/packages/parseutils.py @@ -12,7 +12,8 @@ cleanup_regex = { 'most_punctuations': re.compile(r'([^\.():,\s]+)$'), # This matches everything except a space. 'all_punctuations': re.compile(r'([^\s]+)$'), - } +} + def last_word(text, include='alphanum_underscore'): r""" |