1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# Copyright: (c) 2015, Michael Scherer <misc@zarb.org>
5# inspired by code of github.com/dandiker/
6# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
7
8from __future__ import absolute_import, division, print_function
9__metaclass__ = type
10
11ANSIBLE_METADATA = {'metadata_version': '1.1',
12                    'status': ['preview'],
13                    'supported_by': 'community'}
14
15DOCUMENTATION = r'''
16---
17module: selinux_permissive
18short_description: Change permissive domain in SELinux policy
19description:
20  - Add and remove a domain from the list of permissive domains.
21version_added: "2.0"
22options:
23  domain:
24    description:
25        - The domain that will be added or removed from the list of permissive domains.
26    type: str
27    required: true
28    default: ''
29    aliases: [ name ]
30  permissive:
31    description:
32        - Indicate if the domain should or should not be set as permissive.
33    type: bool
34    required: true
35  no_reload:
36    description:
37        - Disable reloading of the SELinux policy after making change to a domain's permissive setting.
38        - The default is C(no), which causes policy to be reloaded when a domain changes state.
39        - Reloading the policy does not work on older versions of the C(policycoreutils-python) library, for example in EL 6."
40    type: bool
41    default: no
42  store:
43    description:
44      - Name of the SELinux policy store to use.
45    type: str
46notes:
47    - Requires a recent version of SELinux and C(policycoreutils-python) (EL 6 or newer).
48requirements: [ policycoreutils-python ]
49author:
50- Michael Scherer (@mscherer) <misc@zarb.org>
51'''
52
53EXAMPLES = r'''
54- name: Change the httpd_t domain to permissive
55  selinux_permissive:
56    name: httpd_t
57    permissive: true
58'''
59
60import traceback
61
62HAVE_SEOBJECT = False
63SEOBJECT_IMP_ERR = None
64try:
65    import seobject
66    HAVE_SEOBJECT = True
67except ImportError:
68    SEOBJECT_IMP_ERR = traceback.format_exc()
69
70from ansible.module_utils.basic import AnsibleModule, missing_required_lib
71from ansible.module_utils._text import to_native
72
73
74def main():
75    module = AnsibleModule(
76        argument_spec=dict(
77            domain=dict(type='str', required=True, aliases=['name']),
78            store=dict(type='str', default=''),
79            permissive=dict(type='bool', required=True),
80            no_reload=dict(type='bool', default=False),
81        ),
82        supports_check_mode=True,
83    )
84
85    # global vars
86    changed = False
87    store = module.params['store']
88    permissive = module.params['permissive']
89    domain = module.params['domain']
90    no_reload = module.params['no_reload']
91
92    if not HAVE_SEOBJECT:
93        module.fail_json(changed=False, msg=missing_required_lib("policycoreutils-python"),
94                         exception=SEOBJECT_IMP_ERR)
95
96    try:
97        permissive_domains = seobject.permissiveRecords(store)
98    except ValueError as e:
99        module.fail_json(domain=domain, msg=to_native(e), exception=traceback.format_exc())
100
101    # not supported on EL 6
102    if 'set_reload' in dir(permissive_domains):
103        permissive_domains.set_reload(not no_reload)
104
105    try:
106        all_domains = permissive_domains.get_all()
107    except ValueError as e:
108        module.fail_json(domain=domain, msg=to_native(e), exception=traceback.format_exc())
109
110    if permissive:
111        if domain not in all_domains:
112            if not module.check_mode:
113                try:
114                    permissive_domains.add(domain)
115                except ValueError as e:
116                    module.fail_json(domain=domain, msg=to_native(e), exception=traceback.format_exc())
117            changed = True
118    else:
119        if domain in all_domains:
120            if not module.check_mode:
121                try:
122                    permissive_domains.delete(domain)
123                except ValueError as e:
124                    module.fail_json(domain=domain, msg=to_native(e), exception=traceback.format_exc())
125            changed = True
126
127    module.exit_json(changed=changed, store=store,
128                     permissive=permissive, domain=domain)
129
130
131if __name__ == '__main__':
132    main()
133