Merge "Store BMC password in Openstack Barbican instead of keyring."
This commit is contained in:
commit
e1dd3de752
@ -546,20 +546,13 @@ fm::database_max_overflow: 20
|
|||||||
fm::database_max_pool_size: 1
|
fm::database_max_pool_size: 1
|
||||||
|
|
||||||
# Barbican
|
# Barbican
|
||||||
barbican::use_syslog: true
|
|
||||||
barbican::log_facility: 'local2'
|
|
||||||
barbican::database_idle_timeout: 60
|
|
||||||
barbican::database_max_pool_size: 1
|
|
||||||
barbican::database_max_overflow: 10
|
|
||||||
barbican::alarm_history_time_to_live: 86400
|
|
||||||
|
|
||||||
barbican::auth::auth_endpoint_type: 'internalURL'
|
|
||||||
|
|
||||||
barbican::db::sync::user: 'root'
|
|
||||||
|
|
||||||
barbican::api::enabled: false
|
barbican::api::enabled: false
|
||||||
barbican::api::service_name: 'barbican-api'
|
barbican::api::service_name: 'barbican-api'
|
||||||
barbican::api::enable_proxy_headers_parsing: true
|
barbican::api::enable_proxy_headers_parsing: true
|
||||||
|
barbican::api::logging::use_syslog: true
|
||||||
|
barbican::api::logging::log_facility: 'local2'
|
||||||
|
barbican::db::sync::user: 'root'
|
||||||
|
barbican::db::database_idle_timeout: 60
|
||||||
|
barbican::db::database_max_pool_size: 1
|
||||||
barbican::keystone-listener::enabled: false
|
barbican::keystone-listener::enabled: false
|
||||||
barbican::worker::enabled: false
|
barbican::worker::enabled: false
|
||||||
|
@ -55,12 +55,15 @@ class openstack::barbican::service
|
|||||||
}
|
}
|
||||||
$api_fqdn = $::platform::params::controller_hostname
|
$api_fqdn = $::platform::params::controller_hostname
|
||||||
$url_host = "http://${api_fqdn}:${api_port}"
|
$url_host = "http://${api_fqdn}:${api_port}"
|
||||||
|
if str2bool($::is_initial_config_primary) {
|
||||||
|
$enabled = true
|
||||||
|
} else {
|
||||||
|
$enabled = false
|
||||||
|
}
|
||||||
include ::platform::amqp::params
|
include ::platform::amqp::params
|
||||||
|
|
||||||
class { '::barbican::api':
|
class { '::barbican::api':
|
||||||
enabled => true,
|
enabled => $enabled,
|
||||||
manage_service => true,
|
|
||||||
bind_host => $api_host,
|
bind_host => $api_host,
|
||||||
bind_port => $api_port,
|
bind_port => $api_port,
|
||||||
host_href => $url_host,
|
host_href => $url_host,
|
||||||
|
@ -2440,15 +2440,9 @@ class HostController(rest.RestController):
|
|||||||
"problem persists then contact your system "
|
"problem persists then contact your system "
|
||||||
"administrator."))
|
"administrator."))
|
||||||
|
|
||||||
# tell conductor to delete the keystore entry associated
|
# tell conductor to delete the barbican entry associated with this host (if present)
|
||||||
# with this host (if present)
|
pecan.request.rpcapi.delete_barbican_secret(pecan.request.context,
|
||||||
try:
|
host.uuid)
|
||||||
pecan.request.rpcapi.unconfigure_keystore_account(
|
|
||||||
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:
|
||||||
@ -3795,7 +3789,7 @@ class HostController(rest.RestController):
|
|||||||
raise wsme.exc.ClientSideError(
|
raise wsme.exc.ClientSideError(
|
||||||
_("Host-add Rejected: bm_ip %s already exists") % phost['bm_ip'])
|
_("Host-add Rejected: bm_ip %s already exists") % 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:
|
||||||
@ -3806,12 +3800,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,
|
phost['uuid'],
|
||||||
KEYRING_BM_SERVICE,
|
patch_bm_password)
|
||||||
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))
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ import uuid
|
|||||||
import xml.etree.ElementTree as ElementTree
|
import xml.etree.ElementTree as ElementTree
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
import keyring
|
|
||||||
import tsconfig.tsconfig as tsc
|
import tsconfig.tsconfig as tsc
|
||||||
from cgcs_patch.patch_verify import verify_files
|
from cgcs_patch.patch_verify import verify_files
|
||||||
from controllerconfig.upgrades import management as upgrades_management
|
from controllerconfig.upgrades import management as upgrades_management
|
||||||
@ -9428,38 +9427,23 @@ class ConductorManager(service.PeriodicService):
|
|||||||
target_load = self.dbapi.load_get(host_upgrade.target_load)
|
target_load = self.dbapi.load_get(host_upgrade.target_load)
|
||||||
return target_load.software_version == tsc.SW_VERSION
|
return target_load.software_version == tsc.SW_VERSION
|
||||||
|
|
||||||
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.SysinvException(_(
|
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
|
|
||||||
|
|
||||||
def update_snmp_config(self, context):
|
def update_snmp_config(self, context):
|
||||||
"""Update the snmpd configuration"""
|
"""Update the snmpd configuration"""
|
||||||
|
@ -26,7 +26,7 @@ from keystoneclient.auth.identity import v3
|
|||||||
from keystoneclient import session
|
from keystoneclient import session
|
||||||
from sqlalchemy.orm import exc
|
from sqlalchemy.orm import exc
|
||||||
from magnumclient.v1 import client as magnum_client_v1
|
from magnumclient.v1 import client as magnum_client_v1
|
||||||
|
from barbicanclient.v1 import client as barbican_client_v1
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -105,6 +105,9 @@ openstack_keystone_opts = [
|
|||||||
cfg.StrOpt('magnum_region_name',
|
cfg.StrOpt('magnum_region_name',
|
||||||
default='RegionOne',
|
default='RegionOne',
|
||||||
help=_("Magnum Region Name")),
|
help=_("Magnum Region Name")),
|
||||||
|
cfg.StrOpt('barbican_region_name',
|
||||||
|
default='RegionOne',
|
||||||
|
help=_("Barbican Region Name")),
|
||||||
cfg.StrOpt('project_name',
|
cfg.StrOpt('project_name',
|
||||||
default='admin',
|
default='admin',
|
||||||
help=_("keystone user project name")),
|
help=_("keystone user project name")),
|
||||||
@ -129,9 +132,12 @@ 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
|
||||||
|
self.openstack_keystone_client = None
|
||||||
|
self.openstack_keystone_session = None
|
||||||
self.magnum_client = None
|
self.magnum_client = None
|
||||||
self.nova_client = None
|
self.nova_client = None
|
||||||
self.neutron_client = None
|
self.neutron_client = None
|
||||||
@ -530,29 +536,7 @@ class OpenStackOperator(object):
|
|||||||
#################
|
#################
|
||||||
# Keystone
|
# Keystone
|
||||||
#################
|
#################
|
||||||
def _get_keystone_session(self, service_config):
|
def _get_keystone_password(self, service_config):
|
||||||
if not self.keystone_session:
|
|
||||||
if service_config == OPENSTACK_CONFIG:
|
|
||||||
password = keyring.get_password(cfg.CONF[OPENSTACK_CONFIG].
|
|
||||||
keyring_service,
|
|
||||||
cfg.CONF[OPENSTACK_CONFIG].
|
|
||||||
username)
|
|
||||||
else:
|
|
||||||
password = cfg.CONF[service_config].password
|
|
||||||
|
|
||||||
auth = v3.Password(auth_url=self._get_auth_url(service_config),
|
|
||||||
username=cfg.CONF[service_config].username,
|
|
||||||
password=password,
|
|
||||||
user_domain_name=cfg.CONF[service_config].
|
|
||||||
user_domain_name,
|
|
||||||
project_name=cfg.CONF[service_config].
|
|
||||||
project_name,
|
|
||||||
project_domain_name=cfg.CONF[service_config].
|
|
||||||
project_domain_name)
|
|
||||||
self.keystone_session = session.Session(auth=auth)
|
|
||||||
return self.keystone_session
|
|
||||||
|
|
||||||
def _get_keystoneclient(self, service_config):
|
|
||||||
if service_config == OPENSTACK_CONFIG:
|
if service_config == OPENSTACK_CONFIG:
|
||||||
password = keyring.get_password(cfg.CONF[OPENSTACK_CONFIG].
|
password = keyring.get_password(cfg.CONF[OPENSTACK_CONFIG].
|
||||||
keyring_service,
|
keyring_service,
|
||||||
@ -560,18 +544,70 @@ class OpenStackOperator(object):
|
|||||||
username)
|
username)
|
||||||
else:
|
else:
|
||||||
password = cfg.CONF[service_config].password
|
password = cfg.CONF[service_config].password
|
||||||
|
return password
|
||||||
|
|
||||||
if not self.keystone_client: # should not cache this forever
|
def _get_new_keystone_session(self, service_config):
|
||||||
self.keystone_client = keystone_client.Client(
|
auth = v3.Password(auth_url=self._get_auth_url(service_config),
|
||||||
username=cfg.CONF[service_config].username,
|
username=cfg.CONF[service_config].username,
|
||||||
user_domain_name=cfg.CONF[service_config].user_domain_name,
|
password=self._get_keystone_password(service_config),
|
||||||
project_name=cfg.CONF[service_config].project_name,
|
user_domain_name=cfg.CONF[service_config].
|
||||||
project_domain_name=cfg.CONF[service_config]
|
user_domain_name,
|
||||||
.project_domain_name,
|
project_name=cfg.CONF[service_config].
|
||||||
password=password,
|
project_name,
|
||||||
auth_url=self._get_auth_url(service_config),
|
project_domain_name=cfg.CONF[service_config].
|
||||||
region_name=cfg.CONF[service_config].region_name)
|
project_domain_name)
|
||||||
return self.keystone_client
|
sess = session.Session(auth=auth)
|
||||||
|
return sess
|
||||||
|
|
||||||
|
def _get_cached_keystone_session(self, service_config):
|
||||||
|
if service_config == OPENSTACK_CONFIG:
|
||||||
|
return self.openstack_keystone_session
|
||||||
|
else:
|
||||||
|
return self.keystone_session
|
||||||
|
|
||||||
|
def _set_cached_keystone_session(self, service_config, sess):
|
||||||
|
if service_config == OPENSTACK_CONFIG:
|
||||||
|
self.openstack_keystone_session = sess
|
||||||
|
else:
|
||||||
|
self.keystone_session = sess
|
||||||
|
|
||||||
|
def _get_keystone_session(self, service_config):
|
||||||
|
sess = self._get_cached_keystone_session(service_config)
|
||||||
|
if not sess:
|
||||||
|
sess = self._get_new_keystone_session(service_config)
|
||||||
|
self._set_cached_keystone_session(service_config, sess)
|
||||||
|
return sess
|
||||||
|
|
||||||
|
def _get_new_keystone_client(self, service_config):
|
||||||
|
client = keystone_client.Client(
|
||||||
|
username=cfg.CONF[service_config].username,
|
||||||
|
user_domain_name=cfg.CONF[service_config].user_domain_name,
|
||||||
|
project_name=cfg.CONF[service_config].project_name,
|
||||||
|
project_domain_name=cfg.CONF[service_config]
|
||||||
|
.project_domain_name,
|
||||||
|
password=self._get_keystone_password(service_config),
|
||||||
|
auth_url=self._get_auth_url(service_config),
|
||||||
|
region_name=cfg.CONF[service_config].region_name)
|
||||||
|
return client
|
||||||
|
|
||||||
|
def _get_cached_keystone_client(self, service_config):
|
||||||
|
if service_config == OPENSTACK_CONFIG:
|
||||||
|
return self.openstack_keystone_client
|
||||||
|
else:
|
||||||
|
return self.keystone_client
|
||||||
|
|
||||||
|
def _set_cached_keystone_client(self, service_config, client):
|
||||||
|
if service_config == OPENSTACK_CONFIG:
|
||||||
|
self.openstack_keystone_client = client
|
||||||
|
else:
|
||||||
|
self.keystone_client = client
|
||||||
|
|
||||||
|
def _get_keystone_client(self, service_config):
|
||||||
|
client = self._get_cached_keystone_client(service_config)
|
||||||
|
if not client:
|
||||||
|
client = self._get_new_keystone_client(service_config)
|
||||||
|
self._set_cached_keystone_client(service_config, client)
|
||||||
|
return client
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Cinder
|
# Cinder
|
||||||
@ -785,6 +821,56 @@ class OpenStackOperator(object):
|
|||||||
LOG.error("Unable to get backend list of magnum clusters")
|
LOG.error("Unable to get backend list of magnum clusters")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Barbican
|
||||||
|
#################
|
||||||
|
def _get_barbicanclient(self):
|
||||||
|
if not self.barbican_client:
|
||||||
|
self.barbican_client = barbican_client_v1.Client(
|
||||||
|
session=self._get_keystone_session(PLATFORM_CONFIG),
|
||||||
|
interface='internalURL',
|
||||||
|
region_name=cfg.CONF[OPENSTACK_CONFIG].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
|
||||||
|
|
||||||
|
|
||||||
def get_region_name(region):
|
def get_region_name(region):
|
||||||
# get region name from platform.conf
|
# get region name from platform.conf
|
||||||
|
@ -1343,37 +1343,27 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
|
|||||||
return self.call(context,
|
return self.call(context,
|
||||||
self.make_msg('update_vswitch_type'))
|
self.make_msg('update_vswitch_type'))
|
||||||
|
|
||||||
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
|
|
||||||
"""
|
"""
|
||||||
return self.call(context,
|
return self.call(context,
|
||||||
self.make_msg('configure_keystore_account',
|
self.make_msg('create_barbican_secret',
|
||||||
service_name=service_name,
|
name=name,
|
||||||
username=username, password=password))
|
payload=payload))
|
||||||
|
|
||||||
def unconfigure_keystore_account(self, context, service_name, username):
|
def delete_barbican_secret(self, context, name):
|
||||||
"""Synchronously, have a conductor unconfigure a ks(keyring) account.
|
"""Calls Barbican API to delete a secret
|
||||||
|
|
||||||
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
|
|
||||||
"""
|
"""
|
||||||
return self.call(context,
|
return self.call(context,
|
||||||
self.make_msg('unconfigure_keystore_account',
|
self.make_msg('delete_barbican_secret',
|
||||||
service_name=service_name,
|
name=name))
|
||||||
username=username))
|
|
||||||
|
|
||||||
def update_snmp_config(self, context):
|
def update_snmp_config(self, context):
|
||||||
"""Synchronously, have a conductor configure the SNMP configuration.
|
"""Synchronously, have a conductor configure the SNMP configuration.
|
||||||
|
@ -59,7 +59,7 @@ class BarbicanPuppet(openstack.OpenstackBasePuppet):
|
|||||||
'barbican::keystone::authtoken::project_domain_name':
|
'barbican::keystone::authtoken::project_domain_name':
|
||||||
self._get_service_project_domain_name(),
|
self._get_service_project_domain_name(),
|
||||||
'barbican::keystone::authtoken::project_name':
|
'barbican::keystone::authtoken::project_name':
|
||||||
self._get_service_tenant_name(),
|
self._get_service_project_name(),
|
||||||
'barbican::keystone::authtoken::region_name':
|
'barbican::keystone::authtoken::region_name':
|
||||||
self._keystone_region_name(),
|
self._keystone_region_name(),
|
||||||
'barbican::keystone::authtoken::username': ksuser,
|
'barbican::keystone::authtoken::username': ksuser,
|
||||||
|
Loading…
Reference in New Issue
Block a user