Class: AgentsControl::Secrets

Inherits:
Object
  • Object
show all
Defined in:
lib/agents_control/secrets.rb

Overview

Storing tokens outside the repo and outside the config.

Providers are tried in order; the first available one that answers wins. Implemented by shelling out to system binaries rather than gems: gems like keyring pull in C extensions and break installation for some users, while security and secret-tool are always present on their respective platforms.

The rule that shaped the implementation: the secret must never land in argv. Anything passed as an argument is visible in ps to any process the user owns, and it lands in shell history. That's why writing to the Keychain goes through security -i with the command on stdin, and the CLI never accepts the token as a flag.

Defined Under Namespace

Modules: Providers

Constant Summary collapse

SERVICE =
"agents_control"

Instance Method Summary collapse

Constructor Details

#initialize(executor: Executor.new, providers: nil) ⇒ Secrets

Returns a new instance of Secrets.



23
24
25
26
# File 'lib/agents_control/secrets.rb', line 23

def initialize(executor: Executor.new, providers: nil)
  @executor = executor
  @providers = providers || default_providers
end

Instance Method Details

#delete(key) ⇒ Object



45
46
47
# File 'lib/agents_control/secrets.rb', line 45

def delete(key)
  writable.each { |provider| provider.delete(key.to_s) }
end

#get(key) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/agents_control/secrets.rb', line 28

def get(key)
  readable.each do |provider|
    value = provider.get(key.to_s)
    return value if value && !value.empty?
  end

  nil
end

#set(key, value) ⇒ Object

Raises:



37
38
39
40
41
42
43
# File 'lib/agents_control/secrets.rb', line 37

def set(key, value)
  provider = writable.first
  raise Error, "no secret storage available" unless provider

  provider.set(key.to_s, value)
  provider
end

#source_for(key) ⇒ Object

Where a secret lives, and where it will be written — for doctor.



50
51
52
# File 'lib/agents_control/secrets.rb', line 50

def source_for(key)
  readable.find { |provider| provider.get(key.to_s) }
end

#targetObject



54
# File 'lib/agents_control/secrets.rb', line 54

def target = writable.first