Merge pull request #17 from anoldguy/switch-to-docker-secrets
Enable docker secrets as a more secure alternative to build args
This commit is contained in:
36
README.md
36
README.md
@@ -146,26 +146,44 @@ builder:
|
||||
multiarch: false
|
||||
```
|
||||
|
||||
### Configuring build secrets for new images
|
||||
|
||||
Some images need a secret passed in during build time, like a GITHUB_TOKEN to give access to private gem repositories. This can be done by having the secret in ENV, then referencing it like so in the configuration:
|
||||
|
||||
```yaml
|
||||
builder:
|
||||
secrets:
|
||||
- GITHUB_TOKEN
|
||||
```
|
||||
|
||||
This build secret can then be used in the Dockerfile:
|
||||
|
||||
```
|
||||
# Install application gems
|
||||
COPY Gemfile Gemfile.lock ./
|
||||
|
||||
# Private repositories need an access token during the build
|
||||
RUN --mount=type=secret,id=GITHUB_TOKEN \
|
||||
BUNDLE_GITHUB__COM=x-access-token:$(cat /run/secrets/GITHUB_TOKEN) \
|
||||
bundle install
|
||||
```
|
||||
|
||||
### Configuring build args for new images
|
||||
|
||||
Some images might need an argument passed in during build time, like a GITHUB_TOKEN to give access to private gem repositories. This can be done like so:
|
||||
Build arguments that aren't secret can be configured like so:
|
||||
|
||||
```yaml
|
||||
builder:
|
||||
args:
|
||||
GITHUB_TOKEN: <%= ENV["GITHUB_TOKEN"] %>
|
||||
RUBY_VERSION: 3.2.0
|
||||
```
|
||||
|
||||
This build arg can then be used in the Dockerfile:
|
||||
This build argument can then be used in the Dockerfile:
|
||||
|
||||
```
|
||||
# Private repositories need an access token during the build
|
||||
ARG GITHUB_TOKEN
|
||||
ENV BUNDLE_GITHUB__COM=x-access-token:$GITHUB_TOKEN
|
||||
|
||||
# Install application gems
|
||||
COPY Gemfile Gemfile.lock ./
|
||||
RUN bundle install
|
||||
ARG RUBY_VERSION
|
||||
FROM ruby:$RUBY_VERSION-slim as base
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require "mrsk/commands/base"
|
||||
|
||||
class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base
|
||||
delegate :argumentize, to: Mrsk::Configuration
|
||||
delegate :argumentize, to: Mrsk::Utils
|
||||
|
||||
def pull
|
||||
docker :pull, config.absolute_image
|
||||
@@ -11,8 +11,16 @@ class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base
|
||||
argumentize "--build-arg", args, redacted: true
|
||||
end
|
||||
|
||||
def build_secrets
|
||||
argumentize "--secret", secrets.collect { |secret| [ "id", secret ] }
|
||||
end
|
||||
|
||||
private
|
||||
def args
|
||||
config.builder["args"] || {}
|
||||
end
|
||||
|
||||
def secrets
|
||||
config.builder["secrets"] || []
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,6 +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
|
||||
|
||||
class << self
|
||||
def create_from(base_config_file, destination: nil)
|
||||
@@ -18,10 +19,6 @@ class Mrsk::Configuration
|
||||
end)
|
||||
end
|
||||
|
||||
def argumentize(argument, attributes, redacted: false)
|
||||
attributes.flat_map { |k, v| [ argument, redacted ? Mrsk::Utils.redact("#{k}=#{v}") : "#{k}=#{v}" ] }
|
||||
end
|
||||
|
||||
private
|
||||
def load_config_file(file)
|
||||
if file.exist?
|
||||
@@ -94,7 +91,7 @@ class Mrsk::Configuration
|
||||
|
||||
def env_args
|
||||
if config.env.present?
|
||||
self.class.argumentize "-e", config.env
|
||||
argumentize "-e", config.env
|
||||
else
|
||||
[]
|
||||
end
|
||||
@@ -137,7 +134,7 @@ class Mrsk::Configuration
|
||||
|
||||
if config.registry["username"].blank?
|
||||
raise ArgumentError, "You must specify a username for the registry in config/deploy.yml"
|
||||
end
|
||||
end
|
||||
|
||||
if config.registry["password"].blank?
|
||||
raise ArgumentError, "You must specify a password for the registry in config/deploy.yml (or set the ENV variable if that's used)"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Mrsk::Configuration::Role
|
||||
delegate :argumentize, to: Mrsk::Configuration
|
||||
delegate :argumentize, to: Mrsk::Utils
|
||||
|
||||
attr_accessor :name
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
module Mrsk::Utils
|
||||
extend self
|
||||
|
||||
# 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}" ] }
|
||||
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
|
||||
|
||||
@@ -27,6 +27,11 @@ class CommandsBuilderTest < ActiveSupport::TestCase
|
||||
assert_equal [ "--build-arg", "a=1", "--build-arg", "b=2" ], builder.target.build_args
|
||||
end
|
||||
|
||||
test "build secrets" do
|
||||
builder = Mrsk::Commands::Builder.new(Mrsk::Configuration.new(@config.merge({ builder: { "secrets" => ["token_a", "token_b"] } })))
|
||||
assert_equal [ "--secret", "id=token_a", "--secret", "id=token_b" ], builder.target.build_secrets
|
||||
end
|
||||
|
||||
test "native push with build args" do
|
||||
builder = Mrsk::Commands::Builder.new(Mrsk::Configuration.new(@config.merge({ builder: { "multiarch" => false, "args" => { "a" => 1, "b" => 2 } } })))
|
||||
assert_equal [ :docker, :build, "-t", "--build-arg", "a=1", "--build-arg", "b=2", "dhh/app:123", ".", "&&", :docker, :push, "dhh/app:123" ], builder.push
|
||||
|
||||
Reference in New Issue
Block a user