Merge "Audit local sysadmin user password periodically"

This commit is contained in:
Zuul 2023-04-26 01:30:55 +00:00 committed by Gerrit Code Review
commit 9eb224b0a9
3 changed files with 76 additions and 4 deletions

View File

@ -93,7 +93,8 @@ agent_opts = [
audit_intervals_opts = [
cfg.IntOpt('default', default=60),
cfg.IntOpt('inventory_audit', default=60),
cfg.IntOpt('lldp_audit', default=300)
cfg.IntOpt('lldp_audit', default=300),
cfg.IntOpt('security_audit', default=900),
]
dpdk_opts = [
@ -1313,6 +1314,51 @@ class AgentManager(service.PeriodicService):
else:
self._lldp_enable_and_report(icontext, rpcapi, self._ihost_uuid)
@periodic_task.periodic_task(spacing=CONF.agent_periodic_task_intervals.security_audit)
def _security_audit(self, context):
if not self._ihost_uuid:
return
LOG.debug("Sysinv Agent Security Audit running.")
# get sysadmin password locally
with open("/etc/shadow", "r") as f:
user_attrs = []
lines = f.readlines()
for line in lines:
if "sysadmin" in line:
user_attrs = line.split(":")
break
if not user_attrs:
LOG.warn("No shadow entry found for 'sysadmin' user.")
return
icontext = mycontext.get_admin_context()
rpcapi = conductor_rpcapi.ConductorAPI(topic=conductor_rpcapi.MANAGER_TOPIC)
# get user information from the database
try:
iuser = rpcapi.get_iuser(icontext)
except RemoteError as e:
# ignore because active controller is not yet upgraded,
# so it's current load may not implement this RPC call
if "AttributeError" in str(e):
LOG.warn("Skip security audit. Upgrade in progress.")
else:
LOG.error("Failed to get user configuration via RPC.")
return
if not iuser.passwd_hash:
LOG.warn("No password configured for 'sysadmin' in the database.")
return
# compare sysadmin password hash with the value retrieved from the
# database and trigger user config manifest reapply if values differ
if iuser.passwd_hash != user_attrs[1]:
LOG.info("Configuration mismatch for 'sysadmin' user, attempting to reconfigure...")
rpcapi.update_user_config(icontext, [self._ihost_uuid])
else:
LOG.debug("No divergence found within 'sysadmin' user configuration.")
@utils.synchronized(LOCK_AGENT_ACTION, external=False)
def agent_audit(self, context, host_uuid, force_updates, cinder_device=None):
# perform inventory audit

View File

@ -5797,6 +5797,16 @@ class ConductorManager(service.PeriodicService):
system = self.dbapi.isystem_get_one()
return system
def get_iuser(self, context):
"""Return iuser object
This method returns an iuser object
:returns: iuser object, including all field
"""
user = self.dbapi.iuser_get_one()
return user
def get_ihost_by_macs(self, context, ihost_macs):
"""Finds ihost db entry based upon the mac list
@ -8144,7 +8154,7 @@ class ConductorManager(service.PeriodicService):
cutils.touch(
self._get_oam_runtime_apply_file(standby_controller=True))
def update_user_config(self, context):
def update_user_config(self, context, hosts_uuid=None):
"""Update the user configuration"""
LOG.info("update_user_config")
@ -8157,6 +8167,9 @@ class ConductorManager(service.PeriodicService):
"personalities": personalities,
"classes": ['platform::users::runtime']
}
if hosts_uuid:
config_dict.update({"hosts_uuid": hosts_uuid})
self._config_apply_runtime_manifest(context, config_uuid, config_dict)
def update_controller_rollback_flag(self, context):

View File

@ -190,6 +190,15 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
"""
return self.call(context, self.make_msg('get_isystem',))
def get_iuser(self, context):
"""Return iuser object
This method returns an iuser object
:returns: iuser object, including all field
"""
return self.call(context, self.make_msg('get_iuser',))
def get_ihost_by_macs(self, context, ihost_macs):
"""Finds ihost db entry based upon the mac list
@ -752,12 +761,16 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
"""
return self.call(context, self.make_msg('update_oam_config'))
def update_user_config(self, context):
def update_user_config(self, context, hosts_uuid=None):
"""Synchronously, have the conductor update the user configuration.
:param context: request context.
:param hosts_uuid: list of host_uuids to run user puppet manifest
"""
return self.call(context, self.make_msg('update_user_config'))
return self.call(
context,
self.make_msg('update_user_config', hosts_uuid=hosts_uuid)
)
def update_controller_rollback_flag(self, context):
"""Synchronously, have a conductor update controller rollback flag