Ensure env secrets are merged correctly with roles

This commit is contained in:
David Heinemeier Hansson
2023-01-21 11:32:40 +01:00
parent dda20eec11
commit fd23fc1dfd
4 changed files with 99 additions and 13 deletions

View File

@@ -7,7 +7,7 @@ require "mrsk/utils"
class Mrsk::Configuration
delegate :service, :image, :servers, :env, :labels, :registry, :builder, to: :config, allow_nil: true
delegate :argumentize, to: Mrsk::Utils
delegate :argumentize_env_with_secrets, to: Mrsk::Utils
class << self
def create_from(base_config_file, destination: nil, version: "missing")
@@ -81,11 +81,7 @@ class Mrsk::Configuration
def env_args
if config.env.present?
if config.env["secret"].present?
argumentize("-e", expand_env_secrets, redacted: true) + argumentize("-e", config.env["clear"])
else
argumentize "-e", config.env
end
argumentize_env_with_secrets(config.env)
else
[]
end
@@ -138,10 +134,6 @@ class Mrsk::Configuration
def role_names
config.servers.is_a?(Array) ? [ "web" ] : config.servers.keys.sort
end
def expand_env_secrets
config.env["secret"].to_h { |key| [ key, ENV.fetch(key) ] }
end
end
require "mrsk/configuration/role"

View File

@@ -1,5 +1,5 @@
class Mrsk::Configuration::Role
delegate :argumentize, to: Mrsk::Utils
delegate :argumentize, :argumentize_env_with_secrets, to: Mrsk::Utils
attr_accessor :name
@@ -20,11 +20,15 @@ class Mrsk::Configuration::Role
end
def env
(config.env || {}).merge(specializations["env"] || {})
if config.env && config.env["secret"]
merged_env_with_secrets
else
merged_env
end
end
def env_args
argumentize "-e", env
argumentize_env_with_secrets env
end
def cmd
@@ -79,4 +83,20 @@ class Mrsk::Configuration::Role
config.servers[name].except("hosts")
end
end
def specialized_env
specializations["env"] || {}
end
def merged_env
config.env&.merge(specialized_env) || {}
end
# Secrets are stored in an array, which won't merge by default, so have to do it by hand.
def merged_env_with_secrets
merged_env.tap do |new_env|
new_env["secret"] = Array(config.env["secret"]) + Array(specialized_env["secret"])
new_env["clear"] = (Array(config.env["clear"] || config.env) + Array(specialized_env["clear"] || specialized_env)).uniq
end
end
end

View File

@@ -6,6 +6,16 @@ module Mrsk::Utils
Array(attributes).flat_map { |k, v| [ argument, redacted ? redact("#{k}=#{v}") : "#{k}=#{v}" ] }
end
# Return a list of shell arguments using the same named argument against the passed attributes,
# 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"])
else
argumentize "-e", env
end
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