Line
Link Here
|
0 |
-- a/WebappConfig/db.py |
0 |
++ b/WebappConfig/db.py |
Lines 537-544
Link Here
|
537 |
''' |
535 |
''' |
538 |
import WebappConfig.filetype |
536 |
import WebappConfig.filetype |
539 |
|
537 |
|
540 |
server_files = [] |
538 |
self.server_files = [] |
541 |
server_dirs = [] |
539 |
self.server_dirs = [] |
542 |
config_files = [] |
540 |
config_files = [] |
543 |
|
541 |
|
544 |
if os.access(self.appdir() + '/' + config_owned, os.R_OK): |
542 |
if os.access(self.appdir() + '/' + config_owned, os.R_OK): |
Lines 549-555
class WebappSource(AppHierarchy):
Link Here
|
549 |
if os.access(self.appdir() + '/' + server_owned, os.R_OK): |
549 |
if os.access(self.appdir() + '/' + server_owned, os.R_OK): |
550 |
flist = open(self.appdir() + '/' + server_owned) |
550 |
flist = open(self.appdir() + '/' + server_owned) |
551 |
server_files = flist.readlines() |
551 |
self.server_files = flist.readlines() |
552 |
OUT.debug('Identified server-owned files.', 7) |
552 |
OUT.debug('Identified server-owned files.', 7) |
Lines 557-571
class WebappSource(AppHierarchy):
Link Here
|
557 |
if os.access(self.appdir() + '/' + server_owned_r, os.R_OK): |
557 |
if os.access(self.appdir() + '/' + server_owned_r, os.R_OK): |
558 |
flist = open(self.appdir() + '/' + server_owned_r) |
558 |
flist = open(self.appdir() + '/' + server_owned_r) |
559 |
server_dirs = flist.readlines() |
559 |
self.server_dirs = flist.readlines() |
560 |
OUT.debug('Identified server-owned directories.', 7) |
560 |
OUT.debug('Identified server-owned directories.', 7) |
561 |
flist.close() |
561 |
flist.close() |
562 |
self.__types = WebappConfig.filetype.FileType(config_files, |
562 |
self.__types = WebappConfig.filetype.FileType(config_files, |
563 |
server_files, |
563 |
self.server_files, |
564 |
server_dirs, |
564 |
self.server_dirs, |
565 |
virtual_files, |
565 |
virtual_files, |
566 |
default_dirs) |
566 |
default_dirs) |
567 |
-- a/WebappConfig/config.py |
567 |
++ b/WebappConfig/config.py |
Lines 293-298
class Config:
Link Here
|
293 |
'wa_installs' : '%(my_persistdir)s/%(wa_installsbase)s', |
293 |
'wa_installs' : '%(my_persistdir)s/%(wa_installsbase)s', |
294 |
'wa_postinstallinfo': |
294 |
'wa_postinstallinfo': |
295 |
'%(my_appdir)s/post-install-instructions.txt', |
295 |
'%(my_appdir)s/post-install-instructions.txt', |
|
|
296 |
'g_selinux' : 'no', |
296 |
} |
297 |
} |
297 |
# Setup basic defaults |
298 |
# Setup basic defaults |
Lines 541-546
class Config:
Link Here
|
541 |
'rt all values of DEFAULT_DIRS and will report a' |
542 |
'rt all values of DEFAULT_DIRS and will report a' |
542 |
'n error') |
543 |
'n error') |
|
|
544 |
group.add_option('--selinux-module', |
545 |
type = 'choice', |
546 |
choices = ['yes', |
547 |
'no'], |
548 |
help = 'If activated, webapp-config will use a S' |
549 |
'ELinux module to set the file context of server' |
550 |
' owned files to \'httpd_sys_rw_content_t\'. Def' |
551 |
'ault is' + self.config.get('USER', 'g_selinux')) |
552 |
|
543 |
self.parser.add_option_group(group) |
553 |
self.parser.add_option_group(group) |
544 |
#----------------------------------------------------------------- |
554 |
#----------------------------------------------------------------- |
Lines 874-880
class Config:
Link Here
|
874 |
'default_dirs' : 'vhost_config_default_dirs', |
884 |
'default_dirs' : 'vhost_config_default_dirs', |
875 |
'pretend' : 'g_pretend', |
885 |
'pretend' : 'g_pretend', |
876 |
'verbose' : 'g_verbose', |
886 |
'verbose' : 'g_verbose', |
877 |
'bug_report' : 'g_bugreport'} |
887 |
'bug_report' : 'g_bugreport', |
|
|
888 |
'selinux' : 'g_selinux', |
889 |
} |
878 |
for i in option_to_config.keys(): |
890 |
for i in option_to_config.keys(): |
879 |
if i in options.__dict__ and options.__dict__[i]: |
891 |
if i in options.__dict__ and options.__dict__[i]: |
Lines 1496-1502
class Config:
Link Here
|
1496 |
'orig' : self.maybe_get('g_orig_installdir'), |
1508 |
'orig' : self.maybe_get('g_orig_installdir'), |
1497 |
'upgrade' : self.upgrading(), |
1509 |
'upgrade' : self.upgrading(), |
1498 |
'verbose' : self.verbose(), |
1510 |
'verbose' : self.verbose(), |
1499 |
'pretend' : self.pretend()} |
1511 |
'pretend' : self.pretend(), |
|
|
1512 |
'selinux' : self.maybe_get('g_selinux') == 'yes', |
1513 |
} |
1500 |
return allowed_servers[server](directories, |
1514 |
return allowed_servers[server](directories, |
1501 |
self.create_permissions(), |
1515 |
self.create_permissions(), |
1502 |
-- /dev/null |
1516 |
++ b/WebappConfig/selinux.py |
Line 0
Link Here
|
0 |
-- a/WebappConfig/server.py |
1 |
#!/usr/bin/python -O |
|
|
2 |
# |
3 |
# /usr/sbin/webapp-config |
4 |
# Python script for managing the deployment of web-based |
5 |
# applications |
6 |
# |
7 |
# Originally written for the Gentoo Linux distribution |
8 |
# |
9 |
# Copyright (c) 1999-2007 Authors |
10 |
# Released under v2 of the GNU GPL |
11 |
# |
12 |
# ======================================================================== |
13 |
|
14 |
# ======================================================================== |
15 |
# Dependencies |
16 |
# ------------------------------------------------------------------------ |
17 |
|
18 |
import os, os.path, re, shutil, subprocess, tempfile |
19 |
|
20 |
from WebappConfig.debug import OUT |
21 |
|
22 |
# ======================================================================== |
23 |
# Constants |
24 |
# ------------------------------------------------------------------------ |
25 |
|
26 |
MAKE_CONF_FILE = ['/etc/make.conf', '/etc/portage/make.conf'] |
27 |
|
28 |
# ======================================================================== |
29 |
# SELinux handler |
30 |
# ------------------------------------------------------------------------ |
31 |
|
32 |
class SELinux: |
33 |
|
34 |
def __init__(self, package_name, vhost_hostname, policy_types = ()): |
35 |
self.package_name = package_name |
36 |
self.vhost_hostname = vhost_hostname |
37 |
self.policy_name = '{}_{}'.format(package_name, vhost_hostname) |
38 |
self.policy_types = policy_types |
39 |
if self.policy_types is (): |
40 |
for filename in MAKE_CONF_FILE: |
41 |
try: |
42 |
with open(filename) as file: |
43 |
for line in file.readlines(): |
44 |
if line.startswith('POLICY_TYPES='): |
45 |
self.policy_types = line[len('POLICY_TYPES='):-1].strip(' "').split() |
46 |
break |
47 |
if self.policy_types is not None: |
48 |
break |
49 |
except IOError: |
50 |
pass |
51 |
if self.policy_types is (): |
52 |
OUT.die('No SELinux policy was found, abording') |
53 |
|
54 |
def remove_module(self): |
55 |
OUT.info('Removing SELinux modules') |
56 |
for policy in self.policy_types: |
57 |
if subprocess.call(['semodule', '-s', policy, '-r', self.policy_name]): |
58 |
OUT.warn('Unable to remove {} SELinux module for {} @ {}'.format(policy, self.package_name, self.vhost_hostname)) |
59 |
|
60 |
def create_module(self, package_version, vhost_root, server_files, server_dirs): |
61 |
temp_dir = tempfile.mkdtemp() |
62 |
OUT.info('Creating SELinux modules') |
63 |
for policy in self.policy_types: |
64 |
base_dir = os.path.join(temp_dir, policy) |
65 |
os.mkdir(base_dir) |
66 |
with open(os.path.join(base_dir, '{}.te'.format(self.policy_name)), 'w') as te_file: |
67 |
te_file.write('policy_module({},{})\n'.format(self.policy_name, package_version)) |
68 |
te_file.write('require {\n') |
69 |
te_file.write(' type httpd_sys_rw_content_t;\n') |
70 |
te_file.write('}') |
71 |
with open(os.path.join(base_dir, '{}.fc'.format(self.policy_name)), 'w') as fc_file: |
72 |
for files in server_files: |
73 |
fc_file.write('{} gen_context(system_u:object_r:httpd_sys_rw_content_t,s0)\n'.format(SELinux.filename_re_escape(os.path.join(vhost_root, files.rstrip('\n'))))) |
74 |
for dirs in server_dirs: |
75 |
fc_file.write('{}(/.*)? gen_context(system_u:object_r:httpd_sys_rw_content_t,s0)\n'.format(SELinux.filename_re_escape(os.path.join(vhost_root, dirs.rstrip('\n'))))) |
76 |
if subprocess.call(['make', '-s', '-C', base_dir, '-f', os.path.join('/usr/share/selinux', policy, 'include/Makefile'), '{}.pp'.format(self.policy_name)]): |
77 |
if not os.path.isfile(os.path.join('/usr/share/selinux', policy, 'include/Makefile')): |
78 |
OUT.die('Policy {} is not supported, please fix your configuration'.format(policy)) |
79 |
OUT.die('Unable to create {} SELinux module for {} @ {}'.format(policy, self.package_name, self.vhost_hostname)) |
80 |
OUT.info('Installing SELinux modules') |
81 |
try: |
82 |
for policy in self.policy_types: |
83 |
if subprocess.call(['semodule', '-s', policy, '-i', os.path.join(temp_dir, policy, '{}.pp'.format(self.policy_name))]): |
84 |
OUT.die('Unable to install {} SELinux module for {} @ {}'.format(policy, self.package_name, self.vhost_hostname)) |
85 |
except IOError: |
86 |
OUT.die('"semodule" was not found, please check you SELinux installation') |
87 |
shutil.rmtree(temp_dir) |
88 |
|
89 |
@staticmethod |
90 |
def filename_re_escape(string): |
91 |
return re.sub('\.', '\.', string) |
|
|
92 |
++ b/WebappConfig/server.py |
Lines 24-29
import os, os.path
Link Here
|
24 |
from WebappConfig.debug import OUT |
24 |
from WebappConfig.debug import OUT |
25 |
from WebappConfig.worker import WebappRemove, WebappAdd |
25 |
from WebappConfig.worker import WebappRemove, WebappAdd |
26 |
from WebappConfig.permissions import get_group, get_user |
26 |
from WebappConfig.permissions import get_group, get_user |
|
|
27 |
from WebappConfig.selinux import SELinux |
27 |
from WebappConfig.wrapper import package_installed |
28 |
from WebappConfig.wrapper import package_installed |
Lines 95-100
class Basic:
Link Here
|
95 |
self.__v = flags['verbose'] |
96 |
self.__v = flags['verbose'] |
96 |
self.__p = flags['pretend'] |
97 |
self.__p = flags['pretend'] |
|
|
98 |
if flags['selinux']: |
99 |
self.__selinux = SELinux(self.__ws.pn, flags['host']) |
100 |
else: |
101 |
self.__selinux = None |
102 |
|
97 |
wd = WebappRemove(self.__content, |
103 |
wd = WebappRemove(self.__content, |
98 |
self.__v, |
104 |
self.__v, |
99 |
self.__p) |
105 |
self.__p) |
Lines 176-181
class Basic:
Link Here
|
176 |
self.__db.remove(self.__destd) |
182 |
self.__db.remove(self.__destd) |
|
|
183 |
# Remove the selinux module |
184 |
|
185 |
if self.__selinux is not None: |
186 |
self.__selinux.remove_module() |
187 |
|
177 |
# did we leave anything behind? |
188 |
# did we leave anything behind? |
178 |
if self.file_behind_flag: |
189 |
if self.file_behind_flag: |
Lines 188-193
class Basic:
Link Here
|
188 |
OUT.debug('Basic server install', 7) |
199 |
OUT.debug('Basic server install', 7) |
|
|
200 |
# Create the selinux module |
201 |
|
202 |
if self.__selinux is not None: |
203 |
self.__selinux.create_module(self.__ws.pvr, self.__vhostroot, |
204 |
self.__ws.server_files, |
205 |
self.__ws.server_dirs) |
206 |
|
189 |
# The root of the virtual install location needs to exist |
207 |
# The root of the virtual install location needs to exist |
190 |
if not os.path.isdir(self.__destd) and not self.__p: |
208 |
if not os.path.isdir(self.__destd) and not self.__p: |
Lines 314-319
class Basic:
Link Here
|
314 |
self.__content.write() |
314 |
self.__content.write() |
|
|
315 |
# Warn the user about needed relabelling |
316 |
|
317 |
OUT.warn('You probably need to relabel the new installation, using for' |
318 |
'example "restorecon -R ' + self.__destd + '"') |
319 |
|
315 |
# and we're done |
320 |
# and we're done |
316 |
OUT.info('Install completed - success', 1) |
321 |
OUT.info('Install completed - success', 1) |