Merge "Audit local sysadmin user password periodically"
This commit is contained in:
commit
9eb224b0a9
@ -93,7 +93,8 @@ agent_opts = [
|
|||||||
audit_intervals_opts = [
|
audit_intervals_opts = [
|
||||||
cfg.IntOpt('default', default=60),
|
cfg.IntOpt('default', default=60),
|
||||||
cfg.IntOpt('inventory_audit', 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 = [
|
dpdk_opts = [
|
||||||
@ -1313,6 +1314,51 @@ class AgentManager(service.PeriodicService):
|
|||||||
else:
|
else:
|
||||||
self._lldp_enable_and_report(icontext, rpcapi, self._ihost_uuid)
|
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)
|
@utils.synchronized(LOCK_AGENT_ACTION, external=False)
|
||||||
def agent_audit(self, context, host_uuid, force_updates, cinder_device=None):
|
def agent_audit(self, context, host_uuid, force_updates, cinder_device=None):
|
||||||
# perform inventory audit
|
# perform inventory audit
|
||||||
|
@ -5797,6 +5797,16 @@ class ConductorManager(service.PeriodicService):
|
|||||||
system = self.dbapi.isystem_get_one()
|
system = self.dbapi.isystem_get_one()
|
||||||
return system
|
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):
|
def get_ihost_by_macs(self, context, ihost_macs):
|
||||||
"""Finds ihost db entry based upon the mac list
|
"""Finds ihost db entry based upon the mac list
|
||||||
|
|
||||||
@ -8144,7 +8154,7 @@ class ConductorManager(service.PeriodicService):
|
|||||||
cutils.touch(
|
cutils.touch(
|
||||||
self._get_oam_runtime_apply_file(standby_controller=True))
|
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"""
|
"""Update the user configuration"""
|
||||||
LOG.info("update_user_config")
|
LOG.info("update_user_config")
|
||||||
|
|
||||||
@ -8157,6 +8167,9 @@ class ConductorManager(service.PeriodicService):
|
|||||||
"personalities": personalities,
|
"personalities": personalities,
|
||||||
"classes": ['platform::users::runtime']
|
"classes": ['platform::users::runtime']
|
||||||
}
|
}
|
||||||
|
if hosts_uuid:
|
||||||
|
config_dict.update({"hosts_uuid": hosts_uuid})
|
||||||
|
|
||||||
self._config_apply_runtime_manifest(context, config_uuid, config_dict)
|
self._config_apply_runtime_manifest(context, config_uuid, config_dict)
|
||||||
|
|
||||||
def update_controller_rollback_flag(self, context):
|
def update_controller_rollback_flag(self, context):
|
||||||
|
@ -190,6 +190,15 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy):
|
|||||||
"""
|
"""
|
||||||
return self.call(context, self.make_msg('get_isystem',))
|
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):
|
def get_ihost_by_macs(self, context, ihost_macs):
|
||||||
"""Finds ihost db entry based upon the mac list
|
"""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'))
|
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.
|
"""Synchronously, have the conductor update the user configuration.
|
||||||
|
|
||||||
:param context: request context.
|
: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):
|
def update_controller_rollback_flag(self, context):
|
||||||
"""Synchronously, have a conductor update controller rollback flag
|
"""Synchronously, have a conductor update controller rollback flag
|
||||||
|
Loading…
Reference in New Issue
Block a user