mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
seboolean: Fix issue with changing persistent SELinux boolean values (#22779)
Previously, when the active SELinux value was the same as the desired value, regardless of the value of `persistent`, the module would simply exit successfully, assuming no need for update. This made the assumption that the active and persistent values should be the same, but that is not always the case. This modification treats both the active and persistent values separately when checking for the need to update. Note that the persistent update mode, however, will still update the active as well as the persistent value. If this is not desired, it is possible to separately toggle the active value alone. Other changes: * Make the check mode actually perform checks for changes * Organizes semanage commands into set of logical steps
This commit is contained in:
parent
2769a4e2cc
commit
277bb3066c
1 changed files with 150 additions and 62 deletions
|
@ -97,60 +97,149 @@ def get_boolean_value(module, name):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def semanage_get_handle(module):
|
||||||
|
handle = semanage.semanage_handle_create()
|
||||||
|
if not handle:
|
||||||
|
module.fail_json(msg="Failed to create semanage library handle")
|
||||||
|
|
||||||
|
managed = semanage.semanage_is_managed(handle)
|
||||||
|
if managed <= 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
if managed < 0:
|
||||||
|
module.fail_json(msg="Failed to determine whether policy is manage")
|
||||||
|
if managed == 0:
|
||||||
|
if os.getuid() == 0:
|
||||||
|
module.fail_json(msg="Cannot set persistent booleans without managed policy")
|
||||||
|
else:
|
||||||
|
module.fail_json(msg="Cannot set persistent booleans; please try as root")
|
||||||
|
|
||||||
|
if semanage.semanage_connect(handle) < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to connect to semanage")
|
||||||
|
|
||||||
|
return handle
|
||||||
|
|
||||||
|
|
||||||
|
def semanage_begin_transaction(module, handle):
|
||||||
|
if semanage.semanage_begin_transaction(handle) < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to begin semanage transaction")
|
||||||
|
|
||||||
|
|
||||||
|
def semanage_set_boolean_value(module, handle, name, value):
|
||||||
|
rc, t_b = semanage.semanage_bool_create(handle)
|
||||||
|
if rc < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to create seboolean with semanage")
|
||||||
|
|
||||||
|
if semanage.semanage_bool_set_name(handle, t_b, name) < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to set seboolean name with semanage")
|
||||||
|
|
||||||
|
rc, boolkey = semanage.semanage_bool_key_extract(handle, t_b)
|
||||||
|
if rc < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to extract boolean key with semanage")
|
||||||
|
|
||||||
|
rc, exists = semanage.semanage_bool_exists(handle, boolkey)
|
||||||
|
if rc < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to check if boolean is defined")
|
||||||
|
if not exists:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="SELinux boolean %s is not defined in persistent policy" % name)
|
||||||
|
|
||||||
|
rc, sebool = semanage.semanage_bool_query(handle, boolkey)
|
||||||
|
if rc < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to query boolean in persistent policy")
|
||||||
|
|
||||||
|
semanage.semanage_bool_set_value(sebool, value)
|
||||||
|
|
||||||
|
if semanage.semanage_bool_modify_local(handle, boolkey, sebool) < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to modify boolean key with semanage")
|
||||||
|
|
||||||
|
if semanage.semanage_bool_set_active(handle, boolkey, sebool) < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to set boolean key active with semanage")
|
||||||
|
|
||||||
|
semanage.semanage_bool_key_free(boolkey)
|
||||||
|
semanage.semanage_bool_free(t_b)
|
||||||
|
semanage.semanage_bool_free(sebool)
|
||||||
|
|
||||||
|
|
||||||
|
def semanage_get_boolean_value(module, handle, name):
|
||||||
|
rc, t_b = semanage.semanage_bool_create(handle)
|
||||||
|
if rc < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to create seboolean with semanage")
|
||||||
|
|
||||||
|
if semanage.semanage_bool_set_name(handle, t_b, name) < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to set seboolean name with semanage")
|
||||||
|
|
||||||
|
rc, boolkey = semanage.semanage_bool_key_extract(handle, t_b)
|
||||||
|
if rc < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to extract boolean key with semanage")
|
||||||
|
|
||||||
|
rc, exists = semanage.semanage_bool_exists(handle, boolkey)
|
||||||
|
if rc < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to check if boolean is defined")
|
||||||
|
if not exists:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="SELinux boolean %s is not defined in persistent policy" % name)
|
||||||
|
|
||||||
|
rc, sebool = semanage.semanage_bool_query(handle, boolkey)
|
||||||
|
if rc < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to query boolean in persistent policy")
|
||||||
|
|
||||||
|
value = semanage.semanage_bool_get_value(sebool)
|
||||||
|
|
||||||
|
semanage.semanage_bool_key_free(boolkey)
|
||||||
|
semanage.semanage_bool_free(t_b)
|
||||||
|
semanage.semanage_bool_free(sebool)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def semanage_commit(module, handle, load=0):
|
||||||
|
semanage.semanage_set_reload(handle, load)
|
||||||
|
if semanage.semanage_commit(handle) < 0:
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
module.fail_json(msg="Failed to commit changes to semanage")
|
||||||
|
|
||||||
|
|
||||||
|
def semanage_destroy_handle(module, handle):
|
||||||
|
rc = semanage.semanage_disconnect(handle)
|
||||||
|
semanage.semanage_handle_destroy(handle)
|
||||||
|
if rc < 0:
|
||||||
|
module.fail_json(msg="Failed to disconnect from semanage")
|
||||||
|
|
||||||
|
|
||||||
# The following method implements what setsebool.c does to change
|
# The following method implements what setsebool.c does to change
|
||||||
# a boolean and make it persist after reboot..
|
# a boolean and make it persist after reboot..
|
||||||
def semanage_boolean_value(module, name, state):
|
def semanage_boolean_value(module, name, state):
|
||||||
rc = 0
|
|
||||||
value = 0
|
value = 0
|
||||||
|
changed = False
|
||||||
if state:
|
if state:
|
||||||
value = 1
|
value = 1
|
||||||
handle = semanage.semanage_handle_create()
|
|
||||||
if handle is None:
|
|
||||||
module.fail_json(msg="Failed to create semanage library handle")
|
|
||||||
try:
|
try:
|
||||||
managed = semanage.semanage_is_managed(handle)
|
handle = semanage_get_handle(module)
|
||||||
if managed < 0:
|
semanage_begin_transaction(module, handle)
|
||||||
module.fail_json(msg="Failed to determine whether policy is manage")
|
cur_value = semanage_get_boolean_value(module, handle, name)
|
||||||
if managed == 0:
|
if cur_value != value:
|
||||||
if os.getuid() == 0:
|
changed = True
|
||||||
module.fail_json(msg="Cannot set persistent booleans without managed policy")
|
if not module.check_mode:
|
||||||
else:
|
semanage_set_boolean_value(module, handle, name, value)
|
||||||
module.fail_json(msg="Cannot set persistent booleans; please try as root")
|
semanage_commit(module, handle)
|
||||||
if semanage.semanage_connect(handle) < 0:
|
semanage_destroy_handle(module, handle)
|
||||||
module.fail_json(msg="Failed to connect to semanage")
|
|
||||||
|
|
||||||
if semanage.semanage_begin_transaction(handle) < 0:
|
|
||||||
module.fail_json(msg="Failed to begin semanage transaction")
|
|
||||||
|
|
||||||
rc, sebool = semanage.semanage_bool_create(handle)
|
|
||||||
if rc < 0:
|
|
||||||
module.fail_json(msg="Failed to create seboolean with semanage")
|
|
||||||
if semanage.semanage_bool_set_name(handle, sebool, name) < 0:
|
|
||||||
module.fail_json(msg="Failed to set seboolean name with semanage")
|
|
||||||
semanage.semanage_bool_set_value(sebool, value)
|
|
||||||
|
|
||||||
rc, boolkey = semanage.semanage_bool_key_extract(handle, sebool)
|
|
||||||
if rc < 0:
|
|
||||||
module.fail_json(msg="Failed to extract boolean key with semanage")
|
|
||||||
|
|
||||||
if semanage.semanage_bool_modify_local(handle, boolkey, sebool) < 0:
|
|
||||||
module.fail_json(msg="Failed to modify boolean key with semanage")
|
|
||||||
|
|
||||||
if semanage.semanage_bool_set_active(handle, boolkey, sebool) < 0:
|
|
||||||
module.fail_json(msg="Failed to set boolean key active with semanage")
|
|
||||||
|
|
||||||
semanage.semanage_bool_key_free(boolkey)
|
|
||||||
semanage.semanage_bool_free(sebool)
|
|
||||||
|
|
||||||
semanage.semanage_set_reload(handle, 0)
|
|
||||||
if semanage.semanage_commit(handle) < 0:
|
|
||||||
module.fail_json(msg="Failed to commit changes to semanage")
|
|
||||||
|
|
||||||
semanage.semanage_disconnect(handle)
|
|
||||||
semanage.semanage_handle_destroy(handle)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
module.fail_json(msg="Failed to manage policy for boolean %s: %s" % (name, str(e)))
|
module.fail_json(msg="Failed to manage policy for boolean %s: %s" % (name, str(e)))
|
||||||
return True
|
return changed
|
||||||
|
|
||||||
|
|
||||||
def set_boolean_value(module, name, state):
|
def set_boolean_value(module, name, state):
|
||||||
|
@ -193,7 +282,10 @@ def main():
|
||||||
|
|
||||||
result = dict(
|
result = dict(
|
||||||
name=name,
|
name=name,
|
||||||
|
persistent=persistent,
|
||||||
|
state=state
|
||||||
)
|
)
|
||||||
|
changed = False
|
||||||
|
|
||||||
if hasattr(selinux, 'selinux_boolean_sub'):
|
if hasattr(selinux, 'selinux_boolean_sub'):
|
||||||
# selinux_boolean_sub allows sites to rename a boolean and alias the old name
|
# selinux_boolean_sub allows sites to rename a boolean and alias the old name
|
||||||
|
@ -203,26 +295,22 @@ def main():
|
||||||
if not has_boolean_value(module, name):
|
if not has_boolean_value(module, name):
|
||||||
module.fail_json(msg="SELinux boolean %s does not exist." % name)
|
module.fail_json(msg="SELinux boolean %s does not exist." % name)
|
||||||
|
|
||||||
cur_value = get_boolean_value(module, name)
|
|
||||||
|
|
||||||
if cur_value == state:
|
|
||||||
module.exit_json(changed=False, state=cur_value, **result)
|
|
||||||
|
|
||||||
if module.check_mode:
|
|
||||||
module.exit_json(changed=True)
|
|
||||||
|
|
||||||
if persistent:
|
if persistent:
|
||||||
r = semanage_boolean_value(module, name, state)
|
changed = semanage_boolean_value(module, name, state)
|
||||||
else:
|
else:
|
||||||
r = set_boolean_value(module, name, state)
|
cur_value = get_boolean_value(module, name)
|
||||||
|
if cur_value != state:
|
||||||
|
changed = True
|
||||||
|
if not module.check_mode:
|
||||||
|
changed = set_boolean_value(module, name, state)
|
||||||
|
if not changed:
|
||||||
|
module.fail_json(msg="Failed to set boolean %s to %s" % (name, state))
|
||||||
|
try:
|
||||||
|
selinux.security_commit_booleans()
|
||||||
|
except:
|
||||||
|
module.fail_json(msg="Failed to commit pending boolean %s value" % name)
|
||||||
|
|
||||||
result['changed'] = r
|
result['changed'] = changed
|
||||||
if not r:
|
|
||||||
module.fail_json(msg="Failed to set boolean %s to %s" % (name, state))
|
|
||||||
try:
|
|
||||||
selinux.security_commit_booleans()
|
|
||||||
except:
|
|
||||||
module.fail_json(msg="Failed to commit pending boolean %s value" % name)
|
|
||||||
|
|
||||||
module.exit_json(**result)
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue