diff --git a/devstack/lib/ironic b/devstack/lib/ironic index 7b0482dd77..8d71e96623 100644 --- a/devstack/lib/ironic +++ b/devstack/lib/ironic @@ -1395,10 +1395,15 @@ function configure_ironic { if [[ "$IRONIC_JSON_RPC_AUTH_STRATEGY" != "" ]]; then iniset $IRONIC_CONF_FILE json_rpc auth_strategy $IRONIC_JSON_RPC_AUTH_STRATEGY fi - iniset $IRONIC_CONF_FILE json_rpc http_basic_username myName - iniset $IRONIC_CONF_FILE json_rpc http_basic_password myPassword - # json-rpc auth file with bcrypt hash of myPassword - echo 'myName:$2y$05$lE3eGtyj41jZwrzS87KTqe6.JETVCWBkc32C63UP2aYrGoYOEpbJm' > /etc/ironic/htpasswd-json-rpc + if [[ "$IRONIC_JSON_RPC_AUTH_STRATEGY" == "http_basic" ]]; then + iniset $IRONIC_CONF_FILE json_rpc username myName + iniset $IRONIC_CONF_FILE json_rpc password myPassword + # json-rpc auth file with bcrypt hash of myPassword + echo 'myName:$2y$05$lE3eGtyj41jZwrzS87KTqe6.JETVCWBkc32C63UP2aYrGoYOEpbJm' > /etc/ironic/htpasswd-json-rpc + fi + if [[ "$IRONIC_JSON_RPC_AUTH_STRATEGY" == "" ]] || [[ "$IRONIC_JSON_RPC_AUTH_STRATEGY" == "keystone" ]]; then + configure_client_for json_rpc + fi # Set fast track options iniset $IRONIC_CONF_FILE deploy fast_track $IRONIC_DEPLOY_FAST_TRACK @@ -1532,7 +1537,7 @@ function configure_ironic_conductor { # NOTE(pas-ha) service_catalog section is used to discover # ironic API endpoint from keystone catalog - local client_sections="neutron swift glance inspector cinder service_catalog json_rpc nova" + local client_sections="neutron swift glance inspector cinder service_catalog nova" for conf_section in $client_sections; do configure_client_for $conf_section done diff --git a/doc/source/install/standalone.rst b/doc/source/install/standalone.rst index 71479c47e1..8a5175b452 100644 --- a/doc/source/install/standalone.rst +++ b/doc/source/install/standalone.rst @@ -70,8 +70,8 @@ You should make the following changes to ``/etc/ironic/ironic.conf``: [json_rpc] auth_strategy=http_basic - http_basic_username=myName - http_basic_password=myPassword + username=myName + password=myPassword If you don't use Image service, it's possible to provide images to Bare Metal service via a URL. diff --git a/ironic/common/json_rpc/client.py b/ironic/common/json_rpc/client.py index 8d172196fe..f67c90ed9d 100644 --- a/ironic/common/json_rpc/client.py +++ b/ironic/common/json_rpc/client.py @@ -15,8 +15,6 @@ This client is compatible with any JSON RPC 2.0 implementation, including ours. """ -import base64 - from oslo_config import cfg from oslo_log import log from oslo_utils import importutils @@ -38,23 +36,25 @@ def _get_session(): global _SESSION if _SESSION is None: + kwargs = {} auth_strategy = json_rpc.auth_strategy() - if auth_strategy == 'keystone': - auth = keystone.get_auth('json_rpc') - else: - auth = None + if auth_strategy != 'keystone': + auth_type = 'none' if auth_strategy == 'noauth' else auth_strategy + CONF.set_default('auth_type', auth_type, group='json_rpc') + + # Deprecated, remove in W + if auth_strategy == 'http_basic': + if CONF.json_rpc.http_basic_username: + kwargs['username'] = CONF.json_rpc.http_basic_username + if CONF.json_rpc.http_basic_password: + kwargs['password'] = CONF.json_rpc.http_basic_password + + auth = keystone.get_auth('json_rpc', **kwargs) session = keystone.get_session('json_rpc', auth=auth) headers = { 'Content-Type': 'application/json' } - if auth_strategy == 'http_basic': - token = '{}:{}'.format( - CONF.json_rpc.http_basic_username, - CONF.json_rpc.http_basic_password - ).encode('utf-8') - encoded = base64.b64encode(token).decode('utf-8') - headers['Authorization'] = 'Basic {}'.format(encoded) # Adds options like connect_retries _SESSION = keystone.get_adapter('json_rpc', session=session, diff --git a/ironic/conf/json_rpc.py b/ironic/conf/json_rpc.py index d88844e090..3fdff21f45 100644 --- a/ironic/conf/json_rpc.py +++ b/ironic/conf/json_rpc.py @@ -38,16 +38,16 @@ opts = [ default=False, help=_('Whether to use TLS for JSON RPC')), cfg.StrOpt('http_basic_username', - default='', + deprecated_for_removal=True, + deprecated_reason=_("Use username instead"), help=_("Name of the user to use for HTTP Basic authentication " - "client requests. Required when " - "auth_strategy=http_basic.")), + "client requests.")), cfg.StrOpt('http_basic_password', - default='', + deprecated_for_removal=True, + deprecated_reason=_("Use password instead"), secret=True, help=_("Password to use for HTTP Basic authentication " - "client requests. Required when " - "auth_strategy=http_basic.")), + "client requests.")), ] diff --git a/ironic/tests/unit/common/test_json_rpc.py b/ironic/tests/unit/common/test_json_rpc.py index 217a1128c2..8584c1fa09 100644 --- a/ironic/tests/unit/common/test_json_rpc.py +++ b/ironic/tests/unit/common/test_json_rpc.py @@ -584,9 +584,11 @@ class TestSession(test_base.TestCase): self.config(auth_strategy='noauth', group='json_rpc') session = client._get_session() - mock_keystone.get_auth.assert_not_called() + mock_keystone.get_auth.assert_called_once_with('json_rpc') + auth = mock_keystone.get_auth.return_value + mock_keystone.get_session.assert_called_once_with( - 'json_rpc', auth=None) + 'json_rpc', auth=auth) internal_session = mock_keystone.get_session.return_value @@ -620,13 +622,34 @@ class TestSession(test_base.TestCase): def test_http_basic(self, mock_keystone): self.config(auth_strategy='http_basic', group='json_rpc') - self.config(http_basic_username='myName', group='json_rpc') - self.config(http_basic_password='myPassword', group='json_rpc') session = client._get_session() - mock_keystone.get_auth.assert_not_called() + mock_keystone.get_auth.assert_called_once_with('json_rpc') + auth = mock_keystone.get_auth.return_value mock_keystone.get_session.assert_called_once_with( - 'json_rpc', auth=None) + 'json_rpc', auth=auth) + + internal_session = mock_keystone.get_session.return_value + + mock_keystone.get_adapter.assert_called_once_with( + 'json_rpc', + session=internal_session, + additional_headers={ + 'Content-Type': 'application/json' + }) + self.assertEqual(mock_keystone.get_adapter.return_value, session) + + def test_http_basic_deprecated(self, mock_keystone): + self.config(auth_strategy='http_basic', group='json_rpc') + self.config(http_basic_username='myName', group='json_rpc') + self.config(http_basic_password='myPassword', group='json_rpc') + session = client._get_session() + + mock_keystone.get_auth.assert_called_once_with( + 'json_rpc', username='myName', password='myPassword') + auth = mock_keystone.get_auth.return_value + mock_keystone.get_session.assert_called_once_with( + 'json_rpc', auth=auth) internal_session = mock_keystone.get_session.return_value @@ -634,7 +657,6 @@ class TestSession(test_base.TestCase): 'json_rpc', session=internal_session, additional_headers={ - 'Authorization': 'Basic bXlOYW1lOm15UGFzc3dvcmQ=', 'Content-Type': 'application/json' }) self.assertEqual(mock_keystone.get_adapter.return_value, session) diff --git a/lower-constraints.txt b/lower-constraints.txt index 82533a1b1f..ca32f2a82c 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -42,7 +42,7 @@ jmespath==0.9.5 jsonpatch==1.16 jsonpointer==2.0 jsonschema==3.2.0 -keystoneauth1==3.18.0 +keystoneauth1==4.2.0 keystonemiddleware==4.17.0 kombu==4.6.8 linecache2==1.0.0 diff --git a/releasenotes/notes/json_rpc_http_basic-42dfc6ca2471a30e.yaml b/releasenotes/notes/json_rpc_http_basic-42dfc6ca2471a30e.yaml new file mode 100644 index 0000000000..ee1eeef185 --- /dev/null +++ b/releasenotes/notes/json_rpc_http_basic-42dfc6ca2471a30e.yaml @@ -0,0 +1,6 @@ +--- +deprecations: + - | + The configuration options ``[json_rpc]http_basic_username`` and + ``[json_rpc]http_basic_password`` have been deprecated in favour of the + more generic ``[json_rpc]username`` and ``[json_rpc]password``. diff --git a/requirements.txt b/requirements.txt index aa80cd787e..1a32807f98 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ WebOb>=1.7.1 # MIT python-cinderclient!=4.0.0,>=3.3.0 # Apache-2.0 python-neutronclient>=6.7.0 # Apache-2.0 python-glanceclient>=2.8.0 # Apache-2.0 -keystoneauth1>=3.18.0 # Apache-2.0 +keystoneauth1>=4.2.0 # Apache-2.0 ironic-lib>=4.3.0 # Apache-2.0 python-swiftclient>=3.2.0 # Apache-2.0 pytz>=2013.6 # MIT