Add secret envs

This commit is contained in:
David Heinemeier Hansson
2023-01-21 10:56:24 +01:00
parent 3bf56c2fdb
commit f6ca864e06
4 changed files with 53 additions and 2 deletions

View File

@@ -75,6 +75,25 @@ env:
REDIS_URL: redis://redis1:6379/1
```
### Adding secret custom env variables
If you have custom env variables that are secret, you can divide the `env` block into `clear` and `secret`:
```yaml
env:
clear:
DATABASE_URL: mysql2://db1/hey_production/
REDIS_URL: redis://redis1:6379/1
secret:
- DATABASE_PASSWORD
- REDIS_PASSWORD
```
The list of secret env variables will be expanded at run time from your local machine. So a reference to a secret `DATABASE_PASSWORD` will look for `ENV["DATABASE_PASSWORD"]` on the machine running MRSK. Just like with build secrets.
Note: Marking an ENV as secret currently only redacts its value in the output for MRSK. The ENV is still injected in the clear into the container at runtime.
### Splitting servers into different roles
If your application uses separate hosts for running jobs or other roles beyond the default web running, you can specify these hosts and their custom entrypoint command like so:

View File

@@ -81,7 +81,11 @@ 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
else
[]
end
@@ -134,6 +138,10 @@ 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[key] ] }
end
end
require "mrsk/configuration/role"

View File

@@ -3,7 +3,7 @@ module Mrsk::Utils
# Return a list of shell arguments using the same named argument against the passed attributes.
def argumentize(argument, attributes, redacted: false)
attributes.flat_map { |k, v| [ argument, redacted ? redact("#{k}=#{v}") : "#{k}=#{v}" ] }
Array(attributes).flat_map { |k, v| [ argument, redacted ? redact("#{k}=#{v}") : "#{k}=#{v}" ] }
end
# Copied from SSHKit::Backend::Abstract#redact to be available inside Commands classes

View File

@@ -89,6 +89,30 @@ class ConfigurationTest < ActiveSupport::TestCase
assert_equal [ "-e", "REDIS_URL=redis://x/y" ], @config.env_args
end
test "env args with clear and secrets" do
ENV["PASSWORD"] = "secret123"
config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({
env: { "clear" => { "PORT" => "3000" }, "secret" => [ "PASSWORD" ] }
}) })
assert_equal [ "-e", "PASSWORD=secret123", "-e", "PORT=3000" ], config.env_args
assert config.env_args[1].is_a?(SSHKit::Redaction)
ensure
ENV["PASSWORD"] = nil
end
test "env args with only secrets" do
ENV["PASSWORD"] = "secret123"
config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({
env: { "secret" => [ "PASSWORD" ] }
}) })
assert_equal [ "-e", "PASSWORD=secret123" ], config.env_args
assert config.env_args[1].is_a?(SSHKit::Redaction)
ensure
ENV["PASSWORD"] = nil
end
test "ssh options" do
assert_equal "root", @config.ssh_options[:user]