add -w option

Providing passwords via command line is insecure.  Adding an option to read
the password from the TTY or stdin.  When reading from a TTY, getpass() is
used so that the password is not displayed as it is entered.  Getpass()
also displays a prompt, since TTY usage is typically interactive.  When
reading from something other than a TTY (e.g. from a pipe or input
redirection), a plain read from stdin is done (without getpass(); without
any promting).  This allows the user to pipe the password from some type of
password management/entry tool to registry.py.
This commit is contained in:
Garrick James
2018-05-04 23:50:05 -07:00
parent fd774635c8
commit f9edd90d19

View File

@@ -8,9 +8,11 @@ import pprint
import base64 import base64
import re import re
import sys import sys
import os
import argparse import argparse
import www_authenticate import www_authenticate
from datetime import timedelta, datetime as dt from datetime import timedelta, datetime as dt
from getpass import getpass
# this is a registry manipulator, can do following: # this is a registry manipulator, can do following:
# - list all images (including layers) # - list all images (including layers)
@@ -383,10 +385,20 @@ for more detail on garbage collection read here:
""")) """))
parser.add_argument( parser.add_argument(
'-l', '--login', '-l', '--login',
help="Login and password to access to docker registry", help="Login and password for access to docker registry",
required=False, required=False,
metavar="USER:PASSWORD") metavar="USER:PASSWORD")
parser.add_argument(
'-w', '--read-password',
help="Read password from stdin (and prompt if stdin is a TTY); " +
"the final line-ending character(s) will be removed; " +
"the :PASSWORD portion of the -l option is not required and " +
"will be ignored",
action='store_const',
default=False,
const=True)
parser.add_argument( parser.add_argument(
'-r', '--host', '-r', '--host',
help="Hostname for registry server, e.g. https://example.com:5000", help="Hostname for registry server, e.g. https://example.com:5000",
@@ -581,6 +593,33 @@ def main_loop(args):
if args.no_validate_ssl: if args.no_validate_ssl:
requests.packages.urllib3.disable_warnings(InsecureRequestWarning) requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
if args.read_password:
if args.login is None:
print("Please provide -l when using -w")
exit(1)
if ':' in args.login:
(username, password) = args.login.split(':', 1)
else:
username = args.login
if sys.stdin.isatty():
# likely interactive usage
password = getpass()
else:
# allow password to be piped or redirected in
password = sys.stdin.read()
if len(password) == 0:
print("Password was not provided")
exit(1)
if password[-(len(os.linesep)):] == os.linesep:
password = password[0:-(len(os.linesep))]
args.login = username + ':' + password
registry = Registry.create(args.host, args.login, args.no_validate_ssl) registry = Registry.create(args.host, args.login, args.no_validate_ssl)
registry.auth_schemes = get_auth_schemes(registry,'/v2/_catalog') registry.auth_schemes = get_auth_schemes(registry,'/v2/_catalog')