Пример #1
0
    def remove(self, packages, auto=False, purge=False):
        all_packages = ' '.join(packages)
        try:
            with open('/var/log/wo/wordops.log', 'a') as f:
                if purge:
                    proc = subprocess.Popen('apt-get purge -y {0}'
                                            .format(all_packages), shell=True,
                                            stdin=None, stdout=f, stderr=f,
                                            executable="/bin/bash")
                else:
                    proc = subprocess.Popen('apt-get remove -y {0}'
                                            .format(all_packages), shell=True,
                                            stdin=None, stdout=f, stderr=f,
                                            executable="/bin/bash")
                proc.wait()
            if proc.returncode == 0:
                return True
            else:
                Log.info(self, Log.FAIL + "Oops Something went "
                         "wrong!!")
                Log.error(self, "Check the WordOps log for more details "
                          "`tail /var/log/wo/wordops.log` and please try again...")

        except Exception as e:
            Log.error(self, "Error while installing packages, "
                      "apt-get exited with error")
Пример #2
0
    def secure_ip(self):
        """IP whitelisting"""
        WOGit.add(self, ["/etc/nginx"], msg="Add Nginx to into Git")
        pargs = self.app.pargs
        if not pargs.user_input:
            ip = input("Enter the comma separated IP addresses "
                       "to white list [127.0.0.1]:")
            pargs.user_input = ip
        try:
            user_ip = pargs.user_input.split(',')
        except Exception as e:
            Log.debug(self, "{0}".format(e))
            user_ip = ['127.0.0.1']
        for ip_addr in user_ip:
            if not ("exist_ip_address " + ip_addr in open('/etc/nginx/common/'
                                                          'acl.conf').read()):
                WOShellExec.cmd_exec(
                    self, "sed -i "
                    "\"/deny/i allow {whitelist_address}\;\""
                    " /etc/nginx/common/acl.conf".format(
                        whitelist_address=ip_addr))
        WOGit.add(self, ["/etc/nginx"],
                  msg="Adding changed secure ip into Git")

        Log.info(self, "Successfully added IP address in acl.conf file")
Пример #3
0
    def add(self):
        """Swap addition with WordOps"""
        # Get System RAM and SWAP details
        wo_ram = psutil.virtual_memory().total / (1024 * 1024)
        wo_swap = psutil.swap_memory().total / (1024 * 1024)
        if wo_ram < 512:
            if wo_swap < 1000:
                Log.info(self, "Adding SWAP file, please wait...")

                # Install dphys-swapfile
                WOAptGet.update(self)
                WOAptGet.install(self, ["dphys-swapfile"])
                # Stop service
                WOShellExec.cmd_exec(self, "service dphys-swapfile stop")
                # Remove Default swap created
                WOShellExec.cmd_exec(self, "/sbin/dphys-swapfile uninstall")

                # Modify Swap configuration
                if os.path.isfile("/etc/dphys-swapfile"):
                    WOFileUtils.searchreplace(self, "/etc/dphys-swapfile",
                                              "#CONF_SWAPFILE=/var/swap",
                                              "CONF_SWAPFILE=/wo-swapfile")
                    WOFileUtils.searchreplace(self, "/etc/dphys-swapfile",
                                              "#CONF_MAXSWAP=2048",
                                              "CONF_MAXSWAP=1024")
                    WOFileUtils.searchreplace(self, "/etc/dphys-swapfile",
                                              "#CONF_SWAPSIZE=",
                                              "CONF_SWAPSIZE=1024")
                else:
                    with open("/etc/dphys-swapfile", 'w') as conffile:
                        conffile.write("CONF_SWAPFILE=/wo-swapfile\n"
                                       "CONF_SWAPSIZE=1024\n"
                                       "CONF_MAXSWAP=1024\n")
                # Create swap file
                WOShellExec.cmd_exec(self, "service dphys-swapfile start")
Пример #4
0
    def enable(self):
        pargs = self.app.pargs
        if not pargs.site_name:
            try:
                while not pargs.site_name:
                    pargs.site_name = (input('Enter site name : ').strip())
            except IOError as e:
                Log.debug(self, str(e))
                Log.error(self, 'could not input site name')

        pargs.site_name = pargs.site_name.strip()
        # validate domain name
        wo_domain = WODomain.validate(self, pargs.site_name)

        # check if site exists
        if not check_domain_exists(self, wo_domain):
            Log.error(self, "site {0} does not exist".format(wo_domain))
        if os.path.isfile('/etc/nginx/sites-available/{0}'.format(wo_domain)):
            Log.info(self, "Enable domain {0:10} \t".format(wo_domain), end='')
            WOFileUtils.create_symlink(self, [
                '/etc/nginx/sites-available/{0}'.format(wo_domain),
                '/etc/nginx/sites-enabled/{0}'.format(wo_domain)
            ])
            WOGit.add(self, ["/etc/nginx"],
                      msg="Enabled {0} ".format(wo_domain))
            updateSiteInfo(self, wo_domain, enabled=True)
            Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]")
            if not WOService.reload_service(self, 'nginx'):
                Log.error(
                    self, "service nginx reload failed. "
                    "check issues with `nginx -t` command")
        else:
            Log.error(self, 'nginx configuration file does not exist')
Пример #5
0
    def install(self, packages):
        all_packages = ' '.join(packages)
        try:
            with open('/var/log/wo/wordops.log', 'a') as f:
                proc = subprocess.Popen("DEBIAN_FRONTEND=noninteractive "
                                        "apt-get install -o "
                                        "Dpkg::Options::=\"--force-confdef\""
                                        " -o "
                                        "Dpkg::Options::=\"--force-confold\""
                                        " -y --allow-unauthenticated {0}"
                                        .format(all_packages), shell=True,
                                        stdin=None, stdout=f, stderr=f,
                                        executable="/bin/bash")
                proc.wait()

            if proc.returncode == 0:
                return True
            else:
                Log.info(self, Log.FAIL + "Oops Something went "
                         "wrong!!")
                Log.error(self, "Check the WordOps log for more details "
                          "`tail /var/log/wo/wordops.log` and please try again...")

        except Exception as e:
            Log.info(self, Log.FAIL + "Oops Something went "
                     "wrong!!")
            Log.error(self, "Check the WordOps log for more details "
                      "`tail /var/log/wo/wordops.log` and please try again...")
Пример #6
0
    def default(self):
        if ((not self.app.pargs.mariadb)):
            self.app.args.print_help()
        if self.app.pargs.mariadb:
            if WOVariables.wo_mysql_host is not "localhost":
                Log.error(
                    self, "Remote MySQL server in use, skipping local install")

            if WOShellExec.cmd_exec(self, "mysqladmin ping") and (
                    not WOAptGet.is_installed(self, 'mariadb-server')):

                Log.info(
                    self, "If your database size is big, "
                    "migration may take some time.")
                Log.info(
                    self, "During migration non nginx-cached parts of "
                    "your site may remain down")
                start_migrate = input("Type \"mariadb\" to continue:")
                if start_migrate != "mariadb":
                    Log.error(self, "Not starting migration")
                self.migrate_mariadb()
            else:
                Log.error(
                    self, "Your current MySQL is not alive or "
                    "you allready installed MariaDB")
Пример #7
0
    def show(self):
        pargs = self.app.pargs
        if not pargs.site_name:
            try:
                while not pargs.site_name:
                    pargs.site_name = (input('Enter site name : ').strip())
            except IOError as e:
                Log.debug(self, str(e))
                Log.error(self, 'could not input site name')
        # TODO Write code for wo site edit command here
        pargs.site_name = pargs.site_name.strip()
        wo_domain = WODomain.validate(self, pargs.site_name)
        wo_www_domain = "www.{0}".format(wo_domain)

        if not check_domain_exists(self, wo_domain):
            Log.error(self, "site {0} does not exist".format(wo_domain))

        if os.path.isfile('/etc/nginx/sites-available/{0}'.format(wo_domain)):
            Log.info(self,
                     "Display NGINX configuration for {0}".format(wo_domain))
            f = open('/etc/nginx/sites-available/{0}'.format(wo_domain),
                     encoding='utf-8',
                     mode='r')
            text = f.read()
            Log.info(self, Log.ENDC + text)
            f.close()
        else:
            Log.error(self, "nginx configuration file does not exists")
Пример #8
0
 def download(self, packages):
     """Download packages, packges must be list in format of
     [url, path, package name]"""
     for package in packages:
         url = package[0]
         filename = package[1]
         pkg_name = package[2]
         try:
             directory = os.path.dirname(filename)
             if not os.path.exists(directory):
                 os.makedirs(directory)
             Log.info(self, "Downloading {0:20}".format(pkg_name), end=' ')
             req = urllib.request.Request(
                 url, headers={'User-Agent': 'Mozilla/5.0'})
             with urllib.request.urlopen(req) as response, open(filename, 'wb') as out_file:
                 out_file.write(response.read())
             Log.info(self, "{0}".format("[" + Log.ENDC + "Done"
                                         + Log.OKBLUE + "]"))
         except urllib.error.URLError as e:
             Log.debug(self, "[{err}]".format(err=str(e.reason)))
             Log.error(self, "Unable to download file, {0}"
                       .format(filename))
             return False
         except urllib.HTTPError.error as e:
             Log.error(self, "Package download failed. {0}"
                       .format(pkg_name))
             Log.debug(self, "[{err}]".format(err=str(e.reason)))
             return False
         except urllib.ContentTooShortError.error as e:
             Log.debug(self, "{0}{1}".format(e.errno, e.strerror))
             Log.error(self, "Package download failed. The amount of the"
                       " downloaded data is less than "
                       "the expected amount \{0} ".format(pkg_name))
             return False
Пример #9
0
 def clean_fastcgi(self):
     if(os.path.isdir("/var/run/nginx-cache")):
         Log.info(self, "Cleaning NGINX FastCGI cache")
         WOShellExec.cmd_exec(self, "rm -rf /var/run/nginx-cache/*")
         WOService.restart_service(self, 'nginx')
     else:
         Log.error(self, "Unable to clean FastCGI cache", False)
Пример #10
0
 def clean_redis(self):
     """This function clears Redis cache"""
     if (WOAptGet.is_installed(self, "redis-server")):
         Log.info(self, "Cleaning Redis cache")
         WOShellExec.cmd_exec(self, "redis-cli flushall")
     else:
         Log.info(self, "Redis is not installed")
Пример #11
0
 def download(self, packages):
     """Download packages, packages must be list in format of
     [url, path, package name]"""
     for package in packages:
         url = package[0]
         filename = package[1]
         pkg_name = package[2]
         try:
             directory = os.path.dirname(filename)
             if not os.path.exists(directory):
                 os.makedirs(directory)
             Log.info(self, "Downloading {0:20}".format(pkg_name), end=' ')
             with open(filename, "wb") as out_file:
                 req = requests.get(url, timeout=(5, 30))
                 if req.encoding is None:
                     req.encoding = 'utf-8'
                 out_file.write(req.content)
             Log.info(
                 self,
                 "{0}".format("[" + Log.ENDC + "Done" + Log.OKBLUE + "]"))
         except requests.RequestException as e:
             Log.debug(self, "[{err}]".format(err=str(e.reason)))
             Log.error(self,
                       "Unable to download file, {0}".format(filename))
             return False
     return 0
Пример #12
0
    def default(self):
        pargs = self.app.pargs
        if ((not pargs.mariadb)):
            self.app.args.print_help()
        if pargs.mariadb:
            if WOVar.wo_distro == 'raspbian':
                Log.error(self, "MariaDB upgrade is not available on Raspbian")
            if WOVar.wo_mysql_host != "localhost":
                Log.error(
                    self, "Remote MySQL server in use, skipping local install")

            if (WOShellExec.cmd_exec(self, "mysqladmin ping")):

                Log.info(
                    self, "If your database size is big, "
                    "migration may take some time.")
                Log.info(
                    self, "During migration non nginx-cached parts of "
                    "your site may remain down")
                if not pargs.force:
                    start_upgrade = input("Do you want to continue:[y/N]")
                    if start_upgrade != "Y" and start_upgrade != "y":
                        Log.error(self, "Not starting package update")
                if not pargs.ci:
                    self.migrate_mariadb()
                else:
                    self.migrate_mariadb(ci=True)
            else:
                Log.error(
                    self, "Your current MySQL is not alive or "
                    "you allready installed MariaDB")
Пример #13
0
    def deploycert(self, wo_domain_name):
        """Deploy Let's Encrypt certificates with acme.sh"""
        if not os.path.isfile('/etc/letsencrypt/renewal/{0}_ecc/fullchain.cer'.
                              format(wo_domain_name)):
            Log.error(self, 'Certificate not found. Deployment canceled')

        Log.debug(self,
                  "Cert deployment for domain: {0}".format(wo_domain_name))

        try:
            Log.wait(self, "Deploying SSL cert")
            if WOShellExec.cmd_exec(
                    self,
                    "mkdir -p {0}/{1} && {2} --install-cert -d {1} --ecc "
                    "--cert-file {0}/{1}/cert.pem --key-file {0}/{1}/key.pem "
                    "--fullchain-file {0}/{1}/fullchain.pem "
                    "--ca-file {0}/{1}/ca.pem --reloadcmd \"nginx -t && "
                    "service nginx restart\" ".format(WOVar.wo_ssl_live,
                                                      wo_domain_name,
                                                      WOAcme.wo_acme_exec)):
                Log.valide(self, "Deploying SSL cert")
            else:
                Log.failed(self, "Deploying SSL cert")
                Log.error(self, "Unable to deploy certificate")

            if os.path.isdir('/var/www/{0}/conf/nginx'.format(wo_domain_name)):

                sslconf = open(
                    "/var/www/{0}/conf/nginx/ssl.conf".format(wo_domain_name),
                    encoding='utf-8',
                    mode='w')
                sslconf.write("listen 443 ssl http2;\n"
                              "listen [::]:443 ssl http2;\n"
                              "ssl_certificate     {0}/{1}/fullchain.pem;\n"
                              "ssl_certificate_key     {0}/{1}/key.pem;\n"
                              "ssl_trusted_certificate {0}/{1}/ca.pem;\n"
                              "ssl_stapling_verify on;\n".format(
                                  WOVar.wo_ssl_live, wo_domain_name))
                sslconf.close()

            if not WOFileUtils.grep(self, '/var/www/22222/conf/nginx/ssl.conf',
                                    '/etc/letsencrypt'):
                Log.info(self, "Securing WordOps backend with current cert")
                sslconf = open("/var/www/22222/conf/nginx/ssl.conf",
                               encoding='utf-8',
                               mode='w')
                sslconf.write("ssl_certificate     {0}/{1}/fullchain.pem;\n"
                              "ssl_certificate_key     {0}/{1}/key.pem;\n"
                              "ssl_trusted_certificate {0}/{1}/ca.pem;\n"
                              "ssl_stapling_verify on;\n".format(
                                  WOVar.wo_ssl_live, wo_domain_name))
                sslconf.close()

            WOGit.add(self, ["/etc/letsencrypt"],
                      msg="Adding letsencrypt folder")

        except IOError as e:
            Log.debug(self, str(e))
            Log.debug(self, "Error occured while generating " "ssl.conf")
        return 0
Пример #14
0
    def dist_upgrade(self):
        """
        Similar to `apt-get upgrade`
        """
        try:
            with open('/var/log/wo/wordops.log', 'a') as f:
                proc = subprocess.Popen("DEBIAN_FRONTEND=noninteractive "
                                        "apt-get dist-upgrade -o "
                                        "Dpkg::Options::=\"--force-confdef\""
                                        " -o "
                                        "Dpkg::Options::=\"--force-confold\""
                                        " -y ",
                                        shell=True, stdin=None,
                                        stdout=f, stderr=f,
                                        executable="/bin/bash")
                proc.wait()

            if proc.returncode == 0:
                return True
            else:
                Log.info(self, Log.FAIL + "Oops Something went "
                         "wrong!!")
                Log.error(self, "Check the WordOps log for more details "
                          "`tail /var/log/wo/wordops.log` and please try again...")
        except Exception as e:
            Log.error(self, "Error while installing packages, "
                      "apt-get exited with error")
Пример #15
0
    def default(self):
        filename = "woupdate" + time.strftime("%Y%m%d-%H%M%S")

        if self.app.pargs.travis:
            wo_branch = "updating-configuration"
            install_args = "--travis --force "
        elif self.app.pargs.beta:
            wo_branch = "beta"
            install_args = ""
        else:
            wo_branch = "master"
            install_args = ""
        if self.app.pargs.force:
            install_args = install_args + "--force "
        if self.app.pargs.preserve:
            install_args = install_args + "--preserve "

        WODownload.download(self, [[
            "https://raw.githubusercontent.com/"
            "WordOps/WordOps/{0}/install".format(wo_branch),
            "/var/lib/wo/tmp/{0}".format(filename), "update script"
        ]])

        try:
            Log.info(self, "updating WordOps, please wait...")
            os.system("/bin/bash /var/lib/wo/tmp/{0} "
                      "-b {1} {2}".format(filename, wo_branch, install_args))
        except OSError as e:
            Log.debug(self, str(e))
            Log.error(self, "WordOps update failed !")
Пример #16
0
 def clean_memcache(self):
     try:
         if (WOAptGet.is_installed(self, "memcached")):
             WOService.restart_service(self, "memcached")
             Log.info(self, "Cleaning MemCache")
         else:
             Log.info(self, "Memcache not installed")
     except Exception as e:
         Log.debug(self, "{0}".format(e))
         Log.error(self, "Unable to restart Memcached", False)
Пример #17
0
    def setupletsencrypt(self, acme_domains, acmedata):
        """Issue SSL certificates with acme.sh"""
        # check acme.sh is installed
        WOAcme.check_acme(self)
        # define variables
        all_domains = '\' -d \''.join(acme_domains)
        wo_acme_dns = acmedata['acme_dns']
        keylenght = acmedata['keylength']
        if acmedata['dns'] is True:
            acme_mode = "--dns {0}".format(wo_acme_dns)
            validation_mode = "DNS mode with {0}".format(wo_acme_dns)
            if acmedata['dnsalias'] is True:
                acme_mode = acme_mode + \
                    " --challenge-alias {0}".format(acmedata['acme_alias'])
        else:
            acme_mode = "-w /var/www/html"
            validation_mode = "Webroot challenge"
            Log.debug(self, "Validation : Webroot mode")
            if not os.path.isdir('/var/www/html/.well-known/acme-challenge'):
                WOFileUtils.mkdir(self,
                                  '/var/www/html/.well-known/acme-challenge')
            WOFileUtils.chown(self,
                              '/var/www/html/.well-known',
                              'www-data',
                              'www-data',
                              recursive=True)
            WOFileUtils.chmod(self,
                              '/var/www/html/.well-known',
                              0o750,
                              recursive=True)

        Log.info(self, "Validation mode : {0}".format(validation_mode))
        Log.wait(self, "Issuing SSL cert with acme.sh")
        if not WOShellExec.cmd_exec(
                self, "{0} ".format(WOAcme.wo_acme_exec) +
                "--issue -d '{0}' {1} -k {2} -f".format(
                    all_domains, acme_mode, keylenght)):
            Log.failed(self, "Issuing SSL cert with acme.sh")
            if acmedata['dns'] is True:
                Log.error(
                    self, "Please make sure your properly "
                    "set your DNS API credentials for acme.sh\n"
                    "If you are using sudo, use \"sudo -E wo\"")
                return False
            else:
                Log.error(
                    self, "Your domain is properly configured "
                    "but acme.sh was unable to issue certificate.\n"
                    "You can find more informations in "
                    "/var/log/wo/wordops.log")
                return False
        else:
            Log.valide(self, "Issuing SSL cert with acme.sh")
            return True
Пример #18
0
    def import_slow_log(self):
        """Default function for import slow log"""
        if os.path.isdir("{0}22222/htdocs/db/anemometer".format(
                WOVariables.wo_webroot)):
            if os.path.isfile("/var/log/mysql/mysql-slow.log"):
                # Get Anemometer user name and password
                Log.info(self, "Importing MySQL slow log to Anemometer")
                host = os.popen("grep -e \"\'host\'\" {0}22222/htdocs/".format(
                    WOVariables.wo_webroot) +
                                "db/anemometer/conf/config.inc.php  "
                                "| head -1 | cut -d\\\' -f4 | "
                                "tr -d '\n'").read()
                user = os.popen("grep -e \"\'user\'\" {0}22222/htdocs/".format(
                    WOVariables.wo_webroot) +
                                "db/anemometer/conf/config.inc.php  "
                                "| head -1 | cut -d\\\' -f4 | "
                                "tr -d '\n'").read()
                password = os.popen("grep -e \"\'password\'\" {0}22222/".
                                    format(WOVariables.wo_webroot) +
                                    "htdocs/db/anemometer/conf"
                                    "/config.inc.php "
                                    "| head -1 | cut -d\\\' -f4 | "
                                    "tr -d '\n'").read()

                # Import slow log Anemometer using pt-query-digest
                try:
                    WOShellExec.cmd_exec(
                        self, "pt-query-digest --user={0} "
                        "--password={1} "
                        "--review D=slow_query_log,"
                        "t=global_query_review "
                        "--history D=slow_query_log,t="
                        "global_query_review_history "
                        "--no-report --limit=0% "
                        "--filter=\" \\$event->{{Bytes}} = "
                        "length(\\$event->{{arg}}) "
                        "and \\$event->{{hostname}}=\\\""
                        "{2}\\\"\" "
                        "/var/log/mysql/mysql-slow.log".format(
                            user, password, host))
                except CommandExecutionError as e:
                    Log.debug(self, str(e))
                    Log.error(self, "MySQL slow log import failed.")
            else:
                Log.error(
                    self, "MySQL slow log file not found,"
                    " so not imported slow logs")
        else:
            Log.error(
                self, "Anemometer is not installed." + Log.ENDC +
                "\n Install Anemometer with:" + Log.BOLD +
                "\n `wo stack install --utils`" + Log.ENDC)
Пример #19
0
    def debug_mysql(self):
        """Start/Stop MySQL debug"""
        # MySQL start global debug
        if (self.app.pargs.mysql == 'on' and not self.app.pargs.site_name):
            if not WOShellExec.cmd_exec(self, "mysql -e \"show variables like"
                                              " \'slow_query_log\';\" | "
                                              "grep ON"):
                Log.info(self, "Setting up MySQL slow log")
                WOMysql.execute(self, "set global slow_query_log = "
                                      "\'ON\';")
                WOMysql.execute(self, "set global slow_query_log_file = "
                                      "\'/var/log/mysql/mysql-slow.log\';")
                WOMysql.execute(self, "set global long_query_time = 2;")
                WOMysql.execute(self, "set global log_queries_not_using"
                                      "_indexes = \'ON\';")
            else:
                Log.info(self, "MySQL slow log is already enabled")

            self.msg = self.msg + ['/var/log/mysql/mysql-slow.log']

        # MySQL stop global debug
        elif (self.app.pargs.mysql == 'off' and not self.app.pargs.site_name):
            if WOShellExec.cmd_exec(self, "mysql -e \"show variables like \'"
                                    "slow_query_log\';\" | grep ON"):
                Log.info(self, "Disabling MySQL slow log")
                WOMysql.execute(self, "set global slow_query_log = \'OFF\';")
                WOMysql.execute(self, "set global slow_query_log_file = \'"
                                "/var/log/mysql/mysql-slow.log\';")
                WOMysql.execute(self, "set global long_query_time = 10;")
                WOMysql.execute(self, "set global log_queries_not_using_index"
                                "es = \'OFF\';")
                WOShellExec.cmd_exec(self, "crontab -l | sed \'/#WordOps "
                                     "start/,/#WordOps end/d\' | crontab -")
            else:
                Log.info(self, "MySQL slow log already disabled")
Пример #20
0
 def default(self):
     filename = "woupdate" + time.strftime("%Y%m%d-%H%M%S")
     WODownload.download(self, [["https://raw.githubusercontent.com/WordOps/WordOps/master/install",
                                 "/tmp/{0}".format(filename),
                                 "update script"]])
     try:
         Log.info(self, "updating WordOps, please wait...")
         os.system("bash /tmp/{0}".format(filename))
     except OSError as e:
         Log.debug(self, str(e))
         Log.error(self, "WordOps update failed !")
     except Exception as e:
         Log.debug(self, str(e))
         Log.error(self, "WordOps update failed !")
Пример #21
0
 def clean_opcache(self):
     try:
         Log.info(self, "Cleaning opcache")
         urllib.request.urlopen("https://127.0.0.1:22222/cache"
                                "/opcache/opgui.php?reset=1").read()
     except Exception as e:
         Log.debug(self, "{0}".format(e))
         Log.debug(self, "Unable hit url, "
                   " https://127.0.0.1:22222/cache/opcache/"
                   "opgui.php?reset=1,"
                   " please check you have admin tools installed")
         Log.debug(self, "please check you have admin tools installed,"
                   " or install them with `wo stack install --admin`")
         Log.error(self, "Unable to clean opcache", False)
Пример #22
0
    def update(self):
        """
        Similar to `apt-get update`
        """
        try:
            with open('/var/log/wo/wordops.log', 'a') as f:
                proc = subprocess.Popen('apt-get update',
                                        shell=True,
                                        stdin=None,
                                        stdout=f,
                                        stderr=subprocess.PIPE,
                                        executable="/bin/bash")
                proc.wait()
                output, error_output = proc.communicate()

                # Check what is error in error_output
                if "NO_PUBKEY" in str(error_output):
                    # Split the output
                    Log.info(self, "Fixing missing GPG keys, please wait...")
                    error_list = str(error_output).split("\\n")

                    # Use a loop to add misising keys
                    for single_error in error_list:
                        if "NO_PUBKEY" in single_error:
                            key = single_error.rsplit(None, 1)[-1]
                            WORepo.add_key(self,
                                           key,
                                           keyserver="hkp://pgp.mit.edu")

                    proc = subprocess.Popen('apt-get update',
                                            shell=True,
                                            stdin=None,
                                            stdout=f,
                                            stderr=f,
                                            executable="/bin/bash")
                    proc.wait()

                if proc.returncode == 0:
                    return True
                else:
                    Log.info(self,
                             Log.FAIL + "Whoops, something went wrong...")
                    Log.error(
                        self, "Check the WordOps log for more details "
                        "`tail /var/log/wo/wordops.log` "
                        "and please try again...")

        except Exception as e:
            Log.error(self, "apt-get update exited with error")
Пример #23
0
 def httpsredirect(self, wo_domain_name, acme_domains, redirect=True):
     """Create Nginx redirection from http to https"""
     wo_acme_domains = ' '.join(acme_domains)
     if redirect:
         Log.wait(self, "Adding HTTPS redirection")
         if WOFileUtils.enabledisable(
                 self,
                 '/etc/nginx/conf.d/force-ssl-{0}.conf'.format(
                     wo_domain_name),
                 enable=True):
             Log.valide(self, "Adding HTTPS redirection")
             return 0
         else:
             try:
                 sslconf = open(
                     "/etc/nginx/conf.d/force-ssl-{0}.conf".format(
                         wo_domain_name),
                     encoding='utf-8',
                     mode='w')
                 sslconf.write(
                     "server {\n"
                     "\tlisten 80;\n" + "\tlisten [::]:80;\n" +
                     "\tserver_name {0};\n".format(wo_acme_domains) +
                     "\treturn 301 https://$host"
                     "$request_uri;\n}")
                 sslconf.close()
             except IOError as e:
                 Log.debug(self, str(e))
                 Log.debug(
                     self, "Error occured while generating "
                     "/etc/nginx/conf.d/force-ssl-{0}.conf".format(
                         wo_domain_name))
                 return 1
             Log.valide(self, "Adding HTTPS redirection")
             return 0
     else:
         if WOFileUtils.enabledisable(
                 self,
                 "/etc/nginx/conf.d/force-ssl-{0}.conf".format(
                     wo_domain_name),
                 enable=False):
             Log.info(
                 self, "Disabled HTTPS Force Redirection for site "
                 "{0}".format(wo_domain_name))
         else:
             Log.info(
                 self, "HTTPS redirection already disabled for site"
                 "{0}".format(wo_domain_name))
         return 0
Пример #24
0
    def setuphsts(self, wo_domain_name):
        Log.info(
            self,
            "Adding /var/www/{0}/conf/nginx/hsts.conf".format(wo_domain_name))

        hstsconf = open(
            "/var/www/{0}/conf/nginx/hsts.conf".format(wo_domain_name),
            encoding='utf-8',
            mode='w')
        hstsconf.write("more_set_headers "
                       "\"Strict-Transport-Security: "
                       "max-age=31536000; "
                       "includeSubDomains; "
                       "preload\";")
        hstsconf.close()
        return 0
Пример #25
0
    def removeconf(self, domain):
        sslconf = ("/var/www/{0}/conf/nginx/ssl.conf"
                   .format(domain))
        sslforce = ("/etc/nginx/conf.d/force-ssl-{0}.conf"
                    .format(domain))
        acmedir = [
            '{0}'.format(sslforce), '{0}'.format(sslconf),
            '{0}/{1}_ecc'.format(WOVar.wo_ssl_archive, domain),
            '{0}.disabled'.format(sslconf), '{0}.disabled'
            .format(sslforce), '{0}/{1}'
            .format(WOVar.wo_ssl_live, domain),
            '/etc/letsencrypt/shared/{0}.conf'.format(domain)]
        wo_domain = domain
        # check acme.sh is installed
        WOAcme.check_acme(self)
        if WOAcme.cert_check(self, wo_domain):
            Log.info(self, "Removing Acme configuration")
            Log.debug(self, "Removing Acme configuration")
            try:
                WOShellExec.cmd_exec(
                    self, "{0} ".format(WOAcme.wo_acme_exec) +
                    "--remove -d {0} --ecc".format(domain))
            except CommandExecutionError as e:
                Log.debug(self, "{0}".format(e))
                Log.error(self, "Cert removal failed")
            # remove all files and directories
            for dir in acmedir:
                if os.path.exists('{0}'.format(dir)):
                    WOFileUtils.rm(self, '{0}'.format(dir))
            # find all broken symlinks
            WOFileUtils.findBrokenSymlink(self, "/var/www")
        else:
            if os.path.islink("{0}".format(sslconf)):
                WOFileUtils.remove_symlink(self, "{0}".format(sslconf))
                WOFileUtils.rm(self, '{0}'.format(sslforce))

        if WOFileUtils.grepcheck(self, '/var/www/22222/conf/nginx/ssl.conf',
                                 '{0}'.format(domain)):
            Log.info(
                self, "Setting back default certificate for WordOps backend")
            with open("/var/www/22222/conf/nginx/"
                      "ssl.conf", "w") as ssl_conf_file:
                ssl_conf_file.write("ssl_certificate "
                                    "/var/www/22222/cert/22222.crt;\n"
                                    "ssl_certificate_key "
                                    "/var/www/22222/cert/22222.key;\n")
Пример #26
0
    def default(self):
        pargs = self.app.pargs
        filename = "woupdate" + time.strftime("%Y%m%d-%H%M%S")

        install_args = ""
        wo_branch = "master"
        if pargs.mainline or pargs.beta:
            wo_branch = "mainline"
            install_args = install_args + "--mainline "
        elif pargs.branch:
            wo_branch = pargs.branch
            install_args = install_args + "-b {0} ".format(wo_branch)
        if pargs.force:
            install_args = install_args + "--force "
        if pargs.travis:
            install_args = install_args + "--travis "
            wo_branch = "updating-configuration"

        if ((not pargs.force) and (not pargs.travis) and
            (not pargs.mainline) and (not pargs.beta) and
                (not pargs.branch)):
            wo_current = ("v{0}".format(WOVar.wo_version))
            wo_latest = WODownload.latest_release(self, "WordOps/WordOps")
            if wo_current == wo_latest:
                Log.info(
                    self, "WordOps {0} is already installed"
                    .format(wo_latest))
                self.app.close(0)

        if not os.path.isdir('/var/lib/wo/tmp'):
            os.makedirs('/var/lib/wo/tmp')
        WODownload.download(self, [["https://raw.githubusercontent.com/"
                                    "WordOps/WordOps/{0}/install"
                                    .format(wo_branch),
                                    "/var/lib/wo/tmp/{0}".format(filename),
                                    "update script"]])

        if os.path.isfile('install'):
            Log.info(self, "updating WordOps from local install\n")
            try:
                Log.info(self, "updating WordOps, please wait...")
                os.system("/bin/bash install --travis")
            except OSError as e:
                Log.debug(self, str(e))
                Log.error(self, "WordOps update failed !")
        else:
            try:
                Log.info(self, "updating WordOps, please wait...")
                os.system("/bin/bash /var/lib/wo/tmp/{0} "
                          "{1}".format(filename, install_args))
            except OSError as e:
                Log.debug(self, str(e))
                Log.error(self, "WordOps update failed !")

        os.remove("/var/lib/wo/tmp/{0}".format(filename))
Пример #27
0
    def check_upgrade(self):
        """
        Similar to `apt-get upgrade`
        """
        try:
            check_update = subprocess.Popen(['apt-get upgrade -s | grep '
                                            '\"^Inst\" | wc -l'],
                                            stdout=subprocess.PIPE,
                                            shell=True).communicate()[0]
            if check_update == b'0\n':
                Log.error(self, "No package updates available")
            Log.info(self, "Following package updates are available:")
            subprocess.Popen("apt-get -s dist-upgrade | grep \"^Inst\"",
                             shell=True, executable="/bin/bash",
                             stdout=sys.stdout).communicate()

        except Exception as e:
            Log.error(self, "Unable to check for packages upgrades")
Пример #28
0
 def clean_opcache(self):
     try:
         Log.info(self, "Cleaning opcache")
         opgui = requests.get(
             "https://127.0.0.1:22222/cache/opcache/opgui.php?reset=1")
         if opgui.status_code != '200':
             Log.warn(self, 'Cleaning opcache failed')
     except Exception as e:
         Log.debug(self, "{0}".format(e))
         Log.debug(
             self, "Unable hit url, "
             " https://127.0.0.1:22222/cache/opcache/"
             "opgui.php?reset=1,"
             " please check you have admin tools installed")
         Log.debug(
             self, "please check you have admin tools installed,"
             " or install them with `wo stack install --admin`")
         Log.error(self, "Unable to clean opcache", False)
Пример #29
0
    def start_service(self, service_name):
        """
            start service
            Similar to `service xyz start`
        """
        try:
            if service_name in ['nginx']:
                # Check Nginx configuration before executing command
                sub = subprocess.Popen('nginx -t',
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       shell=True)
                output, error_output = sub.communicate()
                if 'emerg' not in str(error_output):
                    service_cmd = ('service {0} start'.format(service_name))
                    retcode = subprocess.getstatusoutput(service_cmd)
                    if retcode[0] == 0:
                        Log.info(
                            self, "Starting Nginx " + "[" + Log.ENDC + "OK" +
                            Log.OKBLUE + "]")
                        return True
                else:
                    Log.info(
                        self, "Starting Nginx " + "[" + Log.FAIL + "Failed" +
                        Log.OKBLUE + "]")
                    return False
            else:
                service_cmd = ('service {0} start'.format(service_name))

                Log.info(self, "Start : {0:10}".format(service_name), end='')
                retcode = subprocess.getstatusoutput(service_cmd)
                if retcode[0] == 0:
                    Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]")
                    return True
                else:
                    Log.debug(self, "{0}".format(retcode[1]))
                    Log.info(self,
                             "[" + Log.FAIL + "Failed" + Log.OKBLUE + "]")
                    return False
        except OSError as e:
            Log.debug(self, "{0}".format(e))
            Log.error(self,
                      "\nFailed to start service   {0}".format(service_name))
Пример #30
0
 def secure_ssh(self):
     """Harden ssh security"""
     pargs = self.app.pargs
     if not pargs.force and not pargs.allowpassword:
         start_secure = input('Are you sure you to want to'
                              ' harden SSH security ?'
                              '\nSSH login with password will not '
                              'be possible anymore. Please make sure '
                              'you are already using SSH Keys.\n'
                              'Harden SSH security [y/N]')
         if start_secure != "Y" and start_secure != "y":
             Log.error(self, "Not hardening SSH security")
     if os.path.exists('/etc/ssh'):
         WOGit.add(self, ["/etc/ssh"], msg="Adding SSH into Git")
     Log.debug(self, "check if /etc/ssh/sshd_config exist")
     if os.path.isfile('/etc/ssh/sshd_config'):
         Log.debug(self, "looking for the current ssh port")
         for line in open('/etc/ssh/sshd_config', encoding='utf-8'):
             if 'Port' in line:
                 ssh_line = line.strip()
                 break
         port = (ssh_line).split(' ')
         current_ssh_port = (port[1]).strip()
         if os.getenv('SUDO_USER'):
             sudo_user = os.getenv('SUDO_USER')
         else:
             sudo_user = ''
         if pargs.allowpassword:
             wo_allowpassword = '******'
         else:
             wo_allowpassword = '******'
         data = dict(sshport=current_ssh_port,
                     allowpass=wo_allowpassword,
                     user=sudo_user)
         WOTemplate.deploy(self, '/etc/ssh/sshd_config', 'sshd.mustache',
                           data)
         WOGit.add(self, ["/etc/ssh"],
                   msg="Adding changed SSH port into Git")
         if not WOService.restart_service(self, 'ssh'):
             Log.error(self, "service SSH restart failed.")
             Log.info(self, "Successfully harden SSH security")
     else:
         Log.error(self, "SSH config file not found")