Ejemplo n.º 1
0
    def handle(self):
        req = self.request.input

        with closing(self.odb.session()) as session:

            # Create the client itself
            client = self._new_zato_instance_with_cluster(
                WebSocketClient, self.server.cluster_id)
            channel = session.query(ChannelWebSocket).\
                filter(Cluster.id==self.server.cluster_id).\
                filter(ChannelWebSocket.name==req.channel_name).\
                one()

            client.is_internal = req.is_internal
            client.pub_client_id = req.pub_client_id
            client.ext_client_id = req.ext_client_id
            client.ext_client_name = req.get('ext_client_name',
                                             '').encode('utf8')
            client.local_address = req.local_address
            client.peer_address = req.peer_address
            client.peer_fqdn = req.peer_fqdn
            client.connection_time = parse(req.connection_time)
            client.last_seen = parse(req.last_seen)
            client.server_proc_pid = self.server.pid
            client.channel_id = channel.id
            client.server_id = self.server.id
            client.server_name = self.server.name

            # Opaque attributes
            set_instance_opaque_attrs(client, req, ['channel_name'])

            session.add(client)
            session.commit()

            self.response.payload.ws_client_id = client.id
Ejemplo n.º 2
0
Archivo: jwt.py Proyecto: Mattlk13/zato
    def handle(self):

        # If we have a rate limiting definition, let's check it upfront
        DefinitionParser.check_definition_from_input(self.request.input)

        input = self.request.input
        input.password = uuid4().hex
        input.secret = Fernet.generate_key()

        with closing(self.odb.session()) as session:
            try:

                # Let's see if we already have a definition of that name before committing
                # any stuff into the database.
                existing_one = session.query(JWT).\
                    filter(Cluster.id==input.cluster_id).\
                    filter(JWT.name==input.name).first()

                if existing_one:
                    raise Exception(
                        'JWT definition `{}` already exists on this cluster'.
                        format(input.name))

                item = self._new_zato_instance_with_cluster(JWT)
                item.name = input.name
                item.is_active = input.is_active
                item.username = input.username
                item.password = input.password
                item.secret = input.secret
                item.ttl = input.ttl
                item.cluster_id = input.cluster_id

                set_instance_opaque_attrs(item, input)

                session.add(item)
                session.commit()

            except Exception:
                self.logger.error('Could not create a JWT definition, e:`%s`',
                                  format_exc())
                session.rollback()

                raise
            else:
                input.id = item.id
                input.action = SECURITY.JWT_CREATE.value
                input.sec_type = SEC_DEF_TYPE.JWT
                self.broker_client.publish(input)

            self.response.payload.id = item.id
            self.response.payload.name = item.name
Ejemplo n.º 3
0
    def handle(self):

        input = self.request.input

        with closing(self.odb.session()) as session:
            existing_one = session.query(OutgoingFTP.id).\
                filter(OutgoingFTP.cluster_id==input.cluster_id).\
                filter(OutgoingFTP.name==input.name).\
                filter(OutgoingFTP.id!=input.id).\
                first()

            if existing_one:
                raise Exception(
                    'Outgoing FTP connection `{}` already exists'.format(
                        input.name))

            try:
                item = session.query(OutgoingFTP).filter_by(id=input.id).one()
                old_name = item.name
                item.name = input.name
                item.is_active = input.is_active
                item.cluster_id = input.cluster_id
                item.dircache = input.dircache
                item.host = input.host
                item.port = input.port
                item.user = input.user
                item.acct = input.acct
                item.timeout = input.timeout or None

                input.password = item.password
                input.old_name = old_name

                # Opaque attributes
                set_instance_opaque_attrs(item, input)

                session.add(item)
                session.commit()

                self.notify_worker_threads(input)

                self.response.payload.id = item.id
                self.response.payload.name = item.name

            except Exception:
                self.logger.error(
                    'Could not update the outgoing FTP connection, e:`{}`',
                    format_exc())
                session.rollback()

                raise
Ejemplo n.º 4
0
    def handle(self):

        # If we have a rate limiting definition, let's check it upfront
        DefinitionParser.check_definition_from_input(self.request.input)

        input = self.request.input
        with closing(self.odb.session()) as session:
            try:
                existing_one = session.query(HTTPBasicAuth).\
                    filter(Cluster.id==input.cluster_id).\
                    filter(HTTPBasicAuth.name==input.name).\
                    filter(HTTPBasicAuth.id!=input.id).\
                    first()

                if existing_one:
                    raise Exception(
                        'HTTP Basic Auth definition `{}` already exists on this cluster'
                        .format(input.name))

                definition = session.query(HTTPBasicAuth).filter_by(
                    id=input.id).one()
                old_name = definition.name

                set_instance_opaque_attrs(definition, input)

                definition.name = input.name
                definition.is_active = input.is_active
                definition.username = input.username
                definition.realm = input.realm or None

                session.add(definition)
                session.commit()

            except Exception:
                self.logger.error(
                    'Could not update HTTP Basic Auth definition, e:`%s`',
                    format_exc())
                session.rollback()

                raise
            else:
                input.action = SECURITY.BASIC_AUTH_EDIT.value
                input.old_name = old_name
                input.sec_type = SEC_DEF_TYPE.BASIC_AUTH
                self.broker_client.publish(input)

                self.response.payload.id = definition.id
                self.response.payload.name = definition.name
Ejemplo n.º 5
0
    def handle(self):

        # If we have a rate limiting definition, let's check it upfront
        DefinitionParser.check_definition_from_input(self.request.input)

        input = self.request.input
        input.password = uuid4().hex

        with closing(self.odb.session()) as session:
            try:
                cluster = session.query(Cluster).filter_by(
                    id=input.cluster_id).first()

                # Let's see if we already have a definition of that name before committing
                # any stuff into the database.
                existing_one = session.query(HTTPBasicAuth).\
                    filter(Cluster.id==input.cluster_id).\
                    filter(HTTPBasicAuth.name==input.name).first()

                if existing_one:
                    raise Exception(
                        'HTTP Basic Auth definition `{}` already exists in this cluster'
                        .format(input.name))

                auth = HTTPBasicAuth(None, input.name, input.is_active,
                                     input.username, input.realm or None,
                                     input.password, cluster)
                set_instance_opaque_attrs(auth, input)

                session.add(auth)
                session.commit()

            except Exception:
                self.logger.error(
                    'Could not create an HTTP Basic Auth definition, e:`%s`',
                    format_exc())
                session.rollback()

                raise
            else:
                input.id = auth.id
                input.action = SECURITY.BASIC_AUTH_CREATE.value
                input.sec_type = SEC_DEF_TYPE.BASIC_AUTH
                self.broker_client.publish(input)

            self.response.payload.id = auth.id
            self.response.payload.name = auth.name
Ejemplo n.º 6
0
    def handle(self):
        input = self.request.input

        # If we have a rate limiting definition, let's check it upfront
        DefinitionParser.check_definition_from_input(input)

        with closing(self.odb.session()) as session:
            try:
                service = session.query(Service).filter_by(
                    id=input.id).one()  # type: Service
                service.is_active = input.is_active
                service.slow_threshold = input.slow_threshold

                set_instance_opaque_attrs(service, input)

                # Configure JSON Schema validation if service has a schema assigned by user.
                class_info = self.server.service_store.get_service_info_by_id(
                    input.id)  # type: dict
                class_ = class_info['service_class']  # type: Service
                if class_.schema:
                    self.server.service_store.set_up_class_json_schema(
                        class_, input)

                # Set up rate-limiting each time an object was edited
                self.server.service_store.set_up_rate_limiting(service.name)

                session.add(service)
                session.commit()

                input.action = SERVICE.EDIT.value
                input.impl_name = service.impl_name
                input.name = service.name
                self.broker_client.publish(input)

                self.response.payload = service
                internal_del = is_boolean(self.server.fs_server_config.misc.
                                          internal_services_may_be_deleted)
                self.response.payload.may_be_deleted = internal_del if service.is_internal else True

            except Exception:
                self.logger.error('Service could not be updated, e:`%s`',
                                  format_exc())
                session.rollback()

                raise
Ejemplo n.º 7
0
Archivo: jwt.py Proyecto: Mattlk13/zato
    def handle(self):
        input = self.request.input
        with closing(self.odb.session()) as session:
            try:
                existing_one = session.query(JWT).\
                    filter(Cluster.id==input.cluster_id).\
                    filter(JWT.name==input.name).\
                    filter(JWT.id!=input.id).\
                    first()

                if existing_one:
                    raise Exception(
                        'JWT definition `{}` already exists on this cluster'.
                        format(input.name))

                item = session.query(JWT).filter_by(id=input.id).one()
                old_name = item.name

                item.name = input.name
                item.is_active = input.is_active
                item.username = input.username
                item.ttl = input.ttl
                item.cluster_id = input.cluster_id

                set_instance_opaque_attrs(item, input)

                session.add(item)
                session.commit()

            except Exception:
                self.logger.error(
                    'Could not update the JWT definition, e:`%s`',
                    format_exc())
                session.rollback()

                raise
            else:
                input.action = SECURITY.JWT_EDIT.value
                input.old_name = old_name
                input.sec_type = SEC_DEF_TYPE.JWT
                self.broker_client.publish(input)

                self.response.payload.id = item.id
                self.response.payload.name = item.name
Ejemplo n.º 8
0
    def handle(self):
        input = self.request.input

        # If we have a rate limiting definition, let's check it upfront
        DefinitionParser.check_definition_from_input(input)

        with closing(self.odb.session()) as session:
            try:
                existing_one = session.query(APIKeySecurity).\
                    filter(Cluster.id==input.cluster_id).\
                    filter(APIKeySecurity.name==input.name).\
                    filter(APIKeySecurity.id!=input.id).\
                    first()

                if existing_one:
                    raise Exception('API key `{}` already exists in this cluster'.format(input.name))

                definition = session.query(APIKeySecurity).filter_by(id=input.id).one()
                old_name = definition.name

                set_instance_opaque_attrs(definition, input)

                definition.name = input.name
                definition.is_active = input.is_active
                definition.username = input.username

                session.add(definition)
                session.commit()

            except Exception:
                self.logger.error('API key could not be updated, e:`{}`', format_exc())
                session.rollback()

                raise
            else:
                input.action = SECURITY.APIKEY_EDIT.value
                input.old_name = old_name
                input.sec_type = SEC_DEF_TYPE.APIKEY
                self.broker_client.publish(input)

                self.response.payload.id = definition.id
                self.response.payload.name = definition.name
Ejemplo n.º 9
0
    def handle(self):
        input = self.request.input
        with closing(self.odb.session()) as session:
            try:
                service = session.query(Service).filter_by(id=input.id).one()
                service.is_active = input.is_active
                service.slow_threshold = input.slow_threshold

                set_instance_opaque_attrs(service, input)

                # Configure JSON Schema validation if service has a schema assigned by user.
                class_info = self.server.service_store.get_service_class_by_id(
                    input.id)  # type: dict
                class_ = class_info['service_class']  # type: Service
                if class_.json_schema:
                    self.server.service_store.set_up_class_json_schema(
                        class_, input)

                session.add(service)
                session.commit()

                input.action = SERVICE.EDIT.value
                input.impl_name = service.impl_name
                self.broker_client.publish(input)

                self.response.payload = service

                internal_del = is_boolean(self.server.fs_server_config.misc.
                                          internal_services_may_be_deleted)
                self.response.payload.may_be_deleted = internal_del if service.is_internal else True

            except Exception:
                msg = 'Service could not be updated, e:`{}`'.format(
                    format_exc())
                self.logger.error(msg)
                session.rollback()

                raise
Ejemplo n.º 10
0
        def handle_impl(self):
            # type: (Service)

            input = self.request.input
            input.update(attrs.initial_input)
            verb = 'edit' if attrs.is_edit else 'create'
            old_name = None

            with closing(self.odb.session()) as session:
                try:
                    attrs._meta_session = session

                    if attrs.check_existing_one:

                        # Let's see if we already have an instance of that name before committing
                        # any stuff to the database. However, this is wrapped in an if condition
                        # because certain models don't have the .name attribute.

                        existing_one = session.query(attrs.model).\
                            filter(Cluster.id==input.cluster_id).\
                            filter(attrs.model.name==input.name)

                        if attrs.is_edit:
                            existing_one = existing_one.filter(
                                attrs.model.id != input.id)

                        existing_one = existing_one.first()

                        if existing_one and not attrs.is_edit:
                            raise Exception(
                                '{} `{}` already exists in this cluster'.
                                format(
                                    attrs.label[0].upper() + attrs.label[1:],
                                    input.name))

                    if attrs.is_edit:
                        instance = session.query(
                            attrs.model).filter_by(id=input.id).one()
                        old_name = instance.name
                    else:
                        instance = self._new_zato_instance_with_cluster(
                            attrs.model)

                    # Update the instance with data received on input, however,
                    # note that this may overwrite some of existing attributes
                    # if they are empty on input. If it's not desired,
                    # set skip_input_params = ['...'] to ignore such input parameters.
                    instance.fromdict(input,
                                      exclude=['password'],
                                      allow_pk=True)

                    # Invoke a hook that will set any additional opaque attrs
                    # that are required but were possibly not given on input.
                    if attrs.pre_opaque_attrs_hook:
                        attrs.pre_opaque_attrs_hook(self, input, instance,
                                                    attrs)

                    # Populate all the opaque attrs now
                    set_instance_opaque_attrs(instance, input)

                    # Now that we have an instance which is known not to be a duplicate
                    # we can possibly invoke a customization function before we commit
                    # anything to the database.
                    if attrs.instance_hook:
                        attrs.instance_hook(self, input, instance, attrs)

                    session.add(instance)
                    session.commit()

                except Exception:
                    msg = 'Could not {} the object, e:`%s`'.format(verb)
                    logger.error(msg, format_exc())
                    session.rollback()
                    raise
                else:

                    if attrs.def_needed:
                        def_ = session.query(
                            attrs.def_needed).filter_by(id=input.def_id).one()
                        input.def_name = def_.name

                    action = getattr(
                        attrs.broker_message,
                        attrs.broker_message_prefix + verb.upper()).value
                    input.id = instance.id
                    input.action = action
                    input.old_name = old_name

                    if attrs.broker_message_hook:
                        attrs.broker_message_hook(self, input, instance, attrs,
                                                  'create_edit')

                    self.broker_client.publish(input)

                    for name in chain(attrs.create_edit_rewrite,
                                      self.SimpleIO.output_required):
                        value = getattr(instance, name, singleton)
                        if value is singleton:
                            value = input[name]

                        setattr(self.response.payload, name, value)

                    if attrs.response_hook:
                        attrs.response_hook(self, input, instance, attrs,
                                            'create_edit')
Ejemplo n.º 11
0
    def handle(self):

        # If we have a rate limiting definition, let's check it upfront
        DefinitionParser.check_definition_from_input(self.request.input)

        input = self.request.input
        input.sec_use_rbac = input.get('sec_use_rbac') or (input.security_id == ZATO_SEC_USE_RBAC)
        input.security_id = input.security_id if input.security_id not in (ZATO_NONE, ZATO_SEC_USE_RBAC) else None
        input.soap_action = input.soap_action if input.soap_action else ''

        if input.content_encoding and input.content_encoding != 'gzip':
            raise Exception('Content encoding must be empty or equal to `gzip`')

        with closing(self.odb.session()) as session:

            existing_one = session.query(HTTPSOAP.id).\
                filter(HTTPSOAP.cluster_id==input.cluster_id).\
                filter(HTTPSOAP.id!=input.id).\
                filter(HTTPSOAP.name==input.name).\
                filter(HTTPSOAP.connection==input.connection).\
                filter(HTTPSOAP.transport==input.transport).\
                first()

            if existing_one:
                raise Exception('An object of that input.name:`{}` already exists in this cluster ' \
                '(input.connection:`{}` input.transport:`{}` input.id:`{}` existing_one.id:`{}`)'.format(
                    input.name, input.connection, input.transport, input.id, existing_one.id))

            # Is the service's name correct?
            service = session.query(Service).\
                filter(Cluster.id==input.cluster_id).\
                filter(Service.cluster_id==Cluster.id).\
                filter(Service.name==input.service).first()

            if input.connection == CONNECTION.CHANNEL and not service:
                msg = 'Service `{}` does not exist on this cluster'.format(input.service)
                self.logger.error(msg)
                raise Exception(msg)

            # Will raise exception if the security type doesn't match connection
            # type and transport
            sec_info = self._handle_security_info(session, input.security_id, input.connection, input.transport)

            # TLS data comes in combinations, i.e. certain elements are required only if TLS keys/certs are used
            self._validate_tls(input, sec_info)

            try:
                item = session.query(HTTPSOAP).filter_by(id=input.id).one()

                opaque = parse_instance_opaque_attr(item)

                old_name = item.name
                old_url_path = item.url_path
                old_soap_action = item.soap_action
                old_http_method = item.method
                old_http_accept = opaque.get('http_accept')

                item.name = input.name
                item.is_active = input.is_active
                item.host = input.host
                item.url_path = input.url_path
                item.security_id = input.security_id or None # So that SQLite does not reject ''
                item.connection = input.connection
                item.transport = input.transport
                item.cluster_id = input.cluster_id
                item.method = input.method
                item.soap_action = input.soap_action
                item.soap_version = input.soap_version or None
                item.data_format = input.data_format
                item.service = service
                item.ping_method = input.get('ping_method') or DEFAULT_HTTP_PING_METHOD
                item.pool_size = input.get('pool_size') or DEFAULT_HTTP_POOL_SIZE
                item.merge_url_params_req = input.get('merge_url_params_req') or False
                item.url_params_pri = input.get('url_params_pri') or URL_PARAMS_PRIORITY.DEFAULT
                item.params_pri = input.get('params_pri') or PARAMS_PRIORITY.DEFAULT
                item.serialization_type = input.get('serialization_type') or HTTP_SOAP_SERIALIZATION_TYPE.DEFAULT.id
                item.timeout = input.get('timeout') or MISC.DEFAULT_HTTP_TIMEOUT
                item.has_rbac = input.get('has_rbac') or input.sec_use_rbac or False
                item.content_type = input.get('content_type')
                item.sec_use_rbac = input.sec_use_rbac
                item.cache_id = input.cache_id or None
                item.cache_expiry = input.cache_expiry
                item.content_encoding = input.content_encoding

                sec_tls_ca_cert_id = input.get('sec_tls_ca_cert_id')
                item.sec_tls_ca_cert_id = sec_tls_ca_cert_id if sec_tls_ca_cert_id and sec_tls_ca_cert_id != ZATO_NONE else None

                # Opaque attributes
                set_instance_opaque_attrs(item, input)

                session.add(item)
                session.commit()

                if input.connection == CONNECTION.CHANNEL:
                    input.impl_name = service.impl_name
                    input.service_id = service.id
                    input.service_name = service.name
                    input.merge_url_params_req = item.merge_url_params_req
                    input.url_params_pri = item.url_params_pri
                    input.params_pri = item.params_pri

                    cache = cache_by_id(session, input.cluster_id, item.cache_id) if item.cache_id else None
                    if cache:
                        input.cache_type = cache.cache_type
                        input.cache_name = cache.name
                    else:
                        input.cache_type = None
                        input.cache_name = None

                else:
                    input.ping_method = item.ping_method
                    input.pool_size = item.pool_size

                input.is_internal = item.is_internal
                input.old_name = old_name
                input.old_url_path = old_url_path
                input.old_soap_action = old_soap_action
                input.old_http_method = old_http_method
                input.old_http_accept = old_http_accept
                input.update(sec_info)

                if item.sec_tls_ca_cert_id and item.sec_tls_ca_cert_id != ZATO_NONE:
                    self.add_tls_ca_cert(input, item.sec_tls_ca_cert_id)

                if input.connection == CONNECTION.CHANNEL:
                    action = CHANNEL.HTTP_SOAP_CREATE_EDIT.value
                else:
                    action = OUTGOING.HTTP_SOAP_CREATE_EDIT.value
                self.notify_worker_threads(input, action)

                self.response.payload.id = item.id
                self.response.payload.name = item.name

            except Exception:
                self.logger.error('Object could not be updated, e:`%s`', format_exc())
                session.rollback()

                raise
Ejemplo n.º 12
0
    def _get_message(self,
                     topic,
                     input,
                     now,
                     pub_pattern_matched,
                     endpoint_id,
                     subscriptions_by_topic,
                     has_wsx_no_server,
                     _initialized=_initialized,
                     _zato_none=ZATO_NONE,
                     _skip=PUBSUB.HOOK_ACTION.SKIP,
                     _default_pri=PUBSUB.PRIORITY.DEFAULT,
                     _opaque_only=PUBSUB.DEFAULT.SK_OPAQUE,
                     _float_str=PUBSUB.FLOAT_STRING_CONVERT):

        priority = get_priority(self.cid, input)

        # So as not to send it to SQL if it is a default value anyway = less overhead = better performance
        if priority == _default_pri:
            priority = None

        expiration = get_expiration(self.cid, input)
        expiration_time = now + (expiration / 1000.0)

        pub_msg_id = input.get('msg_id', '').encode('utf8') or new_msg_id()

        # If there is at least one WSX subscriber to this topic which is not connected at the moment,
        # which means it has no delivery server, we uncoditionally turn this message into a GD one ..
        if has_wsx_no_server:
            has_gd = True
            logger_pubsub.info(_log_turning_gd_msg.format('wsx'), pub_msg_id)

        # .. otherwise, use input GD value or the default per topic.
        else:
            has_gd = input.get('has_gd', _zato_none)
            if has_gd != _zato_none:
                if not isinstance(has_gd, bool):
                    raise ValueError(
                        'Input has_gd is not a bool (found:`{}`)'.format(
                            repr(has_gd)))
            else:
                has_gd = topic.has_gd

        pub_correl_id = input.get('correl_id')
        in_reply_to = input.get('in_reply_to')
        ext_client_id = input.get('ext_client_id')
        mime_type = input.get('mime_type')

        ext_pub_time = input.get('ext_pub_time') or None
        if ext_pub_time:
            ext_pub_time = dt_parse(ext_pub_time)
            ext_pub_time = datetime_to_ms(ext_pub_time) / 1000.0

        pub_correl_id = pub_correl_id.encode('utf8') if pub_correl_id else None
        in_reply_to = in_reply_to.encode('utf8') if in_reply_to else None
        ext_client_id = ext_client_id.encode('utf8') if ext_client_id else None
        mime_type = mime_type.encode('utf8') if mime_type else None
        reply_to_sk = input.get('reply_to_sk') or []
        deliver_to_sk = input.get('deliver_to_sk') or []

        user_ctx = input.get('user_ctx')
        zato_ctx = input.get('zato_ctx')

        ps_msg = PubSubMessage()
        ps_msg.topic = topic
        ps_msg.pub_msg_id = pub_msg_id
        ps_msg.pub_correl_id = pub_correl_id
        ps_msg.in_reply_to = in_reply_to

        # Convert to string to prevent pg8000 from rounding up float values
        ps_msg.pub_time = _float_str.format(now)
        ps_msg.ext_pub_time = _float_str.format(
            ext_pub_time) if ext_pub_time else ext_pub_time

        ps_msg.delivery_status = _initialized
        ps_msg.pub_pattern_matched = pub_pattern_matched
        ps_msg.data = input['data']
        ps_msg.mime_type = mime_type
        ps_msg.priority = priority
        ps_msg.expiration = expiration
        ps_msg.expiration_time = expiration_time
        ps_msg.published_by_id = endpoint_id
        ps_msg.topic_id = topic.id
        ps_msg.topic_name = topic.name
        ps_msg.cluster_id = self.server.cluster_id
        ps_msg.has_gd = has_gd
        ps_msg.ext_client_id = ext_client_id
        ps_msg.group_id = input.get('group_id') or None
        ps_msg.position_in_group = input.get('position_in_group') or None
        ps_msg.is_in_sub_queue = bool(subscriptions_by_topic)
        ps_msg.reply_to_sk = reply_to_sk
        ps_msg.deliver_to_sk = deliver_to_sk
        ps_msg.user_ctx = user_ctx
        ps_msg.zato_ctx = zato_ctx

        # Opaque attributes - we only need reply to sub_keys to be placed in there
        # but we do not do it unless we known that any such sub key was actually requested.
        if reply_to_sk or deliver_to_sk:
            set_instance_opaque_attrs(ps_msg, input, only=_opaque_only)

        # If there are any subscriptions for the topic this message was published to, we want to establish
        # based on what subscription pattern each subscriber will receive the message.
        for sub in subscriptions_by_topic:
            ps_msg.sub_pattern_matched[sub.sub_key] = sub.sub_pattern_matched

        if ps_msg.data:
            ps_msg.size = len(
                ps_msg.data.encode('utf8')
            )  # We need to store the size in bytes rather than Unicode codepoints
        else:
            ps_msg.size = 0

        # Invoke hook service here because it may want to update data in which case
        # we need to take it into account below.
        if topic.before_publish_hook_service_invoker:
            response = topic.before_publish_hook_service_invoker(topic, ps_msg)

            # Hook service decided that we should not process this message
            if response['hook_action'] == _skip:
                logger_audit.info(
                    'Skipping message pub_msg_id:`%s`, pub_correl_id:`%s`, ext_client_id:`%s`',
                    ps_msg.pub_msg_id, ps_msg.pub_correl_id,
                    ps_msg.ext_client_id)
                return

        # These are needed only for GD messages that are stored in SQL
        if has_gd:
            data_prefix, data_prefix_short = self._get_data_prefixes(
                ps_msg.data)
            ps_msg.data_prefix = data_prefix
            ps_msg.data_prefix_short = data_prefix_short

        return ps_msg
Ejemplo n.º 13
0
    def handle(self):
        input = self.request.input
        input.sec_use_rbac = input.security_id == ZATO_SEC_USE_RBAC
        input.security_id = input.security_id if input.security_id not in (
            ZATO_NONE, ZATO_SEC_USE_RBAC) else None
        input.soap_action = input.soap_action if input.soap_action else ''
        input.timeout = input.get('timeout') or MISC.DEFAULT_HTTP_TIMEOUT

        if input.content_encoding and input.content_encoding != 'gzip':
            raise Exception(
                'Content encoding must be empty or equal to `gzip`')

        with closing(self.odb.session()) as session:
            existing_one = session.query(HTTPSOAP.id).\
                filter(HTTPSOAP.cluster_id==input.cluster_id).\
                filter(HTTPSOAP.name==input.name).\
                filter(HTTPSOAP.connection==input.connection).\
                filter(HTTPSOAP.transport==input.transport).\
                first()

            if existing_one:
                raise Exception(
                    'An object of that name `{}` already exists on this cluster'
                    .format(input.name))

            # Is the service's name correct?
            service = session.query(Service).\
                filter(Cluster.id==input.cluster_id).\
                filter(Service.cluster_id==Cluster.id).\
                filter(Service.name==input.service).first()

            if input.connection == CONNECTION.CHANNEL and not service:
                msg = 'Service `{}` does not exist on this cluster'.format(
                    input.service)
                self.logger.error(msg)
                raise Exception(msg)

            # Will raise exception if the security type doesn't match connection
            # type and transport
            sec_info = self._handle_security_info(session, input.security_id,
                                                  input.connection,
                                                  input.transport)

            # Make sure this combination of channel parameters does not exist already
            if input.connection == CONNECTION.CHANNEL:
                self.ensure_channel_is_unique(session, input.url_path,
                                              input.soap_action,
                                              input.cluster_id)

            try:

                item = self._new_zato_instance_with_cluster(HTTPSOAP)
                item.connection = input.connection
                item.transport = input.transport
                item.is_internal = input.is_internal
                item.name = input.name
                item.is_active = input.is_active
                item.host = input.host
                item.url_path = input.url_path
                item.method = input.method
                item.soap_action = input.soap_action
                item.soap_version = input.soap_version or None
                item.data_format = input.data_format
                item.service = service
                item.ping_method = input.get(
                    'ping_method') or DEFAULT_HTTP_PING_METHOD
                item.pool_size = input.get(
                    'pool_size') or DEFAULT_HTTP_POOL_SIZE
                item.merge_url_params_req = input.get(
                    'merge_url_params_req') or True
                item.url_params_pri = input.get(
                    'url_params_pri') or URL_PARAMS_PRIORITY.DEFAULT
                item.params_pri = input.get(
                    'params_pri') or PARAMS_PRIORITY.DEFAULT
                item.serialization_type = input.get(
                    'serialization_type'
                ) or HTTP_SOAP_SERIALIZATION_TYPE.DEFAULT.id
                item.timeout = input.timeout
                item.has_rbac = input.get(
                    'has_rbac') or input.sec_use_rbac or False
                item.content_type = input.get('content_type')
                item.sec_use_rbac = input.sec_use_rbac
                item.cache_id = input.cache_id or None
                item.cache_expiry = input.cache_expiry
                item.content_encoding = input.content_encoding

                if input.security_id:
                    item.security = get_security_by_id(session,
                                                       input.security_id)
                else:
                    input.security_id = None  # To ensure that SQLite doesn't reject ''

                sec_tls_ca_cert_id = input.get('sec_tls_ca_cert_id')
                item.sec_tls_ca_cert_id = sec_tls_ca_cert_id if sec_tls_ca_cert_id and sec_tls_ca_cert_id != ZATO_NONE else None

                # Opaque attributes
                set_instance_opaque_attrs(item, input)

                session.add(item)
                session.commit()

                if input.connection == CONNECTION.CHANNEL:
                    input.impl_name = service.impl_name
                    input.service_id = service.id
                    input.service_name = service.name

                    cache = cache_by_id(
                        session, input.cluster_id,
                        item.cache_id) if item.cache_id else None
                    if cache:
                        input.cache_type = cache.cache_type
                        input.cache_name = cache.name
                    else:
                        input.cache_type = None
                        input.cache_name = None

                if item.sec_tls_ca_cert_id and item.sec_tls_ca_cert_id != ZATO_NONE:
                    self.add_tls_ca_cert(input, item.sec_tls_ca_cert_id)

                input.id = item.id
                input.update(sec_info)

                if input.connection == CONNECTION.CHANNEL:
                    action = CHANNEL.HTTP_SOAP_CREATE_EDIT.value
                else:
                    action = OUTGOING.HTTP_SOAP_CREATE_EDIT.value
                self.notify_worker_threads(input, action)

                self.response.payload.id = item.id
                self.response.payload.name = item.name

            except Exception:
                msg = 'Could not create the object, e:`{}'.format(format_exc())
                self.logger.error(msg)
                session.rollback()

                raise
Ejemplo n.º 14
0
        def handle_impl(self):
            input = self.request.input
            input.update(attrs.initial_input)
            verb = 'edit' if attrs.is_edit else 'create'
            old_name = None

            with closing(self.odb.session()) as session:
                try:
                    attrs._meta_session = session

                    if attrs.check_existing_one:

                        # Let's see if we already have an instance of that name before committing
                        # any stuff to the database. However, this is wrapped in an if condition
                        # because certain models don't have the .name attribute.

                        existing_one = session.query(attrs.model).\
                            filter(Cluster.id==input.cluster_id).\
                            filter(attrs.model.name==input.name)

                        if attrs.is_edit:
                            existing_one = existing_one.filter(
                                attrs.model.id != input.id)

                        existing_one = existing_one.first()

                        if existing_one and not attrs.is_edit:
                            raise Exception(
                                '{} `{}` already exists in this cluster'.
                                format(
                                    attrs.label[0].upper() + attrs.label[1:],
                                    input.name))

                    if attrs.is_edit:
                        instance = session.query(
                            attrs.model).filter_by(id=input.id).one()
                        old_name = instance.name
                    else:
                        instance = self._new_zato_instance_with_cluster(
                            attrs.model)

                    # Update the instance with data received on input, however,
                    # note that this may overwrite some of existing attributes
                    # if they are empty on input. If it's not desired,
                    # set skip_input_params = ['...'] to ignore such input parameters.
                    instance.fromdict(input,
                                      exclude=['password'],
                                      allow_pk=True)

                    # Populate all the opaque attrs now
                    set_instance_opaque_attrs(instance, input)

                    # Now that we have an instance which is known not to be a duplicate
                    # we can possibly invoke a customization function before we commit
                    # anything to the database.
                    if attrs.instance_hook:
                        attrs.instance_hook(self, input, instance, attrs)

                    session.add(instance)
                    session.commit()

                except Exception, e:
                    msg = 'Could not {} the object, e:`%s`'.format(verb)
                    logger.error(msg, format_exc(e))
                    session.rollback()
                    raise
                else: