示例#1
0
    def start(self, node, uri, tunnel=False, external_uri=None):
        """ If not tunnel, start listening on uri and handle http requests.
            If tunnel, setup a tunnel to uri and handle requests.
        """
        self.node = node
        self.security = Security(self.node)
        schema, _ = uri.split(':', 1)
        if tunnel:
            # Connect to tunnel server
            self.tunnel_client = CalvinControlTunnelClient(uri, self)
        else:
            url = urlparse(uri)
            self.port = int(url.port)
            self.host = url.hostname
            if external_uri is not None:
                self.external_host = urlparse(external_uri).hostname
            else:
                self.external_host = self.host
            _log.info("Control API listening on: %s:%s" %
                      (self.host, self.port))

            self.server = server_connection.ServerProtocolFactory(
                self.handle_request, "http", node_name=node.node_name)
            self.server.start(self.host, self.port)

            # Create tunnel server
            self.tunnel_server = CalvinControlTunnelServer(self.node)
示例#2
0
 def add_node(self, node, cb=None):
     """
     Add node to storage
     """
     self.set(prefix="node-", key=node.id,
               value={"uri": node.external_uri,
                      "control_uri": node.external_control_uri,
                      "authz_server": node.authorization.authz_server_id,
                      "attributes": {'public': node.attributes.get_public(),
                                     'indexed_public': node.attributes.get_indexed_public(as_list=False)}}, cb=cb)
     self._add_node_index(node)
     # Store all actors on this node in storage
     GlobalStore(node=node, security=Security(node) if security_enabled() else None, verify=False).export()
示例#3
0
 def new_from_migration(self,
                        actor_type,
                        state,
                        prev_connections=None,
                        connection_list=None,
                        callback=None):
     """Instantiate an actor of type 'actor_type' and apply the 'state' to the actor."""
     try:
         _log.analyze(self.node.id, "+", state)
         subject_attributes = state['security'].pop('_subject_attributes',
                                                    None)
         migration_info = state['private'].pop('_migration_info', None)
         try:
             state['security'].remove('_subject_attributes')
             state['private'].remove('_migration_info')
         except:
             pass
         if security_enabled():
             security = Security(self.node)
             security.set_subject_attributes(subject_attributes)
         else:
             security = None
         actor_def, signer = self.lookup_and_verify(actor_type, security)
         requirements = actor_def.requires if hasattr(
             actor_def, "requires") else []
         self.check_requirements_and_sec_policy(
             requirements, security, state['private']['_id'], signer,
             migration_info,
             CalvinCB(self.new,
                      actor_type,
                      None,
                      state,
                      prev_connections=prev_connections,
                      connection_list=connection_list,
                      callback=callback,
                      actor_def=actor_def,
                      security=security))
     except Exception:
         # Still want to create shadow actor.
         self.new(actor_type,
                  None,
                  state,
                  prev_connections=prev_connections,
                  connection_list=connection_list,
                  callback=callback,
                  shadow_actor=True)
示例#4
0
def compile_script_check_security(data,
                                  filename,
                                  cb,
                                  security=None,
                                  content=None,
                                  verify=True,
                                  node=None,
                                  signature=None):
    """
    Compile a script and return a tuple (deployable, errors, warnings).

    'credentials' are optional security credentials(?)
    'verify' is deprecated and will be removed
    'node' is the runtime performing security check(?)
    'cb' is a CalvinCB callback

    N.B. If callback 'cb' is given, this method calls cb(deployable, errors, warnings) and returns None
    N.B. If callback 'cb' is given, and method runs to completion, cb is called with additional parameter 'security' (?)
    """
    def _exit_with_error(callback):
        """Helper method to generate a proper error"""
        it = IssueTracker()
        it.add_error("UNAUTHORIZED", info={'status': 401})
        callback({}, it)
        return

    def _handle_policy_decision(data,
                                appname,
                                verify,
                                access_decision,
                                org_cb,
                                security=None):
        if not access_decision:
            _log.error("Access denied")
            # This error reason is detected in calvin control and gives proper REST response
            _exit_with_error(org_cb)
            return
        if 'app_info' not in data and 'script' in data:
            deployable, issuetracker = compile_script(data['script'], appname)
        elif 'app_info' in data:
            deployable = data['app_info']
            issuetracker = IssueTracker()
        else:
            _log.error("Neither app_info or script supplied")
            # This error reason is detected in calvin control and gives proper REST response
            _exit_with_error(org_cb)
            return
        org_cb(deployable, issuetracker, security=security)

    #
    # Actual code for compile_script
    #
    appname = appname_from_filename(filename)
    # FIXME: if node is None we bypass security even if enabled. Is that the intention?
    if node is not None and security_enabled():
        # FIXME: If cb is None, we will return from this method with None instead of a tuple, failing silently
        if security:
            sec = security
        else:
            sec = Security(node)

        verified, signer = sec.verify_signature_content(content, "application")
        if not verified:
            # Verification not OK if sign or cert not OK.
            _log.error("Failed application verification")
            # This error reason is detected in calvin control and gives proper REST response
            _exit_with_error(cb)
            return
        sec.check_security_policy(CalvinCB(_handle_policy_decision,
                                           data,
                                           appname,
                                           verify,
                                           security=security,
                                           org_cb=cb),
                                  element_type="application",
                                  element_value=signer)
        return

    #
    # We get here if node is None, or security is disabled
    #
    # This used to be
    # _handle_policy_decision(data, filename, verify, access_decision=True, security=None, org_cb=cb)
    # but since _handle_policy_decision is called with access_decision=True, security=None only compile_script would be called
    if 'app_info' not in data and 'script' in data:
        deployable, issuetracker = compile_script(data['script'], appname)
    elif 'app_info' in data:
        deployable = data['app_info']
        issuetracker = IssueTracker()
    else:
        _log.error("Neither app_info or script supplied")
        # This error reason is detected in calvin control and gives proper REST response
        _exit_with_error(org_cb)
        return
    cb(deployable, issuetracker, security=None)
示例#5
0
def compile_script_check_security(source_text,
                                  filename,
                                  cb,
                                  credentials=None,
                                  verify=True,
                                  node=None):
    """
    Compile a script and return a tuple (deployable, errors, warnings).

    'credentials' are optional security credentials(?)
    'verify' is deprecated and will be removed
    'node' is the runtime performing security check(?)
    'cb' is a CalvinCB callback

    N.B. If callback 'cb' is given, this method calls cb(deployable, errors, warnings) and returns None
    N.B. If callback 'cb' is given, and method runs to completion, cb is called with additional parameter 'security' (?)
    """
    def _exit_with_error(callback):
        """Helper method to generate a proper error"""
        it = IssueTracker()
        it.add_error("UNAUTHORIZED", info={'status': 401})
        callback({}, it)

    def _handle_authentication_decision(source_text,
                                        appname,
                                        verify,
                                        authentication_decision,
                                        security,
                                        org_cb,
                                        content=None):
        if not authentication_decision:
            _log.error("Authentication failed")
            # This error reason is detected in calvin control and gives proper REST response
            _exit_with_error(org_cb)

        verified, signer = security.verify_signature_content(
            content, "application")
        if not verified:
            # Verification not OK if sign or cert not OK.
            _log.error("Failed application verification")
            # This error reason is detected in calvin control and gives proper REST response
            _exit_with_error(org_cb)

        security.check_security_policy(CalvinCB(_handle_policy_decision,
                                                source_text,
                                                appname,
                                                verify,
                                                security=security,
                                                org_cb=org_cb),
                                       "application",
                                       signer=signer)

    def _handle_policy_decision(source_text,
                                appname,
                                verify,
                                access_decision,
                                org_cb,
                                security=None):
        if not access_decision:
            _log.error("Access denied")
            # This error reason is detected in calvin control and gives proper REST response
            _exit_with_error(org_cb)

        deployable, issutracker = compile_script(source_text, appname)

        org_cb(deployable, issutracker, security=security)

    #
    # Actual code for compile_script
    #
    appname = appname_from_filename(filename)
    # FIXME: if node is None we bypass security even if enabled. Is that the intention?
    if node is not None and security_enabled():
        if credentials:
            content = Security.verify_signature_get_files(filename,
                                                          skip_file=True)
            # content is ALWAYS a dict if skip_file is True
            content['file'] = source_text
        else:
            content = None
        # FIXME: If cb is None, we will return from this method with None instead of a tuple, failing silently
        sec = Security(node)
        sec.authenticate_subject(credentials,
                                 callback=CalvinCB(
                                     _handle_authentication_decision,
                                     source_text,
                                     appname,
                                     verify,
                                     security=sec,
                                     org_cb=cb,
                                     content=content))
        return

    #
    # We get here if node is None, or security is disabled
    #
    # This used to be
    # _handle_policy_decision(source_text, filename, verify, access_decision=True, security=None, org_cb=cb)
    # but since _handle_policy_decision is called with access_decision=True, security=None only compile_script would be called
    deployable, issuetracker = compile_script(source_text, appname)
    cb(deployable, issuetracker, security=None)