Support client certificate/key

This change enables to specify a client certificate/key with:
 * usual CLI options (--os-cert/--os-key)
 * usual environment variables ($OS_CERT/$OS_KEY)
 * os-client-config

Change-Id: Ibeaaa5897ae37b37c1e91f3e47076e4e8e4a8ded
Closes-Bug: #1565112
This commit is contained in:
Cedric Brandily 2016-04-01 23:42:27 +02:00
parent a1a470693e
commit 3a8320a1d7
6 changed files with 80 additions and 0 deletions

View File

@ -114,6 +114,12 @@ OPTIONS
:option:`--verify` | :option:`--insecure`
Verify or ignore server certificate (default: verify)
:option:`--os-cert` <certificate-file>
Client certificate bundle file
:option:`--os-key` <key-file>
Client certificate key file
:option:`--os-identity-api-version` <identity-api-version>
Identity API version (Default: 2.0)
@ -367,6 +373,12 @@ The following environment variables can be set to alter the behaviour of :progra
:envvar:`OS_CACERT`
CA certificate bundle file
:envvar:`OS_CERT`
Client certificate bundle file
:envvar:`OS_KEY`
Client certificate key file
:envvar:`OS_IDENTITY_API_VERSION`
Identity API version (Default: 2.0)

View File

@ -110,6 +110,15 @@ class ClientManager(object):
self._cacert = verify
self._insecure = False
# Set up client certificate and key
# NOTE(cbrandily): This converts client certificate/key to requests
# cert argument: None (no client certificate), a path
# to client certificate or a tuple with client
# certificate/key paths.
self._cert = self._cli_options.cert
if self._cert and self._cli_options.key:
self._cert = self._cert, self._cli_options.key
# Get logging from root logger
root_logger = logging.getLogger('')
LOG.setLevel(root_logger.getEffectiveLevel())
@ -194,6 +203,7 @@ class ClientManager(object):
auth=self.auth,
session=request_session,
verify=self._verify,
cert=self._cert,
user_agent=USER_AGENT,
)

View File

@ -189,6 +189,18 @@ class OpenStackShell(app.App):
dest='cacert',
default=utils.env('OS_CACERT'),
help='CA certificate bundle file (Env: OS_CACERT)')
parser.add_argument(
'--os-cert',
metavar='<certificate-file>',
dest='cert',
default=utils.env('OS_CERT'),
help='Client certificate bundle file (Env: OS_CERT)')
parser.add_argument(
'--os-key',
metavar='<key-file>',
dest='key',
default=utils.env('OS_KEY'),
help='Client certificate key file (Env: OS_KEY)')
verify_group = parser.add_mutually_exclusive_group()
verify_group.add_argument(
'--verify',

View File

@ -58,6 +58,8 @@ class FakeOptions(object):
self.interface = None
self.url = None
self.auth = {}
self.cert = None
self.key = None
self.default_domain = 'default'
self.__dict__.update(kwargs)
@ -268,6 +270,21 @@ class TestClientManager(utils.TestCase):
self.assertEqual('cafile', client_manager._cacert)
self.assertTrue(client_manager.is_network_endpoint_enabled())
def test_client_manager_password_no_cert(self):
client_manager = clientmanager.ClientManager(
cli_options=FakeOptions())
self.assertIsNone(client_manager._cert)
def test_client_manager_password_client_cert(self):
client_manager = clientmanager.ClientManager(
cli_options=FakeOptions(cert='cert'))
self.assertEqual('cert', client_manager._cert)
def test_client_manager_password_client_cert_and_key(self):
client_manager = clientmanager.ClientManager(
cli_options=FakeOptions(cert='cert', key='key'))
self.assertEqual(('cert', 'key'), client_manager._cert)
def _select_auth_plugin(self, auth_params, api_version, auth_plugin_name):
auth_params['auth_type'] = auth_plugin_name
auth_params['identity_api_version'] = api_version

View File

@ -79,6 +79,8 @@ CLOUD_2 = {
'region_name': 'occ-cloud,krikkit,occ-env',
'log_file': '/tmp/test_log_file',
'log_level': 'debug',
'cert': 'mycert',
'key': 'mickey',
}
}
}
@ -567,6 +569,24 @@ class TestShellCli(TestShell):
self.assertEqual('foo', _shell.options.cacert)
self.assertFalse(_shell.verify)
def test_shell_args_cert_options(self):
_shell = make_shell()
# Default
fake_execute(_shell, "list user")
self.assertEqual('', _shell.options.cert)
self.assertEqual('', _shell.options.key)
# --os-cert
fake_execute(_shell, "--os-cert mycert list user")
self.assertEqual('mycert', _shell.options.cert)
self.assertEqual('', _shell.options.key)
# --os-key
fake_execute(_shell, "--os-key mickey list user")
self.assertEqual('', _shell.options.cert)
self.assertEqual('mickey', _shell.options.key)
def test_default_env(self):
flag = ""
kwargs = {
@ -670,6 +690,9 @@ class TestShellCli(TestShell):
_shell.cloud.config['region_name'],
)
self.assertEqual('mycert', _shell.cloud.config['cert'])
self.assertEqual('mickey', _shell.cloud.config['key'])
@mock.patch("os_client_config.config.OpenStackConfig._load_vendor_file")
@mock.patch("os_client_config.config.OpenStackConfig._load_config_file")
def test_shell_args_precedence(self, config_mock, vendor_mock):

View File

@ -0,0 +1,6 @@
---
features:
- Support client certificate/key. Client certificate/key can be provided
using --os-cert/--os-key options, $OS_CERT/$OS_KEY environment
variables or os-client-config config.
[Bug `1565112 <https://bugs.launchpad.net/bugs/1565112>`_]