Module: DockerSwarm::LogHelper

Defined in:
lib/docker_swarm/log_helper.rb

Overview

Helper module to centralize logging logic and formatting

Constant Summary collapse

SENSITIVE_KEYS =

data se matchea con \b para que Data (Secret/Config) se filtre pero metadata u otras claves no caigan en falso positivo. auth cubre headers de autenticación (X-Registry-Auth, Authorization), case-insensitive.

/password|pass|passwd|secret|token|api_key|auth|\bdata\b/i.freeze
FILTERED =
"[FILTERED]"
KV_STRING =

Un elemento de Env de Docker: "CLAVE=VALOR". El [^=]+ a la izquierda evita partir en un = que pertenezca al valor (los valores base64 y las URLs los traen), y /m cubre un valor multilínea — una clave PEM pasada por variable de entorno.

/\A([^=]+)=(.+)\z/m

Class Method Summary collapse

Class Method Details

.format_kv(payload) ⇒ String

Formats a hash into a KV structured string with sensitive data masking

Parameters:

  • payload (Hash)

    The data to format

Returns:

  • (String)

    KV formatted string



71
72
73
74
75
76
77
# File 'lib/docker_swarm/log_helper.rb', line 71

def self.format_kv(payload)
  sanitize(payload).map do |k, v|
    "#{k}=#{v}"
  end.join(" ")
rescue
  "event=logging_error"
end

.redact_kv_string(str) ⇒ String

Redacta el VALOR de un String con forma "CLAVE=VALOR" cuando la clave es sensible, conservando el nombre: saber QUÉ secreto apareció es diagnóstico útil, su valor no.

Un String que no tiene esa forma —o cuya clave no es sensible— vuelve tal cual, así que "RAILS_LOG_LEVEL=info" y cualquier mensaje de error quedan intactos.

Parameters:

  • str (String)

Returns:

  • (String)

    con el valor reemplazado por FILTERED, o el original



61
62
63
64
65
66
# File 'lib/docker_swarm/log_helper.rb', line 61

def self.redact_kv_string(str)
  match = KV_STRING.match(str)
  return str unless match && match[1].match?(SENSITIVE_KEYS)

  "#{match[1]}=#{FILTERED}"
end

.sanitize(value) ⇒ Object

Redacta recursivamente los valores sensibles, a cualquier profundidad (hashes y arrays anidados). No muta la entrada: devuelve copias.

Cubre DOS formas, porque el nombre de un secreto no siempre es una clave de hash:

  1. Clave de hash sensibleheaders: { "X-Registry-Auth" => "<cred>" }. Un header sensible puede viajar anidado, y el match por clave de primer nivel no lo alcanzaba: el hash interno se interpolaba entero.
  2. "CLAVE=VALOR" dentro de un String — el Env de un ContainerSpec es un ARRAY DE STRINGS, así que el nombre del secreto vive dentro del elemento y no como clave. Sin esto, Env no matchea SENSITIVE_KEYS, sus elementos caen al else, y el valor de todo secreto pasado por variable de entorno se loguea entero — en request_success, o sea en el camino feliz, a nivel INFO.

Parameters:

  • value (Object)

    hash, array o escalar

Returns:

  • (Object)

    copia con los valores sensibles reemplazados por [FILTERED]



36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/docker_swarm/log_helper.rb', line 36

def self.sanitize(value)
  case value
  when Hash
    value.each_with_object({}) do |(k, v), acc|
      acc[k] = k.to_s.match?(SENSITIVE_KEYS) ? FILTERED : sanitize(v)
    end
  when Array
    value.map { |v| sanitize(v) }
  when String
    redact_kv_string(value)
  else
    value
  end
end