Ejemplo n.º 1
0
def ensure_postgresql_db(db_name='wapt',db_owner='wapt',db_password=''):
    """ create postgresql wapt db and user if it does not exists """
    if type_redhat():
        # we have to check what postgres we use between the upstream packages and the software collection ones
        pass
    elif type_debian():
        run('systemctl start postgresql')
        run('systemctl enable postgresql')

    val = run(""" sudo -u postgres psql template1 -c " select usename from pg_catalog.pg_user where usename='wapt';"  """, cwd='/opt/wapt')
    if 'wapt' in val:
        print ("user wapt already exists, skipping creating user  ")
    else:
        print ("we suppose that the db does not exist either (or the installation has been screwed up")
        if not db_password:
            run(""" sudo -u postgres psql template1 -c "create user %s ; " """ % (db_owner), cwd='/opt/wapt/')
        else:
            run(""" sudo -u postgres psql template1 -c "create user %s with password '%s'; " """ % (db_owner,db_password), cwd='/opt/wapt/')

    val = ''
    #val = subprocess.check_output(""" sudo -u postgres psql template1 -c "select schema_name from information_schema.schemata where schema_name='wapt'; "  """, shell= True)
    val = run(""" sudo -u postgres psql template1 -c " SELECT datname FROM pg_database WHERE datname='wapt';   " """, cwd='/opt/wapt/')

    if 'wapt' in val:
        print ("db already exists, skipping db creation")
    else:
        print ('creating db wapt')
        run(""" sudo -u postgres psql template1 -c "create database %s with owner=%s encoding='utf-8'; " """ % (db_name,db_owner), cwd='/opt/wapt/')

    # check if hstore (for json) is installed
    val = run(""" sudo -u postgres psql wapt -c "select * from pg_extension where extname='hstore';" """, cwd='/opt/wapt/')
    if 'hstore' in val:
        print ("hstore extension already loading into database, skipping create extension")
    else:
        run("""  sudo -u postgres psql wapt -c "CREATE EXTENSION hstore;" """, cwd='/opt/wapt/')
Ejemplo n.º 2
0
def setup_firewall():
    """ Add permanent rules for firewalld """
    if type_redhat():
        output = run('firewall-cmd --list-ports')
        if '443/tcp' in output and '80/tcp' in output:
            print("[*] Firewall already configured, skipping firewalld configuration")
        elif subprocess.call(['firewall-cmd', '--state'], stdout=open(os.devnull, 'w')) == 0:
            run('firewall-cmd --permanent --add-port=443/tcp')
            run('firewall-cmd --permanent --add-port=80/tcp')
            run('firewall-cmd --reload')
        else:
            run('firewall-offline-cmd --add-port=443/tcp')
            run('firewall-offline-cmd --add-port=80/tcp')
Ejemplo n.º 3
0
def setup_firewall():
    """ Add permanent rules for firewalld """
    if type_redhat():
        output = run('firewall-cmd --list-ports')
        if '443/tcp' in output and '80/tcp' in output:
            print("[*] Firewall already configured, skipping firewalld configuration")
            return
        if subprocess.call(['firewall-cmd', '--state'], stdout=open(os.devnull, 'w')) == 0:
            run('firewall-cmd --permanent --add-port=443/tcp')
            run('firewall-cmd --permanent --add-port=80/tcp')
            run('firewall-cmd --reload')
        else:
            run('firewall-offline-cmd --add-port=443/tcp')
            run('firewall-offline-cmd --add-port=80/tcp')
Ejemplo n.º 4
0
def main():
    global wapt_folder, NGINX_GID

    parser = OptionParser(usage=usage, version=__version__)
    parser.add_option('-c',
                      '--config',
                      dest='configfile',
                      default=waptserver.config.DEFAULT_CONFIG_FILE,
                      help='Config file full path (default: %default)')
    parser.add_option(
        "-s",
        "--force-https",
        dest="force_https",
        default=False,
        action='store_true',
        help=
        "Use https only, http is 301 redirected to https (default: False). Requires a proper DNS name"
    )
    parser.add_option(
        '-q',
        '--quiet',
        dest='quiet',
        default=False,
        action="store_true",
        help=
        'Run quiet postconfiguration - default password and simple behavior')

    (options, args) = parser.parse_args()

    quiet = options.quiet

    if not quiet:
        if postconf.yesno("Do you want to launch post configuration tool ?"
                          ) != postconf.DIALOG_OK:
            print("canceling wapt postconfiguration")
            sys.exit(1)
    else:
        print('WAPT silent post-configuration')

    # SELinux rules for CentOS/RedHat
    if type_redhat():
        if re.match('^SELinux status:.*enabled', run('sestatus')):
            if not quiet:
                postconf.msgbox(
                    'SELinux detected, tweaking httpd permissions.')
                selinux_rules()
                postconf.msgbox(
                    'SELinux correctly configured for Nginx reverse proxy')
            else:
                print('[*] Redhat/Centos detected, tweaking SELinux rules')
                selinux_rules()
                print(
                    '[*] Nginx - SELinux correctly configured for Nginx reverse proxy'
                )

    # Load existing config file
    server_config = waptserver.config.load_config(options.configfile)

    if os.path.isfile(options.configfile):
        print('[*] Making a backup copy of the configuration file')
        datetime_now = datetime.datetime.now()
        shutil.copyfile(
            options.configfile,
            '%s.bck_%s' % (options.configfile, datetime_now.isoformat()))

    wapt_folder = server_config['wapt_folder']

    # add secret key initialisation string (for session token)
    if not server_config['secret_key']:
        server_config['secret_key'] = ''.join(
            random.SystemRandom().choice(string.letters + string.digits)
            for _ in range(64))

    # add user db and password in ini file
    if server_config['db_host'] in (None, '', 'localhost', '127.0.0.1', '::1'):
        ensure_postgresql_db(db_name=server_config['db_name'],
                             db_owner=server_config['db_name'],
                             db_password=server_config['db_password'])

    # Password setup/reset screen
    if not quiet:
        if not server_config['wapt_password'] or \
                postconf.yesno("Do you want to reset admin password ?",yes_label='skip',no_label='reset') != postconf.DIALOG_OK:
            wapt_password_ok = False
            while not wapt_password_ok:
                wapt_password = ''
                wapt_password_check = ''

                while wapt_password == '':
                    (code, wapt_password) = postconf.passwordbox(
                        "Please enter the wapt server password (min. 10 characters):  ",
                        insecure=True,
                        width=100)
                    if code != postconf.DIALOG_OK:
                        exit(0)

                while wapt_password_check == '':
                    (code, wapt_password_check) = postconf.passwordbox(
                        "Please enter the wapt server password again:  ",
                        insecure=True,
                        width=100)
                    if code != postconf.DIALOG_OK:
                        exit(0)

                if wapt_password != wapt_password_check:
                    postconf.msgbox('Password mismatch !')
                elif len(wapt_password) < 10:
                    postconf.msgbox(
                        'Password must be at least 10 characters long !')
                else:
                    wapt_password_ok = True

            password = pbkdf2_sha256.hash(wapt_password.encode('utf8'))
            server_config['wapt_password'] = password
    else:
        wapt_password = ''
        if not server_config['wapt_password']:
            print('[*] Generating random password for WAPT server')
            wapt_password = pwd.genword(entropy=56, charset="ascii_62")
            print('[*] WAPT admin password : %s' % wapt_password)
            password = pbkdf2_sha256.hash(wapt_password.encode('utf8'))
            server_config['wapt_password'] = password

    if not server_config['server_uuid']:
        server_config['server_uuid'] = str(uuid.uuid1())

    # waptagent authentication method
    if not quiet:
        choices = [
            ("1",
             "Allow unauthenticated registration, same behavior as WAPT 1.3",
             True),
            ("2",
             "Enable kerberos authentication required for machines registration",
             False),
            ("3",
             "Disable Kerberos but registration require strong authentication",
             False),
        ]

        code, t = postconf.radiolist("WaptAgent Authentication type?",
                                     choices=choices,
                                     width=120)
        if code == 'cancel':
            print("\n\npostconfiguration canceled\n\n")
            sys.exit(1)
        if t == "1":
            server_config['allow_unauthenticated_registration'] = True
            server_config['use_kerberos'] = False
        if t == "2":
            server_config['allow_unauthenticated_registration'] = False
            server_config['use_kerberos'] = True
        if t == "3":
            server_config['allow_unauthenticated_registration'] = False
            server_config['use_kerberos'] = False
    else:
        print(
            '[*] Set default registration method to : Allow anyone to register + Kerberos disabled'
        )
        server_config['allow_unauthenticated_registration'] = True
        server_config['use_kerberos'] = False

    # Guess fqdn using socket
    fqdn = guess_fqdn()

    clients_signing_certificate = server_config.get(
        'clients_signing_certificate')
    clients_signing_key = server_config.get('clients_signing_key')
    clients_signing_crl = server_config.get('clients_signing_crl')

    if not clients_signing_certificate or not clients_signing_key:
        clients_signing_certificate = os.path.join(wapt_root_dir, 'conf',
                                                   'ca-%s.crt' % fqdn)
        clients_signing_key = os.path.join(wapt_root_dir, 'conf',
                                           'ca-%s.pem' % fqdn)

        server_config[
            'clients_signing_certificate'] = clients_signing_certificate
        server_config['clients_signing_key'] = clients_signing_key

    if clients_signing_certificate is not None and clients_signing_key is not None and not os.path.isfile(
            clients_signing_certificate):
        print('Create a certificate and key for clients certificate signing')

        key = SSLPrivateKey(clients_signing_key)
        if not os.path.isfile(clients_signing_key):
            print('Create SSL RSA Key %s' % clients_signing_key)
            key.create()
            key.save_as_pem()

        crt = key.build_sign_certificate(cn=fqdn,
                                         is_code_signing=False,
                                         is_ca=True)
        print('Create X509 cert %s' % clients_signing_certificate)
        crt.save_as_pem(clients_signing_certificate)

    if clients_signing_certificate is not None and clients_signing_key is not None and clients_signing_crl is not None and not os.path.isfile(
            clients_signing_crl):
        print('Create a CRL for clients certificate signing')
        key = SSLPrivateKey(clients_signing_key)
        crt = SSLCertificate(clients_signing_certificate)
        crl = SSLCRL(clients_signing_crl, cacert=crt, cakey=key)
        crl.revoke_cert()
        crl.save_as_pem()

    waptserver.config.write_config_file(cfgfile=options.configfile,
                                        server_config=server_config,
                                        non_default_values_only=True)

    print('[*] Protecting WAPT config file')
    run("/bin/chmod 640 %s" % options.configfile)
    run("/bin/chown wapt %s" % options.configfile)

    print('[*] Update WAPT repository')
    repo = WaptLocalRepo(wapt_folder)
    repo.update_packages_index(force_all=True)

    final_msg = [
        '[*] Postconfiguration completed.',
    ]
    if not quiet:
        postconf.msgbox("Press ok to start waptserver and wapttasks daemons")
    enable_waptserver()
    start_waptserver()

    # In this new version Apache is replaced with Nginx? Proceed to disable Apache. After migration one can remove Apache install altogether
    stop_disable_httpd()

    # Nginx configuration
    if quiet:
        try:
            generate_dhparam()
            nginx_cleanup()
            make_httpd_config('/opt/wapt/waptserver', fqdn,
                              options.force_https, server_config)
            enable_nginx()
            restart_nginx()
            setup_firewall()
        except subprocess.CalledProcessError as cpe:
            final_msg += [
                'Error while trying to configure Nginx!',
                'errno = ' + str(cpe.returncode) + ', output: ' + cpe.output
            ]
        except Exception as e:
            import traceback
            final_msg += [
                'Error while trying to configure Nginx!',
                traceback.format_exc()
            ]
    else:
        reply = postconf.yesno("Do you want to configure nginx?")
        if reply == postconf.DIALOG_OK:
            try:
                msg = 'FQDN for the WAPT server (eg. wapt.acme.com)'
                (code, reply) = postconf.inputbox(text=msg,
                                                  width=len(msg) + 4,
                                                  init=fqdn)
                if code != postconf.DIALOG_OK:
                    exit(1)
                else:
                    fqdn = reply

                generate_dhparam()
                nginx_cleanup()

                if server_config['use_kerberos']:
                    if type_debian():
                        if not check_if_deb_installed(
                                'libnginx-mod-http-auth-spnego'):
                            print(
                                '[*] Nginx - Missing dependency libnginx-mod-http-auth-spnego, please install first before configuring kerberos'
                            )
                            sys.exit(1)

                make_httpd_config('/opt/wapt/waptserver', fqdn,
                                  options.force_https, server_config)
                final_msg.append('Please connect to https://' + fqdn +
                                 '/ to access the server.')
                postconf.msgbox(
                    "The Nginx config is done. We need to restart Nginx?")
                run_verbose('systemctl enable nginx')
                run_verbose('systemctl restart nginx')
                setup_firewall()

            except subprocess.CalledProcessError as cpe:
                final_msg += [
                    'Error while trying to configure Nginx!', 'errno = ' +
                    str(cpe.returncode) + ', output: ' + cpe.output
                ]
            except Exception as e:
                import traceback
                final_msg += [
                    'Error while trying to configure Nginx!',
                    traceback.format_exc()
                ]

    # known certificates
    ssl_dir = server_config['known_certificates_folder']
    if not os.path.isdir(ssl_dir):
        # move existing ssl dir in wapt repo to parent dir (default location)
        if os.path.isdir(os.path.join(server_config['wapt_folder'], 'ssl')):
            shutil.move(os.path.join(server_config['wapt_folder'], 'ssl'),
                        ssl_dir)
        else:
            os.makedirs(ssl_dir)

    #Migrate file for new version waptwua
    wuafolder = server_config['waptwua_folder']
    for (root, dirs, files) in list(os.walk(wuafolder, topdown=False)):
        if root == os.path.join(wuafolder, '.stfolder'):
            continue
        for f in files:
            oldpath = os.path.join(root, f)
            newpath = os.path.join(wuafolder, f)
            if os.path.isfile(newpath):
                continue
            print('Move %s --> %s' % (oldpath, newpath))
            shutil.move(oldpath, newpath)
        for d in dirs:
            if d == '.stfolder':
                continue
            print('Delete folder %s' % os.path.join(root, d))
            shutil.rmtree(os.path.join(root, d))

    final_msg.append('Please connect to https://' + fqdn +
                     '/ to access the server.')

    # Check if Mongodb > PostgreSQL migration is necessary
    if not quiet:
        if check_mongo2pgsql_upgrade_needed(options.configfile) and\
                postconf.yesno("It is necessary to migrate current database backend from mongodb to postgres. Press yes to start migration",no_label='cancel') == postconf.DIALOG_OK:
            upgrade2postgres(options.configfile)
    else:
        if check_mongo2pgsql_upgrade_needed(options.configfile):
            upgrade2postgres(options.configfile)

    WAPT_UID = good_pwd.getpwnam('wapt').pw_uid

    # CHOWN of waptservertasks.sqlite it seems to be created before

    location_waptservertasks = os.path.join(wapt_root_dir, 'db',
                                            'waptservertasks.sqlite')

    if os.path.isfile(location_waptservertasks):
        os.chown(location_waptservertasks, WAPT_UID,
                 os.stat(location_waptservertasks).st_gid)

    # Create empty sync.json and rules.json file for all installations

    sync_json = os.path.join(
        os.path.abspath(os.path.join(wapt_folder, os.pardir)), u'sync.json')
    rules_json = os.path.join(
        os.path.abspath(os.path.join(wapt_folder, os.pardir)), u'rules.json')

    diff_rules_dir = wapt_folder + u'-diff-repos/'

    paths_to_modify = [
        sync_json, rules_json, wapt_folder + '/', wuafolder + '/',
        diff_rules_dir, ssl_dir + '/'
    ]

    for apath in paths_to_modify:
        if os.path.isdir(apath):
            os.chown(apath, WAPT_UID, NGINX_GID)
            os.chmod(apath, 0o750)
            for root, dirs, files in os.walk(apath):
                for d in dirs:
                    full_path = os.path.join(root, d)
                    os.chown(full_path, WAPT_UID, NGINX_GID)
                    os.chmod(full_path, 0o750)
                for f in files:
                    full_path = os.path.join(root, f)
                    os.chown(full_path, WAPT_UID, NGINX_GID)
                    os.chmod(full_path, 0o640)
        else:
            if apath.endswith('/'):
                os.mkdir(apath)
                os.chmod(apath, 0o750)
            else:
                if not (os.path.isfile(apath)):
                    with open(apath, 'w'):
                        pass
                os.chmod(apath, 0o640)
            os.chown(apath, WAPT_UID, NGINX_GID)

    # Final message
    if not quiet:
        width = 4 + max(10, len(max(final_msg, key=len)))
        height = 2 + max(20, len(final_msg))
        postconf.msgbox('\n'.join(final_msg), height=height, width=width)
    else:
        if wapt_password:
            final_msg.append('[*] WAPT admin password : %s\n' % wapt_password)
        for line in final_msg:
            print(line)
Ejemplo n.º 5
0
def make_httpd_config(waptserver_root_dir, fqdn, force_https, server_config):
    ssl_dir = os.path.join(waptserver_root_dir, 'ssl')
    scripts_dir = os.path.join(waptserver_root_dir, 'scripts')
    wapt_ssl_key_file = os.path.join(ssl_dir, 'key.pem')
    wapt_ssl_cert_file = os.path.join(ssl_dir, 'cert.pem')
    mkdir(ssl_dir)

    # write the apache configuration fragment
    jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(scripts_dir))
    template = jinja_env.get_template('wapt.nginxconfig.template')
    krb5_realm = '.'.join(fqdn.split('.')[1:]).upper()

    template_vars = {
        'waptserver_port':
        server_config['waptserver_port'],
        'wapt_repository_path':
        os.path.dirname(server_config['wapt_folder']),
        'windows':
        False,
        'debian':
        type_debian(),
        'redhat':
        type_redhat(),
        'force_https':
        force_https,
        'wapt_ssl_key_file':
        wapt_ssl_key_file,
        'wapt_ssl_cert_file':
        wapt_ssl_cert_file,
        'fqdn':
        fqdn,
        'use_kerberos':
        server_config.get('use_kerberos', False),
        'KRB5_REALM':
        krb5_realm,
        'wapt_root_dir':
        wapt_root_dir,
        'use_ssl_client_auth':
        server_config.get('use_ssl_client_auth', False),
        'clients_signing_certificate':
        server_config.get('clients_signing_certificate'),
        'known_certificates_folder':
        server_config.get('known_certificates_folder', None),
        'clients_signing_crl':
        server_config.get('clients_signing_crl', None),
        'htpasswd_path':
        server_config.get('htpasswd_path', None),
    }

    if quiet:
        print('[*] Nginx - creating wapt.conf virtualhost')

    config_string = template.render(template_vars)
    if type_debian():
        dst_file = file('/etc/nginx/sites-available/wapt.conf', 'wt')
        if not os.path.exists('/etc/nginx/sites-enabled/wapt.conf'):
            print(
                subprocess.check_output(
                    'ln -s /etc/nginx/sites-available/wapt.conf /etc/nginx/sites-enabled/wapt.conf',
                    shell=True))
        if os.path.exists('/etc/nginx/sites-enabled/default'):
            os.unlink('/etc/nginx/sites-enabled/default')

    elif type_redhat():
        dst_file = file('/etc/nginx/conf.d/wapt.conf', 'wt')
    dst_file.write(config_string)
    dst_file.close()

    # create keys for https:// access
    if not os.path.exists(wapt_ssl_key_file) or \
            not os.path.exists(wapt_ssl_cert_file):
        if quiet:
            print('[*] Nginx - generate self-signed certs')
        old_apache_key = '/opt/wapt/waptserver/apache/ssl/key.pem'
        old_apache_cert = '/opt/wapt/waptserver/apache/ssl/cert.pem'

        if os.path.isfile(old_apache_cert) and os.path.isfile(old_apache_key):
            shutil.copyfile(old_apache_cert, wapt_ssl_cert_file)
            shutil.copyfile(old_apache_key, wapt_ssl_key_file)

        else:
            key = SSLPrivateKey(wapt_ssl_key_file)
            if not os.path.isfile(wapt_ssl_key_file):
                print('Create SSL RSA Key %s' % wapt_ssl_key_file)
                key.create()
                key.save_as_pem()

            if os.path.isfile(wapt_ssl_cert_file):
                crt = SSLCertificate(wapt_ssl_cert_file)
                if crt.cn != fqdn:
                    shutil.move(
                        wapt_ssl_cert_file, "%s-%s.old" %
                        (wapt_ssl_cert_file, '{:%Y%m%d-%Hh%Mm%Ss}'.format(
                            datetime.datetime.now())))
                    crt = key.build_sign_certificate(cn=fqdn,
                                                     dnsname=fqdn,
                                                     is_code_signing=False)
                    print('Create X509 cert %s' % wapt_ssl_cert_file)
                    crt.save_as_pem(wapt_ssl_cert_file)
            else:
                crt = key.build_sign_certificate(cn=fqdn,
                                                 dnsname=fqdn,
                                                 is_code_signing=False)
                print('Create X509 cert %s' % wapt_ssl_cert_file)
                crt.save_as_pem(wapt_ssl_cert_file)

    else:
        if quiet:
            print('[*] Nginx - self-signed certs already exists, skipping...')
Ejemplo n.º 6
0
    return subprocess.check_output(*args, shell=True, **kwargs)


def run_verbose(*args, **kwargs):
    output = subprocess.check_output(*args, shell=True, **kwargs)
    print(output)
    return output


if type_debian():
    MONGO_SVC = 'mongodb'
    APACHE_SVC = 'apache2'
    PGSQL_SVC = 'postgresql'
    wapt_folder = '/var/www/wapt'
    NGINX_GID = grp.getgrnam('www-data').gr_gid
elif type_redhat():
    MONGO_SVC = 'mongod'
    APACHE_SVC = 'httpd'
    PGSQL_SVC = 'postgresql-9.6'
    wapt_folder = '/var/www/html/wapt'
    NGINX_GID = grp.getgrnam('nginx').gr_gid
else:
    print("distrib type unknown")
    sys.exit(1)

quiet = False
postconf = dialog.Dialog(dialog="dialog")


def mkdir(path):
    if not os.path.isdir(path):
Ejemplo n.º 7
0
def make_httpd_config(waptserver_root_dir, fqdn, force_https, server_config):
    ssl_dir = os.path.join(waptserver_root_dir, 'ssl')
    scripts_dir = os.path.join(waptserver_root_dir, 'scripts')
    wapt_ssl_key_file = os.path.join(ssl_dir,'key.pem')
    wapt_ssl_cert_file = os.path.join(ssl_dir,'cert.pem')
    mkdir(ssl_dir)

    # write the apache configuration fragment
    jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(scripts_dir))
    template = jinja_env.get_template('wapt.nginxconfig.template')
    krb5_realm = '.'.join(fqdn.split('.')[1:]).upper()

    template_vars = {
        'waptserver_port': server_config['waptserver_port'],
        'wapt_repository_path': os.path.dirname(server_config['wapt_folder']),
        'windows': False,
        'debian': type_debian(),
        'redhat': type_redhat(),
        'force_https': force_https,
        'wapt_ssl_key_file': wapt_ssl_key_file,
        'wapt_ssl_cert_file': wapt_ssl_cert_file,
        'fqdn': fqdn,
        'use_kerberos': server_config.get('use_kerberos',False),
        'KRB5_REALM': krb5_realm,
        'wapt_root_dir': wapt_root_dir,
        'clients_signing_certificate' : server_config.get('clients_signing_certificate'),
        'use_ssl_client_auth' : server_config.get('use_ssl_client_auth',False)
        }

    if quiet:
        print('[*] Nginx - creating wapt.conf virtualhost')

    config_string = template.render(template_vars)
    if type_debian():
        dst_file = file('/etc/nginx/sites-available/wapt.conf', 'wt')
        if not os.path.exists('/etc/nginx/sites-enabled/wapt.conf'):
            print(subprocess.check_output('ln -s /etc/nginx/sites-available/wapt.conf /etc/nginx/sites-enabled/wapt.conf',shell=True))
        if os.path.exists('/etc/nginx/sites-enabled/default'):
            os.unlink('/etc/nginx/sites-enabled/default')

    elif type_redhat():
        dst_file = file('/etc/nginx/conf.d/wapt.conf', 'wt')
    dst_file.write(config_string)
    dst_file.close()

    # create keys for https:// access
    if not os.path.exists(wapt_ssl_key_file) or \
            not os.path.exists(wapt_ssl_cert_file):
        if quiet:
            print('[*] Nginx - generate self-signed certs')
        old_apache_key = '/opt/wapt/waptserver/apache/ssl/key.pem'
        old_apache_cert = '/opt/wapt/waptserver/apache/ssl/cert.pem'

        if os.path.isfile(old_apache_cert) and os.path.isfile(old_apache_key):
            shutil.copyfile(old_apache_cert,wapt_ssl_cert_file)
            shutil.copyfile(old_apache_key,wapt_ssl_key_file)

        else:
            key = SSLPrivateKey(wapt_ssl_key_file)
            if not os.path.isfile(wapt_ssl_key_file):
                print('Create SSL RSA Key %s' % wapt_ssl_key_file)
                key.create()
                key.save_as_pem()

            if os.path.isfile(wapt_ssl_cert_file):
                crt = SSLCertificate(wapt_ssl_cert_file)
                if crt.cn != fqdn:
                    os.rename(wapt_ssl_cert_file,"%s-%s.old" % (wapt_ssl_cert_file,'{:%Y%m%d-%Hh%Mm%Ss}'.format(datetime.datetime.now())))
                    crt = key.build_sign_certificate(cn=fqdn,dnsname=fqdn,is_code_signing=False)
                    print('Create X509 cert %s' % wapt_ssl_cert_file)
                    crt.save_as_pem(wapt_ssl_cert_file)
            else:
                crt = key.build_sign_certificate(cn=fqdn,dnsname=fqdn,is_code_signing=False)
                print('Create X509 cert %s' % wapt_ssl_cert_file)
                crt.save_as_pem(wapt_ssl_cert_file)


    else:
        if quiet:
	        print('[*] Nginx - self-signed certs already exists, skipping...')
Ejemplo n.º 8
0
def main():
    global wapt_folder,NGINX_GID

    parser = OptionParser(usage=usage, version=__version__)
    parser.add_option(
        '-c',
        '--config',
        dest='configfile',
        default=waptserver.config.DEFAULT_CONFIG_FILE,
        help='Config file full path (default: %default)')
    parser.add_option(
        "-s",
        "--force-https",
        dest="force_https",
        default=False,
        action='store_true',
        help="Use https only, http is 301 redirected to https (default: False). Requires a proper DNS name")
    parser.add_option(
        '-q',
        '--quiet',
        dest='quiet',
        default=False,
        action="store_true",
        help='Run quiet postconfiguration - default password and simple behavior')

    (options, args) = parser.parse_args()

    quiet = options.quiet

    if not quiet:
        if postconf.yesno("Do you want to launch post configuration tool ?") != postconf.DIALOG_OK:
            print "canceling wapt postconfiguration"
            sys.exit(1)
    else:
        print('WAPT silent post-configuration')

    # SELinux rules for CentOS/RedHat
    if type_redhat():
        if re.match('^SELinux status:.*enabled', run('sestatus')):
            if not quiet:
                postconf.msgbox('SELinux detected, tweaking httpd permissions.')
                selinux_rules()
                postconf.msgbox('SELinux correctly configured for Nginx reverse proxy')
            else:
                print('[*] Redhat/Centos detected, tweaking SELinux rules')
                selinux_rules()
                print('[*] Nginx - SELinux correctly configured for Nginx reverse proxy')

    # Load existing config file
    server_config = waptserver.config.load_config(options.configfile)

    if os.path.isfile(options.configfile):
        print('[*] Making a backup copy of the configuration file')
        datetime_now = datetime.datetime.now()
        shutil.copyfile(options.configfile,'%s.bck_%s'%  (options.configfile,datetime_now.isoformat()) )

    wapt_folder = server_config['wapt_folder']

    # add secret key initialisation string (for session token)
    if not server_config['secret_key']:
        server_config['secret_key'] = ''.join(random.SystemRandom().choice(string.letters + string.digits) for _ in range(64))

    # add user db and password in ini file
    if server_config['db_host'] in (None,'','localhost','127.0.0.1','::1'):
        ensure_postgresql_db(db_name=server_config['db_name'],db_owner=server_config['db_name'],db_password=server_config['db_password'])

    # Password setup/reset screen
    if not quiet:
        if not server_config['wapt_password'] or \
                postconf.yesno("Do you want to reset admin password ?",yes_label='skip',no_label='reset') != postconf.DIALOG_OK:
            wapt_password_ok = False
            while not wapt_password_ok:
                wapt_password = ''
                wapt_password_check = ''

                while wapt_password == '':
                    (code,wapt_password) = postconf.passwordbox("Please enter the wapt server password (min. 10 characters):  ", insecure=True,width=100)
                    if code != postconf.DIALOG_OK:
                        exit(0)

                while wapt_password_check == '':
                    (code,wapt_password_check) = postconf.passwordbox("Please enter the wapt server password again:  ", insecure=True,width=100)
                    if code != postconf.DIALOG_OK:
                        exit(0)

                if wapt_password != wapt_password_check:
                    postconf.msgbox('Password mismatch !')
                elif len(wapt_password) < 10:
                    postconf.msgbox('Password must be at least 10 characters long !')
                else:
                    wapt_password_ok = True

            password = pbkdf2_sha256.hash(wapt_password.encode('utf8'))
            server_config['wapt_password'] = password
    else:
        wapt_password = ''
        if not server_config['wapt_password']:
            print('[*] Generating random password for WAPT server')
            wapt_password = pwd.genword(entropy=56, charset="ascii_62")
            print('[*] WAPT admin password : %s' % wapt_password)
            password = pbkdf2_sha256.hash(wapt_password.encode('utf8'))
            server_config['wapt_password'] = password

    if not server_config['server_uuid']:
        server_config['server_uuid'] = str(uuid.uuid1())

    # waptagent authentication method
    if not quiet:
        choices = [
                ("1","Allow unauthenticated registration, same behavior as WAPT 1.3", True),
                ("2","Enable kerberos authentication required for machines registration", False),
                ("3","Disable Kerberos but registration require strong authentication", False),
                ]

        code, t = postconf.radiolist("WaptAgent Authentication type?", choices=choices,width=120)
        if code=='cancel':
            print("\n\npostconfiguration canceled\n\n")
            sys.exit(1)
        if t=="1":
            server_config['allow_unauthenticated_registration'] = True
            server_config['use_kerberos'] = False
        if t=="2":
            server_config['allow_unauthenticated_registration'] = False
            server_config['use_kerberos'] = True
        if t=="3":
            server_config['allow_unauthenticated_registration'] = False
            server_config['use_kerberos'] = False
    else:
        print('[*] Set default registration method to : Allow anyone to register + Kerberos disabled')
        server_config['allow_unauthenticated_registration'] = True
        server_config['use_kerberos'] = False


    # Guess fqdn using socket
    fqdn = guess_fqdn()

    clients_signing_certificate =  server_config.get('clients_signing_certificate')
    clients_signing_key = server_config.get('clients_signing_key')

    if not clients_signing_certificate or not clients_signing_key:
        clients_signing_certificate = os.path.join(wapt_root_dir,'conf','ca-%s.crt' % fqdn)
        clients_signing_key = os.path.join(wapt_root_dir,'conf','ca-%s.pem' % fqdn)

        server_config['clients_signing_certificate'] = clients_signing_certificate
        server_config['clients_signing_key'] = clients_signing_key

    if clients_signing_certificate is not None and clients_signing_key is not None and not os.path.isfile(clients_signing_certificate):
        print('Create a certificate and key for clients certificate signing')

        key = SSLPrivateKey(clients_signing_key)
        if not os.path.isfile(clients_signing_key):
            print('Create SSL RSA Key %s' % clients_signing_key)
            key.create()
            key.save_as_pem()

        crt = key.build_sign_certificate(cn=fqdn,is_code_signing=False,is_ca=True)
        print('Create X509 cert %s' % clients_signing_certificate)
        crt.save_as_pem(clients_signing_certificate)

    waptserver.config.write_config_file(cfgfile=options.configfile,server_config=server_config,non_default_values_only=True)

    print('[*] Protecting WAPT config file')
    run("/bin/chmod 640 %s" % options.configfile)
    run("/bin/chown wapt %s" % options.configfile)

    print('[*] Update WAPT repository')
    repo = WaptLocalRepo(wapt_folder)
    repo.update_packages_index(force_all=True)

    final_msg = ['[*] Postconfiguration completed.',]
    if not quiet:
        postconf.msgbox("Press ok to start waptserver and wapttasks daemons")
    enable_waptserver()
    start_waptserver()

    # In this new version Apache is replaced with Nginx? Proceed to disable Apache. After migration one can remove Apache install altogether
    stop_disable_httpd()

    # Nginx configuration
    if quiet:
        try:
            generate_dhparam()
            nginx_cleanup()
            make_httpd_config('/opt/wapt/waptserver', fqdn, options.force_https,server_config)
            enable_nginx()
            restart_nginx()
            setup_firewall()
        except subprocess.CalledProcessError as cpe:
            final_msg += [
                'Error while trying to configure Nginx!',
                'errno = ' + str(cpe.returncode) + ', output: ' + cpe.output
                ]
        except Exception as e:
                import traceback
                final_msg += [
                'Error while trying to configure Nginx!',
                traceback.format_exc()
                ]
    else:
        reply = postconf.yesno("Do you want to configure nginx?")
        if reply == postconf.DIALOG_OK:
            try:
                msg = 'FQDN for the WAPT server (eg. wapt.acme.com)'
                (code, reply) = postconf.inputbox(text=msg, width=len(msg)+4, init=fqdn)
                if code != postconf.DIALOG_OK:
                    exit(1)
                else:
                    fqdn = reply

                generate_dhparam()
                nginx_cleanup()

                if server_config['use_kerberos']:
                    if type_debian():
                        if not check_if_deb_installed('libnginx-mod-http-auth-spnego'):
                            print('[*] Nginx - Missing dependency libnginx-mod-http-auth-spnego, please install first before configuring kerberos')
                            sys.exit(1)

                make_httpd_config('/opt/wapt/waptserver', fqdn, options.force_https, server_config)
                final_msg.append('Please connect to https://' + fqdn + '/ to access the server.')
                postconf.msgbox("The Nginx config is done. We need to restart Nginx?")
                run_verbose('systemctl enable nginx')
                run_verbose('systemctl restart nginx')
                setup_firewall()

            except subprocess.CalledProcessError as cpe:
                final_msg += [
                    'Error while trying to configure Nginx!',
                    'errno = ' + str(cpe.returncode) + ', output: ' + cpe.output
                    ]
            except Exception as e:
                import traceback
                final_msg += [
                'Error while trying to configure Nginx!',
                traceback.format_exc()
                ]

    final_msg.append('Please connect to https://' + fqdn + '/ to access the server.')

    # Check if Mongodb > PostgreSQL migration is necessary
    if not quiet:
        if check_mongo2pgsql_upgrade_needed(options.configfile) and\
                postconf.yesno("It is necessary to migrate current database backend from mongodb to postgres. Press yes to start migration",no_label='cancel') == postconf.DIALOG_OK:
            upgrade2postgres(options.configfile)
    else:
        if check_mongo2pgsql_upgrade_needed(options.configfile):
            upgrade2postgres(options.configfile)

    # Final message
    if not quiet:
        width = 4 + max(10, len(max(final_msg, key=len)))
        height = 2 + max(20, len(final_msg))
        postconf.msgbox('\n'.join(final_msg), height=height, width=width)
    else:
        if wapt_password:
            final_msg.append('[*] WAPT admin password : %s\n' % wapt_password)
        for line in final_msg:
            print(line)
Ejemplo n.º 9
0
def run(*args, **kwargs):
    return subprocess.check_output(*args, shell=True, **kwargs)

def run_verbose(*args, **kwargs):
    output = subprocess.check_output(*args, shell=True, **kwargs)
    print output
    return output

if type_debian():
    MONGO_SVC='mongodb'
    APACHE_SVC='apache2'
    PGSQL_SVC='postgresql'
    wapt_folder = '/var/www/wapt'
    NGINX_GID= grp.getgrnam('www-data').gr_gid
elif type_redhat():
    MONGO_SVC='mongod'
    APACHE_SVC='httpd'
    PGSQL_SVC='postgresql-9.6'
    wapt_folder = '/var/www/html/wapt'
    NGINX_GID= grp.getgrnam('nginx').gr_gid
else:
    print "distrib type unknown"
    sys.exit(1)

quiet = False
postconf = dialog.Dialog(dialog="dialog")

def mkdir(path):
    if not os.path.isdir(path):
        os.makedirs(path)
Ejemplo n.º 10
0
def make_httpd_config(wapt_folder, waptserver_root_dir, fqdn, use_kerberos,force_https, waptserver_port):
    if wapt_folder.endswith('\\') or wapt_folder.endswith('/'):
        wapt_folder = wapt_folder[:-1]

    ssl_dir = os.path.join(waptserver_root_dir, 'ssl')
    scripts_dir = os.path.join(waptserver_root_dir, 'scripts')
    wapt_ssl_key_file = os.path.join(ssl_dir,'key.pem')
    wapt_ssl_cert_file = os.path.join(ssl_dir,'cert.pem')
    mkdir(ssl_dir)

    # write the apache configuration fragment
    jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(scripts_dir))
    template = jinja_env.get_template('wapt.nginxconfig.template')
    krb5_realm = '.'.join(fqdn.split('.')[1:]).upper()

    template_vars = {
        'waptserver_port': waptserver_port,
        'wapt_repository_path': os.path.dirname(wapt_folder),
        'apache_root_folder': '/not/used',
        'windows': False,
        'debian': type_debian(),
        'redhat': type_redhat(),
        'force_https': force_https,
        'wapt_ssl_key_file': wapt_ssl_key_file,
        'wapt_ssl_cert_file': wapt_ssl_cert_file,
        'fqdn': fqdn,
        'use_kerberos': use_kerberos,
        'KRB5_REALM': krb5_realm,
        'wapt_root_dir': wapt_root_dir,
        }

    config_string = template.render(template_vars)
    if type_debian():
        dst_file = file('/etc/nginx/sites-available/wapt.conf', 'wt')
        if not os.path.exists('/etc/nginx/sites-enabled/wapt.conf'):
            print(subprocess.check_output('ln -s /etc/nginx/sites-available/wapt.conf /etc/nginx/sites-enabled/wapt.conf',shell=True))
        if os.path.exists('/etc/nginx/sites-enabled/default'):
            os.unlink('/etc/nginx/sites-enabled/default')

    elif type_redhat():
        dst_file = file('/etc/nginx/conf.d/wapt.conf', 'wt')
    dst_file.write(config_string)
    dst_file.close()

    # create keys for https:// access
    if not os.path.exists(wapt_ssl_key_file) or \
            not os.path.exists(wapt_ssl_cert_file):

        old_apache_key = '/opt/wapt/waptserver/apache/ssl/key.pem'
        old_apache_cert = '/opt/wapt/waptserver/apache/ssl/cert.pem'

        if os.path.isfile(old_apache_cert) and os.path.isfile(old_apache_key):
            shutil.copyfile(old_apache_cert,wapt_ssl_cert_file)
            shutil.copyfile(old_apache_key,wapt_ssl_key_file)

        else:
            void = subprocess.check_output([
                    'openssl',
                    'req',
                    '-new',                # create a request
                    '-x509',               # no, actually, create a self-signed certificate!
                    '-newkey', 'rsa:2048', # and the key that goes along, RSA, 2048 bits
                    '-nodes',              # don't put a passphrase on the key
                    '-days', '3650',       # the cert is valid for ten years
                    '-out', wapt_ssl_cert_file,
                    '-keyout', wapt_ssl_key_file,
                    # fill in the minimum amount of information needed; to be revisited
                    '-subj', '/C=FR/ST=Wapt/L=Wapt/O=Wapt/CN=' + fqdn + '/'
                    ], stderr=subprocess.STDOUT)
Ejemplo n.º 11
0
def main():
    global wapt_folder,NGINX_GID


    parser = OptionParser(usage=usage, version=__version__)
    parser.add_option(
        '-c',
        '--config',
        dest='configfile',
        default=waptserver.config.DEFAULT_CONFIG_FILE,
        help='Config file full path (default: %default)')
    parser.add_option(
        "-s",
        "--force-https",
        dest="force_https",
        default=False,
        action='store_true',
        help="Use https only, http is 301 redirected to https (default: False). Requires a proper DNS name")

    (options, args) = parser.parse_args()

    if postconf.yesno("Do you want to launch post configuration tool ?") != postconf.DIALOG_OK:
        print "canceling wapt postconfiguration"
        sys.exit(1)


    # TODO : check if it a new install or an upgrade (upgrade from mongodb to postgresql)

    if type_redhat():
        if re.match('^SELinux status:.*enabled', run('sestatus')):
            postconf.msgbox('SELinux detected, tweaking httpd permissions.')
            run('setsebool -P httpd_can_network_connect 1')
            run('setsebool -P httpd_setrlimit on')
            for sepath in ('wapt','wapt-host'):
                run('semanage fcontext -a -t httpd_sys_content_t "/var/www/html/%s(/.*)?"' %sepath)
                run('restorecon -R -v /var/www/html/%s' %sepath)
            postconf.msgbox('SELinux correctly configured for Nginx reverse proxy')

    server_config = waptserver.config.load_config(options.configfile)

    if os.path.isfile(options.configfile):
        print('making a backup copy of the configuration file')
        datetime_now = datetime.datetime.now()
        shutil.copyfile(options.configfile,'%s.bck_%s'%  (options.configfile,datetime_now.isoformat()) )

    wapt_folder = server_config['wapt_folder']

    # add secret key initialisation string (for session token)
    if not server_config['secret_key']:
        server_config['secret_key'] = ''.join(random.SystemRandom().choice(string.letters + string.digits) for _ in range(64))

    # add user db and password in ini file
    if server_config['db_host'] in (None,'','localhost','127.0.0.1','::1'):
        ensure_postgresql_db(db_name=server_config['db_name'],db_owner=server_config['db_name'],db_password=server_config['db_password'])

    # Password setup/reset screen
    if not server_config['wapt_password'] or \
            postconf.yesno("Do you want to reset admin password ?",yes_label='skip',no_label='reset') != postconf.DIALOG_OK:
        wapt_password_ok = False
        while not wapt_password_ok:
            wapt_password = ''
            wapt_password_check = ''

            while wapt_password == '':
                (code,wapt_password) = postconf.passwordbox("Please enter the wapt server password (min. 10 characters):  ", insecure=True,width=100)
                if code != postconf.DIALOG_OK:
                    exit(0)

            while wapt_password_check == '':
                (code,wapt_password_check) = postconf.passwordbox("Please enter the wapt server password again:  ", insecure=True,width=100)
                if code != postconf.DIALOG_OK:
                    exit(0)

            if wapt_password != wapt_password_check:
                postconf.msgbox('Password mismatch !')
            elif len(wapt_password) < 10:
                postconf.msgbox('Password must be at least 10 characters long !')
            else:
                wapt_password_ok = True

        password = pbkdf2_sha256.hash(wapt_password.encode('utf8'))
        server_config['wapt_password'] = password

    if not server_config['server_uuid']:
        server_config['server_uuid'] = str(uuid.uuid1())


    # waptagent authentication method
    choices = [
            ("1","Allow unauthenticated registration, same behavior as wapt 1.3", True),
            ("2","Enable kerberos authentication required for machines registration", False),
            ("3","Disable Kerberos but registration require strong authentication", False),
            ]

    code, t = postconf.radiolist("WaptAgent Authentication type?", choices=choices,width=120)
    if code=='cancel':
        print("\n\npostconfiguration canceled\n\n")
        sys.exit(1)
    if t=="1":
        server_config['allow_unauthenticated_registration'] = True
        server_config['use_kerberos'] = False
    if t=="2":
        server_config['allow_unauthenticated_registration'] = False
        server_config['use_kerberos'] = True
    if t=="3":
        server_config['allow_unauthenticated_registration'] = False
        server_config['use_kerberos'] = False


    waptserver.config.write_config_file(cfgfile=options.configfile,server_config=server_config,non_default_values_only=True)

    run("/bin/chmod 640 %s" % options.configfile)
    run("/bin/chown wapt %s" % options.configfile)

    repo = WaptLocalRepo(wapt_folder)
    repo.update_packages_index(force_all=True)

    final_msg = ['Postconfiguration completed.',]
    postconf.msgbox("Press ok to start waptserver and wapttasks daemons")
    enable_waptserver()
    start_waptserver()

    # In this new version Apache is replaced with Nginx? Proceed to disable Apache. After migration one can remove Apache install altogether
    try:
        run_verbose('systemctl stop %s' % APACHE_SVC)
    except:
        pass
    try:
        run_verbose('systemctl disable %s' % APACHE_SVC)
    except:
        pass

    # nginx configuration dialog
    reply = postconf.yesno("Do you want to configure nginx?")
    if reply == postconf.DIALOG_OK:
        try:
            fqdn = socket.getfqdn()
            if not fqdn:
                fqdn = 'wapt'
            if '.' not in fqdn:
                fqdn += '.lan'
            msg = 'FQDN for the WAPT server (eg. wapt.acme.com)'
            (code, reply) = postconf.inputbox(text=msg, width=len(msg)+4, init=fqdn)
            if code != postconf.DIALOG_OK:
                exit(1)
            else:
                fqdn = reply

            dh_filename = '/etc/ssl/certs/dhparam.pem'
            if not os.path.exists(dh_filename):
                run_verbose('openssl dhparam -out %s  2048' % dh_filename)

            os.chown(dh_filename, 0, NGINX_GID) #pylint: disable=no-member
            os.chmod(dh_filename, 0o640)        #pylint: disable=no-member

            # cleanup of nginx.conf file
            with open('/etc/nginx/nginx.conf','r') as read_conf:
                nginx_conf = nginxparser.load(read_conf)
            nginx_conf = nginx_set_worker_limit(nginx_conf)
            nginx_conf = nginx_clean_default_vhost(nginx_conf)
            with open("/etc/nginx/nginx.conf", "w") as nginx_conf_file:
                nginx_conf_file.write(nginxparser.dumps(nginx_conf))

            if server_config['use_kerberos']:
                if type_debian():
                    if not check_if_deb_installed('libnginx-mod-http-auth-spnego'):
                        print('missing dependency libnginx-mod-http-auth-spnego, please install first before configuring kerberos')
                        sys.exit(1)

            make_httpd_config(wapt_folder, '/opt/wapt/waptserver', fqdn, server_config['use_kerberos'], options.force_https,server_config['waptserver_port'])

            final_msg.append('Please connect to https://' + fqdn + '/ to access the server.')

            postconf.msgbox("The Nginx config is done. We need to restart Nginx?")
            run_verbose('systemctl enable nginx')
            run_verbose('systemctl restart nginx')
            setup_firewall()

        except subprocess.CalledProcessError as cpe:
            final_msg += [
                'Error while trying to configure Nginx!',
                'errno = ' + str(cpe.returncode) + ', output: ' + cpe.output
                ]
        except Exception as e:
            import traceback
            final_msg += [
            'Error while trying to configure Nginx!',
            traceback.format_exc()
            ]


    if check_mongo2pgsql_upgrade_needed(options.configfile) and\
            postconf.yesno("It is necessary to migrate current database backend from mongodb to postgres. Press yes to start migration",no_label='cancel') == postconf.DIALOG_OK:
        upgrade2postgres(options.configfile)

    width = 4 + max(10, len(max(final_msg, key=len)))
    height = 2 + max(20, len(final_msg))
    postconf.msgbox('\n'.join(final_msg), height=height, width=width)