Merge "Inventory: store BMC password in Openstack Barbican."
This commit is contained in:
commit
b01f8ea964
@ -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(
|
|
||||||
pecan.request.context,
|
|
||||||
KEYRING_BM_SERVICE,
|
|
||||||
ihost.uuid)
|
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(
|
|
||||||
pecan.request.context,
|
|
||||||
KEYRING_BM_SERVICE,
|
|
||||||
phost['uuid'],
|
phost['uuid'],
|
||||||
patch_bm_password)
|
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
|
||||||
@ -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
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user