def learn_policy(self, identifier): ''' Learn a policy file. Args: identifier: a string, either a URL to a policy file or the text of the policy itself. Keep in mind a policy can be comprised of more than one policy file (a file containing valid policy DSL) or string containing policy DSL. This way you break your rule set, imports, and policy attributes across any number of files. See reason-method for more. Returns: The resulting File Node. Raises: ValueError: if the policy already exists in knowledge. TypeError: if parameter 'identifier' is a NoneType, or is not a string representing either a file path to a policy or the text of the policy itself. ''' is_file = False if identifier: if isinstance(identifier, basestring): if urlparse(identifier).scheme: # Treat 'identifier' as an URL self.log("Learning policy from URL: {0}".format(identifier)) stream = ANTLRStringStream(Intellect.policy_from(identifier)) is_file = True else: #Treat 'identifier' as policy string self.log("Learning policy from string") stream = ANTLRStringStream(identifier) lexer = PolicyLexer(stream) tokens = CommonTokenStream(lexer) tokens.discardOffChannelTokens = True indented_source = PolicyTokenSource(tokens) tokens = CommonTokenStream(indented_source) parser = PolicyParser(tokens) with RedirectStdError() as stderr: try: # ANTL3 may raise an exception, and doing so the stderror # will not be printed hiding the underlying problem. GRRR!!!! file_node = parser.file() except Exception as e: if stderr.getvalue().rstrip() != "": trace = sys.exc_info()[2] raise Exception(stderr.getvalue().rstrip()), None, trace else: raise e # The ANTLR3 Recognizer class prints a number of ANTLR3 Exceptions to # stderr vice throwing an exception, because it will try to recover and # continue parsing. # # In the case of NoViableAltException, I've chosen to raise an # exception. # # Otherwise, all the other error message that Recognizer writes to # stderr will be returned for the benefit of the policy author. if stderr.getvalue().rstrip() != "": # check for stderror msg indicating an NoViableAltException occured. # if did raise an exception with the stderror message. if "no viable alternative at input" in stderr.getvalue().rstrip(): raise Exception("Error parsing policy: {0}\n{1}".format(identifier, stderr.getvalue().rstrip())) else: print >> sys.stderr, stderr.getvalue().rstrip() # set path attribute file_node.path = identifier if is_file else None # associate the path to all descendants file_node.set_file_on_descendants(file_node, file_node) try: # determine if the policy already exists in knowledge self.policy.files.index(file_node) raise ValueError("Policy already exists in knowledge: {0}".format(identifier)) except: pass # store add the policy file to the policy self.policy.append_child(file_node) self.log("learned a policy file") return file_node else: raise TypeError("parameter 'identifier' must be a string, either a file path to a policy or the text of the policy itself") else: raise TypeError("parameter 'identifier' cannot be a NoneType.")
def learn_policy(self, identifier): ''' Learn a policy file. Args: identifier: a string, either a path to a policy file or the text of the policy itself. Keep in mind a policy can be comprised of more than one policy file (a file containing valid policy DSL) or string containing policy DSL. This way you break your rule set, imports, and policy attributes across any number of files. See reason-method for more. Returns: The resulting File Node. Raises: ValueError: if the policy already exists in knowledge. TypeError: if parameter 'identifier' is a NoneType, or is not a string representing either a file path to a policy or the text of the policy itself. ''' isFile = False if identifier: if isinstance(identifier, basestring): if not os.path.isfile(identifier): ''' Try treating 'identifier' as a String containing the text of a policy. ''' stream = ANTLRStringStream(identifier) lexer = PolicyLexer(stream) tokens = CommonTokenStream(lexer) tokens.discardOffChannelTokens = True indentedSource = PolicyTokenSource(tokens) tokens = CommonTokenStream(indentedSource) parser = PolicyParser(tokens) with RedirectStdError() as stderr: try: # ANTL3 may raise an exception, and doing so the stderror # will not be printed hiding the underlying problem. GRRR!!!! file_node = parser.file() except Exception as e: if stderr.getvalue().rstrip() != "": trace = sys.exc_info()[2] raise Exception(stderr.getvalue().rstrip()), None, trace else: raise e # Some times the previous parser.file() will print to stderr, # but not throw an exception. In this case, the parser may # attempt to correct and continue onward, but we should # print the msg to stderr for the benefit of the policy # author if stderr.getvalue().rstrip() != "": print >> sys.stderr, stderr.getvalue().rstrip() else: ''' Try treating 'identifier' as a file path ''' if Intellect.filepath_regex.match(identifier): if os.path.exists(identifier): self.log("Learning policy from file path: {0}".format(identifier)) stream = FileStream(identifier) isFile = True else: raise IOError, "Policy not found: {0}".format(identifier) else: ''' assume the intention was to pass 'identifier' as a String containing the text of a policy, and raise the exception. ''' raise e lexer = PolicyLexer(stream) tokens = CommonTokenStream(lexer) tokens.discardOffChannelTokens = True indentedSource = PolicyTokenSource(tokens) tokens = CommonTokenStream(indentedSource) parser = PolicyParser(tokens) with RedirectStdError() as stderr: try: # ANTL3 may raise an exception, and doing so the stderror # will not be printed hiding the underlying problem. GRRR!!!! file_node = parser.file() except Exception as e: if stderr.getvalue().rstrip() != "": trace = sys.exc_info()[2] raise Exception(stderr.getvalue().rstrip()), None, trace else: raise e # Some times the previous parser.file() will print to stderr, # but not throw an exception. In this case, the parser may # attempt to correct and continue onward, but we should # print the msg to stderr for the benefit of the policy # author if stderr.getvalue().rstrip() != "": print >> sys.stderr, stderr.getvalue().rstrip() # set path attribute file_node.path = identifier if isFile else None # associate the path to all descendants file_node.set_file_on_descendants(file_node, file_node) try: # determine if the policy already exists in knowledge self.policy.files.index(file_node) raise ValueError, "Policy already exists in knowledge: {0}".format(identifier) except: pass # store add the policy file to the policy self.policy.append_child(file_node) self.log("learned a policy file") return file_node else: raise TypeError, "parameter 'identifier' must be a string, either a file path to a policy or the text of the policy itself" else: raise TypeError, "parameter 'identifier' cannot be a NoneType."
def learn_policy(self, identifier): ''' Learn a policy file. Args: identifier: a string, either a path to a policy file or the text of the policy itself. Keep in mind a policy can be comprised of more than one policy file (a file containing valid policy DSL) or string containing policy DSL. This way you break your rule set, imports, and policy attributes across any number of files. See reason-method for more. Returns: The resulting File Node. Raises: ValueError: if the policy already exists in knowledge. TypeError: if parameter 'identifier' is a NoneType, or is not a string representing either a file path to a policy or the text of the policy itself. ''' if identifier: if isinstance(identifier, basestring): isFile = False try: ''' Try treating 'identifier' as a String containing the text of a policy. ''' stream = ANTLRStringStream(identifier) lexer = PolicyLexer(stream) tokens= CommonTokenStream(lexer) tokens.discardOffChannelTokens = True indentedSource = PolicyTokenSource(tokens) tokens = CommonTokenStream(indentedSource) parser = PolicyParser(tokens) with IO.capture_stderr() as stderr: file_node = parser.file() if stderr.getvalue() != "": raise Exception, "Error in String-based policy: {0}".format(stderr.getvalue()) except Exception as e: ''' Try treating 'identifier' as a file path ''' if Intellect.filepath_regex.match(identifier): if os.path.exists(identifier): self.log("Learning policy from file path: {0}".format(identifier)) stream = FileStream(identifier) isFile = True else: raise IOError, "Policy not found: {0}".format(identifier) else: ''' assume the intention was to pass 'identifier' as a String containing the text of a policy, and raise the exception. ''' raise e lexer = PolicyLexer(stream) tokens= CommonTokenStream(lexer) tokens.discardOffChannelTokens = True indentedSource = PolicyTokenSource(tokens) tokens = CommonTokenStream(indentedSource) parser = PolicyParser(tokens) with IO.capture_stderr() as stderr: file_node = parser.file() if stderr.getvalue() != "": raise Exception, "Error in file-based policy for path {0}: {1}".format(identifier, stderr.getvalue()) # set path attribute file_node.path = identifier if isFile else None # associate the path to all descendants file_node.set_file_on_descendants(file_node, file_node) try: # determine if the policy already exists in knowledge self.policy.files.index(file_node) raise ValueError, "Policy already exists in knowledge: {0}".format(identifier) except: pass # store add the policy file to the policy self.policy.append_child(file_node) return file_node else: raise TypeError, "parameter 'identifier' must be a string, either a file path to a policy or the text of the policy itself" else: raise TypeError, "parameter 'identifier' cannot be a NoneType."