mirror of
https://github.com/ansible/awx.git
synced 2026-03-13 23:17:32 -02:30
Upgrade keyring to 4.0
This commit is contained in:
@@ -30,7 +30,7 @@ gevent-websocket==0.9.3 (geventwebsocket/*)
|
||||
httplib2==0.9 (httplib2/*)
|
||||
importlib==1.0.3 (importlib/*, needed for Python 2.6 support)
|
||||
iso8601==0.1.10 (iso8601/*)
|
||||
keyring==3.7 (keyring/*, excluded bin/keyring)
|
||||
keyring==4.0 (keyring/*, excluded bin/keyring)
|
||||
kombu==3.0.14 (kombu/*)
|
||||
Markdown==2.4 (markdown/*, excluded bin/markdown_py)
|
||||
mock==1.0.1 (mock.py)
|
||||
|
||||
@@ -10,10 +10,18 @@ from ..errors import PasswordDeleteError, ExceptionRaisedContext
|
||||
from . import file
|
||||
|
||||
try:
|
||||
import pywintypes
|
||||
import win32cred
|
||||
# prefer pywin32-ctypes
|
||||
from win32ctypes import pywintypes
|
||||
from win32ctypes import win32cred
|
||||
# force demand import to raise ImportError
|
||||
win32cred.__name__
|
||||
except ImportError:
|
||||
pass
|
||||
# fallback to pywin32
|
||||
try:
|
||||
import pywintypes
|
||||
import win32cred
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import winreg
|
||||
@@ -229,9 +237,31 @@ class RegistryKeyring(KeyringBackend):
|
||||
hkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_name, 0,
|
||||
winreg.KEY_ALL_ACCESS)
|
||||
winreg.DeleteValue(hkey, username)
|
||||
winreg.CloseKey(hkey)
|
||||
except WindowsError:
|
||||
e = sys.exc_info()[1]
|
||||
raise PasswordDeleteError(e)
|
||||
self._delete_key_if_empty(service)
|
||||
|
||||
def _delete_key_if_empty(self, service):
|
||||
key_name = r'Software\%s\Keyring' % service
|
||||
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_name, 0,
|
||||
winreg.KEY_ALL_ACCESS)
|
||||
try:
|
||||
winreg.EnumValue(key, 0)
|
||||
return
|
||||
except WindowsError:
|
||||
pass
|
||||
winreg.CloseKey(key)
|
||||
|
||||
# it's empty; delete everything
|
||||
while key_name != 'Software':
|
||||
parent, sep, base = key_name.rpartition('\\')
|
||||
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, parent, 0,
|
||||
winreg.KEY_ALL_ACCESS)
|
||||
winreg.DeleteKey(key, base)
|
||||
winreg.CloseKey(key)
|
||||
key_name = parent
|
||||
|
||||
|
||||
class OldPywinError(object):
|
||||
|
||||
@@ -62,6 +62,8 @@ class Keyring(KeyringBackend):
|
||||
KWallet.__name__
|
||||
if exc:
|
||||
raise RuntimeError("KDE libraries not available")
|
||||
if "DISPLAY" not in os.environ:
|
||||
raise RuntimeError("cannot connect to X server")
|
||||
# Infer if KDE environment is active based on environment vars.
|
||||
# TODO: Does PyKDE provide a better indicator?
|
||||
kde_session_keys = (
|
||||
|
||||
@@ -37,8 +37,9 @@ class CommandLineTool(object):
|
||||
|
||||
if opts.keyring_backend is not None:
|
||||
try:
|
||||
backend = core.load_keyring(opts.keyring_path,
|
||||
opts.keyring_backend)
|
||||
if opts.keyring_path:
|
||||
sys.path.insert(0, opts.keyring_path)
|
||||
backend = core.load_keyring(opts.keyring_backend)
|
||||
set_keyring(backend)
|
||||
except (Exception,):
|
||||
# Tons of things can go wrong here:
|
||||
|
||||
@@ -5,7 +5,6 @@ Created by Kang Zhang on 2009-07-09
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
import logging
|
||||
|
||||
from .py27compat import configparser
|
||||
@@ -71,19 +70,12 @@ def _get_best_keyring():
|
||||
return keyrings[0]
|
||||
|
||||
|
||||
def load_keyring(keyring_path, keyring_name):
|
||||
def load_keyring(keyring_name):
|
||||
"""
|
||||
Load the specified keyring by name (a fully-qualified name to the
|
||||
keyring, such as 'keyring.backends.file.PlaintextKeyring')
|
||||
|
||||
`keyring_path` is an additional, optional search path and may be None.
|
||||
**deprecated** In the future, keyring_path must be None.
|
||||
"""
|
||||
module_name, sep, class_name = keyring_name.rpartition('.')
|
||||
if keyring_path is not None and keyring_path not in sys.path:
|
||||
warnings.warn("keyring_path is deprecated and should always be None",
|
||||
DeprecationWarning)
|
||||
sys.path.insert(0, keyring_path)
|
||||
__import__(module_name)
|
||||
module = sys.modules[module_name]
|
||||
class_ = getattr(module, class_name)
|
||||
@@ -93,46 +85,32 @@ def load_keyring(keyring_path, keyring_name):
|
||||
|
||||
|
||||
def load_config():
|
||||
"""Load a keyring using the config file.
|
||||
|
||||
The config file can be in the current working directory, or in the user's
|
||||
home directory.
|
||||
"""
|
||||
keyring = None
|
||||
"""Load a keyring using the config file in the config root."""
|
||||
|
||||
filename = 'keyringrc.cfg'
|
||||
|
||||
local_path = os.path.join(os.getcwd(), filename)
|
||||
config_path = os.path.join(platform.config_root(), filename)
|
||||
keyring_cfg = os.path.join(platform.config_root(), filename)
|
||||
|
||||
# search from current working directory and the data root
|
||||
keyring_cfg_candidates = [local_path, config_path]
|
||||
if not os.path.exists(keyring_cfg):
|
||||
return
|
||||
|
||||
# initialize the keyring_config with the first detected config file
|
||||
keyring_cfg = None
|
||||
for path in keyring_cfg_candidates:
|
||||
keyring_cfg = path
|
||||
if os.path.exists(path):
|
||||
break
|
||||
config = configparser.RawConfigParser()
|
||||
config.read(keyring_cfg)
|
||||
_load_keyring_path(config)
|
||||
|
||||
if os.path.exists(keyring_cfg):
|
||||
config = configparser.RawConfigParser()
|
||||
config.read(keyring_cfg)
|
||||
_load_keyring_path(config)
|
||||
# load the keyring class name, and then load this keyring
|
||||
try:
|
||||
if config.has_section("backend"):
|
||||
keyring_name = config.get("backend", "default-keyring").strip()
|
||||
else:
|
||||
raise configparser.NoOptionError('backend', 'default-keyring')
|
||||
|
||||
# load the keyring class name, and then load this keyring
|
||||
try:
|
||||
if config.has_section("backend"):
|
||||
keyring_name = config.get("backend", "default-keyring").strip()
|
||||
else:
|
||||
raise configparser.NoOptionError('backend', 'default-keyring')
|
||||
except (configparser.NoOptionError, ImportError):
|
||||
logger.warning("Keyring config file contains incorrect values.\n" +
|
||||
"Config file: %s" % keyring_cfg)
|
||||
return
|
||||
|
||||
keyring = load_keyring(None, keyring_name)
|
||||
except (configparser.NoOptionError, ImportError):
|
||||
logger.warning("Keyring config file contains incorrect values.\n" +
|
||||
"Config file: %s" % keyring_cfg)
|
||||
|
||||
return keyring
|
||||
return load_keyring(keyring_name)
|
||||
|
||||
def _load_keyring_path(config):
|
||||
"load the keyring-path option (if present)"
|
||||
|
||||
@@ -10,17 +10,23 @@ import os
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
from keyring.tests.py30compat import unittest
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
|
||||
import keyring.backend
|
||||
import keyring.core
|
||||
import keyring.util.platform_
|
||||
from keyring import errors
|
||||
|
||||
PASSWORD_TEXT = "This is password"
|
||||
PASSWORD_TEXT_2 = "This is password2"
|
||||
KEYRINGRC = "keyringrc.cfg"
|
||||
|
||||
|
||||
@pytest.yield_fixture()
|
||||
def config_filename(tmpdir):
|
||||
filename = tmpdir / 'keyringrc.cfg'
|
||||
with mock.patch('keyring.util.platform_.config_root', lambda: str(tmpdir)):
|
||||
yield str(filename)
|
||||
|
||||
|
||||
class TestKeyring(keyring.backend.KeyringBackend):
|
||||
@@ -53,7 +59,7 @@ class TestKeyring2(TestKeyring):
|
||||
return PASSWORD_TEXT_2
|
||||
|
||||
|
||||
class CoreTestCase(unittest.TestCase):
|
||||
class TestCore:
|
||||
mock_global_backend = mock.patch('keyring.core._keyring_backend')
|
||||
|
||||
@mock_global_backend
|
||||
@@ -72,7 +78,7 @@ class CoreTestCase(unittest.TestCase):
|
||||
"""
|
||||
result = keyring.core.get_password("test", "user")
|
||||
backend.get_password.assert_called_once_with('test', 'user')
|
||||
self.assertIsNotNone(result)
|
||||
assert result is not None
|
||||
|
||||
@mock_global_backend
|
||||
def test_delete_password(self, backend):
|
||||
@@ -85,71 +91,40 @@ class CoreTestCase(unittest.TestCase):
|
||||
keyring.core.set_keyring(TestKeyring())
|
||||
|
||||
keyring.core.set_password("test", "user", "password")
|
||||
self.assertEqual(keyring.core.get_password("test", "user"),
|
||||
PASSWORD_TEXT)
|
||||
assert keyring.core.get_password("test", "user") == PASSWORD_TEXT
|
||||
|
||||
def test_set_keyring_in_config(self):
|
||||
def test_set_keyring_in_config(self, config_filename):
|
||||
"""Test setting the keyring by config file.
|
||||
"""
|
||||
# create the config file
|
||||
config_file = open(KEYRINGRC, 'w')
|
||||
config_file.writelines([
|
||||
"[backend]\n",
|
||||
# the path for the user created keyring
|
||||
"keyring-path= %s\n" % os.path.dirname(os.path.abspath(__file__)),
|
||||
# the name of the keyring class
|
||||
"default-keyring=test_core.TestKeyring2\n",
|
||||
])
|
||||
config_file.close()
|
||||
with open(config_filename, 'w') as config_file:
|
||||
config_file.writelines([
|
||||
"[backend]\n",
|
||||
# the path for the user created keyring
|
||||
"keyring-path= %s\n" % os.path.dirname(os.path.abspath(__file__)),
|
||||
# the name of the keyring class
|
||||
"default-keyring=test_core.TestKeyring2\n",
|
||||
])
|
||||
|
||||
# init the keyring lib, the lib will automaticlly load the
|
||||
# config file and load the user defined module
|
||||
keyring.core.init_backend()
|
||||
|
||||
keyring.core.set_password("test", "user", "password")
|
||||
self.assertEqual(keyring.core.get_password("test", "user"),
|
||||
PASSWORD_TEXT_2)
|
||||
assert keyring.core.get_password("test", "user") == PASSWORD_TEXT_2
|
||||
|
||||
os.remove(KEYRINGRC)
|
||||
def test_load_config_empty(self, config_filename):
|
||||
"A non-existent or empty config should load"
|
||||
assert keyring.core.load_config() is None
|
||||
|
||||
def test_load_config(self):
|
||||
tempdir = tempfile.mkdtemp()
|
||||
old_location = os.getcwd()
|
||||
os.chdir(tempdir)
|
||||
personal_cfg = os.path.join(os.path.expanduser("~"), "keyringrc.cfg")
|
||||
if os.path.exists(personal_cfg):
|
||||
os.rename(personal_cfg, personal_cfg + '.old')
|
||||
personal_renamed = True
|
||||
else:
|
||||
personal_renamed = False
|
||||
def test_load_config_degenerate(self, config_filename):
|
||||
"load_config should succeed in the absence of a backend section"
|
||||
with open(config_filename, 'w') as config_file:
|
||||
config_file.write('[keyring]')
|
||||
assert keyring.core.load_config() is None
|
||||
|
||||
# loading with an empty environment
|
||||
keyring.core.load_config()
|
||||
|
||||
# loading with a file that doesn't have a backend section
|
||||
cfg = os.path.join(tempdir, "keyringrc.cfg")
|
||||
f = open(cfg, 'w')
|
||||
f.write('[keyring]')
|
||||
f.close()
|
||||
keyring.core.load_config()
|
||||
|
||||
# loading with a file that doesn't have a default-keyring value
|
||||
cfg = os.path.join(tempdir, "keyringrc.cfg")
|
||||
f = open(cfg, 'w')
|
||||
f.write('[backend]')
|
||||
f.close()
|
||||
keyring.core.load_config()
|
||||
|
||||
os.chdir(old_location)
|
||||
shutil.rmtree(tempdir)
|
||||
if personal_renamed:
|
||||
os.rename(personal_cfg + '.old', personal_cfg)
|
||||
|
||||
|
||||
def test_suite():
|
||||
suite = unittest.TestSuite()
|
||||
suite.addTest(unittest.makeSuite(CoreTestCase))
|
||||
return suite
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(defaultTest="test_suite")
|
||||
def test_load_config_blank_backend(self, config_filename):
|
||||
"load_config should succeed with an empty [backend] section"
|
||||
with open(config_filename, 'w') as config_file:
|
||||
config_file.write('[backend]')
|
||||
assert keyring.core.load_config() is None
|
||||
|
||||
Reference in New Issue
Block a user