Пример #1
0
    def create_authenticator(self, connection, debug=False, **kwargs):
        """Create the AMQP session and the CBS channel with which
        to negotiate the token.

        :param connection: The underlying AMQP connection on which
         to create the session.
        :type connection: ~uamqp.connection.Connection
        :param debug: Whether to emit network trace logging events for the
         CBS session. Default is `False`. Logging events are set at INFO level.
        :type debug: bool
        :rtype: uamqp.c_uamqp.CBSTokenAuth
        """
        self._connection = connection
        self._session = Session(connection, **kwargs)
        try:
            self._cbs_auth = c_uamqp.CBSTokenAuth(
                self.audience,
                self.token_type,
                self.token,
                int(self.expires_at),
                self._session._session,  # pylint: disable=protected-access
                self.timeout,
                self._connection.container_id)
            self._cbs_auth.set_trace(debug)
        except ValueError:
            self._session.destroy()
            raise errors.AMQPConnectionError(
                "Unable to open authentication session on connection {}.\n"
                "Please confirm target hostname exists: {}".format(
                    connection.container_id, connection.hostname))
        return self._cbs_auth
Пример #2
0
    async def mgmt_request_async(self,
                                 message,
                                 operation,
                                 op_type=None,
                                 node=None,
                                 **kwargs):
        """Asynchronously run a request/response operation. These are frequently used
        for management tasks against a $management node, however any node name can be
        specified and the available options will depend on the target service.

        :param message: The message to send in the management request.
        :type message: ~uamqp.message.Message
        :param operation: The type of operation to be performed. This value will
         be service-specific, but common values include READ, CREATE and UPDATE.
         This value will be added as an application property on the message.
        :type operation: bytes or str
        :param op_type: The type on which to carry out the operation. This will
         be specific to the entities of the service. This value will be added as
         an application property on the message.
        :type op_type: bytes or str
        :param node: The target node. Default is `b"$management"`.
        :type node: bytes or str
        :param timeout: Provide an optional timeout in milliseconds within which a response
         to the management request must be received.
        :type timeout: int
        :param status_code_field: Provide an alternate name for the status code in the
         response body which can vary between services due to the spec still being in draft.
         The default is `b"statusCode"`.
        :type status_code_field: bytes or str
        :param description_fields: Provide an alternate name for the description in the
         response body which can vary between services due to the spec still being in draft.
         The default is `b"statusDescription"`.
        :type description_fields: bytes or str
        :param encoding: The encoding to use for parameters supplied as strings.
         Default is 'UTF-8'
        :type encoding: str
        :rtype: ~uamqp.message.Message
        """
        timeout = kwargs.pop('timeout', None) or 0
        try:
            mgmt_link = self._mgmt_links[node]
        except KeyError:
            mgmt_link = MgmtOperationAsync(self,
                                           target=node,
                                           loop=self.loop,
                                           **kwargs)
            self._mgmt_links[node] = mgmt_link
            while not mgmt_link.open and not mgmt_link.mgmt_error:
                await self._connection.work_async()
            if mgmt_link.mgmt_error:
                raise mgmt_link.mgmt_error
            elif mgmt_link.open != constants.MgmtOpenStatus.Ok:
                raise errors.AMQPConnectionError(
                    "Failed to open mgmt link: {}".format(mgmt_link.open))
        op_type = op_type or b'empty'
        response = await mgmt_link.execute_async(operation,
                                                 op_type,
                                                 message,
                                                 timeout=timeout)
        return response
Пример #3
0
    def __init__(self,
                 session,
                 target=None,
                 debug=False,
                 status_code_field=b'statusCode',
                 description_fields=b'statusDescription',
                 encoding='UTF-8'):
        self._encoding = encoding
        self.connection = session._connection  # pylint: disable=protected-access
        # self.session = Session(
        #     connection,
        #     incoming_window=constants.MAX_FRAME_SIZE_BYTES,
        #     outgoing_window=constants.MAX_FRAME_SIZE_BYTES)
        self.target = self._encode(target or constants.MGMT_TARGET)
        status_code_field = self._encode(status_code_field)
        description_fields = self._encode(description_fields)
        self._responses = {}

        self._counter = c_uamqp.TickCounter()
        self._mgmt_op = c_uamqp.create_management_operation(
            session._session, self.target)  # pylint: disable=protected-access
        self._mgmt_op.set_response_field_names(status_code_field,
                                               description_fields)
        self._mgmt_op.set_trace(debug)
        self.open = None
        try:
            self._mgmt_op.open(self)
        except ValueError:
            self.mgmt_error = errors.AMQPConnectionError(
                "Unable to open management session. "
                "Please confirm URI namespace exists.")
        else:
            self.mgmt_error = None
Пример #4
0
 def _client_ready(self):
     """Determine whether the client is ready to start receiving messages.
     To be ready, the connection must be open and authentication complete,
     The Session, Link and MessageReceiver must be open and in non-errored
     states.
     :returns: bool
     :raises: ~uamqp.errors.AMQPConnectionError if the MessageReceiver
      goes into an error state.
     """
     # pylint: disable=protected-access
     if not self._message_receiver:
         self._message_receiver = self.receiver_type(
             self._session, self._remote_address, self._name,
             on_message_received=self,
             name='receiver-link-{}'.format(uuid.uuid4()),
             debug=self._debug_trace,
             receive_settle_mode=self._receive_settle_mode,
             prefetch=self._prefetch,
             max_message_size=self._max_message_size,
             properties=self._link_properties,
             encoding=self._encoding)
         self._message_receiver.open()
         return False
     elif self._message_receiver._state == constants.MessageReceiverState.Error:
         raise errors.AMQPConnectionError(
             "Message Receiver Client was unable to open. "
             "Please confirm credentials and access permissions."
             "\nSee debug trace for more details.")
     elif self._message_receiver._state != constants.MessageReceiverState.Open:
         self._last_activity_timestamp = self._counter.get_current_ms()
         return False
     return True
Пример #5
0
 async def _client_ready(self):
     """Determine whether the client is ready to start sending messages.
     To be ready, the connection must be open and authentication complete,
     The Session, Link and MessageSender must be open and in non-errored
     states.
     :returns: bool
     :raises: ~uamqp.errors.AMQPConnectionError if the MessageSender
      goes into an error state.
     """
     # pylint: disable=protected-access
     if not self._message_sender:
         self._message_sender = self.sender_type(
             self._session,
             self._name,
             self._remote_address,
             name='sender-link-{}'.format(uuid.uuid4()),
             debug=self._debug_trace,
             send_settle_mode=self._send_settle_mode,
             max_message_size=self._max_message_size,
             properties=self._link_properties,
             encoding=self._encoding,
             loop=self.loop)
         await self._message_sender.open_async()
         return False
     elif self._message_sender._state == constants.MessageSenderState.Error:
         raise errors.AMQPConnectionError(
             "Message Sender Client was unable to open. "
             "Please confirm credentials and access permissions."
             "\nSee debug trace for more details.")
     elif self._message_sender._state != constants.MessageSenderState.Open:
         return False
     return True
Пример #6
0
    def create_authenticator(self, connection, debug=False):
        """Create the AMQP session and the CBS channel with which
        to negotiate the token.

        :param connection: The underlying AMQP connection on which
         to create the session.
        :type connection: ~uamqp.Connection
        :param debug: Whether to emit network trace logging events for the
         CBS session. Default is `False`. Logging events are set at INFO level.
        :type debug: bool
        :returns: ~uamqp.c_uamqp.CBSTokenAuth
        """
        self._lock = threading.Lock()
        self._session = Session(
            connection,
            incoming_window=constants.MAX_FRAME_SIZE_BYTES,
            outgoing_window=constants.MAX_FRAME_SIZE_BYTES)
        try:
            self._cbs_auth = c_uamqp.CBSTokenAuth(
                self.audience,
                self.token_type,
                self.token,
                int(self.expires_at),
                self._session._session,  # pylint: disable=protected-access
                self.timeout)
            self._cbs_auth.set_trace(debug)
        except ValueError:
            raise errors.AMQPConnectionError(
                "Unable to open authentication session. "
                "Please confirm target URI exists.")
        return self._cbs_auth
Пример #7
0
 def _attach_received(self, source, target, properties, error=None):
     if error:
         self._link_error = errors.AMQPConnectionError(error)
     if self._on_attach:
         if source and target:
             source = Source.from_c_obj(source)
             target = Target.from_c_obj(target)
         if properties:
             properties = properties.value
         self._on_attach(source, target, properties, self._link_error)
 async def _management_request_async(self, mgmt_msg: Message,
                                     op_type: bytes) -> Any:
     retried_times = 0
     last_exception = None
     while retried_times <= self._config.max_retries:
         mgmt_auth = await self._create_auth_async()
         mgmt_client = AMQPClientAsync(self._mgmt_target,
                                       auth=mgmt_auth,
                                       debug=self._config.network_tracing)
         try:
             conn = await self._conn_manager_async.get_connection(
                 self._address.hostname, mgmt_auth)
             mgmt_msg.application_properties[
                 "security_token"] = mgmt_auth.token
             await mgmt_client.open_async(connection=conn)
             response = await mgmt_client.mgmt_request_async(
                 mgmt_msg,
                 constants.READ_OPERATION,
                 op_type=op_type,
                 status_code_field=MGMT_STATUS_CODE,
                 description_fields=MGMT_STATUS_DESC,
             )
             status_code = int(
                 response.application_properties[MGMT_STATUS_CODE])
             description = response.application_properties.get(
                 MGMT_STATUS_DESC)  # type: Optional[Union[str, bytes]]
             if description and isinstance(description, six.binary_type):
                 description = description.decode('utf-8')
             if status_code < 400:
                 return response
             if status_code in [401]:
                 raise errors.AuthenticationException(
                     "Management authentication failed. Status code: {}, Description: {!r}"
                     .format(status_code, description))
             if status_code in [404]:
                 raise ConnectError(
                     "Management connection failed. Status code: {}, Description: {!r}"
                     .format(status_code, description))
             raise errors.AMQPConnectionError(
                 "Management request error. Status code: {}, Description: {!r}"
                 .format(status_code, description))
         except asyncio.CancelledError:  # pylint: disable=try-except-raise
             raise
         except Exception as exception:  # pylint:disable=broad-except
             last_exception = await _handle_exception(exception, self)
             await self._backoff_async(retried_times=retried_times,
                                       last_exception=last_exception)
             retried_times += 1
             if retried_times > self._config.max_retries:
                 _LOGGER.info("%r returns an exception %r",
                              self._container_id, last_exception)
                 raise last_exception
         finally:
             await mgmt_client.close_async()
Пример #9
0
    def open(self):
        """Open the MessageSender in order to start processing messages.

        :raises: ~uamqp.errors.AMQPConnectionError if the Sender raises
         an error on opening. This can happen if the target URI is invalid
         or the credentials are rejected.
        """
        try:
            self._sender.open()
        except ValueError:
            raise errors.AMQPConnectionError(
                "Failed to open Message Sender. "
                "Please confirm credentials and target URI.")
Пример #10
0
    async def open_async(self):
        """Asynchronously open the MessageReceiver in order to start
        processing messages.

        :raises: ~uamqp.errors.AMQPConnectionError if the Receiver raises
         an error on opening. This can happen if the source URI is invalid
         or the credentials are rejected.
        """
        try:
            self._receiver.open(self)
        except ValueError:
            raise errors.AMQPConnectionError(
                "Failed to open Message Receiver. "
                "Please confirm credentials and target URI.")
Пример #11
0
def test_unknown_connection_error():
    logger = logging.getLogger("testlogger")
    amqp_error = AMQPErrors.AMQPConnectionError(AMQPConstants.ErrorCodes.UnknownError)
    sb_error = _create_servicebus_exception(logger, amqp_error)
    assert isinstance(sb_error,ServiceBusConnectionError)
    assert sb_error._retryable
    assert sb_error._shutdown_handler

    amqp_error = AMQPErrors.AMQPError(AMQPConstants.ErrorCodes.UnknownError)
    sb_error = _create_servicebus_exception(logger, amqp_error)
    assert not isinstance(sb_error,ServiceBusConnectionError)
    assert isinstance(sb_error,ServiceBusError)
    assert not sb_error._retryable
    assert sb_error._shutdown_handler
Пример #12
0
    async def open_async(self):
        """Asynchronously open the MessageSender in order to start
        processing messages.

        :raises: ~uamqp.errors.AMQPConnectionError if the Sender raises
         an error on opening. This can happen if the target URI is invalid
         or the credentials are rejected.
        """
        try:
            await self.loop.run_in_executor(
                None, functools.partial(self._sender.open))
        except ValueError:
            raise errors.AMQPConnectionError(
                "Failed to open Message Sender. "
                "Please confirm credentials and target URI.")
Пример #13
0
    async def create_authenticator_async(self,
                                         connection,
                                         debug=False,
                                         loop=None,
                                         **kwargs):
        """Create the async AMQP session and the CBS channel with which
        to negotiate the token.

        :param connection: The underlying AMQP connection on which
         to create the session.
        :type connection: ~uamqp.async_ops.connection_async.ConnectionAsync
        :param debug: Whether to emit network trace logging events for the
         CBS session. Default is `False`. Logging events are set at INFO level.
        :type debug: bool
        :param loop: A user specified event loop.
        :type loop: ~asycnio.AbstractEventLoop
        :rtype: uamqp.c_uamqp.CBSTokenAuth
        """
        self.loop = loop or get_running_loop()
        self._connection = connection
        self._session = SessionAsync(connection, loop=self.loop, **kwargs)

        if self.token_type == b'jwt':  # Async initialize the jwt token
            await self.update_token()

        try:
            self._cbs_auth = c_uamqp.CBSTokenAuth(
                self.audience,
                self.token_type,
                self.token,
                int(self.expires_at),
                self._session._session,  # pylint: disable=protected-access
                self.timeout,
                self._connection.container_id)
            self._cbs_auth.set_trace(debug)
        except ValueError:
            await self._session.destroy_async()
            raise errors.AMQPConnectionError(
                "Unable to open authentication session on connection {}.\n"
                "Please confirm target hostname exists: {}".format(
                    connection.container_id, connection.hostname)) from None
        return self._cbs_auth
Пример #14
0
    async def create_authenticator_async(self,
                                         connection,
                                         debug=False,
                                         loop=None,
                                         **kwargs):
        """Create the async AMQP session and the CBS channel with which
        to negotiate the token.

        :param connection: The underlying AMQP connection on which
         to create the session.
        :type connection: ~uamqp.async_ops.connection_async.ConnectionAsync
        :param debug: Whether to emit network trace logging events for the
         CBS session. Default is `False`. Logging events are set at INFO level.
        :type debug: bool
        :rtype: uamqp.c_uamqp.CBSTokenAuth
        """
        self._internal_kwargs = get_dict_with_loop_if_needed(loop)
        self._connection = connection
        kwargs.update(self._internal_kwargs)
        self._session = SessionAsync(connection, **kwargs)

        try:
            self._cbs_auth = c_uamqp.CBSTokenAuth(
                self.audience,
                self.token_type,
                self.token,
                int(self.expires_at),
                self._session._session,  # pylint: disable=protected-access
                self.timeout,
                self._connection.container_id,
                self._refresh_window)
            self._cbs_auth.set_trace(debug)
        except ValueError:
            await self._session.destroy_async()
            raise errors.AMQPConnectionError(
                "Unable to open authentication session on connection {}.\n"
                "Please confirm target hostname exists: {}".format(
                    connection.container_id, connection.hostname)) from None
        return self._cbs_auth
    async def create_authenticator_async(self,
                                         connection,
                                         debug=False,
                                         loop=None):
        """Create the async AMQP session and the CBS channel with which
        to negotiate the token.

        :param connection: The underlying AMQP connection on which
         to create the session.
        :type connection: ~uamqp.async.ConnectionAsync
        :param debug: Whether to emit network trace logging events for the
         CBS session. Default is `False`. Logging events are set at INFO level.
        :type debug: bool
        :param loop: A user specified event loop.
        :type loop: ~asycnio.AbstractEventLoop
        :returns: ~uamqp.c_uamqp.CBSTokenAuth
        """
        self.loop = loop or asyncio.get_event_loop()
        self._lock = asyncio.Lock(loop=self.loop)
        self._session = SessionAsync(
            connection,
            incoming_window=constants.MAX_FRAME_SIZE_BYTES,
            outgoing_window=constants.MAX_FRAME_SIZE_BYTES,
            loop=self.loop)
        try:
            self._cbs_auth = c_uamqp.CBSTokenAuth(
                self.audience,
                self.token_type,
                self.token,
                int(self.expires_at),
                self._session._session,  # pylint: disable=protected-access
                self.timeout)
            self._cbs_auth.set_trace(debug)
        except ValueError:
            raise errors.AMQPConnectionError(
                "Unable to open authentication session. "
                "Please confirm target URI exists.") from None
        return self._cbs_auth