Пример #1
0
def delete(self, remove_dirs=True, **UserOptions):
    user = User({'username': UserOptions['username']})
    for vhost in UserOptions['vhosts']:
        try:
            os.remove(vhost_dir + user.username + '_' + vhost['name'] +
                      '.conf')
        except OSError:
            pass

        if os.path.exists('/etc/nginx/ssl/' + vhost['name'] + '.pem'):
            os.unlink('/etc/nginx/ssl/' + vhost['name'] + '.pem')

        if os.path.exists('/etc/nginx/ssl/' + vhost['name'] + '.key'):
            os.unlink('/etc/nginx/ssl/' + vhost['name'] + '.key')

        if remove_dirs and user.info() is not False:
            try:
                logger.info(u'Removing domain directory for ' + vhost['name'])
                #shutil.rmtree(os.path.join(user.info()[5] + '/domains/', vhost['name']), True)
                basic.run_command(
                    '/bin/rm -rf \'' +
                    os.path.join(user.info()[5] + '/domains/', vhost['name']) +
                    '\'')  # TODO
            except OSError:
                pass

    basic.run_command('/usr/sbin/nginx -t')
    basic.run_command('/usr/sbin/nginx -s reload')
Пример #2
0
def setup(self, **UserOptions):
    user_obj = {'username': UserOptions['username']}
    user = User(user_obj)

    basic.copytree('/etc/php5',
                   '/home/' + user.username + '/.config/php5',
                   symlinks=True)

    # So called environment for jinja2 template
    template_data = {
        "username": user.username,
        "homedir": user.info()[5],
    }

    with open('/home/' + user.username + '/.config/php5/fpm/php-fpm.conf',
              'w') as f:
        f.write(templates.php_fpm_template.render(template_data))

    with open('/home/' + user.username + '/.config/php5/fpm/php.ini',
              'w') as f:
        f.write(templates.php_ini_template.render(template_data))

    with open('/home/' + user.username + '/.config/php5/fpm/pool.d/www.conf',
              'w') as f:
        f.write(templates.php_pool_template.render(template_data))

    basic.ensure_path('/home/' + user.username + '/.config/upstart')
    with open('/home/' + user.username + '/.config/upstart/php5-fpm.conf',
              'w') as f:
        f.write(templates.php_upstart_template.render(template_data))

    basic.rec_chown(user.info()[5] + '/.config/php5',
                    user.info()[2],
                    user.info()[3])
    '''
    try:
        basic.run_command("XDG_RUNTIME_DIR=/run/user/`id -u "+user.username+"` UPSTART_SESSION=`initctl list-sessions | awk -F' ' '{ print $2 }'` restart php5-fpm", executable='/bin/bash')
    except Exception:
        basic.run_command("XDG_RUNTIME_DIR=/run/user/`id -u "+user.username+"` UPSTART_SESSION=`initctl list-sessions | awk -F' ' '{ print $2 }'` start php5-fpm", executable='/bin/bash')
    '''

    # stop PHP (and other daemons)
    try:
        basic.run_command('stop session-init USER='******'/bin/bash')
    except Exception:
        pass

    # and start
    basic.run_command('start session-init USER='******'/bin/bash')

    basic.run_command('/bin/setfacl -m u:www-data:rX /home/' + user.username +
                      '/.cache')
Пример #3
0
def WebAccount(self, **AccountObject):
    #logger.info(repr(AccountObject))

    ############################### deal with system account ###############################
    # Validate state
    if AccountObject['state'] not in [
            'active', 'locked', 'suspended', 'deleted'
    ]:
        raise Exception('Unrecognized WebAccount state value: ' +
                        AccountObject['state'])

    if AccountObject['state'] == 'deleted':
        user = User({'username': AccountObject['username']})
        if user.exists():
            logger.info('Deleting user: '******'s group is deleted automatically by deluser
    else:
        user_obj = {
            'username': AccountObject['username'],
            'password': AccountObject['password'],
            'password_login': AccountObject.get('password_login', True),
            'groups_in': ['web'],
            'groups_out': []
        }

        if AccountObject.get('sftp_only', False):
            user_obj['groups_in'].append('sftponly')
            user_obj['shell'] = '/usr/sbin/nologin'
        else:
            user_obj['groups_out'].append('sftponly')
            user_obj['shell'] = '/bin/bash'

        if AccountObject['state'] == 'active':
            user_obj['expires'] = ''
        else:
            # account is either locked or suspended, in both cases we want to disable login
            user_obj['expires'] = '1'

        user = User(user_obj)
        # state is not deleted - it means account should exist
        if not user.exists():
            logger.info('Creating user: '******'s make sure it is exactly what it should be
            logger.info('Modifying user: '******'sftp_only', False):
            os.chown(user.info()[5], 0, user.info()[3])
            os.chmod(user.info()[5], 0750)
        else:
            os.chown(user.info()[5], user.info()[2], user.info()[3])

        # XATTRs - allow www-data to access userdir
        # setfacl -m u:www-data:rX /home/web34/
        basic.run_command('/bin/setfacl -m u:www-data:rX /home/' +
                          user.username)

        # Make sure domains directory exists
        library.basic.make_sure_path_exists(user.info()[5] + '/domains')
        os.chown(user.info()[5] + '/domains', user.info()[2], user.info()[3])
        os.chmod(user.info()[5] + '/domains', 0555)

    ############################### deal with vhosts ###############################
    # Delete all vhost configs
    existing_vhosts = os.listdir(config.LSWS_VHOST_DIR)
    for file in existing_vhosts:
        if re.compile('^' + user.username + '_(.*)\.xml$').match(file):
            os.remove(os.path.join(config.LSWS_VHOST_DIR, file))

    # load main LSWS config
    httpd_config = etree.parse(config.LSWS_CONFIG_PATH,
                               etree.XMLParser(remove_blank_text=True))
    # print etree.tostring(httpd_config, pretty_print=True)

    # Unbind all vhost configs
    for virtualHost in httpd_config.find('virtualHostList').findall(
            'virtualHost'):
        if re.compile('/' + user.username + '_(.*)\.xml$').match(
                virtualHost.find('configFile').text):
            httpd_config.find('virtualHostList').remove(virtualHost)

    if AccountObject['state'] not in ['suspended', 'deleted']:
        for vhost in AccountObject['vhosts']:
            # Create domain directory
            library.basic.make_sure_path_exists(user.info()[5] + '/domains/' +
                                                vhost['name'])
            os.chown(user.info()[5] + '/domains/' + vhost['name'],
                     user.info()[2],
                     user.info()[3])
            os.chmod(user.info()[5] + '/domains', 0555)

            # So called environment for jinja2 template
            vhost_data = {
                "username": user.username,
                "homedir": user.info()[5],
                "name": vhost['name'],
                "index_files": "index.php, index.html",
                "appmap": vhost['appmap']
            }
            with open(
                    config.LSWS_VHOST_DIR + user.username + '_' +
                    vhost['name'] + '.xml', 'w') as vhost_file:
                vhost_file.write(vhost_template.render(vhost_data))
                vhost_file.close()

            with open(
                    user.info()[5] + '/domains/' + vhost['name'] +
                    '/index.html', 'w') as vhost_file:
                vhost_file.write(index_template.render(vhost_data))
                vhost_file.close()
            os.chown(
                user.info()[5] + '/domains/' + vhost['name'] + '/index.html',
                user.info()[2],
                user.info()[3])
            os.chmod(
                user.info()[5] + '/domains/' + vhost['name'] + '/index.html',
                0644)

            # look for the vhost in config and remove it
            # xpath("//virtualHostList/virtualHost[name='".$vhost['domain']."']")
            for virtualHost in httpd_config.find('virtualHostList').findall(
                    'virtualHost'):
                #logger.info('Name: ' + virtualHost.find('name').text)
                if virtualHost.find('name').text == vhost['name']:
                    httpd_config.find('virtualHostList').remove(virtualHost)
                    #logger.info("removing vhost")

            # look for listener and remove it
            # $lshttpd_config->xpath("//vhostMap[vhost='".$vhost['domain']."']")
            for listener in httpd_config.find('listenerList').findall(
                    'listener'):
                for mapping in listener.find('vhostMapList').findall(
                        'vhostMap'):
                    if mapping.find('vhost').text == vhost['name']:
                        listener.find('vhostMapList').remove(mapping)
                        #logger.info("removing vhost")

            # add new vhost to the config file
            newVH = etree.fromstring('''
            <virtualHost>
                <name></name>
                <vhRoot></vhRoot>
                <configFile></configFile>
                <note/>
                <allowSymbolLink>2</allowSymbolLink>
                <enableScript>1</enableScript>
                <restrained>1</restrained>
                <maxKeepAliveReq/>
                <smartKeepAlive>1</smartKeepAlive>
                <setUIDMode>2</setUIDMode>
                <chrootMode>0</chrootMode>
                <chrootPath/>
                <staticReqPerSec/>
                <dynReqPerSec/>
                <outBandwidth/>
                <inBandwidth/>
            </virtualHost>
            ''')
            newVH.find('name').text = vhost['name']
            newVH.find(
                'vhRoot').text = user.info()[5] + '/domains/' + vhost['name']
            newVH.find(
                'configFile'
            ).text = config.LSWS_VHOST_DIR + user.username + '_' + vhost[
                'name'] + '.xml'
            newVH.find('note').text = user.username
            httpd_config.find('virtualHostList').append(newVH)

            # Add new vhost to the first listener available (this is stupid)
            # TODO: improve & SSL support
            newVHMapping = etree.fromstring('''
            <vhostMap>
              <vhost></vhost>
              <domain></domain>
            </vhostMap>
            ''')
            newVHMapping.find('vhost').text = vhost['name']
            newVHMapping.find('domain').text = ','.join(vhost['domains'])
            httpd_config.find('listenerList').find('listener').find(
                'vhostMapList').append(newVHMapping)

    ##### Delete obsolete domain directories under /domains #####
    try:
        current_domain_dirs = os.listdir(user.info()[5] + '/domains/')
        valid_domain_dirs = []
        for vhost in AccountObject['vhosts']:
            valid_domain_dirs.append(vhost['name'])

        for directory in list(
                set(current_domain_dirs) - set(valid_domain_dirs)):
            logger.info('Removing obsolete domain directory: ' + directory)
            shutil.rmtree(
                os.path.join(user.info()[5] + '/domains/', directory), True)
    except OSError:
        pass

    ############################### deal with apps ###############################
    # look for all apps of this user and delete them
    for oldapp in httpd_config.find('extProcessorList').findall(
            'extProcessor'):
        if re.compile('^' + user.username + '_').match(
                oldapp.find('name').text):
            httpd_config.find('extProcessorList').remove(oldapp)

    # look for all php ini dirs of this user and delete them
    for oldinidir in os.listdir('/opt/php/ini/'):
        if re.compile('^' + user.username + '_').match(oldinidir):
            shutil.rmtree(os.path.join('/opt/php/ini/', oldinidir), True)

    # add apps for this user
    if AccountObject['state'] not in ['suspended', 'deleted']:
        for app in AccountObject['apps']:
            if app['type'] != 'php':
                raise Exception('Unrecognized app type: ' + app['type'])

            newProcessor = etree.fromstring('''
            <extProcessor>
                <type>lsapi</type>
                <name>lsphp5_...</name>
                <address>uds://tmp/lshttpd/somethinghere.sock</address>
                <note/>
                <maxConns>10</maxConns>
                <env>PHP_LSAPI_MAX_REQUESTS=500</env>
                <env>PHP_LSAPI_CHILDREN=10</env>
                <env>LSAPI_AVOID_FORK=1</env>
                <env>LSAPI_MAX_IDLE=300</env>
                <env>LSAPI_ACCEPT_NOTIFY=0</env>
                <env>PHP_INI_SCAN_DIR=/opt/php/ini/''' + user.username + '_' +
                                            strtosafe(app['name']) + '''</env>
                <initTimeout>60</initTimeout>
                <retryTimeout>0</retryTimeout>
                <persistConn>1</persistConn>
                <pcKeepAliveTimeout/>
                <respBuffer>0</respBuffer>
                <autoStart>1</autoStart>
                <path>/opt/php/php-5.4.15/bin/lsphp</path>
                <backlog>10</backlog>
                <instances>1</instances>
                <extUser>someuser</extUser>
                <extGroup>somegrup</extGroup>
                <runOnStartUp/>
                <extMaxIdleTime>-1</extMaxIdleTime>
                <priority>0</priority>
                <memSoftLimit>6G</memSoftLimit>
                <memHardLimit>8G</memHardLimit>
                <procSoftLimit>800</procSoftLimit>
                <procHardLimit>1000</procHardLimit>
            </extProcessor>
            ''')

            newProcessor.find('name').text = user.username + '_' + strtosafe(
                app['name'])
            newProcessor.find(
                'address'
            ).text = 'uds://tmp/lshttpd/lsphp5_' + user.username + '_' + strtosafe(
                app['name']) + '.sock'
            newProcessor.find('path').text = '/opt/php/php-5.5/bin/lsphp'
            newProcessor.find('extUser').text = user.username
            newProcessor.find('extGroup').text = user.username
            if not os.path.isfile('/opt/php/php-' + app['version'] +
                                  '/bin/lsphp'):
                raise Exception('PHP version ' + app['version'] +
                                ' is not available on this server.')
            newProcessor.find(
                'path').text = '/opt/php/php-' + app['version'] + '/bin/lsphp'
            httpd_config.find('extProcessorList').append(newProcessor)

            # install Pecl extensions

            # install PEAR stuff

            # Save php.ini
            library.basic.make_sure_path_exists('/opt/php/ini/' +
                                                user.username + '_' +
                                                strtosafe(app['name']))
            os.chown(
                '/opt/php/ini/' + user.username + '_' + strtosafe(app['name']),
                0,
                user.info()[3])
            os.chmod(
                '/opt/php/ini/' + user.username + '_' + strtosafe(app['name']),
                0750)
            ini = ConfigParser.ConfigParser()
            for setting in app['ini']:
                if setting['section'].upper() == 'DEFAULT':
                    setting['section'] = 'PHP'
                try:
                    ini.add_section(setting['section'])
                except DuplicateSectionError:
                    pass
                ini.set(setting['section'], setting['name'], setting['value'])

            with open(
                    '/opt/php/ini/' + user.username + '_' +
                    strtosafe(app['name']) + '/php.ini', 'w') as inifile:
                ini.write(inifile)

    #### End of LSWS operations ####
    # save global config
    httpd_config.write(config.LSWS_CONFIG_PATH,
                       xml_declaration=True,
                       pretty_print=True,
                       encoding="UTF-8")
    # restart LSWS
    if os.path.isfile('/tmp/lshttpd/lshttpd.pid'):
        basic.run_command(
            '/bin/kill -USR1 `/bin/cat /tmp/lshttpd/lshttpd.pid`')
    else:
        logger.warn('Not restarting LSWS - not running.')

    ############################### MySQL ###############################
    # deal with databases
    mm = MySQLManager()
    current_user_dbs = []
    for db in mm.db_list():
        if re.compile('^' + user.username + '_').match(db):
            current_user_dbs.append(db)

    user_dbs = []
    for db in AccountObject['mysqldbs']:
        user_dbs.append(user.username + '_' + db['name'])

    if AccountObject['state'] not in ['deleted']:
        dbs_to_delete = set(current_user_dbs) - set(user_dbs)
        for db in dbs_to_delete:
            mm.db_delete(db)
            logger.info('Deleted database ' + db)

        for db in AccountObject['mysqldbs']:
            if user.username + '_' + db['name'] not in current_user_dbs:
                mm.db_create(user.username + '_' + db['name'], 'utf8')
                logger.info('Creating database ' + db['name'])
    else:
        # delete all databases
        for db in current_user_dbs:
            mm.db_delete(db)
            logger.info('Deleted database ' + db)

    # deal with users
    current_user_users = mm.user_find_like(
        user.username + '_%')  # ((user, host), (user, host)...)
    if AccountObject['state'] not in ['deleted']:
        for u in current_user_users:
            if u[0] not in user_dbs:
                mm.user_delete(u[0], u[1])
                logger.info('Deleted %s @ %s', (u[0], u[1]))

        for u in AccountObject['mysqldbs']:
            privs = mm.privileges_unpack(user.username + '_' + u['name'] +
                                         '.*:ALL')
            if not mm.user_exists(user.username + '_' + u['name'], '%'):
                mm.user_add(user.username + '_' + u['name'], '%',
                            u['password'], privs)
            else:
                mm.user_mod(user.username + '_' + u['name'], '%',
                            u['password'], privs)
    else:
        for u in current_user_users:
            mm.user_delete(u[0], u[1])
            logger.info('Deleted %s @ %s', (u[0], u[1]))
Пример #4
0
def create(self, **UserOptions):
    user_obj = {
        'username': UserOptions['username'],
        'password': UserOptions['password'],
        'password_login': UserOptions.get('password_login', True),
        'groups_in': ['web'],
        'groups_out': []
    }

    user = User(user_obj)

    if UserOptions['state'] not in ['suspended', 'terminated']:
        for vhost in UserOptions['vhosts']:
            # Create domain directory
            basic.ensure_path(user.info()[5] + '/domains/' + vhost['name'] +
                              '/public_html')
            basic.rec_chown(user.info()[5] + '/domains/' + vhost['name'],
                            user.info()[2],
                            user.info()[3])
            os.chmod(user.info()[5] + '/domains', 0555)

            # So called environment for jinja2 template
            vhost_data = {
                'username': user.username,
                'homedir': user.info()[5],
                'name': vhost['name'],
                'domains': vhost['domains'],
                'rewrite_catchall': vhost.get('rewrite_catchall', '=404'),
                'ssl': UserOptions.get('ssl', False)
            }

            with open(
                    vhost_dir + user.username + '_' + vhost['name'] + '.conf',
                    'w') as f:
                f.write(vhost_template.render(vhost_data))

            if not os.path.exists(user.info()[5] + '/domains/' +
                                  vhost['name'] + '/public_html/index.php'):
                with open(
                        user.info()[5] + '/domains/' + vhost['name'] +
                        '/public_html/index.php', 'w') as f:
                    f.write(index_template.render(vhost_data))

            os.chown(
                user.info()[5] + '/domains/' + vhost['name'] +
                '/public_html/index.php',
                user.info()[2],
                user.info()[3])
            os.chmod(
                user.info()[5] + '/domains/' + vhost['name'] +
                '/public_html/index.php', 0644)
            """
            if vhost.get('ssl', False):
                with open('/etc/nginx/ssl/' + vhost['name'] + '.pem', 'w') as f:
                    f.write(vhost.get('ssl_pem'))
                os.chmod('/etc/nginx/ssl/' + vhost['name'] + '.pem', 0600)

                with open('/etc/nginx/ssl/' + vhost['name'] + '.key', 'w') as f:
                    f.write(vhost.get('ssl_key'))
                os.chmod('/etc/nginx/ssl/' + vhost['name'] + '.key', 0600)
            """

            if UserOptions.get('ssl', False):
                with open('/etc/nginx/ssl/' + vhost['name'] + '.pem',
                          'w') as f:
                    f.write(UserOptions.get('ssl_pem'))
                os.chmod('/etc/nginx/ssl/' + vhost['name'] + '.pem', 0600)

                with open('/etc/nginx/ssl/' + vhost['name'] + '.key',
                          'w') as f:
                    f.write(UserOptions.get('ssl_key'))
                os.chmod('/etc/nginx/ssl/' + vhost['name'] + '.key', 0600)

            try:
                basic.run_command('/usr/sbin/nginx -t')
            except Exception:
                os.remove(vhost_dir + user.username + '_' + vhost['name'] +
                          '.conf')
                raise

        basic.run_command('/usr/sbin/nginx -s reload')

    # XATTRs - allow www-data to access userdir
    # setfacl -m u:www-data:rX /home/web34/
    basic.run_command('/bin/setfacl -m u:www-data:rX /home/' + user.username)

    # Make sure domains directory exists
    basic.ensure_path(user.info()[5] + '/domains')
    os.chown(user.info()[5] + '/domains', user.info()[2], user.info()[3])
    os.chmod(user.info()[5] + '/domains', 0555)