Skip to content

Commit 05c87d8

Browse files
jeromegitgfrlv
andauthored
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>
1 parent 695ce02 commit 05c87d8

File tree

5 files changed

+34
-7
lines changed

5 files changed

+34
-7
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
[![Build Status](https://github.com/dbcli/mycli/workflows/mycli/badge.svg)](https://github.com/dbcli/mycli/actions?query=workflow%3Amycli)
44
[![PyPI](https://img.shields.io/pypi/v/mycli.svg?style=plastic)](https://pypi.python.org/pypi/mycli)
5-
[![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)
65

76
A command line client for MySQL that can do auto-completion and syntax highlighting.
87

@@ -109,6 +108,8 @@ $ sudo apt-get install mycli # Only on debian or ubuntu
109108
-e, --execute TEXT Execute command and quit.
110109
--init-command TEXT SQL statement to execute after connecting.
111110
--charset TEXT Character set for MySQL session.
111+
--password-file PATH File or FIFO path containing the password
112+
to connect to the db if not specified otherwise
112113
--help Show this message and exit.
113114

114115

changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Features:
1212
---------
1313
* Add `-g` shortcut to option `--login-path`.
1414
* Alt-Enter dispatches the command in multi-line mode.
15+
* 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)
1516

1617
Internal:
1718
---------

mycli/AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Contributors:
8484
* xeron
8585
* 0xflotus
8686
* Seamile
87+
* Jerome Provensal
8788

8889
Creator:
8990
--------

mycli/main.py

+28-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import logging
77
import threading
88
import re
9+
import stat
10+
import fileinput
911
from collections import namedtuple
1012
try:
1113
from pwd import getpwuid
@@ -387,7 +389,7 @@ def merge_ssl_with_cnf(self, ssl, cnf):
387389
def connect(self, database='', user='', passwd='', host='', port='',
388390
socket='', charset='', local_infile='', ssl='',
389391
ssh_user='', ssh_host='', ssh_port='',
390-
ssh_password='', ssh_key_filename='', init_command=''):
392+
ssh_password='', ssh_key_filename='', init_command='', password_file=''):
391393

392394
cnf = {'database': None,
393395
'user': None,
@@ -443,6 +445,10 @@ def connect(self, database='', user='', passwd='', host='', port='',
443445
if not any(v for v in ssl.values()):
444446
ssl = None
445447

448+
# if the passwd is not specfied try to set it using the password_file option
449+
password_from_file = self.get_password_from_file(password_file)
450+
passwd = passwd or password_from_file
451+
446452
# Connect to the database.
447453

448454
def _connect():
@@ -454,8 +460,11 @@ def _connect():
454460
)
455461
except OperationalError as e:
456462
if e.args[0] == ERROR_CODE_ACCESS_DENIED:
457-
new_passwd = click.prompt('Password', hide_input=True,
458-
show_default=False, type=str, err=True)
463+
if password_from_file:
464+
new_passwd = password_from_file
465+
else:
466+
new_passwd = click.prompt('Password', hide_input=True,
467+
show_default=False, type=str, err=True)
459468
self.sqlexecute = SQLExecute(
460469
database, user, new_passwd, host, port, socket,
461470
charset, local_infile, ssl, ssh_user, ssh_host,
@@ -510,6 +519,17 @@ def _connect():
510519
self.echo(str(e), err=True, fg='red')
511520
exit(1)
512521

522+
def get_password_from_file(self, password_file):
523+
password_from_file = None
524+
if password_file:
525+
if (os.path.isfile(password_file) or stat.S_ISFIFO(os.stat(password_file).st_mode)) \
526+
and os.access(password_file, os.R_OK):
527+
with open(password_file) as fp:
528+
password_from_file = fp.readline()
529+
password_from_file = password_from_file.rstrip().lstrip()
530+
531+
return password_from_file
532+
513533
def handle_editor_command(self, text):
514534
r"""Editor command is any query that is prefixed or suffixed by a '\e'.
515535
The reason for a while loop is because a user might edit a query
@@ -1112,6 +1132,8 @@ def get_last_query(self):
11121132
help='SQL statement to execute after connecting.')
11131133
@click.option('--charset', type=str,
11141134
help='Character set for MySQL session.')
1135+
@click.option('--password-file', type=click.Path(),
1136+
help='File or FIFO path containing the password to connect to the db if not specified otherwise.')
11151137
@click.argument('database', default='', nargs=1)
11161138
def cli(database, user, host, port, socket, password, dbname,
11171139
version, verbose, prompt, logfile, defaults_group_suffix,
@@ -1120,7 +1142,7 @@ def cli(database, user, host, port, socket, password, dbname,
11201142
ssl_verify_server_cert, table, csv, warn, execute, myclirc, dsn,
11211143
list_dsn, ssh_user, ssh_host, ssh_port, ssh_password,
11221144
ssh_key_filename, list_ssh_config, ssh_config_path, ssh_config_host,
1123-
init_command, charset):
1145+
init_command, charset, password_file):
11241146
"""A MySQL terminal client with auto-completion and syntax highlighting.
11251147
11261148
\b
@@ -1246,7 +1268,8 @@ def cli(database, user, host, port, socket, password, dbname,
12461268
ssh_password=ssh_password,
12471269
ssh_key_filename=ssh_key_filename,
12481270
init_command=init_command,
1249-
charset=charset
1271+
charset=charset,
1272+
password_file=password_file
12501273
)
12511274

12521275
mycli.logger.debug('Launch Params: \n'

mycli/packages/parseutils.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
'most_punctuations': re.compile(r'([^\.():,\s]+)$'),
1313
# This matches everything except a space.
1414
'all_punctuations': re.compile(r'([^\s]+)$'),
15-
}
15+
}
16+
1617

1718
def last_word(text, include='alphanum_underscore'):
1819
r"""

0 commit comments

Comments
 (0)