2012-08-30 21:29:59 +02:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2012, Derek Carter<goozbach@friocorte.com>
#
# 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 <http://www.gnu.org/licenses/>.
2012-09-30 15:34:26 +02:00
DOCUMENTATION = '''
---
module: selinux
short_description: Change policy and state of SELinux
description:
- Configures the SELinux mode and policy. A reboot may be required after usage. Ansible will not issue this reboot but will let you know when it is required.
version_added: "0.7"
options:
policy:
description:
2012-11-21 18:49:30 +01:00
- "name of the SELinux policy to use (example: C(targeted)) will be required if state is not C(disabled)"
2012-10-19 23:17:30 +02:00
required: false
2012-09-30 15:34:26 +02:00
default: null
state:
description:
- The SELinux mode
required: true
default: null
choices: [ "enforcing", "permissive", "disabled" ]
conf:
description:
- path to the SELinux configuration file, if non-standard
required: false
default: "/etc/selinux/config"
examples:
2012-10-23 15:14:01 +02:00
- code: "selinux: policy=targeted state=enforcing"
- code: "selinux: policy=targeted state=permissive"
- code: "selinux: state=disabled"
2012-09-30 15:34:26 +02:00
notes:
- Not tested on any debian based system
2012-10-19 23:17:30 +02:00
requirements: [ libselinux-python ]
author: Derek Carter <goozbach@friocorte.com>
2012-09-30 15:34:26 +02:00
'''
2012-08-30 21:29:59 +02:00
import os
import re
2012-11-15 00:19:16 +01:00
import sys
2012-08-30 21:29:59 +02:00
try:
import selinux
except ImportError:
2012-11-14 23:28:10 +01:00
print json.dumps(failed=True, msg='python-selinux required for this module')
2012-10-24 17:51:15 +02:00
sys.exit(1)
2012-08-30 21:29:59 +02:00
# 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
2012-10-19 23:17:30 +02:00
module.fail_json(msg=msg)
2012-08-30 21:29:59 +02:00
def set_config_policy(policy, configfile):
# edit config file with state value
2012-09-30 15:34:26 +02:00
#SELINUXTYPE=targeted
2012-08-30 21:29:59 +02:00
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():
module = AnsibleModule(
argument_spec = dict(
2012-10-19 23:17:30 +02:00
policy=dict(required=False),
2012-08-31 01:09:02 +02:00
state=dict(choices=['enforcing', 'permissive', 'disabled'], required=True),
2012-08-30 21:29:59 +02:00
configfile=dict(aliases=['conf','file'], default='/etc/selinux/config')
2013-02-27 21:23:35 +01:00
),
supports_check_mode=True
2012-08-30 21:29:59 +02:00
)
# 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)
2012-10-19 23:17:30 +02:00
# check to see if policy is set if state is not 'disabled'
if (state != 'disabled'):
2013-02-10 00:49:54 +01:00
if not policy:
2012-10-19 23:17:30 +02:00
module.fail_json(msg='policy is required if state is not \'disabled\'')
else:
2013-02-10 00:49:54 +01:00
if not policy:
2012-10-19 23:17:30 +02:00
policy = config_policy
2012-08-30 21:29:59 +02:00
# check changed values and run changes
if (policy != runtime_policy):
2013-02-27 21:23:35 +01:00
if module.check_mode:
module.exit_json(changed=True)
2012-08-30 21:29:59 +02:00
# cannot change runtime policy
msgs.append('reboot to change the loaded policy')
2012-09-30 15:34:26 +02:00
changed=True
2012-08-30 21:29:59 +02:00
if (policy != config_policy):
2013-02-27 21:23:35 +01:00
if module.check_mode:
module.exit_json(changed=True)
2012-08-30 21:29:59 +02:00
msgs.append('config policy changed from \'%s\' to \'%s\'' % (config_policy, policy))
set_config_policy(policy, configfile)
2012-09-30 15:34:26 +02:00
changed=True
2012-08-30 21:29:59 +02:00
if (state != runtime_state):
2013-02-27 21:23:35 +01:00
if module.check_mode:
module.exit_json(changed=True)
2012-08-30 21:29:59 +02:00
if (state == 'disabled'):
2012-10-19 23:17:30 +02:00
msgs.append('state change will take effect next reboot')
2012-08-30 21:29:59 +02:00
else:
2012-10-19 23:17:30 +02:00
if (runtime_enabled):
set_state(state)
msgs.append('runtime state changed from \'%s\' to \'%s\'' % (runtime_state, state))
else:
msgs.append('state change will take effect next reboot')
2012-09-30 15:34:26 +02:00
changed=True
2012-08-30 21:29:59 +02:00
if (state != config_state):
2013-02-27 21:23:35 +01:00
if module.check_mode:
module.exit_json(changed=True)
2012-08-30 21:29:59 +02:00
msgs.append('config state changed from \'%s\' to \'%s\'' % (config_state, state))
set_config_state(state, configfile)
2012-09-30 15:34:26 +02:00
changed=True
2012-08-30 21:29:59 +02:00
module.exit_json(changed=changed, msg=', '.join(msgs),
configfile=configfile,
policy=policy, state=state)
#################################################
# include magic from lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()