Inventory: store BMC password in Openstack Barbican.
Replacing existing mechanism of storing BMC passwords in Inventory. Porting all the changes made in SysInv to Inventory to make them on par. Inventory is going to use Barbican API instead of keyring to store BMC passwords for MTCE as well. Depends-On: I7102a9662f3757c062ab310737f4ba08379d0100 Change-Id: I74e971495fa7538d77cfebc28d76fd752af69f5e Story: 2003108 Task: 27700 Signed-off-by: Alex Kozyrev <alex.kozyrev@windriver.com>
This commit is contained in:
parent
887bd34471
commit
938d9551c4
@ -1,2 +1,2 @@
|
|||||||
SRC_DIR="inventory"
|
SRC_DIR="inventory"
|
||||||
TIS_PATCH_VER=1
|
TIS_PATCH_VER=2
|
||||||
|
@ -78,7 +78,6 @@ import xml.etree.ElementTree as ET
|
|||||||
import xml.etree.ElementTree as et
|
import xml.etree.ElementTree as et
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
KEYRING_BM_SERVICE = "BM"
|
|
||||||
ERR_CODE_LOCK_SOLE_SERVICE_PROVIDER = "-1003"
|
ERR_CODE_LOCK_SOLE_SERVICE_PROVIDER = "-1003"
|
||||||
|
|
||||||
|
|
||||||
@ -1819,15 +1818,10 @@ class HostController(rest.RestController):
|
|||||||
LOG.info("notify systemconfig of host-delete which will"
|
LOG.info("notify systemconfig of host-delete which will"
|
||||||
"also do stors, lvgs, pvs, ceph crush remove")
|
"also do stors, lvgs, pvs, ceph crush remove")
|
||||||
|
|
||||||
# tell conductor to delete the keystore entry associated
|
# tell conductor to delete the barbican secret associated
|
||||||
# with this host (if present)
|
# with this host (if present)
|
||||||
try:
|
pecan.request.rpcapi.delete_barbican_secret(pecan.request.context,
|
||||||
pecan.request.rpcapi.unconfigure_keystore_account(
|
ihost.uuid)
|
||||||
pecan.request.context,
|
|
||||||
KEYRING_BM_SERVICE,
|
|
||||||
ihost.uuid)
|
|
||||||
except exception.NotFound:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Notify patching to drop the host
|
# Notify patching to drop the host
|
||||||
if ihost.hostname is not None:
|
if ihost.hostname is not None:
|
||||||
@ -2295,7 +2289,7 @@ class HostController(rest.RestController):
|
|||||||
_("Host-add Rejected: bm_ip %s already exists") %
|
_("Host-add Rejected: bm_ip %s already exists") %
|
||||||
phost['bm_ip'])
|
phost['bm_ip'])
|
||||||
|
|
||||||
# Update keyring with updated board management credentials, if supplied
|
# Update barbican with updated board management credentials if supplied
|
||||||
if (ohost['bm_username'] and phost['bm_username'] and
|
if (ohost['bm_username'] and phost['bm_username'] and
|
||||||
(ohost['bm_username'] != phost['bm_username'])):
|
(ohost['bm_username'] != phost['bm_username'])):
|
||||||
if not password_exists:
|
if not password_exists:
|
||||||
@ -2306,13 +2300,11 @@ class HostController(rest.RestController):
|
|||||||
ohost['bm_username'],
|
ohost['bm_username'],
|
||||||
phost['bm_username'])))
|
phost['bm_username'])))
|
||||||
|
|
||||||
if password_exists:
|
if password_exists and patch_bm_password:
|
||||||
# The conductor will handle creating the keystore acct
|
pecan.request.rpcapi.create_barbican_secret(pecan.request.context,
|
||||||
pecan.request.rpcapi.configure_keystore_account(
|
phost['uuid'],
|
||||||
pecan.request.context,
|
patch_bm_password)
|
||||||
KEYRING_BM_SERVICE,
|
|
||||||
phost['uuid'],
|
|
||||||
patch_bm_password)
|
|
||||||
LOG.info("%s bm semantic checks for user_agent %s passed" %
|
LOG.info("%s bm semantic checks for user_agent %s passed" %
|
||||||
(phost['hostname'], pecan.request.user_agent))
|
(phost['hostname'], pecan.request.user_agent))
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ Commands are received via RPC calls.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import grp
|
import grp
|
||||||
import keyring
|
|
||||||
import os
|
import os
|
||||||
import oslo_messaging as messaging
|
import oslo_messaging as messaging
|
||||||
import pwd
|
import pwd
|
||||||
@ -1912,35 +1911,20 @@ class ConductorManager(base_manager.BaseConductorManager):
|
|||||||
network_type)
|
network_type)
|
||||||
return "%s-cinder-%s" % ADDRESS_FORMAT_ARGS
|
return "%s-cinder-%s" % ADDRESS_FORMAT_ARGS
|
||||||
|
|
||||||
def configure_keystore_account(self, context, service_name,
|
def create_barbican_secret(self, context, name, payload):
|
||||||
username, password):
|
"""Calls Barbican API to create a secret
|
||||||
"""Synchronously, have a conductor configure a ks(keyring) account.
|
|
||||||
|
|
||||||
Does the following tasks:
|
|
||||||
- call keyring API to create an account under a service.
|
|
||||||
|
|
||||||
:param context: request context.
|
:param context: request context.
|
||||||
:param service_name: the keystore service.
|
:param name: secret name
|
||||||
:param username: account username
|
:param payload: secret payload
|
||||||
:param password: account password
|
|
||||||
"""
|
"""
|
||||||
if not service_name.strip():
|
self._openstack.create_barbican_secret(context=context,
|
||||||
raise exception.InventoryException(_(
|
name=name, payload=payload)
|
||||||
"Keystore service is a blank value"))
|
|
||||||
|
|
||||||
keyring.set_password(service_name, username, password)
|
def delete_barbican_secret(self, context, name):
|
||||||
|
"""Calls Barbican API to delete a secret
|
||||||
def unconfigure_keystore_account(self, context, service_name, username):
|
|
||||||
"""Synchronously, have a conductor unconfigure a ks(keyring) account.
|
|
||||||
|
|
||||||
Does the following tasks:
|
|
||||||
- call keyring API to delete an account under a service.
|
|
||||||
|
|
||||||
:param context: request context.
|
:param context: request context.
|
||||||
:param service_name: the keystore service.
|
:param name: secret name
|
||||||
:param username: account username
|
|
||||||
"""
|
"""
|
||||||
try:
|
self._openstack.delete_barbican_secret(context=context, name=name)
|
||||||
keyring.delete_password(service_name, username)
|
|
||||||
except keyring.errors.PasswordDeleteError:
|
|
||||||
pass
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
""" Inventory Openstack Utilities and helper functions."""
|
""" Inventory Openstack Utilities and helper functions."""
|
||||||
|
|
||||||
|
from barbicanclient.v1 import client as barbican_client_v1
|
||||||
from cinderclient.v2 import client as cinder_client_v2
|
from cinderclient.v2 import client as cinder_client_v2
|
||||||
from inventory.common import constants
|
from inventory.common import constants
|
||||||
from inventory.common import exception
|
from inventory.common import exception
|
||||||
@ -70,6 +71,9 @@ keystone_opts = [
|
|||||||
cfg.StrOpt('nova_region_name',
|
cfg.StrOpt('nova_region_name',
|
||||||
default='RegionOne',
|
default='RegionOne',
|
||||||
help=_("Nova Region Name")),
|
help=_("Nova Region Name")),
|
||||||
|
cfg.StrOpt('barbican_region_name',
|
||||||
|
default='RegionOne',
|
||||||
|
help=_("Barbican Region Name")),
|
||||||
cfg.StrOpt('username',
|
cfg.StrOpt('username',
|
||||||
default='inventory',
|
default='inventory',
|
||||||
help=_("Inventory keystone user name")),
|
help=_("Inventory keystone user name")),
|
||||||
@ -96,6 +100,7 @@ class OpenStackOperator(object):
|
|||||||
|
|
||||||
def __init__(self, dbapi):
|
def __init__(self, dbapi):
|
||||||
self.dbapi = dbapi
|
self.dbapi = dbapi
|
||||||
|
self.barbican_client = None
|
||||||
self.cinder_client = None
|
self.cinder_client = None
|
||||||
self.keystone_client = None
|
self.keystone_client = None
|
||||||
self.keystone_session = None
|
self.keystone_session = None
|
||||||
@ -795,6 +800,58 @@ class OpenStackOperator(object):
|
|||||||
|
|
||||||
return volume_types_list
|
return volume_types_list
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Barbican
|
||||||
|
#################
|
||||||
|
def _get_barbicanclient(self):
|
||||||
|
if not self.barbican_client:
|
||||||
|
self.barbican_client = barbican_client_v1.Client(
|
||||||
|
session=self._get_keystone_session(),
|
||||||
|
auth_url=self.auth_url,
|
||||||
|
endpoint_type='internalURL',
|
||||||
|
region_name=cfg.CONF.KEYSTONE_AUTHTOKEN.barbican_region_name)
|
||||||
|
return self.barbican_client
|
||||||
|
|
||||||
|
def get_barbican_secret_by_name(self, context, name):
|
||||||
|
try:
|
||||||
|
client = self._get_barbicanclient()
|
||||||
|
secret_list = client.secrets.list(name=name)
|
||||||
|
secret = next(iter(secret_list), None)
|
||||||
|
return secret
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Unable to find Barbican secret %s", name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def create_barbican_secret(self, context, name, payload):
|
||||||
|
if not payload:
|
||||||
|
LOG.error("Empty password is passed to Barbican %s" % name)
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
client = self._get_barbicanclient()
|
||||||
|
secret = self.get_barbican_secret_by_name(context, name)
|
||||||
|
if secret:
|
||||||
|
client.secrets.delete(secret.secret_ref)
|
||||||
|
secret = client.secrets.create(name, payload)
|
||||||
|
secret.store()
|
||||||
|
return secret.secret_ref
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Unable to create Barbican secret %s" % name)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def delete_barbican_secret(self, context, name):
|
||||||
|
try:
|
||||||
|
client = self._get_barbicanclient()
|
||||||
|
secret = self.get_barbican_secret_by_name(context=context,
|
||||||
|
name=name)
|
||||||
|
if not secret:
|
||||||
|
LOG.error("Unable to delete unknown Barbican secret %s" % name)
|
||||||
|
return False
|
||||||
|
client.secrets.delete(secret_ref=secret.secret_ref)
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
LOG.error("Unable to delete Barbican secret %s" % name)
|
||||||
|
return False
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
# Primary Region Inventory
|
# Primary Region Inventory
|
||||||
# Region specific methods
|
# Region specific methods
|
||||||
|
@ -516,40 +516,29 @@ class ConductorAPI(object):
|
|||||||
cctxt = self.client.prepare(topic=topic or self.topic, version='1.0')
|
cctxt = self.client.prepare(topic=topic or self.topic, version='1.0')
|
||||||
return cctxt.call(context, 'update_cpu_config')
|
return cctxt.call(context, 'update_cpu_config')
|
||||||
|
|
||||||
def configure_keystore_account(self, context, service_name,
|
def create_barbican_secret(self, context, name, payload, topic=None):
|
||||||
username, password, topic=None):
|
"""Calls Barbican API to create a secret
|
||||||
"""Synchronously, have a conductor configure a ks(keyring) account.
|
|
||||||
|
|
||||||
Does the following tasks:
|
|
||||||
- call keyring API to create an account under a service.
|
|
||||||
|
|
||||||
:param context: request context.
|
:param context: request context.
|
||||||
:param service_name: the keystore service.
|
:param name: secret name
|
||||||
:param username: account username
|
:param payload: secret payload
|
||||||
:param password: account password
|
|
||||||
"""
|
"""
|
||||||
cctxt = self.client.prepare(topic=topic or self.topic, version='1.0')
|
cctxt = self.client.prepare(topic=topic or self.topic, version='1.0')
|
||||||
return cctxt.call(context,
|
return cctxt.call(context,
|
||||||
'configure_keystore_account',
|
'create_barbican_secret',
|
||||||
service_name=service_name,
|
name=name,
|
||||||
username=username, password=password)
|
payload=payload)
|
||||||
|
|
||||||
def unconfigure_keystore_account(self, context,
|
def delete_barbican_secret(self, context, name, topic=None):
|
||||||
service_name, username, topic=None):
|
"""Calls Barbican API to delete a secret
|
||||||
"""Synchronously, have a conductor unconfigure a ks(keyring) account.
|
|
||||||
|
|
||||||
Does the following tasks:
|
|
||||||
- call keyring API to delete an account under a service.
|
|
||||||
|
|
||||||
:param context: request context.
|
:param context: request context.
|
||||||
:param service_name: the keystore service.
|
:param name: secret name
|
||||||
:param username: account username
|
|
||||||
"""
|
"""
|
||||||
cctxt = self.client.prepare(topic=topic or self.topic, version='1.0')
|
cctxt = self.client.prepare(topic=topic or self.topic, version='1.0')
|
||||||
return cctxt.call(context,
|
return cctxt.call(context,
|
||||||
'unconfigure_keystore_account',
|
'delete_barbican_secret',
|
||||||
service_name=service_name,
|
name=name)
|
||||||
username=username)
|
|
||||||
|
|
||||||
def reload_snmp_config(self, context, topic=None):
|
def reload_snmp_config(self, context, topic=None):
|
||||||
"""Synchronously, have a conductor reload the SNMP configuration.
|
"""Synchronously, have a conductor reload the SNMP configuration.
|
||||||
|
@ -31,7 +31,6 @@ oslo.utils>=3.5.0 # Apache-2.0
|
|||||||
osprofiler>=1.4.0 # Apache-2.0
|
osprofiler>=1.4.0 # Apache-2.0
|
||||||
python-cinderclient>=3.1.0 # Apache-2.0
|
python-cinderclient>=3.1.0 # Apache-2.0
|
||||||
python-keystoneclient>=3.8.0 # Apache-2.0
|
python-keystoneclient>=3.8.0 # Apache-2.0
|
||||||
keyring
|
|
||||||
keystonemiddleware>=4.12.0 # Apache-2.0
|
keystonemiddleware>=4.12.0 # Apache-2.0
|
||||||
oslo.messaging!=5.25.0,>=5.24.2 # Apache-2.0
|
oslo.messaging!=5.25.0,>=5.24.2 # Apache-2.0
|
||||||
retrying!=1.3.0,>=1.2.3 # Apache-2.0
|
retrying!=1.3.0,>=1.2.3 # Apache-2.0
|
||||||
|
@ -26,7 +26,6 @@ testtools!=1.2.0,>=0.9.36
|
|||||||
tempest-lib<0.5.0,>=0.4.0
|
tempest-lib<0.5.0,>=0.4.0
|
||||||
ipaddr
|
ipaddr
|
||||||
pytest
|
pytest
|
||||||
keyring
|
|
||||||
pyudev
|
pyudev
|
||||||
libvirt-python>=1.2.5
|
libvirt-python>=1.2.5
|
||||||
migrate
|
migrate
|
||||||
|
@ -19,5 +19,4 @@ testresources>=0.2.4 # Apache-2.0/BSD
|
|||||||
tempest>=16.1.0 # Apache-2.0
|
tempest>=16.1.0 # Apache-2.0
|
||||||
httplib2
|
httplib2
|
||||||
python-keystoneclient
|
python-keystoneclient
|
||||||
keyring
|
|
||||||
pyOpenSSL>=0.14 # Apache-2.0
|
pyOpenSSL>=0.14 # Apache-2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user