Module: BugBunny::Observability Private
- Included in:
- BugBunny, Consumer, Controller, Producer, Session
- Defined in:
- lib/bug_bunny/observability.rb
This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.
Constant Summary collapse
- SENSITIVE_KEYS =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Patrones de keys que deben ser ocultados en los logs. Se usa substring matching en lowercase para cubrir variantes como "user_password", "accessToken", "X-Authorization", etc. Excluye "pass" y "session" bare para evitar falsos positivos en keys como "passport_number" o "processing_session_count".
%w[ password passwd secret token api_key auth authorization credential private_key csrf session_id ].freeze
- SENSITIVE_KEYS_ALTERNATION =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Alternación de keys sensibles ordenada de más larga a más corta: en un regex la alternación matchea leftmost-first, así que sin este orden
authganaría sobreauthorizationy el patrón dejaría de matchear (orization=xno sigue con[:=]). SENSITIVE_KEYS.sort_by { |k| -k.length }.join('|').freeze
- SENSITIVE_VALUE_RULES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Reglas de VALOR sensible, como pares
[regex, reemplazo].sensitive_key? solo ve el NOMBRE de la clave; no puede ver una credencial embebida en TEXTO LIBRE. El caso canónico es el
messagede una excepción inesperada (llega comoreason=oerror_message=, nombres no sensibles): unNoMethodErrorsobre un objeto de respuesta HTTP puede arrastrarAuthorization: "Bearer eyJ..."en su mensaje y el filtro por-clave lo deja pasar entero al log.El reemplazo conserva el nombre de la clave cuando viaja dentro del texto (
token=[FILTERED], no[FILTERED]): saber QUÉ credencial apareció es diagnóstico útil; su valor no. [ # Esquemas de autenticación HTTP: "Bearer <jwt>", "Basic <base64>". [/\b(?:bearer|basic)\s+[A-Za-z0-9\-._~+\/]{8,}={0,2}/i, '[FILTERED]'], # La key viaja DENTRO del texto: `token=abc`, `password: 'x'`, `"api_key" => "y"`. # # El prefijo `\w*` va en lugar de un `\b`: `_` es word-char, así que un borde de # palabra NO existe dentro de `access_token` ni de `accessToken` y esas variantes # se colarían en claro — justo las que {.sensitive_key?} cubre a propósito con # substring matching. Se captura el prefijo para conservar el nombre COMPLETO de la # key en el log (`access_token=[FILTERED]`): saber qué credencial apareció es # diagnóstico útil. No reintroduce el falso positivo de `passport_number` porque # ninguna key de SENSITIVE_KEYS es substring suyo (por eso `pass` bare está excluida). [/(\w*(?:#{SENSITIVE_KEYS_ALTERNATION}))["']?\s*(?:=>|[:=])\s*["']?[^\s,;"'}\])]+/i, '\1=[FILTERED]'], # Credenciales en una URL: `amqp://user:pass@host` → conserva el esquema y el host. [%r{(://)[^\s/:@]+:[^\s/@]+@}, '\1[FILTERED]@'] ].freeze
Class Method Summary collapse
-
.redact_structure(obj) ⇒ Object
private
Redacta una estructura ANTES de serializarla, recorriendo keys y valores.
-
.redact_value(value) ⇒ String
private
Redacta credenciales embebidas en un valor de texto libre.
-
.sensitive_key?(key) ⇒ Boolean
private
Determina si una key es sensible y debe filtrarse en los logs.
Class Method Details
.redact_structure(obj) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Redacta una estructura ANTES de serializarla, recorriendo keys y valores.
Se usa para los valores Hash de #safe_log. Redactar el JSON ya serializado con
redact_value no sirve: la regla de key-dentro-del-texto normaliza el separador a
= y se come la comilla de cierre de la key, dejando un objeto donde el par
"token": "abc" quedó colapsado en "token=[FILTERED]" — el secreto desaparece,
pero el campo deja de ser JSON parseable y quien consume el log pierde el objeto
entero, no solo el valor redactado.
Recorriendo la estructura, además, las keys internas SÍ pasan por sensitive_key? (que solo veía las keys de primer nivel del metadata).
93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/bug_bunny/observability.rb', line 93 def self.redact_structure(obj) case obj when Hash obj.each_with_object({}) do |(k, v), acc| acc[k] = sensitive_key?(k) ? '[FILTERED]' : redact_structure(v) end when Array then obj.map { |element| redact_structure(element) } when Numeric, TrueClass, FalseClass, NilClass then obj else redact_value(obj) end end |
.redact_value(value) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Redacta credenciales embebidas en un valor de texto libre.
Complementa a sensitive_key?: esa filtra por NOMBRE de clave, esta por CONTENIDO. Se aplica a todo valor no numérico que #safe_log serializa.
73 74 75 76 77 |
# File 'lib/bug_bunny/observability.rb', line 73 def self.redact_value(value) SENSITIVE_VALUE_RULES.reduce(value.to_s) do |acc, (pattern, replacement)| acc.gsub(pattern, replacement) end end |
.sensitive_key?(key) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Determina si una key es sensible y debe filtrarse en los logs. Accesible como método de módulo para que otros componentes puedan reutilizarlo.
23 24 25 26 27 28 |
# File 'lib/bug_bunny/observability.rb', line 23 def self.sensitive_key?(key) # Normalize hyphens → underscores so HTTP headers like "X-Api-Key" # match the same patterns as Ruby symbol keys like :api_key. key_str = key.to_s.downcase.tr('-', '_') SENSITIVE_KEYS.any? { |sensitive| key_str.include?(sensitive) } end |