Session loading from conf
Allow loading session objects from oslo.config. We want a generic way to do this for auth_token middleware and for servers creating session objects for inter-service communication. DocImpact: This is the first step in standardizing all the config options across projects. There are no changes to the config options that keystoneclient actually consumes in this review. Implements: blueprint standard-client-params Change-Id: I1e83280b2f76f16041ed8d5ed598db70210112bd
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from oslo.config import cfg
|
||||||
import requests
|
import requests
|
||||||
import six
|
import six
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
@@ -355,12 +356,26 @@ class Session(object):
|
|||||||
functionswithout session arguments.
|
functionswithout session arguments.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
verify = kwargs.pop('verify', None)
|
params = {}
|
||||||
cacert = kwargs.pop('cacert', None)
|
|
||||||
cert = kwargs.pop('cert', None)
|
|
||||||
key = kwargs.pop('key', None)
|
|
||||||
insecure = kwargs.pop('insecure', False)
|
|
||||||
|
|
||||||
|
for attr in ('verify', 'cacert', 'cert', 'key', 'insecure',
|
||||||
|
'timeout', 'session', 'original_ip', 'user_agent'):
|
||||||
|
try:
|
||||||
|
params[attr] = kwargs.pop(attr)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return cls._make(**params)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _make(cls, insecure=False, verify=None, cacert=None, cert=None,
|
||||||
|
key=None, **kwargs):
|
||||||
|
"""Create a session with individual certificate parameters.
|
||||||
|
|
||||||
|
Some parameters used to create a session don't lend themselves to be
|
||||||
|
loaded from config/CLI etc. Create a session by converting those
|
||||||
|
parameters into session __init__ parameters.
|
||||||
|
"""
|
||||||
if verify is None:
|
if verify is None:
|
||||||
if insecure:
|
if insecure:
|
||||||
verify = False
|
verify = False
|
||||||
@@ -372,11 +387,7 @@ class Session(object):
|
|||||||
# requests lib form of having the cert and key as a tuple
|
# requests lib form of having the cert and key as a tuple
|
||||||
cert = (cert, key)
|
cert = (cert, key)
|
||||||
|
|
||||||
return cls(verify=verify, cert=cert,
|
return cls(verify=verify, cert=cert, **kwargs)
|
||||||
timeout=kwargs.pop('timeout', None),
|
|
||||||
session=kwargs.pop('session', None),
|
|
||||||
original_ip=kwargs.pop('original_ip', None),
|
|
||||||
user_agent=kwargs.pop('user_agent', None))
|
|
||||||
|
|
||||||
def get_token(self, auth=None):
|
def get_token(self, auth=None):
|
||||||
"""Return a token as provided by the auth plugin.
|
"""Return a token as provided by the auth plugin.
|
||||||
@@ -432,3 +443,106 @@ class Session(object):
|
|||||||
raise exceptions.MissingAuthPlugin(msg)
|
raise exceptions.MissingAuthPlugin(msg)
|
||||||
|
|
||||||
return auth.invalidate()
|
return auth.invalidate()
|
||||||
|
|
||||||
|
@utils.positional.classmethod()
|
||||||
|
def get_conf_options(cls, deprecated_opts=None):
|
||||||
|
"""Get the oslo.config options that are needed for a session.
|
||||||
|
|
||||||
|
These may be useful without being registered for config file generation
|
||||||
|
or to manipulate the options before registering them yourself.
|
||||||
|
|
||||||
|
The options that are set are:
|
||||||
|
:cafile: The certificate authority filename.
|
||||||
|
:certfile: The client certificate file to present.
|
||||||
|
:keyfile: The key for the client certificate.
|
||||||
|
:insecure: Whether to ignore SSL verification.
|
||||||
|
:timeout: The max time to wait for HTTP connections.
|
||||||
|
|
||||||
|
:param dict deprecated_opts: Deprecated options that should be included
|
||||||
|
in the definition of new options. This should be a dictionary from
|
||||||
|
the name of the new option to a list of oslo.DeprecatedOpts that
|
||||||
|
correspond to the new option. (optional)
|
||||||
|
|
||||||
|
Example to support the 'ca_file' option pointing to the new
|
||||||
|
'cafile' option name::
|
||||||
|
|
||||||
|
old_opt = oslo.cfg.DeprecatedOpt('ca_file', 'old_group')
|
||||||
|
deprecated_opts={'cafile': [old_opt]}
|
||||||
|
|
||||||
|
:returns: A list of oslo.config options.
|
||||||
|
"""
|
||||||
|
if deprecated_opts is None:
|
||||||
|
deprecated_opts = {}
|
||||||
|
|
||||||
|
return [cfg.StrOpt('cafile',
|
||||||
|
deprecated_opts=deprecated_opts.get('cafile'),
|
||||||
|
help='PEM encoded Certificate Authority to use '
|
||||||
|
'when verifying HTTPs connections.'),
|
||||||
|
cfg.StrOpt('certfile',
|
||||||
|
deprecated_opts=deprecated_opts.get('certfile'),
|
||||||
|
help='PEM encoded client certificate cert file'),
|
||||||
|
cfg.StrOpt('keyfile',
|
||||||
|
deprecated_opts=deprecated_opts.get('keyfile'),
|
||||||
|
help='PEM encoded client certificate key file'),
|
||||||
|
cfg.BoolOpt('insecure',
|
||||||
|
default=False,
|
||||||
|
deprecated_opts=deprecated_opts.get('insecure'),
|
||||||
|
help='Verify HTTPS connections.'),
|
||||||
|
cfg.IntOpt('timeout',
|
||||||
|
deprecated_opts=deprecated_opts.get('timeout'),
|
||||||
|
help='Timeout value for http requests'),
|
||||||
|
]
|
||||||
|
|
||||||
|
@utils.positional.classmethod()
|
||||||
|
def register_conf_options(cls, conf, group, deprecated_opts=None):
|
||||||
|
"""Register the oslo.config options that are needed for a session.
|
||||||
|
|
||||||
|
The options that are set are:
|
||||||
|
:cafile: The certificate authority filename.
|
||||||
|
:certfile: The client certificate file to present.
|
||||||
|
:keyfile: The key for the client certificate.
|
||||||
|
:insecure: Whether to ignore SSL verification.
|
||||||
|
:timeout: The max time to wait for HTTP connections.
|
||||||
|
|
||||||
|
:param oslo.config.Cfg conf: config object to register with.
|
||||||
|
:param string group: The ini group to register options in.
|
||||||
|
:param dict deprecated_opts: Deprecated options that should be included
|
||||||
|
in the definition of new options. This should be a dictionary from
|
||||||
|
the name of the new option to a list of oslo.DeprecatedOpts that
|
||||||
|
correspond to the new option. (optional)
|
||||||
|
|
||||||
|
Example to support the 'ca_file' option pointing to the new
|
||||||
|
'cafile' option name::
|
||||||
|
|
||||||
|
old_opt = oslo.cfg.DeprecatedOpt('ca_file', 'old_group')
|
||||||
|
deprecated_opts={'cafile': [old_opt]}
|
||||||
|
|
||||||
|
:returns: The list of options that was registered.
|
||||||
|
"""
|
||||||
|
opts = cls.get_conf_options(deprecated_opts=deprecated_opts)
|
||||||
|
conf.register_group(cfg.OptGroup(group))
|
||||||
|
conf.register_opts(opts, group=group)
|
||||||
|
return opts
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_from_conf_options(cls, conf, group, **kwargs):
|
||||||
|
"""Create a session object from an oslo.config object.
|
||||||
|
|
||||||
|
The options must have been previously registered with
|
||||||
|
register_conf_options.
|
||||||
|
|
||||||
|
:param oslo.config.Cfg conf: config object to register with.
|
||||||
|
:param string group: The ini group to register options in.
|
||||||
|
:param dict kwargs: Additional parameters to pass to session
|
||||||
|
construction.
|
||||||
|
:returns: A new session object.
|
||||||
|
"""
|
||||||
|
c = conf[group]
|
||||||
|
|
||||||
|
kwargs['insecure'] = c.insecure
|
||||||
|
kwargs['cacert'] = c.cafile
|
||||||
|
kwargs['cert'] = c.certfile
|
||||||
|
kwargs['key'] = c.keyfile
|
||||||
|
kwargs['timeout'] = c.timeout
|
||||||
|
|
||||||
|
return cls._make(**kwargs)
|
||||||
|
@@ -14,12 +14,15 @@ import uuid
|
|||||||
|
|
||||||
import httpretty
|
import httpretty
|
||||||
import mock
|
import mock
|
||||||
|
from oslo.config import cfg
|
||||||
import requests
|
import requests
|
||||||
import six
|
import six
|
||||||
|
from testtools import matchers
|
||||||
|
|
||||||
from keystoneclient import adapter
|
from keystoneclient import adapter
|
||||||
from keystoneclient.auth import base
|
from keystoneclient.auth import base
|
||||||
from keystoneclient import exceptions
|
from keystoneclient import exceptions
|
||||||
|
from keystoneclient.openstack.common.fixture import config
|
||||||
from keystoneclient.openstack.common import jsonutils
|
from keystoneclient.openstack.common import jsonutils
|
||||||
from keystoneclient import session as client_session
|
from keystoneclient import session as client_session
|
||||||
from keystoneclient.tests import utils
|
from keystoneclient.tests import utils
|
||||||
@@ -599,3 +602,62 @@ class AdapterTest(utils.TestCase):
|
|||||||
with mock.patch.object(adpt, 'request') as m:
|
with mock.patch.object(adpt, 'request') as m:
|
||||||
getattr(adpt, method)(url)
|
getattr(adpt, method)(url)
|
||||||
m.assert_called_once_with(url, method.upper())
|
m.assert_called_once_with(url, method.upper())
|
||||||
|
|
||||||
|
|
||||||
|
class ConfLoadingTests(utils.TestCase):
|
||||||
|
|
||||||
|
GROUP = 'sessiongroup'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(ConfLoadingTests, self).setUp()
|
||||||
|
|
||||||
|
self.conf_fixture = self.useFixture(config.Config())
|
||||||
|
client_session.Session.register_conf_options(self.conf_fixture.conf,
|
||||||
|
self.GROUP)
|
||||||
|
|
||||||
|
def config(self, **kwargs):
|
||||||
|
kwargs['group'] = self.GROUP
|
||||||
|
self.conf_fixture.config(**kwargs)
|
||||||
|
|
||||||
|
def get_session(self, **kwargs):
|
||||||
|
return client_session.Session.load_from_conf_options(
|
||||||
|
self.conf_fixture.conf,
|
||||||
|
self.GROUP,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
def test_insecure_timeout(self):
|
||||||
|
self.config(insecure=True, timeout=5)
|
||||||
|
s = self.get_session()
|
||||||
|
|
||||||
|
self.assertFalse(s.verify)
|
||||||
|
self.assertEqual(5, s.timeout)
|
||||||
|
|
||||||
|
def test_client_certs(self):
|
||||||
|
cert = '/path/to/certfile'
|
||||||
|
key = '/path/to/keyfile'
|
||||||
|
|
||||||
|
self.config(certfile=cert, keyfile=key)
|
||||||
|
s = self.get_session()
|
||||||
|
|
||||||
|
self.assertTrue(s.verify)
|
||||||
|
self.assertEqual((cert, key), s.cert)
|
||||||
|
|
||||||
|
def test_cacert(self):
|
||||||
|
cafile = '/path/to/cacert'
|
||||||
|
|
||||||
|
self.config(cafile=cafile)
|
||||||
|
s = self.get_session()
|
||||||
|
|
||||||
|
self.assertEqual(cafile, s.verify)
|
||||||
|
|
||||||
|
def test_deprecated(self):
|
||||||
|
def new_deprecated():
|
||||||
|
return cfg.DeprecatedOpt(uuid.uuid4().hex, group=uuid.uuid4().hex)
|
||||||
|
|
||||||
|
opt_names = ['cafile', 'certfile', 'keyfile', 'insecure', 'timeout']
|
||||||
|
depr = dict([(n, [new_deprecated()]) for n in opt_names])
|
||||||
|
opts = client_session.Session.get_conf_options(deprecated_opts=depr)
|
||||||
|
|
||||||
|
self.assertThat(opt_names, matchers.HasLength(len(opts)))
|
||||||
|
for opt in opts:
|
||||||
|
self.assertIn(depr[opt.name][0], opt.deprecated_opts)
|
||||||
|
Reference in New Issue
Block a user