anycable-core 1.4.0 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/anycable/config.rb +1 -1
- data/lib/anycable/grpc/config.rb +16 -0
- data/lib/anycable/grpc/server.rb +8 -1
- data/lib/anycable/grpc_kit/server.rb +29 -3
- data/lib/anycable/version.rb +1 -1
- data/sig/anycable/grpc/config.rbs +6 -0
- data/sig/anycable/grpc/server.rbs +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fead71a088b7431fb65a3cfdd16ebee3760700496e9cc0d440f40b118952ac6a
|
4
|
+
data.tar.gz: 26c7f7d1fd4fa3aefbf8e43358b8eb959e3aa707ec36d2d7775f657748e1afc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 887068bded37ce33ebdb0a5ae2ffce3afbb545053a544db83ad581008ac0ec603a45019df8a87281030b790db90f2aae3c812b3434b3c782ac69f29d04c535bd
|
7
|
+
data.tar.gz: c2e49c2fc7becb3c9b9076fd57f988abec053bd419e56dd0769d4e086704a66fd80dab0ffa485a9221053b9742a55de38c90b1463d1d5264b385c7b2f132d33d
|
data/CHANGELOG.md
CHANGED
data/lib/anycable/config.rb
CHANGED
@@ -98,7 +98,7 @@ module AnyCable
|
|
98
98
|
--http-health-path=path Endpoint to serve health checks, default: "/health"
|
99
99
|
|
100
100
|
REDIS PUB/SUB
|
101
|
-
--redis-url=url Redis URL for pub/sub, default: REDIS_URL or "redis://localhost:6379
|
101
|
+
--redis-url=url Redis URL for pub/sub, default: REDIS_URL or "redis://localhost:6379"
|
102
102
|
--redis-channel=name Redis channel for broadcasting, default: "__anycable__"
|
103
103
|
--redis-sentinels=<...hosts> Redis Sentinel followers addresses (as a comma-separated list), default: nil
|
104
104
|
--redis-tls-verify=yes|no Whether to perform server certificate check in case of rediss:// protocol. Default: yes
|
data/lib/anycable/grpc/config.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
AnyCable::Config.attr_config(
|
4
4
|
### gRPC options
|
5
5
|
rpc_host: "127.0.0.1:50051",
|
6
|
+
rpc_tls_cert: nil,
|
7
|
+
rpc_tls_key: nil,
|
6
8
|
rpc_pool_size: 30,
|
7
9
|
rpc_max_waiting_requests: 20,
|
8
10
|
rpc_poll_period: 1,
|
@@ -32,6 +34,7 @@ module AnyCable
|
|
32
34
|
max_waiting_requests: rpc_max_waiting_requests,
|
33
35
|
poll_period: rpc_poll_period,
|
34
36
|
pool_keep_alive: rpc_pool_keep_alive,
|
37
|
+
tls_credentials: tls_credentials,
|
35
38
|
server_args: enhance_grpc_server_args(normalized_grpc_server_args)
|
36
39
|
}
|
37
40
|
end
|
@@ -53,6 +56,17 @@ module AnyCable
|
|
53
56
|
opts["grpc.max_connection_age_ms"] = rpc_max_connection_age.to_i * 1000
|
54
57
|
opts
|
55
58
|
end
|
59
|
+
|
60
|
+
def tls_credentials
|
61
|
+
cert_path_or_content = rpc_tls_cert # Assign to local variable to make steep happy
|
62
|
+
key_path_or_content = rpc_tls_key # Assign to local variable to make steep happy
|
63
|
+
return {} if cert_path_or_content.nil? || key_path_or_content.nil?
|
64
|
+
|
65
|
+
cert = File.exist?(cert_path_or_content) ? File.read(cert_path_or_content) : cert_path_or_content
|
66
|
+
pkey = File.exist?(key_path_or_content) ? File.read(key_path_or_content) : key_path_or_content
|
67
|
+
|
68
|
+
{cert: cert, pkey: pkey}
|
69
|
+
end
|
56
70
|
end
|
57
71
|
end
|
58
72
|
end
|
@@ -62,6 +76,8 @@ AnyCable::Config.prepend AnyCable::GRPC::Config
|
|
62
76
|
AnyCable::Config.usage <<~TXT
|
63
77
|
GRPC OPTIONS
|
64
78
|
--rpc-host=host Local address to run gRPC server on, default: "127.0.0.1:50051"
|
79
|
+
--rpc-tls-cert=path TLS certificate file path or contents in PEM format, default: <none> (TLS disabled)
|
80
|
+
--rpc-tls-key=path TLS private key file path or contents in PEM format, default: <none> (TLS disabled)
|
65
81
|
--rpc-pool-size=size gRPC workers pool size, default: 30
|
66
82
|
--rpc-max-waiting-requests=num Max waiting requests queue size, default: 20
|
67
83
|
--rpc-poll-period=seconds Poll period (sec), default: 1
|
data/lib/anycable/grpc/server.rb
CHANGED
@@ -83,8 +83,9 @@ module AnyCable
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def build_server(**options)
|
86
|
+
tls_credentials = options.delete(:tls_credentials)
|
86
87
|
::GRPC::RpcServer.new(**options).tap do |server|
|
87
|
-
server.add_http2_port(host,
|
88
|
+
server.add_http2_port(host, server_credentials(**tls_credentials))
|
88
89
|
server.handle(AnyCable::GRPC::Handler)
|
89
90
|
server.handle(build_health_checker)
|
90
91
|
end
|
@@ -102,6 +103,12 @@ module AnyCable
|
|
102
103
|
)
|
103
104
|
health_checker
|
104
105
|
end
|
106
|
+
|
107
|
+
def server_credentials(cert: nil, pkey: nil)
|
108
|
+
return :this_port_is_insecure if cert.nil? || pkey.nil?
|
109
|
+
|
110
|
+
::GRPC::Core::ServerCredentials.new(nil, [{private_key: pkey, cert_chain: cert}], false)
|
111
|
+
end
|
105
112
|
end
|
106
113
|
end
|
107
114
|
end
|
@@ -44,6 +44,7 @@ module AnyCable
|
|
44
44
|
@hostname = host_parts[:hostname]
|
45
45
|
@port = host_parts[:port].to_i
|
46
46
|
|
47
|
+
@tls_credentials = options.delete(:tls_credentials)
|
47
48
|
@grpc_server = build_server(**options)
|
48
49
|
end
|
49
50
|
|
@@ -56,7 +57,7 @@ module AnyCable
|
|
56
57
|
|
57
58
|
logger.info "RPC server (grpc_kit) is starting..."
|
58
59
|
|
59
|
-
@sock =
|
60
|
+
@sock = build_server_socket
|
60
61
|
|
61
62
|
server = grpc_server
|
62
63
|
|
@@ -66,6 +67,12 @@ module AnyCable
|
|
66
67
|
server.run(conn)
|
67
68
|
rescue IOError
|
68
69
|
# ignore broken connections
|
70
|
+
rescue OpenSSL::SSL::SSLError => ssl_error
|
71
|
+
if ssl_error.message.match?(/SSL_read: unexpected eof while reading/i)
|
72
|
+
# ignore broken connections
|
73
|
+
else
|
74
|
+
raise
|
75
|
+
end
|
69
76
|
end
|
70
77
|
end
|
71
78
|
|
@@ -81,13 +88,18 @@ module AnyCable
|
|
81
88
|
|
82
89
|
loop do
|
83
90
|
sock = TCPSocket.new(hostname, port, connect_timeout: 1)
|
91
|
+
if @tls_credentials&.any?
|
92
|
+
sock = OpenSSL::SSL::SSLSocket.new(sock, tls_context)
|
93
|
+
sock.sync_close = true
|
94
|
+
sock.connect
|
95
|
+
end
|
84
96
|
stub = ::Grpc::Health::V1::Health::Stub.new(sock)
|
85
97
|
stub.check(::Grpc::Health::V1::HealthCheckRequest.new)
|
86
98
|
sock.close
|
87
99
|
break
|
88
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError
|
100
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError, OpenSSL::SSL::SSLError => e
|
89
101
|
timeout -= 1
|
90
|
-
raise "Server is not responding" if timeout.zero?
|
102
|
+
raise "Server is not responding: #{e}" if timeout.zero?
|
91
103
|
end
|
92
104
|
end
|
93
105
|
|
@@ -125,6 +137,20 @@ module AnyCable
|
|
125
137
|
@logger ||= AnyCable.logger
|
126
138
|
end
|
127
139
|
|
140
|
+
def build_server_socket
|
141
|
+
tcp_server = TCPServer.new(hostname, port)
|
142
|
+
return tcp_server unless @tls_credentials&.any?
|
143
|
+
|
144
|
+
OpenSSL::SSL::SSLServer.new(tcp_server, tls_context)
|
145
|
+
end
|
146
|
+
|
147
|
+
def tls_context
|
148
|
+
OpenSSL::SSL::SSLContext.new.tap do |tls_context|
|
149
|
+
tls_context.cert = OpenSSL::X509::Certificate.new(@tls_credentials.fetch(:cert))
|
150
|
+
tls_context.key = OpenSSL::PKey.read(@tls_credentials.fetch(:pkey))
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
128
154
|
def build_server(**options)
|
129
155
|
pool_size = options[:pool_size]
|
130
156
|
|
data/lib/anycable/version.rb
CHANGED
@@ -3,6 +3,10 @@ module AnyCable
|
|
3
3
|
interface _Config
|
4
4
|
def rpc_host: () -> String
|
5
5
|
def rpc_host=: (String) -> void
|
6
|
+
def rpc_tls_cert: () -> String?
|
7
|
+
def rpc_tls_cert=: (String?) -> void
|
8
|
+
def rpc_tls_key: () -> String?
|
9
|
+
def rpc_tls_key=: (String?) -> void
|
6
10
|
def rpc_pool_size: () -> Integer
|
7
11
|
def rpc_pool_size=: (Integer) -> void
|
8
12
|
def rpc_max_waiting_requests: () -> Integer
|
@@ -28,11 +32,13 @@ module AnyCable
|
|
28
32
|
max_waiting_requests: Integer,
|
29
33
|
poll_period: Numeric,
|
30
34
|
pool_keep_alive: Numeric,
|
35
|
+
tls_credentials: Hash[Symbol, String],
|
31
36
|
server_args: Hash[String, untyped]
|
32
37
|
}
|
33
38
|
|
34
39
|
def normalized_grpc_server_args: () -> Hash[String, untyped]
|
35
40
|
def enhance_grpc_server_args: (Hash[String, untyped]) -> Hash[String, untyped]
|
41
|
+
def tls_credentials: () -> Hash[Symbol, String]
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
@@ -15,6 +15,7 @@ module AnyCable
|
|
15
15
|
def logger: () -> Logger
|
16
16
|
def build_server: (**untyped options) -> untyped
|
17
17
|
def build_health_checker: () -> untyped
|
18
|
+
def server_credentials: (?cert: String?, ?pkey: String?) -> (::GRPC::Core::ServerCredentials | :this_port_is_insecure)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anycable-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: anyway_config
|