Only redact the non-sensitive bits of build args and env vars.
* `-e [REDACTED]` → `-e SOME_SECRET=[REDACTED]` * Replaces `Utils.redact` with `Utils.sensitive` to clarify that we're indicating redactability, not actually performing redaction. * Redacts from YAML output, including `mrsk config` (fixes #96)
This commit is contained in:
@@ -119,7 +119,7 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
|
||||
desc "config", "Show combined config (including secrets!)"
|
||||
def config
|
||||
run_locally do
|
||||
puts MRSK.config.to_h.to_yaml
|
||||
puts Mrsk::Utils.redacted(MRSK.config.to_h).to_yaml
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module Mrsk::Commands
|
||||
class Base
|
||||
delegate :redact, :argumentize, to: Mrsk::Utils
|
||||
delegate :sensitive, :argumentize, to: Mrsk::Utils
|
||||
|
||||
attr_accessor :config
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base
|
||||
end
|
||||
|
||||
def build_args
|
||||
argumentize "--build-arg", args, redacted: true
|
||||
argumentize "--build-arg", args, sensitive: true
|
||||
end
|
||||
|
||||
def build_secrets
|
||||
|
||||
@@ -2,7 +2,7 @@ class Mrsk::Commands::Registry < Mrsk::Commands::Base
|
||||
delegate :registry, to: :config
|
||||
|
||||
def login
|
||||
docker :login, registry["server"], "-u", redact(lookup("username")), "-p", redact(lookup("password"))
|
||||
docker :login, registry["server"], "-u", sensitive(lookup("username")), "-p", sensitive(lookup("password"))
|
||||
end
|
||||
|
||||
def logout
|
||||
|
||||
@@ -2,11 +2,12 @@ module Mrsk::Utils
|
||||
extend self
|
||||
|
||||
# Return a list of escaped shell arguments using the same named argument against the passed attributes (hash or array).
|
||||
def argumentize(argument, attributes, redacted: false)
|
||||
def argumentize(argument, attributes, sensitive: false)
|
||||
Array(attributes).flat_map do |key, value|
|
||||
if value.present?
|
||||
escaped_pair = [ key, escape_shell_value(value) ].join("=")
|
||||
[ argument, redacted ? redact(escaped_pair) : escaped_pair ]
|
||||
attr = "#{key}=#{escape_shell_value(value)}"
|
||||
attr = self.sensitive(attr, redaction: "#{key}=[REDACTED]") if sensitive
|
||||
[ argument, attr]
|
||||
else
|
||||
[ argument, key ]
|
||||
end
|
||||
@@ -17,7 +18,7 @@ module Mrsk::Utils
|
||||
# but redacts and expands secrets.
|
||||
def argumentize_env_with_secrets(env)
|
||||
if (secrets = env["secret"]).present?
|
||||
argumentize("-e", secrets.to_h { |key| [ key, ENV.fetch(key) ] }, redacted: true) + argumentize("-e", env["clear"])
|
||||
argumentize("-e", secrets.to_h { |key| [ key, ENV.fetch(key) ] }, sensitive: true) + argumentize("-e", env["clear"])
|
||||
else
|
||||
argumentize "-e", env.fetch("clear", env)
|
||||
end
|
||||
@@ -39,9 +40,37 @@ module Mrsk::Utils
|
||||
args.flat_map { |key, value| value.try(:map) { |entry| [key, entry] } || [ [ key, value ] ] }
|
||||
end
|
||||
|
||||
# Copied from SSHKit::Backend::Abstract#redact to be available inside Commands classes
|
||||
def redact(arg) # Used in execute_command to hide redact() args a user passes in
|
||||
arg.to_s.extend(SSHKit::Redaction) # to_s due to our inability to extend Integer, etc
|
||||
# Marks sensitive values for redaction in logs and human-visible output.
|
||||
# Pass `redaction:` to change the default `"[REDACTED]"` redaction, e.g.
|
||||
# `sensitive "#{arg}=#{secret}", redaction: "#{arg}=xxxx"
|
||||
def sensitive(...)
|
||||
Mrsk::Utils::Sensitive.new(...)
|
||||
end
|
||||
|
||||
def redacted(value)
|
||||
case
|
||||
when value.respond_to?(:redaction)
|
||||
value.redaction
|
||||
when value.respond_to?(:transform_values)
|
||||
value.transform_values { |value| redacted value }
|
||||
when value.respond_to?(:map)
|
||||
value.map { |element| redacted element }
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
def unredacted(value)
|
||||
case
|
||||
when value.respond_to?(:unredacted)
|
||||
value.unredacted
|
||||
when value.respond_to?(:transform_values)
|
||||
value.transform_values { |value| unredacted value }
|
||||
when value.respond_to?(:map)
|
||||
value.map { |element| unredacted element }
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
# Escape a value to make it safe for shell use.
|
||||
|
||||
19
lib/mrsk/utils/sensitive.rb
Normal file
19
lib/mrsk/utils/sensitive.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require "active_support/core_ext/module/delegation"
|
||||
|
||||
class Mrsk::Utils::Sensitive
|
||||
# So SSHKit knows to redact these values.
|
||||
include SSHKit::Redaction
|
||||
|
||||
attr_reader :unredacted, :redaction
|
||||
delegate :to_s, to: :unredacted
|
||||
delegate :inspect, to: :redaction
|
||||
|
||||
def initialize(value, redaction: "[REDACTED]")
|
||||
@unredacted, @redaction = value, redaction
|
||||
end
|
||||
|
||||
# Sensitive values won't leak into YAML output.
|
||||
def encode_with(coder)
|
||||
coder.represent_scalar nil, redaction
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user