diff --git a/puppet-manifests/src/hieradata/controller.yaml b/puppet-manifests/src/hieradata/controller.yaml index c7e1336342..ef0ab3bf11 100644 --- a/puppet-manifests/src/hieradata/controller.yaml +++ b/puppet-manifests/src/hieradata/controller.yaml @@ -546,20 +546,13 @@ fm::database_max_overflow: 20 fm::database_max_pool_size: 1 # 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::service_name: 'barbican-api' 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::worker::enabled: false diff --git a/puppet-manifests/src/modules/openstack/manifests/barbican.pp b/puppet-manifests/src/modules/openstack/manifests/barbican.pp index c8086682e6..dd1a5d14b7 100644 --- a/puppet-manifests/src/modules/openstack/manifests/barbican.pp +++ b/puppet-manifests/src/modules/openstack/manifests/barbican.pp @@ -55,12 +55,15 @@ class openstack::barbican::service } $api_fqdn = $::platform::params::controller_hostname $url_host = "http://${api_fqdn}:${api_port}" - + if str2bool($::is_initial_config_primary) { + $enabled = true + } else { + $enabled = false + } include ::platform::amqp::params class { '::barbican::api': - enabled => true, - manage_service => true, + enabled => $enabled, bind_host => $api_host, bind_port => $api_port, host_href => $url_host, diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/host.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/host.py index 3bf1916ff6..c2556f9356 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/host.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/host.py @@ -2440,15 +2440,9 @@ class HostController(rest.RestController): "problem persists then contact your system " "administrator.")) - # tell conductor to delete the keystore entry associated - # with this host (if present) - try: - pecan.request.rpcapi.unconfigure_keystore_account( - pecan.request.context, - KEYRING_BM_SERVICE, - ihost.uuid) - except exception.NotFound: - pass + # tell conductor to delete the barbican entry associated with this host (if present) + pecan.request.rpcapi.delete_barbican_secret(pecan.request.context, + host.uuid) # Notify patching to drop the host if ihost.hostname is not None: @@ -3795,7 +3789,7 @@ class HostController(rest.RestController): raise wsme.exc.ClientSideError( _("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 (ohost['bm_username'] != phost['bm_username'])): if not password_exists: @@ -3806,12 +3800,11 @@ class HostController(rest.RestController): ohost['bm_username'], phost['bm_username']))) - if password_exists: - # The conductor will handle creating the keystore acct - pecan.request.rpcapi.configure_keystore_account(pecan.request.context, - KEYRING_BM_SERVICE, - phost['uuid'], - patch_bm_password) + if password_exists and patch_bm_password: + pecan.request.rpcapi.create_barbican_secret(pecan.request.context, + phost['uuid'], + patch_bm_password) + LOG.info("%s bm semantic checks for user_agent %s passed" % (phost['hostname'], pecan.request.user_agent)) diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py index 84a35b2f59..bd678038a1 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py @@ -45,7 +45,6 @@ import uuid import xml.etree.ElementTree as ElementTree from contextlib import contextmanager -import keyring import tsconfig.tsconfig as tsc from cgcs_patch.patch_verify import verify_files 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) return target_load.software_version == tsc.SW_VERSION - def configure_keystore_account(self, context, service_name, - username, password): - """Synchronously, have a conductor configure a ks(keyring) account. - - Does the following tasks: - - call keyring API to create an account under a service. + def create_barbican_secret(self, context, name, payload): + """Calls Barbican API to create a secret :param context: request context. - :param service_name: the keystore service. - :param username: account username - :param password: account password + :param name: secret name + :param payload: secret payload """ - if (not service_name.strip()): - raise exception.SysinvException(_( - "Keystore service is a blank value")) + self._openstack.create_barbican_secret(context=context, + name=name, payload=payload) - keyring.set_password(service_name, username, password) - - 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. + def delete_barbican_secret(self, context, name): + """Calls Barbican API to delete a secret :param context: request context. - :param service_name: the keystore service. - :param username: account username + :param name: secret name """ - try: - keyring.delete_password(service_name, username) - except keyring.errors.PasswordDeleteError: - pass + self._openstack.delete_barbican_secret(context=context, name=name) def update_snmp_config(self, context): """Update the snmpd configuration""" diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/openstack.py b/sysinv/sysinv/sysinv/sysinv/conductor/openstack.py index 28fc478630..517cc950cd 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/openstack.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/openstack.py @@ -26,7 +26,7 @@ from keystoneclient.auth.identity import v3 from keystoneclient import session from sqlalchemy.orm import exc from magnumclient.v1 import client as magnum_client_v1 - +from barbicanclient.v1 import client as barbican_client_v1 LOG = logging.getLogger(__name__) @@ -105,6 +105,9 @@ openstack_keystone_opts = [ cfg.StrOpt('magnum_region_name', default='RegionOne', help=_("Magnum Region Name")), + cfg.StrOpt('barbican_region_name', + default='RegionOne', + help=_("Barbican Region Name")), cfg.StrOpt('project_name', default='admin', help=_("keystone user project name")), @@ -129,9 +132,12 @@ class OpenStackOperator(object): def __init__(self, dbapi): self.dbapi = dbapi + self.barbican_client = None self.cinder_client = None self.keystone_client = None self.keystone_session = None + self.openstack_keystone_client = None + self.openstack_keystone_session = None self.magnum_client = None self.nova_client = None self.neutron_client = None @@ -530,29 +536,7 @@ class OpenStackOperator(object): ################# # Keystone ################# - def _get_keystone_session(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): + def _get_keystone_password(self, service_config): if service_config == OPENSTACK_CONFIG: password = keyring.get_password(cfg.CONF[OPENSTACK_CONFIG]. keyring_service, @@ -560,18 +544,70 @@ class OpenStackOperator(object): username) else: password = cfg.CONF[service_config].password + return password - if not self.keystone_client: # should not cache this forever - self.keystone_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=password, - auth_url=self._get_auth_url(service_config), - region_name=cfg.CONF[service_config].region_name) - return self.keystone_client + def _get_new_keystone_session(self, service_config): + auth = v3.Password(auth_url=self._get_auth_url(service_config), + username=cfg.CONF[service_config].username, + password=self._get_keystone_password(service_config), + 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) + 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 @@ -785,6 +821,56 @@ class OpenStackOperator(object): LOG.error("Unable to get backend list of magnum clusters") 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): # get region name from platform.conf diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py index 3c064f6a56..0c8e866302 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py @@ -1343,37 +1343,27 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy): return self.call(context, self.make_msg('update_vswitch_type')) - def configure_keystore_account(self, context, service_name, - username, password): - """Synchronously, have a conductor configure a ks(keyring) account. - - Does the following tasks: - - call keyring API to create an account under a service. + def create_barbican_secret(self, context, name, payload): + """Calls Barbican API to create a secret :param context: request context. - :param service_name: the keystore service. - :param username: account username - :param password: account password + :param name: secret name + :param payload: secret payload """ return self.call(context, - self.make_msg('configure_keystore_account', - service_name=service_name, - username=username, password=password)) + self.make_msg('create_barbican_secret', + name=name, + payload=payload)) - 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. + def delete_barbican_secret(self, context, name): + """Calls Barbican API to delete a secret :param context: request context. - :param service_name: the keystore service. - :param username: account username + :param name: secret name """ return self.call(context, - self.make_msg('unconfigure_keystore_account', - service_name=service_name, - username=username)) + self.make_msg('delete_barbican_secret', + name=name)) def update_snmp_config(self, context): """Synchronously, have a conductor configure the SNMP configuration. diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/barbican.py b/sysinv/sysinv/sysinv/sysinv/puppet/barbican.py index c108949852..b20f9733af 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/barbican.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/barbican.py @@ -59,7 +59,7 @@ class BarbicanPuppet(openstack.OpenstackBasePuppet): 'barbican::keystone::authtoken::project_domain_name': self._get_service_project_domain_name(), 'barbican::keystone::authtoken::project_name': - self._get_service_tenant_name(), + self._get_service_project_name(), 'barbican::keystone::authtoken::region_name': self._keystone_region_name(), 'barbican::keystone::authtoken::username': ksuser,