Merge "Inventory: store BMC password in Openstack Barbican."

This commit is contained in:
Zuul 2019-02-13 15:54:43 +00:00 committed by Gerrit Code Review
commit b01f8ea964
8 changed files with 89 additions and 70 deletions

View File

@ -1,2 +1,2 @@
SRC_DIR="inventory" SRC_DIR="inventory"
TIS_PATCH_VER=1 TIS_PATCH_VER=2

View File

@ -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))

View File

@ -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

View File

@ -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
@ -67,6 +68,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")),
@ -93,6 +97,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
@ -632,6 +637,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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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