Ejemplo n.º 1
0
 def setUp(self):
     self.testDir = Framework.getTestDir()
     self.databaseName = "CocoscatsTest"
     self.databasePath = "{0}/{1}".format(Framework.getDataDir(), self.databaseName)
     self.cfgPath = "{0}/test.json".format(self.testDir)
     self.tmpCfgPath = "{0}/Tmp/tmp.json".format(self.testDir)
     warnings.simplefilter("ignore", category=DeprecationWarning)
     warnings.simplefilter("ignore", category=ImportWarning)
Ejemplo n.º 2
0
 def __init__(self, cfgPath):
     self.cfgPath = cfgPath
     self.cfg = None
     self.installDir = Framework.getInstallDir()
     self.pluginTypes = ["IO", "Analyzer", "Translator", "Demo"]
     self.pluginTypeAlias = \
         {"Input": "IO", "Analyzer": "Analyzer", "Translator": "Translator", "Output": "IO", "Demo": "Demo"}
Ejemplo n.º 3
0
 def getSubresourceIntegrityHashes(displayValues=False):
     sriHashes = {}
     webDir = Framework.getWebDir()
     for subDir in ["Css", "Js"]:
         for path in Directory.getFiles("{0}/{1}".format(webDir, subDir)):
             sriHashes[path] = Security.getSubresourceIntegrityHash(path)
             if displayValues:
                 print("\n{0}\n{1}\n".format(path, sriHashes[path]))
Ejemplo n.º 4
0
 def getCredentials(self):
     stack = inspect.stack()
     className = str(stack[1][0].f_locals["self"].__class__.__name__)
     path = "{0}/{1}.json".format(Framework.getVaultDir(), className)
     if not File.exists(path):
         self.raiseException(
             "Missing {0} credentials file".format(className))
     return File.getContent(path, asJson=True)
Ejemplo n.º 5
0
 def __showLogin():
     p = bottle.request.forms.get("password")
     if p is not None:
         passwordPath = "{0}/Password.json".format(Framework.getVaultDir())
         if Security.verifyPasswordByFile(p, passwordPath):
             bottle.request.environ.get('beaker.session').invalidate()
             WebApp.__setSession("Authenticated", "True")
             WebApp.__redirect("/")
             return ""
         else:
             WebApp.__setSession("authenticated", "False")
     return """{0}{1}{2}""".format(WebApp.getHeader("Welcome to CoCoScatS"),
                                   bottle.template("Web/Tpl/Login.tpl", {}),
                                   WebApp.getFooter())
Ejemplo n.º 6
0
 def verify(self):
     for name, value in self.cfg.items():
         if name == "ProjectID":
             if len(value) > 256 or Text.isNothing(value):
                 Error.raiseException(
                     "{0} can only be 256 characters or less: {1}".format(
                         name, value))
             if re.search(r'[^A-Za-z0-9_\-\\]', value):
                 Error.raiseException(
                     "{0} contains invalid characters: {1}".format(
                         name, value))
         if Text.isNothing(value):
             Error.raiseException("Missing '{0}' value in {1}".format(
                 name, self.cfgPath))
     pluginLookupMap = []
     for plugin in self.cfg["Plugin"]:
         pluginMethods = self.getPluginMethods(plugin["Type"],
                                               plugin["Name"])
         for pluginMethod in pluginMethods["Method"]:
             if not Framework.hasPluginClassMethod(
                     plugin["Type"], plugin["Name"], pluginMethod["Name"]):
                 Error.raiseException("Can't find {0}::{1}::{2}()".format(
                     plugin["Type"], plugin["Name"], pluginMethod["Name"]))
             pluginLookupMap.append("{0}{1}{2}".format(
                 plugin["Type"], plugin["Name"], pluginMethod["Name"]))
     if len(self.cfg["Workflow"]["Demo"]["Plugin"]) != len(
             self.cfg["Workflow"]["Demo"]["Method"]):
         Error.raiseException(
             "Mismatched number of demo plugins and methods")
     workflowPluginLookupMap = []
     for workflowPluginType, workflowPluginCfg in self.cfg[
             "Workflow"].items():
         pluginType = self.pluginTypeAlias[workflowPluginType]
         if pluginType != "Demo":
             workflowPluginLookupMap.append("{0}{1}{2}".format(
                 pluginType, workflowPluginCfg["Plugin"],
                 workflowPluginCfg["Method"]))
         else:
             for i in range(0, len(workflowPluginCfg["Plugin"])):
                 key = "{0}{1}{2}".format(pluginType,
                                          workflowPluginCfg["Plugin"][i],
                                          workflowPluginCfg["Method"][i])
                 if key not in pluginLookupMap:
                     Error.raiseException(
                         "Can't find workflow plugin {0}::{1}::{2}()".
                         format(workflowPluginType,
                                workflowPluginCfg["Plugin"][i],
                                workflowPluginCfg["Method"][i]))
Ejemplo n.º 7
0
 def testFrameworkGetInstallDir(self):
     installDir = Framework.getInstallDir()
     self.assertTrue(
         os.path.isdir(installDir),
         "Incorrect installation directory")
Ejemplo n.º 8
0
 def setName(name):
     Database.name = name
     Database.path = "{0}/{1}.db".format(Framework.getDataDir(), name)
Ejemplo n.º 9
0
class Database():
    directory = Framework.getDataDir()
    name = "Cocoscats"
    path = "{0}/{1}.db".format(directory, name)
    debugFlag = False
    ORM = orm
    ODB = orm.Database()

    class Table():
        Project = NotImplemented
        Input = NotImplemented
        Analyzer = NotImplemented
        Translator = NotImplemented
        Output = NotImplemented

    @staticmethod
    def checkProjectExists(projectID):
        return Database.getProject(projectID) is not None

    @staticmethod
    def commit():
        Database.ODB.commit()

    @staticmethod
    def connect():
        try:
            Database.ODB.bind("sqlite", Database.path, create_db=True)
        except TypeError:
            pass
        else:
            Database.ODB.generate_mapping(create_tables=True)

    @staticmethod
    def create(forceDeleteIfExists=False):
        if Database.exists():
            if forceDeleteIfExists:
                Database.drop()
            else:
                return
        Directory.make(Database.directory)
        try:
            Database.ODB.bind("sqlite", Database.path, create_db=True)
        except TypeError:
            pass
        else:
            Database.ODB.generate_mapping(create_tables=True)
            Database.ODB.disconnect()

    @staticmethod
    def disconnect():
        Database.ODB.disconnect()

    @staticmethod
    def drop():
        if Database.exists():
            os.unlink(Database.path)

    @staticmethod
    def execute(sql, commit=True, asScript=False):
        conn = sqlite3.connect(Database.path)
        cur = conn.cursor()
        if not asScript:
            cur.execute(sql)
        else:
            cur.executescript(sql)
        results = cur.fetchall()
        if commit:
            conn.commit()
        conn.close()
        return results

    @staticmethod
    def exists():
        return os.path.isfile(Database.path)

    @staticmethod
    def getAnalyzerContent(projectID):
        with Database.ORM.db_session:
            result = Database.Table.Analyzer.get(ProjectID=projectID)
            if result is None:
                return result
            return {
                "ID": result.ID,
                "ProjectID": projectID,
                "Content": result.Content,
                "PluginName": result.PluginName,
                "PluginMethod": result.PluginMethod,
                "Plugin": result.Plugin
            }

    @staticmethod
    def getInputContent(projectID):
        with Database.ORM.db_session:
            result = Database.Table.Input.get(ProjectID=projectID)
            if result is None:
                return result
            return {
                "ID": result.ID,
                "ProjectID": projectID,
                "Content": result.Content,
                "Source": result.Source,
                "PluginName": result.PluginName,
                "PluginMethod": result.PluginMethod,
                "Plugin": result.Plugin
            }

    @staticmethod
    def getOutputContent(projectID):
        with Database.ORM.db_session:
            result = Database.Table.Output.get(ProjectID=projectID)
            if result is None:
                return result
            return {
                "ID": result.ID,
                "ProjectID": projectID,
                "Content": result.Content,
                "Target": result.Target,
                "PluginName": result.PluginName,
                "PluginMethod": result.PluginMethod,
                "Plugin": result.Plugin
            }

    @staticmethod
    def getProject(projectID):
        result = {
            "ProjectID": projectID,
            "Message": "",
            "Error": False,
            "Title": "",
            "Description": "",
            "DataTime": "",
            "Vocabulary": [],
            "VocabularyParsed": [],
            "VocabularyCnt": 0,
            "Rejected": [],
            "RejectedCnt": 0,
            "L1": "",
            "L2": "",
            "L1L2": "",
        }
        projectDetails = Database.getProjectDetails(projectID)
        if projectDetails is not None:
            result["Title"] = projectDetails["Title"]
            result["Description"] = projectDetails["Description"]
            result["DateTime"] = projectDetails["DateTime"]
        else:
            result["Error"] = True
            result["Message"] = "No project found with ID: {0}".format(projectID)
            return result
        translatorContent = Database.getTranslatorContent(projectID)
        if translatorContent is not None and "ContentParsed" in translatorContent:
            result["Vocabulary"] = translatorContent["ContentParsed"]["Vocabulary"]
            result["VocabularyParsed"] = translatorContent["ContentParsed"]["VocabularyParsed"]
            result["VocabularyCnt"] = translatorContent["ContentParsed"]["VocabularyCnt"]
            result["Rejected"] = translatorContent["ContentParsed"]["Rejected"]
            result["RejectedCnt"] = translatorContent["ContentParsed"]["RejectedCnt"]
            result["L1"] = translatorContent["ContentParsed"]["L1"]
            result["L2"] = translatorContent["ContentParsed"]["L2"]
            result["L1L2"] = translatorContent["ContentParsed"]["L1L2"]
        else:
            result["Error"] = True
            result["Message"] = "No content found for project ID: {0}".format(projectID)
        return result

    @staticmethod
    def getProjectAll(projectID):
        result = {}
        result["ProjectID"] = projectID
        result["Project"] = Database.getProjectDetails(projectID)
        if result["Project"] is None:
            return None
        result["Input"] = Database.getInputContent(projectID)
        result["Analyzer"] = Database.getAnalyzerContent(projectID)
        result["Translator"] = Database.getTranslatorContent(projectID)
        result["Output"] = Database.getOutputContent(projectID)
        return result

    @staticmethod
    def getProjectDetails(projectID):
        with Database.ORM.db_session:
            result = Database.Table.Project.get(ID=projectID)
            if result is None:
                return result
            return {
                "ID": result.ID,
                "Title": result.Title,
                "Description": result.Description,
                "DateTime": result.DateTime,
                "Workflow": result.Workflow
            }

    @staticmethod
    def getAllProjectDetails():
        with Database.ORM.db_session:
            result = Database.Table.Project.select()
            if result is None or result.count() < 1:
                return None
            projects = []
            for r in result:
                projects.append(Database.getProjectDetails(r.ID))
            return projects

    @staticmethod
    def getTranslatorContent(projectID):
        with Database.ORM.db_session:
            result =  Database.Table.Translator.get(ProjectID=projectID)
            if result is None:
                return result
            return {
                "ID": result.ID,
                "ProjectID": projectID,
                "Content": result.Content,
                "ContentParsed": result.ContentParsed,
                "PluginName": result.PluginName,
                "PluginMethod": result.PluginMethod,
                "Plugin": result.Plugin
            }

    @staticmethod
    def sanitize(something):
        if something is str:
            something = something.replace("'", "\\'")
        return bleach.clean(something)

    @staticmethod
    def setDebug(debugFlag):
        orm.sql_debug(debugFlag)

    @staticmethod
    def setName(name):
        Database.name = name
        Database.path = "{0}/{1}.db".format(Framework.getDataDir(), name)
Ejemplo n.º 10
0
class Security():
    __vaultDir = Framework.getVaultDir()
    __certificatePemPath = "{0}/Certificate.pem".format(__vaultDir)
    __certificateCrtPath = "{0}/Certificate.crt".format(__vaultDir)
    __passwordPath = "{0}/Password.json".format(__vaultDir)
    __privateKeyPath = "{0}/PrivateKey.pem".format(__vaultDir)
    __publicKeyPath = "{0}/PublicKey.pem".format(__vaultDir)

    @staticmethod
    def authenticate(path, password=None):
        if password == None:
            password = Security.promptForPassword(False)
        return Security.verifyPasswordByFile(password, path)

    @staticmethod
    def certsAndKeysExist():
        for path in [
                Security.__privateKeyPath, Security.__publicKeyPath,
                Security.__certificatePemPath
        ]:
            if not File.exists(path):
                return False
        if Security.hasOpenSSL():
            return File.exists(Security.__certificateCrtPath)
        return True

    @staticmethod
    def createCertsAndKeys(host=None):
        if host is None:
            host = socket.gethostname()
        File.deletes([
            Security.__privateKeyPath, Security.__publicKeyPath,
            Security.__certificatePemPath, Security.__certificateCrtPath
        ])
        key = OpenSSL.crypto.PKey()
        key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
        certificate = OpenSSL.crypto.X509()
        certificate.get_subject().C = "US"
        certificate.get_subject().ST = "Oregon"
        certificate.get_subject().L = "Portland"
        certificate.get_subject().O = "Cocoscats"
        certificate.get_subject().OU = "Cocoscats"
        certificate.get_subject().CN = host
        certificate.set_serial_number(random.randint(1, 99999999999))
        certificate.gmtime_adj_notBefore(0)
        certificate.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60)
        certificate.set_issuer(certificate.get_subject())
        certificate.set_pubkey(key)
        certificate.sign(key, "sha512")
        privateKeyData = OpenSSL.crypto.dump_privatekey(
            OpenSSL.crypto.FILETYPE_PEM, key)
        publicKeyData = OpenSSL.crypto.dump_publickey(
            OpenSSL.crypto.FILETYPE_PEM, key)
        certificateData = OpenSSL.crypto.dump_certificate(
            OpenSSL.crypto.FILETYPE_PEM, certificate)
        File.setContent(Security.__privateKeyPath,
                        privateKeyData,
                        asBytes=True,
                        mkdirs=True)
        File.setContent(Security.__publicKeyPath,
                        publicKeyData,
                        asBytes=True,
                        mkdirs=True)
        File.setContent(Security.__certificatePemPath,
                        certificateData,
                        asBytes=True,
                        mkdirs=True)
        if Security.hasOpenSSL():
            ret = os.system(
                "openssl x509 -outform der -in {0} -out {1}".format(
                    Security.__certificatePemPath,
                    Security.__certificateCrtPath))

    @staticmethod
    def createPassword():
        Security.deletePassword()
        p = Security.promptForPassword(True)
        Msg.flush()
        Msg.show("Thanks ... please wait")
        Msg.flush()
        h = Security.hashAndSaltPassword(p)
        File.setContent(Security.__passwordPath, {"Password": h}, asJson=True)

    @staticmethod
    def deleteCertsAndKeys():
        File.deletes([
            Security.__certificateCrtPath, Security.__certificatePemPath,
            Security.__privateKeyPath, Security.__publicKeyPath
        ])

    @staticmethod
    def deletePassword():
        File.delete(Security.__passwordPath)

    @staticmethod
    def getCertificateCrtPath():
        return Security.__certificateCrtPath

    @staticmethod
    def getCertificatePemPath():
        return Security.__certificatePemPath

    @staticmethod
    def getPrivateKeyPath():
        return Security.__privateKeyPath

    @staticmethod
    def getPublicKeyPath():
        return Security.__publicKeyPath

    @staticmethod
    def getRandomToken():
        return uuid.uuid4()

    @staticmethod
    def getSubresourceIntegrityHash(path):
        content = File.getContent(path)
        hash = hashlib.sha512(content.encode("utf-8")).digest()
        return "sha512-{}".format(base64.b64encode(hash).decode())

    @staticmethod
    def hasOpenSSL():
        if File.find("openssl") is not None:
            return True
        ret = os.system("openssl version")
        return ret == 0

    @staticmethod
    def hashAndSaltPassword(password):
        return pbkdf2_sha512.encrypt(password, rounds=999999, salt_size=64)

    @staticmethod
    def hasPasswordFile():
        return File.exists(Security.__passwordPath)

    @staticmethod
    def promptForPassword(isNewFlag=False):
        if isNewFlag:
            p1 = Security.__showHiddenPrompt("Enter a new password")
            p2 = Security.__showHiddenPrompt("Enter a new password again")
            if p1 != p2:
                Error.raiseException("Mismatched passwords")
            return p1
        return Security.__showHiddenPrompt("Enter your password")

    @staticmethod
    def __showHiddenPrompt(prompt):
        response = None
        sys.stdout.write("{0}: ".format(prompt))
        sys.stdout.flush()
        if sys.stdout.isatty():
            response = getpass.getpass(prompt="")
        else:
            if File.finds(["stty", "stty.exe"]) is not None:
                os.system("stty -echo")
                response = sys.stdin.readline()
                os.system("stty echo")
            else:
                response = input("")
        sys.stdout.write("\n")
        return response.rstrip()

    @staticmethod
    def verifyPassword(password, hash):
        return pbkdf2_sha512.verify(password, hash)

    @staticmethod
    def verifyPasswordByFile(password, path):
        return Security.verifyPassword(
            password,
            File.getContent(path, asJson=True)["Password"])
Ejemplo n.º 11
0
 def getVaultPath(self, name=None):
     if name is None:
         return Framework.getVaultDir()
     return "{0}/{1}".format(Framework.getVaultDir(), name)
Ejemplo n.º 12
0
 def getVaultContent(self, name, asJson=False):
     path = "{0}/{1}".format(Framework.getVaultDir(), name)
     return File.getContent(path, asJson)