Skip to content

Commit

Permalink
Add secrets-common for shared secrets
Browse files Browse the repository at this point in the history
Add a shared secrets file used across all destinations. Useful for
things Github tokens or registry passwords.

The secrets are added to a new file called `secrets-common` to highlight
they are shared, and to avoid acciedentally inheriting a secret from the
`secrets` file to `secrets.destination`.
  • Loading branch information
djmb committed Sep 11, 2024
1 parent c994680 commit 9089c41
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 16 deletions.
19 changes: 7 additions & 12 deletions lib/kamal/secrets.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
require "dotenv"

class Kamal::Secrets
attr_reader :secrets_file
attr_reader :secrets_files

Kamal::Secrets::Dotenv::InlineCommandSubstitution.install!

def initialize(destination: nil)
@secrets_file = [ *(".kamal/secrets.#{destination}" if destination), ".kamal/secrets" ].find { |f| File.exist?(f) }
@secrets_files = \
[ ".kamal/secrets-common", ".kamal/secrets#{(".#{destination}" if destination)}" ].select { |f| File.exist?(f) }
end

def [](key)
secrets.fetch(key)
rescue KeyError
if secrets_file
raise Kamal::ConfigurationError, "Secret '#{key}' not found in #{secrets_file}"
if secrets_files
raise Kamal::ConfigurationError, "Secret '#{key}' not found in #{secrets_files.join(", ")}"
else
raise Kamal::ConfigurationError, "Secret '#{key}' not found, no secret files provided"
end
Expand All @@ -25,14 +26,8 @@ def to_h

private
def secrets
@secrets ||= parse_secrets
end

def parse_secrets
if secrets_file
::Dotenv.parse(secrets_file)
else
{}
@secrets ||= secrets_files.inject({}) do |secrets, secrets_file|
secrets.merge!(::Dotenv.parse(secrets_file))
end
end
end
2 changes: 0 additions & 2 deletions test/integration/docker/deployer/app/.kamal/secrets
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
SECRET_TOKEN='1234 with "中文"'
SECRET_TAG='TAGME'
SECRETS=$(kamal secrets fetch --adapter test --account test INTERPOLATED_SECRET1 INTERPOLATED_SECRET2 INTERPOLATED_中文)
INTERPOLATED_SECRET1=$(kamal secrets extract INTERPOLATED_SECRET1 ${SECRETS})
INTERPOLATED_SECRET2=$(kamal secrets extract INTERPOLATED_SECRET2 ${SECRETS})
Expand Down
2 changes: 2 additions & 0 deletions test/integration/docker/deployer/app/.kamal/secrets-common
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SECRET_TOKEN='1234 with "中文"'
SECRET_TAG='TAGME'
8 changes: 6 additions & 2 deletions test/secrets_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ class SecretsTest < ActiveSupport::TestCase
end

test "destinations" do
with_test_secrets("secrets.dest" => "SECRET=DEF", "secrets" => "SECRET=ABC") do
with_test_secrets("secrets.dest" => "SECRET=DEF", "secrets" => "SECRET=ABC", "secrets-common" => "SECRET=GHI\nSECRET2=JKL") do
assert_equal "ABC", Kamal::Secrets.new["SECRET"]
assert_equal "DEF", Kamal::Secrets.new(destination: "dest")["SECRET"]
assert_equal "ABC", Kamal::Secrets.new(destination: "nodest")["SECRET"]
assert_equal "GHI", Kamal::Secrets.new(destination: "nodest")["SECRET"]

assert_equal "JKL", Kamal::Secrets.new["SECRET2"]
assert_equal "JKL", Kamal::Secrets.new(destination: "dest")["SECRET2"]
assert_equal "JKL", Kamal::Secrets.new(destination: "nodest")["SECRET2"]
end
end
end

0 comments on commit 9089c41

Please sign in to comment.