Class: Protobuf::Nats::Config
- Inherits:
-
Object
- Object
- Protobuf::Nats::Config
- Defined in:
- lib/protobuf/nats/config.rb
Constant Summary collapse
- CONFIG_MUTEX =
::Mutex.new
- DEFAULTS =
{ :connect_timeout => nil, # Per-server reconnect attempt cap. -1 means reconnect forever # (nats-pure treats a negative value as infinite). When exhausted on # every server, nats-pure fires on_close and the connection is # terminally dead. :max_reconnect_attempts => 60_000, # Failover tuning; nil falls through to the nats-pure defaults # (reconnect_time_wait: 2s, ping_interval: 120s, max_outstanding_pings: 2). # A node that dies silently (partition, hard host failure) is only # detected after ping_interval * max_outstanding_pings, so lower these # for faster failover to a healthy node. :reconnect_time_wait => nil, :ping_interval => nil, :max_outstanding_pings => nil, :servers => nil, :connection_name => nil, :tls_client_cert => nil, :tls_client_key => nil, :tls_ca_cert => nil, :uses_tls => false, :server_subscription_key_do_not_subscribe_to_when_includes_any_of => [], :server_subscription_key_only_subscribe_to_when_includes_any_of => [], :subscription_key_replacements => [], }.freeze
Instance Attribute Summary collapse
-
#connect_timeout ⇒ Object
Returns the value of attribute connect_timeout.
-
#connection_name ⇒ Object
Returns the value of attribute connection_name.
-
#max_outstanding_pings ⇒ Object
Returns the value of attribute max_outstanding_pings.
-
#max_reconnect_attempts ⇒ Object
Returns the value of attribute max_reconnect_attempts.
-
#ping_interval ⇒ Object
Returns the value of attribute ping_interval.
-
#reconnect_time_wait ⇒ Object
Returns the value of attribute reconnect_time_wait.
-
#server_subscription_key_do_not_subscribe_to_when_includes_any_of ⇒ Object
Returns the value of attribute server_subscription_key_do_not_subscribe_to_when_includes_any_of.
-
#server_subscription_key_only_subscribe_to_when_includes_any_of ⇒ Object
Returns the value of attribute server_subscription_key_only_subscribe_to_when_includes_any_of.
-
#servers ⇒ Object
Returns the value of attribute servers.
-
#subscription_key_replacements ⇒ Object
Returns the value of attribute subscription_key_replacements.
-
#tls_ca_cert ⇒ Object
Returns the value of attribute tls_ca_cert.
-
#tls_client_cert ⇒ Object
Returns the value of attribute tls_client_cert.
-
#tls_client_key ⇒ Object
Returns the value of attribute tls_client_key.
-
#uses_tls ⇒ Object
Returns the value of attribute uses_tls.
Instance Method Summary collapse
-
#connection_options(reload = false) ⇒ Object
Only the keys nats-pure's
connectactually consumes. -
#initialize ⇒ Config
constructor
A new instance of Config.
- #load_from_yml(reload = false) ⇒ Object
- #make_subscription_key_replacements(subscription_key) ⇒ Object
- #new_tls_context ⇒ Object
-
#resolved_connection_name ⇒ Object
Precedence: PB_NATS_CONNECTION_NAME env var > yaml/DEFAULT connection_name > hostname.
Constructor Details
Instance Attribute Details
#connect_timeout ⇒ Object
Returns the value of attribute connect_timeout.
9 10 11 |
# File 'lib/protobuf/nats/config.rb', line 9 def connect_timeout @connect_timeout end |
#connection_name ⇒ Object
Returns the value of attribute connection_name.
9 10 11 |
# File 'lib/protobuf/nats/config.rb', line 9 def connection_name @connection_name end |
#max_outstanding_pings ⇒ Object
Returns the value of attribute max_outstanding_pings.
10 11 12 |
# File 'lib/protobuf/nats/config.rb', line 10 def max_outstanding_pings @max_outstanding_pings end |
#max_reconnect_attempts ⇒ Object
Returns the value of attribute max_reconnect_attempts.
9 10 11 |
# File 'lib/protobuf/nats/config.rb', line 9 def max_reconnect_attempts @max_reconnect_attempts end |
#ping_interval ⇒ Object
Returns the value of attribute ping_interval.
10 11 12 |
# File 'lib/protobuf/nats/config.rb', line 10 def ping_interval @ping_interval end |
#reconnect_time_wait ⇒ Object
Returns the value of attribute reconnect_time_wait.
10 11 12 |
# File 'lib/protobuf/nats/config.rb', line 10 def reconnect_time_wait @reconnect_time_wait end |
#server_subscription_key_do_not_subscribe_to_when_includes_any_of ⇒ Object
Returns the value of attribute server_subscription_key_do_not_subscribe_to_when_includes_any_of.
11 12 13 |
# File 'lib/protobuf/nats/config.rb', line 11 def server_subscription_key_do_not_subscribe_to_when_includes_any_of @server_subscription_key_do_not_subscribe_to_when_includes_any_of end |
#server_subscription_key_only_subscribe_to_when_includes_any_of ⇒ Object
Returns the value of attribute server_subscription_key_only_subscribe_to_when_includes_any_of.
11 12 13 |
# File 'lib/protobuf/nats/config.rb', line 11 def server_subscription_key_only_subscribe_to_when_includes_any_of @server_subscription_key_only_subscribe_to_when_includes_any_of end |
#servers ⇒ Object
Returns the value of attribute servers.
9 10 11 |
# File 'lib/protobuf/nats/config.rb', line 9 def servers @servers end |
#subscription_key_replacements ⇒ Object
Returns the value of attribute subscription_key_replacements.
11 12 13 |
# File 'lib/protobuf/nats/config.rb', line 11 def subscription_key_replacements @subscription_key_replacements end |
#tls_ca_cert ⇒ Object
Returns the value of attribute tls_ca_cert.
9 10 11 |
# File 'lib/protobuf/nats/config.rb', line 9 def tls_ca_cert @tls_ca_cert end |
#tls_client_cert ⇒ Object
Returns the value of attribute tls_client_cert.
9 10 11 |
# File 'lib/protobuf/nats/config.rb', line 9 def tls_client_cert @tls_client_cert end |
#tls_client_key ⇒ Object
Returns the value of attribute tls_client_key.
9 10 11 |
# File 'lib/protobuf/nats/config.rb', line 9 def tls_client_key @tls_client_key end |
#uses_tls ⇒ Object
Returns the value of attribute uses_tls.
9 10 11 |
# File 'lib/protobuf/nats/config.rb', line 9 def uses_tls @uses_tls end |
Instance Method Details
#connection_options(reload = false) ⇒ Object
Only the keys nats-pure's connect actually consumes. App-level settings
(uses_tls, tls_client_cert, tls_client_key, tls_ca_cert,
server_subscription_key_*, subscription_key_replacements) are read
directly via their accessors elsewhere and must NOT be forwarded to
nats-pure (it ignores unknown keys today, but that is brittle). The TLS
cert/key/CA are folded into the :tls context by #new_tls_context.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/protobuf/nats/config.rb', line 89 def (reload = false) @connection_options = false if reload @connection_options ||= begin = { servers: servers, max_reconnect_attempts: max_reconnect_attempts, connect_timeout: connect_timeout, # nil values are safe to forward: nats-pure nil-fills each of these # with its own default during connect. reconnect_time_wait: reconnect_time_wait, ping_interval: ping_interval, max_outstanding_pings: max_outstanding_pings, # A friendly connection name surfaces in NATS server monitoring, # error reporting, and debugging (highly recommended by the NATS # docs). Shared by both the client and server connections since both # build from this hash. name: resolved_connection_name, } [:tls] = {:context => new_tls_context} if uses_tls end end |
#load_from_yml(reload = false) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/protobuf/nats/config.rb', line 49 def load_from_yml(reload = false) CONFIG_MUTEX.synchronize do @load_from_yml = nil if reload @load_from_yml ||= begin env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || ENV["APP_ENV"] || "development" yaml_config = {} config_path = ENV["PROTOBUF_NATS_CONFIG_PATH"] || ::File.join("config", "protobuf_nats.yml") absolute_config_path = ::File.(config_path) if ::File.exist?(absolute_config_path) yaml_string = ::ERB.new(::File.read(absolute_config_path)).result # safe_load (no arbitrary object deserialization) with aliases # enabled so the common `&defaults` / `<<: *defaults` pattern works. parsed = ::YAML.safe_load(yaml_string, :aliases => true) # An empty file parses to nil/false, and a file without a section # for the current env yields nil on lookup -- guard both so we # don't blow up with NoMethodError below. yaml_config = (parsed && parsed[env]) || {} end DEFAULTS.each_pair do |key, value| setting = yaml_config[key.to_s] __send__("#{key}=", setting) if setting end # Reload the connection options hash (true) true end end end |
#make_subscription_key_replacements(subscription_key) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/protobuf/nats/config.rb', line 166 def make_subscription_key_replacements(subscription_key) subscription_key_replacements.each do |replacement| match = replacement.keys.first replacement = replacement[match] if subscription_key.include?(match) return subscription_key.gsub(match, replacement) end end subscription_key end |
#new_tls_context ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/protobuf/nats/config.rb', line 119 def new_tls_context tls_context = ::OpenSSL::SSL::SSLContext.new # Floor at TLS 1.2, ceiling at TLS 1.3 (replaces the deprecated # ssl_version=:TLSv1_2 hard pin). The client offers 1.2 and 1.3 and # negotiates the highest the server also supports, so a TLS-1.2-only # transport still connects (verified on JRuby 9.4 and 10.0). # # An OpenSSL build without TLS 1.3 support does not define # TLS1_3_VERSION (#7); degrade to a 1.2-only ceiling there instead of # raising NameError at connect time. tls_context.min_version = ::OpenSSL::SSL::TLS1_2_VERSION tls_context.max_version = if defined?(::OpenSSL::SSL::TLS1_3_VERSION) ::OpenSSL::SSL::TLS1_3_VERSION else ::OpenSSL::SSL::TLS1_2_VERSION end tls_context.cert = ::OpenSSL::X509::Certificate.new(::File.read(tls_client_cert)) if tls_client_cert # PKey.read handles any key type (RSA, EC, Ed25519...); the previous # PKey::RSA.new rejected non-RSA client keys. tls_context.key = ::OpenSSL::PKey.read(::File.read(tls_client_key)) if tls_client_key # Verify the NATS server's certificate chain. This context is handed to # nats-pure as :tls => {:context => ...}; nats-pure uses a supplied # context verbatim and does NOT call #set_params, so verification has to # be configured here. Without this the OpenSSL default (VERIFY_NONE) # stood and any certificate -- including an attacker's -- was accepted. tls_context.verify_mode = ::OpenSSL::SSL::VERIFY_PEER cert_store = ::OpenSSL::X509::Store.new if tls_ca_cert # Trust the configured CA bundle (the private-CA deployment case). cert_store.add_file(tls_ca_cert) else # No CA configured: fall back to the system trust store. cert_store.set_default_paths end tls_context.cert_store = cert_store # NOTE: hostname (SAN/CN) verification is NOT enabled here. nats-pure only # sets the SSLSocket hostname from @tls[:hostname], which it populates # itself only when it builds the context; for a supplied context it stays # nil, and a single static hostname would be wrong for a multi-server # cluster that reconnects across hosts. Chain verification above still # ensures the cert is signed by the trusted CA. Plumbing per-connection # hostname verification is tracked separately. tls_context end |
#resolved_connection_name ⇒ Object
Precedence: PB_NATS_CONNECTION_NAME env var > yaml/DEFAULT connection_name
hostname. Env wins so ops can set a per-pod/per-host name without a config file; the hostname fallback ensures the name is never blank.
115 116 117 |
# File 'lib/protobuf/nats/config.rb', line 115 def resolved_connection_name ::ENV["PB_NATS_CONNECTION_NAME"] || connection_name || ::Socket.gethostname end |