Example #1
0
 def new_from_migration(self, actor_type, state, prev_connections=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.pop('subject_attributes', None)
         migration_info = state.pop('migration_info', None)
         try:
             state['_managed'].remove('subject_attributes')
             state['_managed'].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['id'],
                                                signer, migration_info,
                                                CalvinCB(self.new, actor_type, None,
                                                         state, prev_connections,
                                                         callback=callback,
                                                         actor_def=actor_def,
                                                         security=security))
     except Exception:
         # Still want to create shadow actor.
         self.new(actor_type, None, state, prev_connections, callback=callback, shadow_actor=True)
Example #2
0
    def testNegative_Deny_SignedApp_SignedActor_UnallowedRequirement(self):
        _log.analyze("TESTRUN", "+", {})
        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(application_store_path, "correctly_signed.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({"user": "******", "password": "******"})
            result = request_handler.deploy_application(runtimes[2]["RT"], "correctly_signed", content['file'], 
                        content=content,
                        check=True)
        except Exception as e:
            _log.debug(str(e))
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app correctly_signed, no use to verify if requirements fulfilled")

        # Verify that actors exist like this
        try:
            actors = helpers.fetch_and_log_runtime_actors(runtimes, request_handler)
        except Exception as err:
            _log.error("Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['correctly_signed:src'] in actors[2]
        assert result['actor_map']['correctly_signed:sum'] in actors[2]
        assert result['actor_map']['correctly_signed:snk'] in actors[2]

        actual = request_handler.report(runtimes[2]["RT"], result['actor_map']['correctly_signed:snk'])
        _log.debug("actual={}".format(actual))
        assert len(actual) == 0  # Means that the actor with unallowed requirements was not accepted

        request_handler.delete_application(runtimes[2]["RT"], result['application_id'])
Example #3
0
def control_deploy(args):
    response = None
    reqs = requirements_file(args.reqs) if args.reqs else None
    if args.signer:
        conf = certificate.Config(configfile=None, domain=args.signer, readonly=True)
        certificate.sign_file(conf, args.script.name)
    source_text = args.script.read()
    credentials_ = None
    content = None
    if args.credentials:
        try:
            credentials_ = json.loads(args.credentials)
        except Exception as e:
            print "Credentials not JSON:\n", e
            return -1
        if credentials_:
            content = Security.verify_signature_get_files(args.script.name, skip_file=True)
            if content:
                content['file'] = source_text
    try:
        response = get_request_handler().deploy_application(args.node, args.script.name, source_text, reqs,
                                            credentials=credentials_, content=content, check=args.check)
    except Exception as e:
        print e
    return response
Example #4
0
    def testPositive_External_Authentication(self):
        _log.analyze("TESTRUN", "+", {})
        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(application_store_path, "correctly_signed.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({"user": "******", "password": "******"})
            result = request_handler.deploy_application(runtimes[1]["RT"], "correctly_signed", content['file'], 
                        content=content,
                        check=True)
        except Exception as e:
            if isinstance(e, Timeout):
                raise Exception("Can't connect to runtime 5.\n\te={}".format(e))
            elif e.message.startswith("401"):
                raise Exception("Failed security verification of app correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app correctly_signed, no use to verify if requirements fulfilled")

        # Verify that actors exist like this
        try:
            actors = helpers.fetch_and_log_runtime_actors(runtimes, request_handler)
        except Exception as err:
            _log.error("Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['correctly_signed:src'] in actors[1]
        assert result['actor_map']['correctly_signed:sum'] in actors[1]
        assert result['actor_map']['correctly_signed:snk'] in actors[1]

        time.sleep(0.1)
        actual = request_handler.report(runtimes[1]["RT"], result['actor_map']['correctly_signed:snk'])
        assert len(actual) > 2

        request_handler.delete_application(runtimes[1]["RT"], result['application_id']) 
Example #5
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)
Example #6
0
    def testSecurity_NEGATIVE_IncorrectPassword(self):
        _log.analyze("TESTRUN", "+", {})
        global storage_verified
        if not storage_verified:
            try:
                storage_verified = helpers.security_verify_storage(
                    rt, request_handler)
            except Exception as err:
                _log.error("Failed storage verification, err={}".format(err))
                raise

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(application_store_path,
                             "correctly_signed.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({
                "user": "******",
                "password": "******"
            })
            result = helpers.deploy_signed_application_that_should_fail(
                request_handler, rt[1], "incorrectly_signed", content)
        except Exception as e:
            _log.error(
                "Test deploy failed for non security reasons, e={}".format(e))
            raise Exception(
                "Deployment of app correctly_signed, did not fail for security reasons"
            )
        return
Example #7
0
    def testSecurity_NEGATIVE_CorrectlySignedApp_IncorrectlySignedActor(self):
        _log.analyze("TESTRUN", "+", {})
        global rt1
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(security_test_dir + "/scripts/test_security1_correctlySignedApp_incorrectlySignedActor.calvin")
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt1, "test_security1_correctlySignedApp_incorrectlySignedActor", content['file'], 
                        credentials={"user": ["user1"], "password": ["pass1"]}, content=content, 
                        check=True)
        except Exception as e:
            _log.debug(str(e))
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app testSecurity_NEGATIVE_CorrectlySignedApp_IncorrectlySignedActor")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app testSecurity_NEGATIVE_CorrectlySignedApp_IncorrectlySignedActor, no use to verify if requirements fulfilled")
        #print "RESULT:", result
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt1)
        assert result['actor_map']['test_security1_correctlySignedApp_incorrectlySignedActor:src'] in actors
        assert result['actor_map']['test_security1_correctlySignedApp_incorrectlySignedActor:sum'] in actors
        assert result['actor_map']['test_security1_correctlySignedApp_incorrectlySignedActor:snk'] in actors

        actual = request_handler.report(rt1, result['actor_map']['test_security1_correctlySignedApp_incorrectlySignedActor:snk'])
        assert len(actual) == 0

        request_handler.delete_application(rt1, result['application_id'])
Example #8
0
def control_deploy(args):
    response = None
    reqs = requirements_file(args.reqs) if args.reqs else None
    if args.signer:
        conf = certificate.Config(configfile=None,
                                  domain=args.signer,
                                  readonly=True)
        certificate.sign_file(conf, args.script.name)
    source_text = args.script.read()
    credentials_ = None
    content = None
    if args.credentials:
        content = Security.verify_signature_get_files(args.script.name,
                                                      skip_file=True)
        if content:
            content['file'] = source_text
    req_handler = handle_security_arguments(args)
    try:
        response = req_handler.deploy_application(args.node,
                                                  args.script.name,
                                                  source_text,
                                                  reqs,
                                                  content=content,
                                                  check=args.check)
    except Exception as e:
        print e
    return response
Example #9
0
def control_deploy(args):
    response = None
    reqs = requirements_file(args.reqs) if args.reqs else None
    if args.signer:
        conf = certificate.Config(configfile=None,
                                  domain=args.signer,
                                  readonly=True)
        certificate.sign_file(conf, args.script.name)
    source_text = args.script.read()
    credentials_ = None
    content = None
    if args.credentials:
        try:
            credentials_ = json.loads(args.credentials)
        except Exception as e:
            print "Credentials not JSON:\n", e
            return -1
        if credentials_:
            content = Security.verify_signature_get_files(args.script.name,
                                                          skip_file=True)
            if content:
                content['file'] = source_text
    try:
        response = get_request_handler().deploy_application(
            args.node,
            args.script.name,
            source_text,
            reqs,
            credentials=credentials_,
            content=content,
            check=args.check)
    except Exception as e:
        print e
    return response
Example #10
0
 def __init__(self, deployable, node, name=None, deploy_info=None, credentials=None, verify=True, cb=None):
     super(Deployer, self).__init__()
     self.deployable = deployable
     self.deploy_info = deploy_info
     self.credentials = credentials
     self.sec = Security(node)
     self.sec.set_subject(self.credentials)
     self.actorstore = ActorStore(security=self.sec)
     self.actor_map = {}
     self.actor_connections = {}
     self.node = node
     self.verify = verify
     self.cb = cb
     self._deploy_cont_done = False
     if name:
         self.name = name
         self.app_id = self.node.app_manager.new(self.name)
         self.ns = os.path.splitext(os.path.basename(self.name))[0]
     elif "name" in self.deployable:
         self.name = self.deployable["name"]
         self.app_id = self.node.app_manager.new(self.name)
         self.ns = os.path.splitext(os.path.basename(self.name))[0]
     else:
         self.app_id = self.node.app_manager.new(None)
         self.name = self.app_id
         self.ns = ""
     self.group_components()
     _log.analyze(self.node.id, "+ SECURITY", {'sec': str(self.sec)})
Example #11
0
    def testSecurity_POSITIVE_RADIUS_Authentication(self):
        _log.analyze("TESTRUN", "+", {})
        global rt3
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(security_test_dir, "scripts", "test_security1_correctly_signed.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt3, "test_security1_correctly_signed", content['file'], 
                        credentials={"testdomain":{"user":"******", "password":"******"}}, content=content, 
                        check=True)
        except Exception as e:
            if isinstance(e, Timeout):
                raise Exception("Can't connect to RADIUS server. Have you started a RADIUS server?")
            elif e.message.startswith("401"):
                raise Exception("Failed security verification of app test_security1_correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app test_security1_correctly_signed, no use to verify if requirements fulfilled")
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt3)
        assert result['actor_map']['test_security1_correctly_signed:src'] in actors
        assert result['actor_map']['test_security1_correctly_signed:sum'] in actors
        assert result['actor_map']['test_security1_correctly_signed:snk'] in actors

        actual = request_handler.report(rt3, result['actor_map']['test_security1_correctly_signed:snk'])
        assert len(actual) > 5

        request_handler.delete_application(rt3, result['application_id'])
Example #12
0
    def testSecurity_POSITIVE_External_Authorization(self):
        _log.analyze("TESTRUN", "+", {})
        global rt4
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(security_test_dir, "scripts", "test_security1_unsignedApp_signedActors.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt4, "test_security1_unsignedApp_signedActors", content['file'], 
                        credentials={"testdomain":{"user":"******","password":"******"}}, content=content, 
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app test_security1_unsignedApp_signedActors")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app test_security1_unsignedApp_signedActors, no use to verify if requirements fulfilled")
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt4)
        assert result['actor_map']['test_security1_unsignedApp_signedActors:src'] in actors
        assert result['actor_map']['test_security1_unsignedApp_signedActors:sum'] in actors
        assert result['actor_map']['test_security1_unsignedApp_signedActors:snk'] in actors

        actual = request_handler.report(rt4, result['actor_map']['test_security1_unsignedApp_signedActors:snk'])
        assert len(actual) > 5

        request_handler.delete_application(rt4, result['application_id'])
Example #13
0
    def testSecurity_NEGATIVE_Deny_SignedApp_SignedActor_UnallowedRequirement(self):
        _log.analyze("TESTRUN", "+", {})
        global rt2
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(security_test_dir, "scripts", "test_security1_correctly_signed.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt2, "test_security1_correctly_signed", content['file'], 
                        credentials={"testdomain":{"user":"******", "password":"******"}}, content=content, 
                        check=True)
        except Exception as e:
            _log.debug(str(e))
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app test_security1_correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app test_security1_correctly_signed, no use to verify if requirements fulfilled")
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt2)
        assert result['actor_map']['test_security1_correctly_signed:src'] in actors
        assert result['actor_map']['test_security1_correctly_signed:sum'] in actors
        assert result['actor_map']['test_security1_correctly_signed:snk'] in actors

        actual = request_handler.report(rt2, result['actor_map']['test_security1_correctly_signed:snk'])
        assert len(actual) == 0  # Means that the actor with unallowed requirements was not accepted

        request_handler.delete_application(rt2, result['application_id'])
Example #14
0
    def testSecurity_POSITIVE_External_Authorization(self):
        _log.analyze("TESTRUN", "+", {})
        global rt4
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(security_test_dir, "scripts", "test_security1_unsignedApp_signedActors.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt4, "test_security1_unsignedApp_signedActors", content['file'], 
                        credentials={"user": ["user2"], "password": ["pass2"]}, content=content, 
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app test_security1_unsignedApp_signedActors")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app test_security1_unsignedApp_signedActors, no use to verify if requirements fulfilled")
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt4)
        assert result['actor_map']['test_security1_unsignedApp_signedActors:src'] in actors
        assert result['actor_map']['test_security1_unsignedApp_signedActors:sum'] in actors
        assert result['actor_map']['test_security1_unsignedApp_signedActors:snk'] in actors

        actual = request_handler.report(rt4, result['actor_map']['test_security1_unsignedApp_signedActors:snk'])
        assert len(actual) > 5

        request_handler.delete_application(rt4, result['application_id'])
Example #15
0
    def testSecurity_NEGATIVE_Deny_SignedApp_SignedActor_UnallowedRequirement(self):
        _log.analyze("TESTRUN", "+", {})
        global rt2
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(security_test_dir, "scripts", "test_security1_correctly_signed.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt2, "test_security1_correctly_signed", content['file'], 
                        credentials={"user": ["user1"], "password": ["pass1"]}, content=content, 
                        check=True)
        except Exception as e:
            _log.debug(str(e))
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app test_security1_correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app test_security1_correctly_signed, no use to verify if requirements fulfilled")
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt2)
        assert result['actor_map']['test_security1_correctly_signed:src'] in actors
        assert result['actor_map']['test_security1_correctly_signed:sum'] in actors
        assert result['actor_map']['test_security1_correctly_signed:snk'] in actors

        actual = request_handler.report(rt2, result['actor_map']['test_security1_correctly_signed:snk'])
        assert len(actual) == 0  # Means that the actor with unallowed requirements was not accepted

        request_handler.delete_application(rt2, result['application_id'])
Example #16
0
    def testSecurity_NEGATIVE_IncorrectPassword(self):
        _log.analyze("TESTRUN", "+", {})
        global rt1
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(security_test_dir, "scripts", "test_security1_correctly_signed.calvin")
            )
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(
                rt1,
                "test_security1_correctly_signed",
                content["file"],
                credentials={"testdomain": {"user": "******", "password": "******"}},
                content=content,
                check=True,
            )
        except Exception as e:
            if e.message.startswith("401"):
                # We were blocked, as we should
                return
            _log.exception("Test deploy failed for non security reasons")

        raise Exception("Deployment of app test_security1_correctly_signed, did not fail for security reasons")
Example #17
0
def deploy_signed_application_that_should_fail(request_handler, runtimes, name, application_path, retries=20):
    """
    Deploys app associated w/ deployer and then tries to verify its
    presence in registry (for all runtimes).
    """
    from calvin.utilities.security import Security
    delay = 0.1
    retry = 0
    result = None
    while retry < retries:
        try:
            content = Security.verify_signature_get_files(application_path)
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(runtimes, name, script=content['file'], content=content, check=True)
        except Exception as e:
            try:
                if e.message.startswith("401"):
                    return
            except Exception as e:
                _log.error("Failed for other reasons, continue, e={}".format(e))
                continue
        delay = min(2, delay * 1.5); retry += 1
        time.sleep(delay)
        _log.info("Deployment failed, but not due to security reasons, %d retries" % (retry))
    raise Exception("Deployment of app correctly_signed, did not fail for security reasons")
Example #18
0
    def testSecurity_POSITIVE_RADIUS_Authentication(self):
        _log.analyze("TESTRUN", "+", {})
        global rt3
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(security_test_dir + "/scripts/test_security1_correctly_signed.calvin")
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt3, "test_security1_correctly_signed", content['file'], 
                        credentials={"user": ["radius_user1"], "password": ["radius_passwd1"]}, content=content, 
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app test_security1_correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app test_security1_correctly_signed, no use to verify if requirements fulfilled")
        #print "RESULT:", result
        time.sleep(2)

        # For example verify that actors exist like this
        actors = request_handler.get_actors(rt3)
        assert result['actor_map']['test_security1_correctly_signed:src'] in actors
        assert result['actor_map']['test_security1_correctly_signed:sum'] in actors
        assert result['actor_map']['test_security1_correctly_signed:snk'] in actors

        actual = request_handler.report(rt3, result['actor_map']['test_security1_correctly_signed:snk'])
        assert len(actual) > 5

        request_handler.delete_application(rt3, result['application_id'])
Example #19
0
    def testSecurity_NEGATIVE_UnallowedUser(self):
        _log.analyze("TESTRUN", "+", {})
        global storage_verified
        if not storage_verified:
            try:
                storage_verified = helpers.security_verify_storage(rt, request_handler)
            except Exception as err:
                _log.error("Failed storage verification, err={}".format(err))
                raise

        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(application_store_path, "correctly_signed.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({"user": "******", "password": "******"})
            result = request_handler.deploy_application(rt[1], "correctly_signed", content['file'], 
                        content=content,
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                # We were blocked, as we should
                return
            _log.exception("Test deploy failed for non security reasons")

        raise Exception("Deployment of app correctly_signed did not fail for security reasons")  
Example #20
0
    def testPositive_Permit_UnsignedApp_Unsigned_Actor(self):
        _log.analyze("TESTRUN", "+", {})
        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(application_store_path, "unsignedApp_unsignedActors.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({"user": "******", "password": "******"})
            result = request_handler.deploy_application(runtimes[1]["RT"], "unsignedApp_unsignedActors", content['file'], 
                        content=content,
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app unsignedApp_unsignedActors")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app unsignedApp_unsignedActors, no use to verify if requirements fulfilled")

        # Verify that actors exist like this
        try:
            actors = helpers.fetch_and_log_runtime_actors(runtimes, request_handler)
        except Exception as err:
            _log.error("Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['unsignedApp_unsignedActors:src'] in actors[1]
        assert result['actor_map']['unsignedApp_unsignedActors:sum'] in actors[1]
        assert result['actor_map']['unsignedApp_unsignedActors:snk'] in actors[1]

        actual = request_handler.report(runtimes[1]["RT"], result['actor_map']['unsignedApp_unsignedActors:snk'])
        assert len(actual) > 2

        request_handler.delete_application(runtimes[1]["RT"], result['application_id'])
Example #21
0
    def testSecurity_NEGATIVE_CorrectlySignedApp_IncorrectlySignedActor(self):
        _log.analyze("TESTRUN", "+", {})
        global storage_verified
        if not storage_verified:
            try:
                storage_verified = helpers.security_verify_storage(
                    rt, request_handler)
            except Exception as err:
                _log.error("Failed storage verification, err={}".format(err))
                raise

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(
                    application_store_path,
                    "correctlySignedApp_incorrectlySignedActor.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({
                "user": "******",
                "password": "******"
            })
            result = helpers.deploy_signed_application(
                request_handler, rt[1],
                "correctlySignedApp_incorrectlySignedActor", content)
        except Exception as e:
            _log.debug(str(e))
            if e.message.startswith("401"):
                raise Exception(
                    "Failed security verification of app correctlySignedApp_incorrectlySignedActor"
                )
            _log.error(
                "Test deploy failed for non security reasons, e={}".format(e))
            raise Exception(
                "Failed deployment of app correctlySignedApp_incorrectlySignedActor, no use to verify if requirements fulfilled"
            )

        snk = result['actor_map'][
            'correctlySignedApp_incorrectlySignedActor:snk']
        request_handler.set_credentials({"user": "******", "password": "******"})
        request_handler.report(rt[1], snk, kwargs={'active': True})
        try:
            helpers.actual_tokens(request_handler,
                                  rt[1],
                                  snk,
                                  size=5,
                                  retries=2)
        except Exception as e:
            if e.message.startswith("Not enough tokens"):
                # We were blocked, as we should
                helpers.delete_app(request_handler, rt[1],
                                   result['application_id'])
                return
            _log.error(
                "Test deploy failed for non security reasons, e={}".format(e))
        raise Exception(
            "Incorrectly signed actor was not stopped as it should have been")
Example #22
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)
Example #23
0
    def testSecurity_POSITIVE_Migration_When_Denied(self):
        _log.analyze("TESTRUN", "+", {})
        global storage_verified
        if not storage_verified:
            try:
                storage_verified = helpers.security_verify_storage(
                    rt, request_handler)
            except Exception as err:
                _log.error("Failed storage verification, err={}".format(err))
                raise

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(application_store_path,
                             "correctly_signed.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({
                "user": "******",
                "password": "******"
            })
            result = helpers.deploy_signed_application(request_handler, rt[1],
                                                       "correctly_signed",
                                                       content)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception(
                    "Failed security verification of app correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of app correctly_signed, no use to verify if requirements fulfilled"
            )

        # Verify that actors exist like this (all of them should have migrated to rt[2])
        try:
            actors = helpers.fetch_and_log_runtime_actors(rt, request_handler)
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['correctly_signed:src'] in actors[2]
        assert result['actor_map']['correctly_signed:sum'] in actors[2]
        assert result['actor_map']['correctly_signed:snk'] in actors[2]

        snk = result['actor_map']['correctly_signed:snk']
        request_handler.set_credentials({"user": "******", "password": "******"})
        request_handler.report(rt[2], snk, kwargs={'active': True})
        actual = helpers.actual_tokens(request_handler,
                                       rt[2],
                                       snk,
                                       size=5,
                                       retries=20)
        assert len(actual) > 4

        helpers.delete_app(request_handler, rt[1], result['application_id'])
Example #24
0
def compile_file(file, credentials=None):
    with open(file, 'r') as source:
        sourceText = source.read()
        content = None
        if credentials:
            content = Security.verify_signature_get_files(file, skip_file=True)
            if content:
                content['file'] = sourceText
        return compile(sourceText, file, content=content, credentials=credentials)
    def testSecurity_POSITIVE_CorrectlySignedApp_CorrectlySignedActors(self):
        _log.analyze("TESTRUN", "+", {})
        global rt
        global request_handler
        global security_testdir

        try:
            helpers.security_verify_storage(rt, request_handler)
        except Exception as err:
            _log.error("Failed storage verification, err={}".format(err))
            raise

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(application_store_path,
                             "correctly_signed.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({
                "user": "******",
                "password": "******"
            })
            result = request_handler.deploy_application(rt[1],
                                                        "correctly_signed",
                                                        content['file'],
                                                        content=content,
                                                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception(
                    "Failed security verification of app correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of app correctly_signed, no use to verify if requirements fulfilled"
            )

        # Verify that actors exist like this
        try:
            actors = helpers.fetch_and_log_runtime_actors(rt, request_handler)
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['correctly_signed:src'] in actors[1]
        assert result['actor_map']['correctly_signed:sum'] in actors[1]
        assert result['actor_map']['correctly_signed:snk'] in actors[1]
        request_handler.set_credentials({"user": "******", "password": "******"})
        actual = request_handler.report(
            rt[1], result['actor_map']['correctly_signed:snk'])
        print "actual=", actual
        assert len(actual) > 2

        request_handler.delete_application(rt[1], result['application_id'])
Example #26
0
def deploy_signed_application(request_handler, runtimes, name, application_path, retries=10):
    """
    Deploys app associated w/ deployer and then tries to verify its
    presence in registry (for all runtimes).
    """
    from functools import partial
    from calvin.utilities.security import Security
    content = Security.verify_signature_get_files(application_path)
    if not content:
        raise Exception("Failed finding script, signature and cert, stopping here")
    return retry(retries, partial(request_handler.deploy_application, runtimes, name, script=content['file'], content=content, check=True), lambda _: True, "Failed to deploy application")
Example #27
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()
Example #28
0
def compile(source_text, filename='', content=None, credentials=None, verify=True):
    # Steps taken:
    # 1) Verify signature when credentials supplied
    # 2) parser .calvin file -> IR. May produce syntax errors/warnings
    # 3) checker IR -> IR. May produce syntax errors/warnings
    # 4) analyzer IR -> app. Should not fail. Sets 'valid' property of IR to True/False

    deployable = {'valid': False, 'actors': {}, 'connections': {}}
    errors = [] #TODO: fill in something meaningful
    warnings = []
    if credentials:
        _log.debug("Check credentials...")
        sec = Security()
        sec.set_principal(credentials)
        if not sec.authenticate_principal():
            _log.error("Check credentials...failed authentication")
            # This error reason is detected in calvin control and gives proper REST response
            errors.append({'reason': "401: UNAUTHORIZED", 'line': 0, 'col': 0})
            return deployable, errors, warnings
        if not sec.verify_signature_content(content, "application"):
            _log.error("Check credentials...failed application verification")
            # This error reason is detected in calvin control and gives proper REST response
            errors.append({'reason': "401: UNAUTHORIZED", 'line': None, 'col': None})
            return deployable, errors, warnings

    _log.debug("Parsing...")
    ir, errors, warnings = calvin_parser(source_text, filename)
    _log.debug("Parsed %s, %s, %s" % (ir, errors, warnings))
    # If there were errors during parsing no IR will be generated
    if not errors:
        c_errors, c_warnings = check(ir, verify=verify)
        errors.extend(c_errors)
        warnings.extend(c_warnings)
        deployable = generate_app_info(ir, verify=verify)
        if errors:
            deployable['valid'] = False
    _log.debug("Compiled %s, %s, %s" % (deployable, errors, warnings))
    return deployable, errors, warnings
Example #29
0
    def testSecurity_POSITIVE_External_Authentication(self):
        _log.analyze("TESTRUN", "+", {})
        global storage_verified
        if not storage_verified:
            try:
                storage_verified = helpers.security_verify_storage(
                    rt, request_handler)
            except Exception as err:
                _log.error("Failed storage verification, err={}".format(err))
                raise

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(application_store_path,
                             "correctly_signed.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({
                "user": "******",
                "password": "******"
            })
            result = helpers.deploy_signed_application(request_handler, rt[1],
                                                       "correctly_signed",
                                                       content)
        except Exception as e:
            if isinstance(e, Timeout):
                raise Exception(
                    "Can't connect to runtime 5.\n\te={}".format(e))
            elif e.message.startswith("401"):
                raise Exception(
                    "Failed security verification of app correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of app correctly_signed, no use to verify if requirements fulfilled"
            )

        snk = result['actor_map']['correctly_signed:snk']
        request_handler.set_credentials({"user": "******", "password": "******"})
        request_handler.report(rt[1], snk, kwargs={'active': True})
        actual = helpers.actual_tokens(request_handler,
                                       rt[1],
                                       snk,
                                       size=5,
                                       retries=20)
        assert len(actual) > 4

        helpers.delete_app(request_handler, rt[1], result['application_id'])
Example #30
0
 def _new_actor(self, actor_type, actor_id=None, credentials=None):
     """Return a 'bare' actor of actor_type, raises an exception on failure."""
     if credentials is not None:
         sec = Security(self.node)
         sec.set_subject(credentials)
         sec.authenticate_subject()
     else:
         sec = None
     (found, is_primitive, class_) = ActorStore(security=sec).lookup(actor_type)
     if not found:
         # Here assume a primitive actor, now become shadow actor
         _log.analyze(self.node.id, "+ NOT FOUND CREATE SHADOW ACTOR", {'class': class_})
         found = True
         is_primitive = True
         class_ = ShadowActor
     if not found or not is_primitive:
         _log.error("Requested actor %s is not available" % (actor_type))
         raise Exception("ERROR_NOT_FOUND")
     try:
         # Create a 'bare' instance of the actor
         a = class_(actor_type, actor_id=actor_id)
     except Exception as e:
         _log.exception("")
         _log.error("The actor %s(%s) can't be instantiated." % (actor_type, class_.__init__))
         raise(e)
     try:
         a.set_credentials(credentials, security=sec)
         a._calvinsys = self.node.calvinsys()
         a.check_requirements()
     except Exception as e:
         _log.exception("Catched new from state")
         _log.analyze(self.node.id, "+ FAILED REQS CREATE SHADOW ACTOR", {'class': class_})
         a = ShadowActor(actor_type, actor_id=actor_id)
         a.set_credentials(credentials, security=sec)
         a._calvinsys = self.node.calvinsys()
     return a
Example #31
0
    def testSecurity_NEGATIVE_CorrectlySignedApp_IncorrectlySignedActor(self):
        _log.analyze("TESTRUN", "+", {})
        global rt1
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(
                    security_test_dir, "scripts", "test_security1_correctlySignedApp_incorrectlySignedActor.calvin"
                )
            )
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(
                rt1,
                "test_security1_correctlySignedApp_incorrectlySignedActor",
                content["file"],
                credentials={"testdomain": {"user": "******", "password": "******"}},
                content=content,
                check=True,
            )
        except Exception as e:
            _log.debug(str(e))
            if e.message.startswith("401"):
                raise Exception(
                    "Failed security verification of app test_security1_correctlySignedApp_incorrectlySignedActor"
                )
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of app test_security1_correctlySignedApp_incorrectlySignedActor, no use to verify if requirements fulfilled"
            )
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt1)
        assert result["actor_map"]["test_security1_correctlySignedApp_incorrectlySignedActor:src"] in actors
        assert result["actor_map"]["test_security1_correctlySignedApp_incorrectlySignedActor:sum"] in actors
        assert result["actor_map"]["test_security1_correctlySignedApp_incorrectlySignedActor:snk"] in actors

        actual = request_handler.report(
            rt1, result["actor_map"]["test_security1_correctlySignedApp_incorrectlySignedActor:snk"]
        )
        assert len(actual) == 0  # Means that the incorrectly signed actor was not accepted

        request_handler.delete_application(rt1, result["application_id"])
Example #32
0
 def set_credentials(self, credentials, security=None):
     """ Sets the credentials the actor operates under
         This will trigger an authentication of the credentials
         Optionally an authenticated Security instance can be supplied,
         to reduce the needed authentication processing.
     """
     _log.debug("actor.py: set_credentials: %s" % credentials)
     if credentials is None:
         return
     self.credentials = credentials
     if security:
         self.sec = security
     else:
         self.sec = Security()
         self.sec.set_principal(self.credentials)
         self.sec.authenticate_principal()
Example #33
0
    def testNegative_IncorrectPassword(self):
        _log.analyze("TESTRUN", "+", {})
        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(application_store_path, "correctly_signed.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({"user": "******", "password": "******"})
            result = request_handler.deploy_application(runtimes[1]["RT"], "correctly_signed", content['file'], 
                        content=content,
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                # We were blocked, as we should
                return
            _log.exception("Test deploy failed for non security reasons")

        raise Exception("Deployment of app correctly_signed, did not fail for security reasons")  
Example #34
0
    def testSecurity_POSITIVE_RADIUS_Authentication(self):
        _log.analyze("TESTRUN", "+", {})
        global rt3
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(security_test_dir, "scripts", "test_security1_correctly_signed.calvin")
            )
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(
                rt3,
                "test_security1_correctly_signed",
                content["file"],
                credentials={"testdomain": {"user": "******", "password": "******"}},
                content=content,
                check=True,
            )
        except Exception as e:
            if isinstance(e, Timeout):
                raise Exception("Can't connect to RADIUS server. Have you started a RADIUS server?")
            elif e.message.startswith("401"):
                raise Exception("Failed security verification of app test_security1_correctly_signed")
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of app test_security1_correctly_signed, no use to verify if requirements fulfilled"
            )
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt3)
        assert result["actor_map"]["test_security1_correctly_signed:src"] in actors
        assert result["actor_map"]["test_security1_correctly_signed:sum"] in actors
        assert result["actor_map"]["test_security1_correctly_signed:snk"] in actors

        actual = request_handler.report(rt3, result["actor_map"]["test_security1_correctly_signed:snk"])
        assert len(actual) > 5

        request_handler.delete_application(rt3, result["application_id"])
Example #35
0
    def set_credentials(self, credentials, security=None):
        """
        Set the credentials the actor operates under.

        This will trigger an authentication of the credentials.
        Optionally an authenticated Security instance can be supplied,
        to reduce the needed authentication processing.
        """
        _log.debug("actor.py: set_credentials: %s" % credentials)
        if credentials is None:
            return
        self.credentials = credentials
        if security:
            self.sec = security
        else:
            if self._calvinsys is not None:
                self.sec = Security(self._calvinsys._node)
                self.sec.set_subject(self.credentials)
                self.sec.authenticate_subject()
    def test_deploy_and_migrate_with_automatice_ca_discovery(self):
        _log.analyze("TESTRUN", "+", {})
        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(application_store_path, "unsignedApp_unsignedActors.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({"user": "******", "password": "******"})
            result = request_handler.deploy_application(runtimes[0]["RT"], "unsignedApp_unsignedActors", content['file'], 
                        content=content,
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed to deploy unsignedApp_unsignedActors")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app unsignedApp_unsignedActors, no use to verify if requirements fulfilled")
        #Log actor ids:
        _log.info("Actors id:s:\n\tsrc id={}\n\tsum={}\n\tsnk={}".format(result['actor_map']['unsignedApp_unsignedActors:src'],
                                                                        result['actor_map']['unsignedApp_unsignedActors:sum'],
                                                                        result['actor_map']['unsignedApp_unsignedActors:snk']))


        # Verify that actors exist like this
        try:
            actors = helpers.fetch_and_log_runtime_actors(runtimes, request_handler)
        except Exception as err:
            _log.error("Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['unsignedApp_unsignedActors:src'] in actors[0]
        assert result['actor_map']['unsignedApp_unsignedActors:sum'] in actors[0]
        assert result['actor_map']['unsignedApp_unsignedActors:snk'] in actors[0]
        time.sleep(1)
        try:
            actual = request_handler.report(runtimes[0]["RT"], result['actor_map']['unsignedApp_unsignedActors:snk'])
        except Exception as err:
            _log.error("Failed to report from runtime 0, err={}".format(err))
            raise
        _log.info("actual={}".format(actual))
        assert len(actual) > 5

        time.sleep(1)
        request_handler.delete_application(runtimes[0]["RT"], result['application_id'])
Example #37
0
def control_deploy(args):
    response = None
    reqs = requirements_file(args.reqs) if args.reqs else None
    if args.signer:
        conf = certificate.Config(configfile=None, domain=args.signer, readonly=True)
        certificate.sign_file(conf, args.script.name)
    source_text = args.script.read()
    credentials_ = None
    content = None
    if args.credentials:
        content = Security.verify_signature_get_files(args.script.name, skip_file=True)
        if content:
            content['file'] = source_text
    req_handler= handle_security_arguments(args)
    try:
        response = req_handler.deploy_application(args.node, args.script.name, source_text, reqs,
                                            content=content, check=args.check)
    except Exception as e:
        print e
    return response
Example #38
0
    def testSecurity_NEGATIVE_CorrectlySignedApp_IncorrectlySignedActor(self):
        _log.analyze("TESTRUN", "+", {})
        global storage_verified
        if not storage_verified:
            try:
                storage_verified = helpers.security_verify_storage(rt, request_handler)
            except Exception as err:
                _log.error("Failed storage verification, err={}".format(err))
                raise

        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(application_store_path, "correctlySignedApp_incorrectlySignedActor.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({"user": "******", "password": "******"})
            result = request_handler.deploy_application(rt[1], "correctlySignedApp_incorrectlySignedActor", content['file'], 
                    credentials={domain_name:{"user": "******", "password": "******"}}, content=content,
                        check=True)
        except Exception as e:
            _log.debug(str(e))
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app correctlySignedApp_incorrectlySignedActor")
            _log.exception("Test deploy failed")
            raise Exception("Failed deployment of app correctlySignedApp_incorrectlySignedActor, no use to verify if requirements fulfilled")

        # Verify that actors exist like this
        try:
            actors = helpers.fetch_and_log_runtime_actors(rt, request_handler)
        except Exception as err:
            _log.error("Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['correctlySignedApp_incorrectlySignedActor:src'] in actors[1]
        assert result['actor_map']['correctlySignedApp_incorrectlySignedActor:sum'] in actors[1]
        assert result['actor_map']['correctlySignedApp_incorrectlySignedActor:snk'] in actors[1]

        actual = request_handler.report(rt[1], result['actor_map']['correctlySignedApp_incorrectlySignedActor:snk'])
        _log.info("actual={}".format(actual))
        assert len(actual) == 0  # Means that the incorrectly signed actor was not accepted

        request_handler.delete_application(rt[1], result['application_id'])
Example #39
0
def deploy_signed_application_that_should_fail(request_handler,
                                               runtimes,
                                               name,
                                               application_path,
                                               retries=20):
    """
    Deploys app associated w/ deployer and then tries to verify its
    presence in registry (for all runtimes).
    """
    from calvin.utilities.security import Security
    delay = 0.1
    retry = 0
    result = None
    while retry < retries:
        try:
            content = Security.verify_signature_get_files(application_path)
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(runtimes,
                                                        name,
                                                        script=content['file'],
                                                        content=content,
                                                        check=True)
        except Exception as e:
            try:
                if e.message.startswith("401"):
                    return
            except Exception as e:
                _log.error(
                    "Failed for other reasons, continue, e={}".format(e))
                continue
        delay = min(2, delay * 1.5)
        retry += 1
        time.sleep(delay)
        _log.info(
            "Deployment failed, but not due to security reasons, %d retries" %
            (retry))
    raise Exception(
        "Deployment of app correctly_signed, did not fail for security reasons"
    )
Example #40
0
    def testSecurity_POSITIVE_Permit_UnsignedApp_Unsigned_Actor(self):
        _log.analyze("TESTRUN", "+", {})
        global rt2
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(security_test_dir, "scripts", "test_security1_unsignedApp_unsignedActors.calvin")
            )
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(
                rt2,
                "test_security1_unsignedApp_unsignedActors",
                content["file"],
                credentials={"testdomain": {"user": "******", "password": "******"}},
                content=content,
                check=True,
            )
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed security verification of app test_security1_unsignedApp_unsignedActors")
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of app test_security1_unsignedApp_unsignedActors, no use to verify if requirements fulfilled"
            )
        time.sleep(2)

        # Verify that actors exist like this
        actors = request_handler.get_actors(rt2)
        assert result["actor_map"]["test_security1_unsignedApp_unsignedActors:src"] in actors
        assert result["actor_map"]["test_security1_unsignedApp_unsignedActors:sum"] in actors
        assert result["actor_map"]["test_security1_unsignedApp_unsignedActors:snk"] in actors

        actual = request_handler.report(rt2, result["actor_map"]["test_security1_unsignedApp_unsignedActors:snk"])
        assert len(actual) > 5

        request_handler.delete_application(rt2, result["application_id"])
Example #41
0
    def testSecurity_NEGATIVE_IncorrectPassword(self):
        _log.analyze("TESTRUN", "+", {})
        global rt1
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(os.path.join(security_test_dir, "scripts", "test_security1_correctly_signed.calvin"))
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt1, "test_security1_correctly_signed", content['file'], 
                        credentials={"testdomain":{"user":"******", "password":"******"}}, content=content, 
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                # We were blocked, as we should
                return
            _log.exception("Test deploy failed for non security reasons")

        raise Exception("Deployment of app test_security1_correctly_signed, did not fail for security reasons")  
Example #42
0
    def testSecurity_NEGATIVE_UnallowedUser(self):
        _log.analyze("TESTRUN", "+", {})
        global rt1
        global security_test_dir

        self.verify_storage()

        result = {}
        try:
            content = Security.verify_signature_get_files(security_test_dir + "/scripts/test_security1_correctly_signed.calvin")
            if not content:
                raise Exception("Failed finding script, signature and cert, stopping here")
            result = request_handler.deploy_application(rt1, "test_security1_correctly_signed", content['file'], 
                        credentials={"user": ["user_not_allowed"], "password": ["pass1"]}, content=content, 
                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                # We were blocked, as we should
                return
            _log.exception("Test deploy failed for non security reasons")

        raise Exception("Deployment of app test_security1_correctly_signed, did not fail for security reasons")  
Example #43
0
def deploy_signed_application(request_handler,
                              runtimes,
                              name,
                              application_path,
                              retries=10):
    """
    Deploys app associated w/ deployer and then tries to verify its
    presence in registry (for all runtimes).
    """
    from functools import partial
    from calvin.utilities.security import Security
    content = Security.verify_signature_get_files(application_path)
    if not content:
        raise Exception(
            "Failed finding script, signature and cert, stopping here")
    return retry(
        retries,
        partial(request_handler.deploy_application,
                runtimes,
                name,
                script=content['file'],
                content=content,
                check=True), lambda _: True, "Failed to deploy application")
Example #44
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)
Example #45
0
class Actor(object):

    """
    Base class for all actors
    Need a name supplied.
    Subclasses need to declare the parameter
    calvinsys if they want access to system
    interface on the node, this parameter
    will be supplied by the node and not by user
    """

    # Class variable controls action priority order
    action_priority = tuple()

    # Internal state (status)
    class FSM(object):

        def __init__(self, states, initial, transitions, hooks=None, allow_invalid_transitions=True,
                     disable_transition_checks=False, disable_state_checks=False):
            self.states = states
            self._state = initial
            self.transitions = transitions
            self.hooks = hooks or {}
            self.allow_invalid_transitions = allow_invalid_transitions
            self.disable_transition_checks = disable_transition_checks
            # disable_state_checks is used in the verify_status decorator
            self.disable_state_checks = disable_state_checks

        def state(self):
            return self._state

        def transition_to(self, new_state):
            if new_state in self.transitions[self._state] or self.disable_transition_checks:
                hook = self.hooks.get((self._state, new_state), None)
                if hook:
                    hook()
                self._state = new_state
            else:
                msg = "Invalid transition %s -> %s" % (self, self.printable(new_state))
                if self.allow_invalid_transitions:
                    _log.warning("ALLOWING " + msg)
                    self._state = new_state
                else:
                    raise Exception(msg)

        def printable(self, state):
            return self.states.reverse_mapping[state]

        def __str__(self):
            return self.printable(self._state)

    STATUS = enum('LOADED', 'READY', 'PENDING', 'ENABLED')

    VALID_TRANSITIONS = {
        STATUS.LOADED : [STATUS.READY],
        STATUS.READY  : [STATUS.PENDING, STATUS.ENABLED],
        STATUS.PENDING: [STATUS.READY, STATUS.PENDING, STATUS.ENABLED],
        STATUS.ENABLED: [STATUS.READY, STATUS.PENDING]
    }

    test_args = ()
    test_kwargs = {}

    # What are the arguments, really?
    def __init__(self, actor_type, name='', allow_invalid_transitions=True, disable_transition_checks=False,
                 disable_state_checks=False, actor_id=None):
        """Should _not_ be overridden in subclasses."""
        super(Actor, self).__init__()
        self._type = actor_type
        self.name = name  # optional: human_readable_name
        self.id = actor_id or calvinuuid.uuid("ACTOR")
        _log.debug("New actor id: %s, supplied actor id %s" % (self.id, actor_id))
        self._deployment_requirements = []
        self._signature = None
        self._component_members = set([self.id])  # We are only part of component if this is extended
        self._managed = set(('id', 'name', '_deployment_requirements', '_signature', 'credentials'))
        self._calvinsys = None
        self._using = {}
        self.control = calvincontrol.get_calvincontrol()
        self.metering = metering.get_metering()
        self._migrating_to = None  # During migration while on the previous node set to the next node id
        self._last_time_warning = 0.0
        self.credentials = None

        self.inports = {p: actorport.InPort(p, self) for p in self.inport_names}
        self.outports = {p: actorport.OutPort(p, self) for p in self.outport_names}

        hooks = {
            (Actor.STATUS.PENDING, Actor.STATUS.ENABLED): self.will_start,
            (Actor.STATUS.ENABLED, Actor.STATUS.PENDING): self.will_stop,
        }
        self.fsm = Actor.FSM(Actor.STATUS, Actor.STATUS.LOADED, Actor.VALID_TRANSITIONS, hooks,
                             allow_invalid_transitions=allow_invalid_transitions,
                             disable_transition_checks=disable_transition_checks,
                             disable_state_checks=disable_state_checks)
        self.metering.add_actor_info(self)

    def set_credentials(self, credentials, security=None):
        """ Sets the credentials the actor operates under
            This will trigger an authentication of the credentials
            Optionally an authenticated Security instance can be supplied,
            to reduce the needed authentication processing.
        """
        _log.debug("actor.py: set_credentials: %s" % credentials)
        if credentials is None:
            return
        self.credentials = credentials
        if security:
            self.sec = security
        else:
            self.sec = Security()
            self.sec.set_principal(self.credentials)
            self.sec.authenticate_principal()

    def get_credentials(self):
        _log.debug("actor.py: get_credentials: %s" % self.credentials)
        return self.credentials

    @verify_status([STATUS.LOADED])
    def setup_complete(self):
        self.fsm.transition_to(Actor.STATUS.READY)

    def init(self):
        raise Exception("Implementing 'init()' is mandatory.")

    def will_start(self):
        """Override in actor subclass if actions need to be taken before starting."""
        pass

    def will_stop(self):
        """Override in actor subclass if actions need to be taken before stopping."""
        pass

    def will_migrate(self):
        """Override in actor subclass if actions need to be taken before migrating."""
        pass

    def did_migrate(self):
        """Override in actor subclass if actions need to be taken after migrating."""
        pass

    def will_end(self):
        """Override in actor subclass if actions need to be taken before destruction."""
        pass

    @verify_status([STATUS.LOADED])
    def check_requirements(self):
        """ Checks that all requirements are available and accessable in calvinsys """
        # Check the runtime and calvinsys execution access rights
        # Note when no credentials set no verification done
        if hasattr(self, 'sec') and not self.sec.check_security_actor_requirements(['runtime'] +
                                            (self.requires if hasattr(self, "requires") else [])):
            _log.debug("Security check on actor requirements failed")
            raise Exception('actor calvinsys security requirement not fullfilled')
        # Check availability of calvinsys subsystems
        if hasattr(self, "requires"):
            for req in self.requires:
                if not self._calvinsys.has_capability(req):
                    raise Exception("%s requires %s" % (self.id, req))

    def __getitem__(self, attr):
        if attr in self._using:
            return self._using[attr]
        raise KeyError(attr)

    def use(self, requirement, shorthand):
        self._using[shorthand] = self._calvinsys.use_requirement(self, requirement)

    def __str__(self):
        ip = ""
        for p in self.inports.values():
            ip = ip + str(p)
        op = ""
        for p in self.outports.values():
            op = op + str(p)
        s = "Actor: '%s' class '%s'\nstatus: %s\ninports: %s\noutports:%s" % (
            self.name, self._type, self.fsm, ip, op)
        return s

    @verify_status([STATUS.READY])
    def set_port_property(self, port_type, port_name, port_property, value):
        """Change a port property. Currently, setting 'fanout' on output ports is only allowed operation."""

        if port_type not in ('in', 'out'):
            _log.error("Illegal port type '%s' for actor '%s' of type '%s'" % (port_type, self.name, self._type))
            return False
        ports = self.outports if port_type == 'out' else self.inports
        if port_name not in ports:
            _log.error("Illegal %sport name '%s' for actor '%s' of type '%s'" %
                       (port_type, port_name, self.name, self._type))
            return False
        port = ports[port_name]
        if not hasattr(port, port_property):
            _log.error("Illegal property '%s' for %sport '%s' in actor '%s' of type '%s'" %
                       (port_property, port_type, port_name, self.name, self._type))
            return False
        setattr(port, port_property, value)
        return True

    @verify_status([STATUS.READY, STATUS.PENDING])
    def did_connect(self, port):
        """Called when a port is connected, checks actor is fully connected."""
        # If we happen to by in READY, go to PENDING
        if self.fsm.state() == Actor.STATUS.READY:
            self.fsm.transition_to(Actor.STATUS.PENDING)
        # Three non-patological options:
        # have inports, have outports, or have in- and outports

        if self.inports:
            for p in self.inports.values():
                if not p.is_connected():
                    return

        if self.outports:
            for p in self.outports.values():
                if not p.is_connected():
                    return

        # If we made it here, all ports are connected
        self.fsm.transition_to(Actor.STATUS.ENABLED)

        # Actor enabled, inform scheduler
        self._calvinsys.scheduler_wakeup()

    @verify_status([STATUS.ENABLED, STATUS.PENDING])
    def did_disconnect(self, port):
        """Called when a port is disconnected, checks actor is fully disconnected."""
        # If we happen to by in ENABLED, go to PENDING
        if self.fsm.state() == Actor.STATUS.ENABLED:
            self.fsm.transition_to(Actor.STATUS.PENDING)

        # Three non-patological options:
        # have inports, have outports, or have in- and outports
        if self.inports:
            for p in self.inports.values():
                if p.is_connected():
                    return

        if self.outports:
            for p in self.outports.values():
                if p.is_connected():
                    return

        # If we made it here, all ports are disconnected
        self.fsm.transition_to(Actor.STATUS.READY)

    @verify_status([STATUS.ENABLED])
    def fire(self):
        start_time = time.time()
        total_result = ActionResult(did_fire=False)
        while True:
            # Re-try action in list order after EVERY firing
            for action_method in self.__class__.action_priority:
                action_result = action_method(self)
                total_result.merge(action_result)
                # Action firing should fire the first action that can fire,
                # hence when fired start from the beginning
                if action_result.did_fire:
                    # FIXME: Make this a hook for the runtime too use, don't
                    #        import and use calvin_control or metering in actor
                    self.metering.fired(self.id, action_method.__name__)
                    self.control.log_actor_firing(
                        self.id,
                        action_method.__name__,
                        action_result.tokens_produced,
                        action_result.tokens_consumed,
                        action_result.production)
                    _log.debug("Actor %s(%s) did fire %s -> %s" % (
                        self._type, self.id,
                        action_method.__name__,
                        str(action_result)))
                    break

            if not action_result.did_fire:
                diff = time.time() - start_time
                if diff > 0.2 and start_time - self._last_time_warning > 120.0:
                    # Every other minute warn if an actor runs for longer than 200 ms
                    self._last_time_warning = start_time
                    _log.warning("%s (%s) actor blocked for %f sec" % (self.name, self._type, diff))
                # We reached the end of the list without ANY firing => return
                return total_result
        # Redundant as of now, kept as reminder for when rewriting exeption handling.
        raise Exception('Exit from fire should ALWAYS be from previous line.')

    def enabled(self):
        return self.fsm.state() == Actor.STATUS.ENABLED

    # DEPRECATED: Only here for backwards compatibility
    @verify_status([STATUS.ENABLED])
    def enable(self):
        self.fsm.transition_to(Actor.STATUS.ENABLED)

    @verify_status([STATUS.READY, STATUS.PENDING, STATUS.LOADED])
    # DEPRECATED: Only here for backwards compatibility
    def disable(self):
        self.fsm.transition_to(Actor.STATUS.PENDING)

    @verify_status([STATUS.LOADED, STATUS.READY, STATUS.PENDING])
    def state(self):
        state = {}
        # Manual state handling
        # Not available until after __init__ completes
        state['_managed'] = list(self._managed)
        state['inports'] = {port: self.inports[port]._state()
                            for port in self.inports}
        state['outports'] = {
            port: self.outports[port]._state() for port in self.outports}
        state['_component_members'] = list(self._component_members)

        # Managed state handling
        for key in self._managed:
            obj = self.__dict__[key]
            if _implements_state(obj):
                state[key] = obj.state()
            else:
                state[key] = obj

        return state

    @verify_status([STATUS.LOADED, STATUS.READY, STATUS.PENDING])
    def _set_state(self, state):
        # Managed state handling

        # Update since if previously a shadow actor the init has been called first
        # which potentially have altered the managed attributes set compared
        # with the recorded state
        self._managed.update(set(state['_managed']))

        for key in state['_managed']:
            if key not in self.__dict__:
                self.__dict__[key] = state.pop(key)
            else:
                obj = self.__dict__[key]
                if _implements_state(obj):
                    obj.set_state(state.pop(key))
                else:
                    self.__dict__[key] = state.pop(key)

        # Manual state handling
        for port in state['inports']:
            # Uses setdefault to support shadow actor
            self.inports.setdefault(port, actorport.InPort(port, self))._set_state(state['inports'][port])
        for port in state['outports']:
            # Uses setdefault to support shadow actor
            self.outports.setdefault(port, actorport.OutPort(port, self))._set_state(state['outports'][port])
        self._component_members= set(state['_component_members'])

    # TODO verify status should only allow reading connections when and after being fully connected (enabled)
    @verify_status([STATUS.ENABLED, STATUS.READY, STATUS.PENDING])
    def connections(self, node_id):
        c = {'actor_id': self.id, 'actor_name': self.name}
        inports = {}
        for port in self.inports.values():
            peer = port.get_peer()
            if peer[0] == 'local':
                peer = (node_id, peer[1])
            inports[port.id] = peer
        c['inports'] = inports
        outports = {}
        for port in self.outports.values():
            peers = [
                (node_id, p[1]) if p[0] == 'local' else p for p in port.get_peers()]
            outports[port.id] = peers
        c['outports'] = outports
        return c

    def serialize(self):
        return self.state()

    def deserialize(self, data):
        self._set_state(data)

    def exception_handler(self, action, args, context):
        """Defult handler when encountering ExceptionTokens"""
        _log.error("ExceptionToken encountered\n  name: %s\n  type: %s\n  action: %s\n  args: %s\n  context: %s\n" %
                   (self.name, self._type, action.__name__, args, context))
        raise Exception("ExceptionToken NOT HANDLED")

    def events(self):
        return []

    def component_add(self, actor_ids):
        if not isinstance(actor_ids, (set, list, tuple)):
            actor_ids = [actor_ids]
        self._component_members.update(actor_ids)

    def component_remove(self, actor_ids):
        if not isinstance(actor_ids, (set, list, tuple)):
            actor_ids = [actor_ids]
        self._component_members -= set(actor_ids)

    def part_of_component(self):
        return len(self._component_members - set([self.id]))>0

    def component_members(self):
        return self._component_members

    def requirements_add(self, deploy_reqs, extend=False):
        if extend:
            self._deployment_requirements.extend(deploy_reqs)
        else:
            self._deployment_requirements = deploy_reqs

    def requirements_get(self):
        return self._deployment_requirements + (
                [{'op': 'actor_reqs_match',
                  'kwargs': {'requires': self.requires},
                  'type': '+'}]
                if hasattr(self, 'requires') else [])

    def signature_set(self, signature):
        if self._signature is None:
            self._signature = signature
Example #46
0
    def testSecurity_deploy_and_migrate(self):
        _log.analyze("TESTRUN", "+", {})
        global rt
        global request_handler
        global security_testdir
        try:
            self.verify_storage()
        except Exception as err:
            _log.error("Failed storage verification, err={}".format(err))
            raise
        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(
                    application_store_path,
                    "test_security1_unsignedApp_unsignedActors.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials(
                {domain_name: {
                    "user": "******",
                    "password": "******"
                }})
            result = request_handler.deploy_application(
                rt[2],
                "test_security1_unsignedApp_unsignedActors",
                content['file'],
                content=content,
                check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception(
                    "Failed to deploy test_security1_unsignedApp_unsignedActors"
                )
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of app test_security1_unsignedApp_unsignedActors, no use to verify if requirements fulfilled"
            )
        time.sleep(2)
        # Verify that actors exist like this
        try:
            actors = fetch_and_log_runtime_actors()
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:src'] in actors[2]
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:sum'] in actors[2]
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:snk'] in actors[2]
        actual = request_handler.report(
            rt[2], result['actor_map']
            ['test_security1_unsignedApp_unsignedActors:snk'])
        _log.info("actual={}".format(actual))
        assert len(actual) > 5

        #Migrate snk actor to rt1
        time.sleep(1)
        request_handler.migrate(
            rt[2], result['actor_map']
            ['test_security1_unsignedApp_unsignedActors:snk'],
            request_handler.get_node_id(rt[1]))
        time.sleep(1)
        try:
            actors = fetch_and_log_runtime_actors()
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:src'] in actors[2]
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:sum'] in actors[2]
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:snk'] in actors[1]
        _log.info("kommer hit")
        actual = request_handler.report(
            rt[1], result['actor_map']
            ['test_security1_unsignedApp_unsignedActors:snk'])
        _log.info("actual={}".format(actual))
        assert len(actual) > 3

        #Migrate src actor to rt3
        time.sleep(1)
        request_handler.migrate(
            rt[2], result['actor_map']
            ['test_security1_unsignedApp_unsignedActors:src'],
            request_handler.get_node_id(rt[3]))
        time.sleep(1)
        try:
            actors = fetch_and_log_runtime_actors()
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:src'] in actors[3]
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:sum'] in actors[2]
        assert result['actor_map'][
            'test_security1_unsignedApp_unsignedActors:snk'] in actors[1]
        actual = request_handler.report(
            rt[1], result['actor_map']
            ['test_security1_unsignedApp_unsignedActors:snk'])
        _log.info("actual={}".format(actual))
        assert len(actual) > 3

        request_handler.delete_application(rt[2], result['application_id'])
Example #47
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)
Example #48
0
    def testSecurity_deploy_and_migrate(self):
        _log.analyze("TESTRUN", "+", {})
        global rt
        global request_handler
        global security_testdir
        start = time.time()
        try:
            helpers.security_verify_storage(rt, request_handler)
        except Exception as err:
            _log.error("Failed storage verification, err={}".format(err))
            raise
        time_to_verify_storaget = time.time() - start
        time.sleep(1)
        try:
            rt0_id = request_handler.get_node_id(rt[0])
            rt1_id = request_handler.get_node_id(rt[1])
        except Exception as err:
            _log.error("Failed to fetch runtime ids, err={}".format(err))
            raise
        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(application_store_path,
                             "unsignedApp_unsignedActors.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials({
                "user": "******",
                "password": "******"
            })
            result = request_handler.deploy_application(
                rt[0],
                "unsignedApp_unsignedActors",
                content['file'],
                content=content,
                check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed to deploy unsignedApp_unsignedActors")
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of app unsignedApp_unsignedActors, no use to verify if requirements fulfilled"
            )
        try:
            actors = helpers.fetch_and_log_runtime_actors(rt, request_handler)
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
#Log actor ids:
        _log.info("Actors id:s:\n\tsrc id={}\n\tsum={}\n\tsnk={}".format(
            result['actor_map']['unsignedApp_unsignedActors:src'],
            result['actor_map']['unsignedApp_unsignedActors:sum'],
            result['actor_map']['unsignedApp_unsignedActors:snk']))

        # Verify that actors exist like this
        try:
            actors = helpers.fetch_and_log_runtime_actors(rt, request_handler)
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['unsignedApp_unsignedActors:src'] in actors[
            0]
        assert result['actor_map']['unsignedApp_unsignedActors:sum'] in actors[
            0]
        assert result['actor_map']['unsignedApp_unsignedActors:snk'] in actors[
            0]
        time.sleep(1)
        try:
            actual = request_handler.report(
                rt[0], result['actor_map']['unsignedApp_unsignedActors:snk'])
        except Exception as err:
            _log.error("Failed to report from runtime 0, err={}".format(err))
            raise
        _log.info("actual={}".format(actual))
        assert len(actual) > 5

        #Migrate snk actor to rt1
        time.sleep(2)
        _log.info(
            "Let's migrate actor {} from runtime {}(rt0) to runtime {}(rt1)".
            format(rt0_id,
                   result['actor_map']['unsignedApp_unsignedActors:snk'],
                   rt1_id))
        try:
            request_handler.migrate(
                rt[0], result['actor_map']['unsignedApp_unsignedActors:snk'],
                rt1_id)
        except Exception as err:
            _log.error(
                "Failed to send first migration request to runtime 0, err={}".
                format(err))
            raise
        try:
            actors = helpers.fetch_and_log_runtime_actors(rt, request_handler)
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['unsignedApp_unsignedActors:src'] in actors[
            0]
        assert result['actor_map']['unsignedApp_unsignedActors:sum'] in actors[
            0]
        assert result['actor_map']['unsignedApp_unsignedActors:snk'] in actors[
            1]
        time.sleep(1)
        try:
            actual = request_handler.report(
                rt[1], result['actor_map']['unsignedApp_unsignedActors:snk'])
        except Exception as err:
            _log.error(
                "Failed to report snk values from runtime 1, err={}".format(
                    err))
            raise
        _log.info("actual={}".format(actual))
        assert len(actual) > 3

        #Migrate src actor to rt3
        time.sleep(1)
        try:
            request_handler.migrate(
                rt[0], result['actor_map']['unsignedApp_unsignedActors:src'],
                rt1_id)
        except Exception as err:
            _log.error(
                "Failed to send second migration requestfrom runtime 0, err={}"
                .format(err))
            raise
        try:
            actors = helpers.fetch_and_log_runtime_actors(rt, request_handler)
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['unsignedApp_unsignedActors:src'] in actors[
            1]
        assert result['actor_map']['unsignedApp_unsignedActors:sum'] in actors[
            0]
        assert result['actor_map']['unsignedApp_unsignedActors:snk'] in actors[
            1]
        time.sleep(1)
        try:
            actual = request_handler.report(
                rt[1], result['actor_map']['unsignedApp_unsignedActors:snk'])
        except Exception as err:
            _log.error(
                "Failed to report snk values from runtime 1, err={}".format(
                    err))
            raise
        _log.info("actual={}".format(actual))
        assert len(actual) > 3
        _log.info(
            "\n\t----------------------------"
            "\n\tTotal time to verify storage is {} seconds"
            "\n\tTotal time of entire (including storage verification) is {} seconds"
            "\n\t----------------------------".format(time_to_verify_storaget,
                                                      time.time() - start))

        time.sleep(1)
        request_handler.delete_application(rt[0], result['application_id'])
Example #49
0
class Deployer(object):

    """
    Process an app_info dictionary (output from calvin parser) to
    produce a running calvin application.
    """

    def __init__(self, deployable, node, name=None, deploy_info=None, credentials=None, verify=True, cb=None):
        super(Deployer, self).__init__()
        self.deployable = deployable
        self.deploy_info = deploy_info
        self.credentials = credentials
        self.sec = Security(node)
        self.sec.set_subject(self.credentials)
        self.actorstore = ActorStore(security=self.sec)
        self.actor_map = {}
        self.actor_connections = {}
        self.node = node
        self.verify = verify
        self.cb = cb
        self._deploy_cont_done = False
        if name:
            self.name = name
            self.app_id = self.node.app_manager.new(self.name)
            self.ns = os.path.splitext(os.path.basename(self.name))[0]
        elif "name" in self.deployable:
            self.name = self.deployable["name"]
            self.app_id = self.node.app_manager.new(self.name)
            self.ns = os.path.splitext(os.path.basename(self.name))[0]
        else:
            self.app_id = self.node.app_manager.new(None)
            self.name = self.app_id
            self.ns = ""
        self.group_components()
        _log.analyze(self.node.id, "+ SECURITY", {'sec': str(self.sec)})

    # TODO Make deployer use the Application class group_components, component_name and get_req
    def group_components(self):
        self.components = {}
        l = (len(self.ns)+1) if self.ns else 0
        for name in self.deployable['actors']:
             if name.find(':',l)> -1:
                # This is part of a component
                # component name including optional namespace
                component = ':'.join(name.split(':')[0:(2 if self.ns else 1)])
                if component in self.components:
                    self.components[component].append(name)
                else:
                    self.components[component] = [name]

    def component_name(self, name):
        l = (len(self.ns)+1) if self.ns else 0
        if name.find(':',l)> -1:
            return ':'.join(name.split(':')[0:(2 if self.ns else 1)])
        else:
            return None

    def get_req(self, actor_name):
        name = self.component_name(actor_name) or actor_name
        name = name.split(':', 1)[1] if self.ns else name
        return self.deploy_info['requirements'][name] if (self.deploy_info and 'requirements' in self.deploy_info
                                                            and name in self.deploy_info['requirements']) else []

    def instantiate(self, actor_name, actor_type, argd, signature=None):
        """
        Instantiate an actor.
          - 'actor_name' is <namespace>:<identifier>, e.g. app:src, or app:component:src
          - 'actor_type' is the actor class to instatiate
          - 'argd' is a dictionary with <actor_name>:<argdict> pairs
          - 'signature' is the GlobalStore actor-signature to lookup the actor
        """
        req = self.get_req(actor_name)
        _log.analyze(self.node.id, "+ SECURITY", {'sec': str(self.sec)})
        found, is_primitive, actor_def = self.actorstore.lookup(actor_type)
        if not found or not is_primitive:
            raise Exception("Not known actor type: %s" % actor_type)

        actor_id = self.instantiate_primitive(actor_name, actor_type, argd, req, signature)
        if not actor_id:
            raise Exception(
                "Could not instantiate actor of type: %s" % actor_type)
        self.actor_map[actor_name] = actor_id
        self.node.app_manager.add(self.app_id, actor_id)

    def instantiate_primitive(self, actor_name, actor_type, args, req=None, signature=None):
        # name is <namespace>:<identifier>, e.g. app:src, or app:component:src
        # args is a **dictionary** of key-value arguments for this instance
        # signature is the GlobalStore actor-signature to lookup the actor
        args['name'] = actor_name
        actor_id = self.node.am.new(actor_type=actor_type, args=args, signature=signature, credentials=self.credentials)
        if req:
            self.node.am.actors[actor_id].requirements_add(req, extend=False)
        return actor_id

    def connectid(self, connection):
        src_actor, src_port, dst_actor, dst_port = connection
        # connect from dst to src
        # use node info if exists, otherwise assume local node

        dst_actor_id = self.actor_map[dst_actor]
        src_actor_id = self.actor_map[src_actor]
        src_node = self.node.id
        result = self.node.connect(
            actor_id=dst_actor_id,
            port_name=dst_port,
            port_dir='in',
            peer_node_id=src_node,
            peer_actor_id=src_actor_id,
            peer_port_name=src_port,
            peer_port_dir='out')
        return result

    def set_port_property(self, actor, port_type, port_name, port_property, value):
        self.node.am.set_port_property(self.actor_map[actor], port_type, port_name, port_property, value)

    def select_actor(self, out_iter, kwargs, final, comp_name_desc):
        _log.analyze(self.node.id, "+", {'comp_name_desc': comp_name_desc}, tb=True)
        if final[0] and not kwargs['done']:
            kwargs['done'] = True
            for name, desc_list in kwargs['priority'].iteritems():
                if desc_list:
                    out_iter.append(desc_list[0])
            out_iter.final()
            return
        desc = comp_name_desc[1]
        try:
            # List of (found, is_primitive, info)
            actor_types = [self.actorstore.lookup(actor['actor_type'])
                                for actor in desc['component']['structure']['actors'].values()]
        except KeyError:
            actor_types = []
            # Not a component, shadow actor candidate, likely
            kwargs['priority'][comp_name_desc[0]].insert(0, comp_name_desc)
            comp_name_desc[1]['shadow_actor'] = True
            return
        except Exception as e:
            # FIXME Handled when security verification failed
            _log.exception("select_actor desc: %s" % desc)
            raise e
        if all([a[0] and a[1] for a in actor_types]):
            # All found and primitive (quite unlikely), insert after any primitive shadow actors in priority
            index = len([1 for a in kwargs['priority'][comp_name_desc[0]] if 'shadow_actor' in a[1]])
            kwargs['priority'][comp_name_desc[0]].insert(index, comp_name_desc)
            comp_name_desc[1]['shadow_component'] = actor_types
            return
        # A component containing shadow actors
        # TODO Dig deeper to priorities between shadow components, now just insert in order
        kwargs['priority'][comp_name_desc[0]].append(comp_name_desc)
        comp_name_desc[1]['shadow_component'] = actor_types

    def resolve_remote(self, deployables):
        all_desc_iters = dynops.List()
        store = GlobalStore(node=self.node)
        for actor_name, info in deployables.iteritems():
            desc_iter = store.global_lookup_iter(info['signature'], info['args'].keys())
            all_desc_iters.append((actor_name, desc_iter), trigger_iter=desc_iter)
        all_desc_iters.final()
        collect_desc_iter = dynops.Collect(all_desc_iters).set_name("collected_desc")
        select_iter = dynops.Map(self.select_actor, collect_desc_iter, done=False,
                                                         priority={k:[] for k in self.deployable['actors'].keys()},
                                                         eager=True).set_name("select_actor")
        select_iter.set_cb(self.deploy_unhandled_actors, select_iter)
        self.deploy_unhandled_actors(select_iter)

    def deploy_unhandled_actors(self, comp_name_desc):
        while True:
            try:
                name, desc = comp_name_desc.next()
                _log.analyze(self.node.id, "+", {'name': name, 'desc': desc}, tb=True)
            except StopIteration:
                # Done
                if self._deploy_cont_done:
                    return
                self._deploy_cont_done = True
                self.group_components()
                _log.analyze(self.node.id, "+ DONE", {'deployable': self.deployable, 'components': self.components})
                self._deploy_cont()
                return
            except dynops.PauseIteration:
                return
            if 'shadow_actor' in desc:
                _log.analyze(self.node.id, "+ SHADOW ACTOR", {'name': name})
                # It was a normal primitive shadow actor, just instanciate
                req = self.get_req(name)
                info = self.deployable['actors'][name]
                actor_id = self.instantiate_primitive(name, info['actor_type'], info['args'], req, info['signature'])
                if not actor_id:
                    _log.error("Second phase, could not make shadow actor %s!" % info['actor_type'])
                self.actor_map[name] = actor_id
                self.node.app_manager.add(self.app_id, actor_id)
            elif 'shadow_component' in desc:
                _log.analyze(self.node.id, "+ SHADOW COMPONENT", {'name': name})
                # A component that needs to be broken up into individual primitive actors
                # First get the info and remove the component
                req = self.get_req(name)
                info = self.deployable['actors'][name]
                self.deployable['actors'].pop(name)
                # Then add the new primitive actors
                for actor_name, actor_desc in desc['component']['structure']['actors'].iteritems():
                    args = {k: v[1] if v[0] == 'VALUE' else info['args'][v[1]] for k, v in actor_desc['args'].iteritems()}
                    inports = [c['dst_port'] for c in desc['component']['structure']['connections'] if c['dst'] == actor_name]
                    outports = [c['src_port'] for c in desc['component']['structure']['connections'] if c['src'] == actor_name]
                    sign_desc = {'is_primitive': True,
                                 'actor_type': actor_desc['actor_type'],
                                 'inports': inports[:],
                                 'outports': outports[:]}
                    sign = GlobalStore.actor_signature(sign_desc)
                    self.deployable['actors'][name + ":" + actor_name] = {'args': args,
                                                                          'actor_type': actor_desc['actor_type'],
                                                                          'signature_desc': sign_desc,
                                                                          'signature': sign}
                    # Replace component connections with actor connection
                    #   outports
                    comp_outports = [(c['dst_port'], c['src_port']) for c in desc['component']['structure']['connections']
                                        if c['src'] == actor_name and c['dst'] == "."]
                    for c_port, a_port in comp_outports:
                        if (name + "." + c_port) in self.deployable['connections']:
                            self.deployable['connections'][name + ":" + actor_name + "." + a_port] = \
                                self.deployable['connections'].pop(name + "." + c_port)
                    #   inports
                    comp_inports = [(c['src_port'], c['dst_port']) for c in desc['component']['structure']['connections']
                                        if c['dst'] == actor_name and c['src'] == "."]
                    for outport, ports in self.deployable['connections'].iteritems():
                        for c_inport, a_inport in comp_inports:
                            if (name + "." + c_inport) in ports:
                                ports.remove(name + "." + c_inport)
                                ports.append(name + ":" + actor_name + "." + a_inport)
                    _log.analyze(self.node.id, "+ REPLACED PORTS", {'comp_outports': comp_outports,
                                                                   'comp_inports': comp_inports,
                                                                   'actor_name': actor_name,
                                                                   'connections': self.deployable['connections']})
                    # Add any new component internal connections (enough with outports)
                    for connection in desc['component']['structure']['connections']:
                        if connection['src'] == actor_name and connection['src_port'] in outports and connection['dst'] != ".":
                            self.deployable['connections'].setdefault(
                                name + ":" + actor_name + "." + connection['src_port'], []).append(
                                    name + ":" + connection['dst'] + "." + connection['dst_port'])
                    _log.analyze(self.node.id, "+ ADDED PORTS", {'connections': self.deployable['connections']})
                    # Instanciate it
                    actor_id = self.instantiate_primitive(name + ":" + actor_name, actor_desc['actor_type'], args, req, sign)
                    if not actor_id:
                        _log.error("Third phase, could not make shadow actor %s!" % info['actor_type'])
                    self.actor_map[name + ":" + actor_name] = actor_id
                    self.node.app_manager.add(self.app_id, actor_id)


    def deploy(self):
        """
        Instantiate actors and link them together.
        """
        if not self.deployable['valid']:
            raise Exception("Deploy information is not valid")

        unhandled = {}

        for actor_name, info in self.deployable['actors'].iteritems():
            try:
                self.instantiate(actor_name, info['actor_type'], info['args'], signature=info['signature'])
            except:
                unhandled[actor_name] = info

        if unhandled:
            _log.analyze(self.node.id, "+ UNHANDLED", {'unhandled': unhandled})
            self.resolve_remote(unhandled)
            return

        self._deploy_cont()

    def _deploy_cont(self):
        for component_name, actor_names in self.components.iteritems():
            actor_ids = [self.actor_map[n] for n in actor_names]
            for actor_id in actor_ids:
                self.node.am.actors[actor_id].component_add(actor_ids)

        for src, dst_list in self.deployable['connections'].iteritems():
            if len(dst_list) > 1:
                src_name, src_port = src.split('.')
                self.set_port_property(src_name, 'out', src_port, 'fanout', len(dst_list))

        for src, dst_list in self.deployable['connections'].iteritems():
            src_actor, src_port = src.split('.')
            for dst in dst_list:
                dst_actor, dst_port = dst.split('.')
                c = (src_actor, src_port, dst_actor, dst_port)
                self.connectid(c)

        self.node.app_manager.finalize(self.app_id, migrate=True if self.deploy_info else False,
                                       cb=CalvinCB(self.cb, deployer=self))
Example #50
0
    def testSecurity_deploy_and_migrate(self):
        _log.analyze("TESTRUN", "+", {})
        global storage_verified
        if not storage_verified:
            try:
                storage_verified = helpers.security_verify_storage(
                    rt, request_handler)
            except Exception as err:
                _log.error("Failed storage verification, err={}".format(err))
                raise
        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(orig_application_store_path,
                             "correctly_signed.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials(
                {domain_name: {
                    "user": "******",
                    "password": "******"
                }})
            result = request_handler.deploy_application(rt[2],
                                                        "test_script",
                                                        content['file'],
                                                        content=content,
                                                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed to deploy script")
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of script, no use to verify if requirements fulfilled"
            )

        #Log actor ids:
        _log.info("Actors id:s:\n\tsrc id={}\n\tsum={}\n\tsnk={}".format(
            result['actor_map']['test_script:src'],
            result['actor_map']['test_script:sum'],
            result['actor_map']['test_script:snk']))

        # Verify that actors exist like this
        try:
            actors = helpers.fetch_and_log_runtime_actors(rt, request_handler)
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['test_script:src'] in actors[2]
        assert result['actor_map']['test_script:sum'] in actors[2]
        assert result['actor_map']['test_script:snk'] in actors[2]
        time.sleep(1)
        try:
            actual = request_handler.report(
                rt[2], result['actor_map']['test_script:snk'])
        except Exception as err:
            _log.error("Failed to report from runtime 2, err={}".format(err))
            raise
        _log.info("actual={}".format(actual))
        assert len(actual) > 5

        time.sleep(1)
        request_handler.delete_application(rt[2], result['application_id'])
Example #51
0
    def testSecurity_deploy_and_migrate(self):
        _log.analyze("TESTRUN", "+", {})
        global rt
        global request_handler
        global security_testdir
        try:
            rt0_id = request_handler.get_node_id(rt[0])
            rt1_id = request_handler.get_node_id(rt[1])
            rt2_id = request_handler.get_node_id(rt[2])
            rt3_id = request_handler.get_node_id(rt[3])
            rt4_id = request_handler.get_node_id(rt[4])
            rt5_id = request_handler.get_node_id(rt[5])
        except Exception as err:
            _log.error("Failed to fetch runtime ids, err={}".format(err))
            raise
        time.sleep(1)
        try:
            self.verify_storage()
        except Exception as err:
            _log.error("Failed storage verification, err={}".format(err))
            raise
        result = {}
        try:
            content = Security.verify_signature_get_files(
                os.path.join(orig_application_store_path,
                             "test_security1_correctly_signed.calvin"))
            if not content:
                raise Exception(
                    "Failed finding script, signature and cert, stopping here")
            request_handler.set_credentials(
                {domain_name: {
                    "user": "******",
                    "password": "******"
                }})
            result = request_handler.deploy_application(rt[2],
                                                        "test_script",
                                                        content['file'],
                                                        content=content,
                                                        check=True)
        except Exception as e:
            if e.message.startswith("401"):
                raise Exception("Failed to deploy script")
            _log.exception("Test deploy failed")
            raise Exception(
                "Failed deployment of script, no use to verify if requirements fulfilled"
            )
        time.sleep(2)

        #Log actor ids:
        _log.info("Actors id:s:\n\tsrc id={}\n\tsum={}\n\tsnk={}".format(
            result['actor_map']['test_script:src'],
            result['actor_map']['test_script:sum'],
            result['actor_map']['test_script:snk']))

        # Verify that actors exist like this
        try:
            actors = fetch_and_log_runtime_actors()
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['test_script:src'] in actors[2]
        assert result['actor_map']['test_script:sum'] in actors[2]
        assert result['actor_map']['test_script:snk'] in actors[2]
        time.sleep(1)
        try:
            actual = request_handler.report(
                rt[2], result['actor_map']['test_script:snk'])
        except Exception as err:
            _log.error("Failed to report from runtime 2, err={}".format(err))
            raise
        _log.info("actual={}".format(actual))
        assert len(actual) > 5

        #Migrate snk actor to rt1
        time.sleep(2)
        _log.info(
            "Let's migrate actor {} from runtime {}(rt2) to runtime {}(rt1)".
            format(rt2_id, result['actor_map']['test_script:snk'], rt1_id))
        try:
            request_handler.migrate(rt[2],
                                    result['actor_map']['test_script:snk'],
                                    rt1_id)
        except Exception as err:
            _log.error(
                "Failed to send first migration request to runtime 2, err={}".
                format(err))
            raise
        time.sleep(3)
        try:
            actors = fetch_and_log_runtime_actors()
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['test_script:src'] in actors[2]
        assert result['actor_map']['test_script:sum'] in actors[2]
        assert result['actor_map']['test_script:snk'] in actors[1]
        time.sleep(1)
        try:
            actual = request_handler.report(
                rt[1], result['actor_map']['test_script:snk'])
        except Exception as err:
            _log.error(
                "Failed to report snk values from runtime 1, err={}".format(
                    err))
            raise
        _log.info("actual={}".format(actual))
        assert len(actual) > 3

        #Migrate src actor to rt3
        time.sleep(1)
        try:
            request_handler.migrate(rt[2],
                                    result['actor_map']['test_script:src'],
                                    rt3_id)
        except Exception as err:
            _log.error(
                "Failed to send second migration requestfrom runtime 2, err={}"
                .format(err))
            raise
        time.sleep(3)
        try:
            actors = fetch_and_log_runtime_actors()
        except Exception as err:
            _log.error(
                "Failed to get actors from runtimes, err={}".format(err))
            raise
        assert result['actor_map']['test_script:src'] in actors[3]
        assert result['actor_map']['test_script:sum'] in actors[2]
        assert result['actor_map']['test_script:snk'] in actors[1]
        time.sleep(1)
        try:
            actual = request_handler.report(
                rt[1], result['actor_map']['test_script:snk'])
        except Exception as err:
            _log.error(
                "Failed to report snk values from runtime 1, err={}".format(
                    err))
            raise
        _log.info("actual={}".format(actual))
        assert len(actual) > 3

        time.sleep(1)
        request_handler.delete_application(rt[2], result['application_id'])
Example #52
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)
Example #53
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)