summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjerome provensal <552382+jeromegit@users.noreply.github.com>2021-03-01 08:54:15 -0800
committerGitHub <noreply@github.com>2021-03-01 19:54:15 +0300
commit05c87d8f29d3caaf6a437db336feb0735d4d085e (patch)
tree59dd467abd12b6590ff242965d63ef6a1d037703
parent695ce02f52a67310baa4cc1a51dcc37faa1be0d4 (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.md3
-rw-r--r--changelog.md1
-rw-r--r--mycli/AUTHORS1
-rwxr-xr-xmycli/main.py33
-rw-r--r--mycli/packages/parseutils.py3
5 files changed, 34 insertions, 7 deletions
diff --git a/README.md b/README.md
index 8da08a4..46b5fd3 100644
--- a/README.md
+++ b/README.md
@@ -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"""