async-rabbitmq 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +268 -0
- data/LICENSE +21 -0
- data/README.md +594 -0
- data/exe/async-rabbitmq +12 -0
- data/lib/async_rabbitmq/channel.rb +1422 -0
- data/lib/async_rabbitmq/channel_id_allocator.rb +57 -0
- data/lib/async_rabbitmq/cli.rb +300 -0
- data/lib/async_rabbitmq/cluster.rb +433 -0
- data/lib/async_rabbitmq/errors.rb +113 -0
- data/lib/async_rabbitmq/exchange.rb +70 -0
- data/lib/async_rabbitmq/frame_io.rb +309 -0
- data/lib/async_rabbitmq/log.rb +52 -0
- data/lib/async_rabbitmq/notifier.rb +122 -0
- data/lib/async_rabbitmq/pool.rb +43 -0
- data/lib/async_rabbitmq/queue.rb +88 -0
- data/lib/async_rabbitmq/sasl.rb +123 -0
- data/lib/async_rabbitmq/session.rb +1154 -0
- data/lib/async_rabbitmq/telemetry/open_telemetry.rb +211 -0
- data/lib/async_rabbitmq/tls.rb +82 -0
- data/lib/async_rabbitmq/topology_registry.rb +210 -0
- data/lib/async_rabbitmq/version.rb +3 -0
- data/lib/async_rabbitmq/versioned_delivery_tag.rb +62 -0
- data/lib/async_rabbitmq.rb +18 -0
- metadata +180 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
module AsyncRabbitMQ
|
|
2
|
+
module SASL
|
|
3
|
+
class Base
|
|
4
|
+
# The AMQP mechanism name sent in connection.start-ok.
|
|
5
|
+
def mechanism_name
|
|
6
|
+
raise NotImplementedError
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Initial response sent with connection.start-ok.
|
|
10
|
+
def initial_response
|
|
11
|
+
raise NotImplementedError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Handle a connection.secure challenge from the broker.
|
|
15
|
+
# Returns the response string for connection.secure-ok.
|
|
16
|
+
def challenge_response(_challenge)
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Plain < Base
|
|
22
|
+
def initialize(username, password)
|
|
23
|
+
@username = username
|
|
24
|
+
@password = password
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def mechanism_name
|
|
28
|
+
"PLAIN"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def initial_response
|
|
32
|
+
"\x00#{@username}\x00#{@password}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def challenge_response(_challenge)
|
|
36
|
+
initial_response
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class External < Base
|
|
41
|
+
def mechanism_name
|
|
42
|
+
"EXTERNAL"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# EXTERNAL relies on the transport layer (TLS client cert) for identity.
|
|
46
|
+
# The initial response is empty — the broker extracts the identity from the cert.
|
|
47
|
+
def initial_response
|
|
48
|
+
""
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def challenge_response(_challenge)
|
|
52
|
+
""
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Challenge-response mechanism for testing SASL multi-step flows.
|
|
57
|
+
# The broker sends a challenge; we echo it back as the response.
|
|
58
|
+
class CRRabbitMQDemo < Base
|
|
59
|
+
def mechanism_name
|
|
60
|
+
"RABBIT-CR-DEMO"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def initialize(username, password)
|
|
64
|
+
@username = username
|
|
65
|
+
@password = password
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Initial response is just the username — password comes in challenge_response.
|
|
69
|
+
def initial_response
|
|
70
|
+
@username
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# The broker sends "Please tell me your password" (or similar);
|
|
74
|
+
# we respond with the password.
|
|
75
|
+
def challenge_response(_challenge)
|
|
76
|
+
@password
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Registry of built-in mechanism classes keyed by AMQP mechanism name.
|
|
81
|
+
REGISTRY = {
|
|
82
|
+
"PLAIN" => Plain,
|
|
83
|
+
"EXTERNAL" => External,
|
|
84
|
+
"RABBIT-CR-DEMO" => CRRabbitMQDemo,
|
|
85
|
+
}.freeze
|
|
86
|
+
|
|
87
|
+
# Select the best mechanism the broker supports, in preference order.
|
|
88
|
+
# Returns an instantiated mechanism object.
|
|
89
|
+
# Raises AuthenticationError if no common mechanism is found.
|
|
90
|
+
def self.negotiate(broker_mechanisms_string, preferred: nil, username: nil, password: nil)
|
|
91
|
+
broker_list = broker_mechanisms_string.split(/\s+/)
|
|
92
|
+
|
|
93
|
+
if preferred
|
|
94
|
+
name = preferred.upcase
|
|
95
|
+
unless broker_list.include?(name)
|
|
96
|
+
raise AuthenticationError, "Requested SASL mechanism #{name} not offered by broker (available: #{broker_list.join(', ')})"
|
|
97
|
+
end
|
|
98
|
+
return instantiate(name, username: username, password: password)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Preference order: EXTERNAL (strongest, no credentials on wire), PLAIN (universal)
|
|
102
|
+
%w[EXTERNAL PLAIN].each do |name|
|
|
103
|
+
if broker_list.include?(name)
|
|
104
|
+
return instantiate(name, username: username, password: password)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
raise AuthenticationError, "No supported SASL mechanism (broker offers: #{broker_list.join(', ')})"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.instantiate(name, username: nil, password: nil)
|
|
112
|
+
klass = REGISTRY[name]
|
|
113
|
+
raise AuthenticationError, "Unknown SASL mechanism: #{name}" unless klass
|
|
114
|
+
|
|
115
|
+
if klass.instance_method(:initialize).arity == 0
|
|
116
|
+
klass.new
|
|
117
|
+
else
|
|
118
|
+
klass.new(username, password)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
private_class_method :instantiate
|
|
122
|
+
end
|
|
123
|
+
end
|