Module: Legion::Extensions::Mesh::Helpers::PeerVerify

Defined in:
lib/legion/extensions/mesh/helpers/peer_verify.rb

Class Method Summary collapse

Class Method Details

.check_rate_limit(org_id) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/legion/extensions/mesh/helpers/peer_verify.rb', line 36

def check_rate_limit(org_id)
  @counters ||= Hash.new { |h, k| h[k] = { count: 0, window_start: Time.now.utc } } # rubocop:disable ThreadSafety/ClassInstanceVariable
  counter = @counters[org_id] # rubocop:disable ThreadSafety/ClassInstanceVariable
  peer  = find_peer(org_id)
  limit = peer&.dig(:rate_limit) || 100

  if Time.now.utc - counter[:window_start] > 60
    counter[:count] = 0
    counter[:window_start] = Time.now.utc
  end

  counter[:count] += 1
  return { allowed: true, remaining: limit - counter[:count] } if counter[:count] <= limit

  { allowed: false, error: :rate_limited, org_id: org_id }
end

.reset_counters!Object



53
54
55
# File 'lib/legion/extensions/mesh/helpers/peer_verify.rb', line 53

def reset_counters!
  @counters = nil # rubocop:disable ThreadSafety/ClassInstanceVariable
end

.sign_message(payload, private_key_b64) ⇒ Object



11
12
13
14
15
16
17
# File 'lib/legion/extensions/mesh/helpers/peer_verify.rb', line 11

def sign_message(payload, private_key_b64)
  require 'ed25519'
  key = Ed25519::SigningKey.new(Base64.strict_decode64(private_key_b64))
  message_bytes = json_dump(payload)
  signature = key.sign(message_bytes)
  { payload: payload, signature: Base64.strict_encode64(signature), signed_bytes: message_bytes }
end

.verify_message(signed_message, org_id:) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/legion/extensions/mesh/helpers/peer_verify.rb', line 19

def verify_message(signed_message, org_id:)
  peer = find_peer(org_id)
  return { valid: false, org_id: org_id, reason: :unknown_peer } unless peer

  require 'ed25519'
  pub_key_b64 = peer[:public_key].delete_prefix('ed25519:')
  verify_key  = Ed25519::VerifyKey.new(Base64.strict_decode64(pub_key_b64))
  signature   = Base64.strict_decode64(signed_message[:signature])
  message_bytes = signed_message[:signed_bytes] || json_dump(signed_message[:payload])
  verify_key.verify(signature, message_bytes)
  { valid: true, org_id: org_id }
rescue Ed25519::VerifyError => _e
  { valid: false, org_id: org_id, reason: :invalid_signature }
rescue StandardError => e
  { valid: false, org_id: org_id, reason: :error, message: e.message }
end