Class: Shippy::SecretsManager

Inherits:
Object
  • Object
show all
Defined in:
lib/shippy/secrets_manager.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content_path: "config/secrets.yml.enc", key_path: "config/master.key", env_key: "SHIPPY_MASTER_KEY", output: $stdout) ⇒ SecretsManager

Returns a new instance of SecretsManager.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/shippy/secrets_manager.rb', line 10

def initialize(
  content_path: "config/secrets.yml.enc",
  key_path: "config/master.key",
  env_key: "SHIPPY_MASTER_KEY",
  output: $stdout
)
  @content_path = content_path
  @key_path = key_path
  @env_key = env_key
  @output = output

  @config = ActiveSupport::EncryptedConfiguration.new(
    config_path: @content_path,
    key_path: @key_path,
    env_key: @env_key,
    raise_if_missing_key: true
  )
end

Instance Attribute Details

#content_path ⇒ Object (readonly)

Returns the value of attribute content_path.



8
9
10
# File 'lib/shippy/secrets_manager.rb', line 8

def content_path
  @content_path
end

#key_path ⇒ Object (readonly)

Returns the value of attribute key_path.



8
9
10
# File 'lib/shippy/secrets_manager.rb', line 8

def key_path
  @key_path
end

#output ⇒ Object (readonly)

Returns the value of attribute output.



8
9
10
# File 'lib/shippy/secrets_manager.rb', line 8

def output
  @output
end

Instance Method Details

#edit ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/shippy/secrets_manager.rb', line 29

def edit
  ensure_key_exists!

  original_content = if File.exist?(content_path)
    @config.read
  else
    "# Add your secrets here. They will be encrypted on save.\n" \
    "# proxy:\n" \
    "#   cloudflare_token: value\n" \
    "#   cloudflare_email: [email protected]\n" \
    "# other_service:\n" \
    "#   value: secret\n"
  end

  Tempfile.create(["secrets", ".yml"]) do |tmp_file|
    tmp_file.write(original_content)
    tmp_file.close

    editor = ENV["EDITOR"] || "vim"
    system("#{editor} #{tmp_file.path}")

    new_content = File.read(tmp_file.path)

    if new_content != original_content
      @config.write(new_content)
      output.puts "✅ Secrets updated and encrypted to #{content_path}"
    else
      output.puts "⚠️ No changes detected."
    end
  end
rescue ActiveSupport::EncryptedFile::MissingKeyError
  output.puts "❌ Error: Missing '#{key_path}'. Run 'setup' first to generate a key."
end

#ensure_key_exists! ⇒ Object



69
70
71
72
73
74
75
76
# File 'lib/shippy/secrets_manager.rb', line 69

def ensure_key_exists!
  return if File.exist?(key_path)

  output.puts "Generating new master key at #{key_path}..."
  FileUtils.mkdir_p(File.dirname(key_path))
  File.write(key_path, ActiveSupport::EncryptedConfiguration.generate_key)
  output.puts "⚠️ IMPORTANT: Add #{key_path} to your .gitignore!"
end

#read ⇒ Object



63
64
65
66
67
# File 'lib/shippy/secrets_manager.rb', line 63

def read
  YAML.safe_load(@config.read, symbolize_names: true).to_h
rescue Errno::ENOENT
  {}
end