diff --git a/selinux b/selinux new file mode 100644 index 00000000000..0e38fdf1343 --- /dev/null +++ b/selinux @@ -0,0 +1,159 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2012, Derek Carter +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# selinux module - change policy and state of SELinux +# usage: +# +# selinux policy= state=[enforcing|permissive|disabled] configfile=[SELINUX_CONFIG_FILE] +# +# configfile defaults to /etc/selinux/config +# policy files should be installed via the yum/apt modules +# +# bugs: +# +# Not tested on any debian based system + +import os +import re + +try: + import selinux + HAVE_SELINUX=True +except ImportError: + HAVE_SELINUX=False + +# getter subroutines +def get_config_state(configfile): + myfile = open(configfile, "r") + lines = myfile.readlines() + myfile.close() + for line in lines: + stateline = re.match('^SELINUX=.*$', line) + if (stateline): + return(line.split('=')[1].strip()) + +def get_config_policy(configfile): + myfile = open(configfile, "r") + lines = myfile.readlines() + myfile.close() + for line in lines: + stateline = re.match('^SELINUXTYPE=.*$', line) + if (stateline): + return(line.split('=')[1].strip()) + +# setter subroutines +def set_config_state(state, configfile): + #SELINUX=permissive + # edit config file with state value + stateline='SELINUX=%s' % state + myfile = open(configfile, "r") + lines = myfile.readlines() + myfile.close() + myfile = open(configfile, "w") + for line in lines: + myfile.write(re.sub(r'^SELINUX=.*', stateline, line)) + myfile.close() + +def set_state(state): + if (state == 'enforcing'): + selinux.security_setenforce(1) + elif (state == 'permissive'): + selinux.security_setenforce(0) + elif (state == 'disabled'): + pass + else: + msg = 'trying to set invalid runtime state %s' % state + fail_json(msg=msg) + +def set_config_policy(policy, configfile): + # edit config file with state value + #SELINUXTYPE=targeted + policyline='SELINUXTYPE=%s' % policy + myfile = open(configfile, "r") + lines = myfile.readlines() + myfile.close() + myfile = open(configfile, "w") + for line in lines: + myfile.write(re.sub(r'^SELINUXTYPE=.*', policyline, line)) + myfile.close() + +def main(): + if (not HAVE_SELINUX): + fail_json(msg='python-selinux required for this module') + + module = AnsibleModule( + argument_spec = dict( + policy=dict(required=True), + state=dict(choices=['enforcing', 'permissive', 'disabled'], default='enforcing'), + configfile=dict(aliases=['conf','file'], default='/etc/selinux/config') + ) + ) + + # global vars + changed=False + msgs = [] + configfile = module.params['configfile'] + policy = module.params['policy'] + state = module.params['state'] + runtime_enabled = selinux.is_selinux_enabled() + runtime_policy = selinux.selinux_getpolicytype()[1] + runtime_state = 'disabled' + if (runtime_enabled): + # enabled means 'enforcing' or 'permissive' + if (selinux.security_getenforce()): + runtime_state = 'enforcing' + else: + runtime_state = 'permissive' + config_policy = get_config_policy(configfile) + config_state = get_config_state(configfile) + + # check changed values and run changes + if (policy != runtime_policy): + # cannot change runtime policy + msgs.append('reboot to change the loaded policy') + changed=True + + if (policy != config_policy): + msgs.append('config policy changed from \'%s\' to \'%s\'' % (config_policy, policy)) + set_config_policy(policy, configfile) + changed=True + + if (state != runtime_state): + if (state == 'disabled'): + msgs.append('disabled state will take effect next reboot') + else: + msgs.append('runtime state changed from \'%s\' to \'%s\'' % (runtime_state, state)) + set_state(state) + changed=True + + if (state != config_state): + msgs.append('config state changed from \'%s\' to \'%s\'' % (config_state, state)) + set_config_state(state, configfile) + changed=True + + module.exit_json(changed=changed, msg=', '.join(msgs), + configfile=configfile, + policy=policy, state=state) + +################################################# +# include magic from lib/ansible/module_common.py +#<> + +main()