1 # vgp_sudoers_ext samba gpo policy
2 # Copyright (C) David Mulder <dmulder@suse.com> 2020
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 from samba
.gpclass
import gp_xml_ext
19 from base64
import b64encode
20 from tempfile
import NamedTemporaryFile
21 from subprocess
import Popen
, PIPE
22 from samba
.gp_sudoers_ext
import visudo
, intro
24 class vgp_sudoers_ext(gp_xml_ext
):
26 return 'VGP/Unix Settings/Sudo Rights'
28 def process_group_policy(self
, deleted_gpo_list
, changed_gpo_list
,
29 sdir
='/etc/sudoers.d'):
30 for guid
, settings
in deleted_gpo_list
:
31 self
.gp_db
.set_guid(guid
)
32 if str(self
) in settings
:
33 for attribute
, sudoers
in settings
[str(self
)].items():
34 if os
.path
.exists(sudoers
):
36 self
.gp_db
.delete(str(self
), attribute
)
39 for gpo
in changed_gpo_list
:
41 self
.gp_db
.set_guid(gpo
.name
)
42 xml
= 'MACHINE/VGP/VTLA/Sudo/SudoersConfiguration/manifest.xml'
43 path
= os
.path
.join(gpo
.file_sys_path
, xml
)
44 xml_conf
= self
.parse(path
)
47 policy
= xml_conf
.find('policysetting')
48 data
= policy
.find('data')
49 for entry
in data
.findall('sudoers_entry'):
50 command
= entry
.find('command').text
51 user
= entry
.find('user').text
52 listelements
= entry
.findall('listelement')
54 for listelement
in listelements
:
55 principals
.extend(listelement
.findall('principal'))
56 if len(principals
) > 0:
57 uname
= ','.join([u
.text
if u
.attrib
['type'] == 'user' \
58 else '%s%%' % u
.text
for u
in principals
])
61 nopassword
= entry
.find('password') == None
62 np_entry
= ' NOPASSWD:' if nopassword
else ''
63 p
= '%s ALL=(%s)%s %s' % (uname
, user
, np_entry
, command
)
64 attribute
= b64encode(p
.encode()).decode()
65 old_val
= self
.gp_db
.retrieve(str(self
), attribute
)
68 contents
+= '%s\n' % p
69 with
NamedTemporaryFile() as f
:
70 with
open(f
.name
, 'w') as w
:
73 Popen([visudo
, '-c', '-f', f
.name
],
74 stdout
=PIPE
, stderr
=PIPE
).wait()
75 if sudo_validation
== 0:
76 with
NamedTemporaryFile(prefix
='gp_',
79 with
open(f
.name
, 'w') as w
:
81 self
.gp_db
.store(str(self
),
85 self
.logger
.warn('Sudoers apply "%s" failed'
91 xml
= 'MACHINE/VGP/VTLA/Sudo/SudoersConfiguration/manifest.xml'
93 path
= os
.path
.join(gpo
.file_sys_path
, xml
)
94 xml_conf
= self
.parse(path
)
97 policy
= xml_conf
.find('policysetting')
98 data
= policy
.find('data')
99 for entry
in data
.findall('sudoers_entry'):
100 command
= entry
.find('command').text
101 user
= entry
.find('user').text
102 listelements
= entry
.findall('listelement')
104 for listelement
in listelements
:
105 principals
.extend(listelement
.findall('principal'))
106 if len(principals
) > 0:
107 uname
= ','.join([u
.text
if u
.attrib
['type'] == 'user' \
108 else '%s%%' % u
.text
for u
in principals
])
111 nopassword
= entry
.find('password') == None
112 np_entry
= ' NOPASSWD:' if nopassword
else ''
113 p
= '%s ALL=(%s)%s %s' % (uname
, user
, np_entry
, command
)
114 if str(self
) not in output
.keys():
115 output
[str(self
)] = []
116 output
[str(self
)].append(p
)