Class: Kodo::Secrets::Broker

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

Constant Summary collapse

GRANTS =
[
  Grant.new(secret_name: 'anthropic_api_key', requestor: 'llm'),
  Grant.new(secret_name: 'openai_api_key', requestor: 'llm'),
  Grant.new(secret_name: 'gemini_api_key', requestor: 'llm'),
  Grant.new(secret_name: 'deepseek_api_key', requestor: 'llm'),
  Grant.new(secret_name: 'mistral_api_key', requestor: 'llm'),
  Grant.new(secret_name: 'openrouter_api_key', requestor: 'llm'),
  Grant.new(secret_name: 'perplexity_api_key', requestor: 'llm'),
  Grant.new(secret_name: 'xai_api_key', requestor: 'llm'),
  Grant.new(secret_name: 'tavily_api_key', requestor: 'search'),
  Grant.new(secret_name: 'telegram_bot_token', requestor: 'telegram')
].freeze
ENV_FALLBACKS =
{
  'anthropic_api_key' => 'ANTHROPIC_API_KEY',
  'openai_api_key' => 'OPENAI_API_KEY',
  'gemini_api_key' => 'GEMINI_API_KEY',
  'deepseek_api_key' => 'DEEPSEEK_API_KEY',
  'mistral_api_key' => 'MISTRAL_API_KEY',
  'openrouter_api_key' => 'OPENROUTER_API_KEY',
  'perplexity_api_key' => 'PERPLEXITY_API_KEY',
  'xai_api_key' => 'XAI_API_KEY',
  'tavily_api_key' => 'TAVILY_API_KEY',
  'telegram_bot_token' => 'TELEGRAM_BOT_TOKEN'
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(store:, audit:) ⇒ Broker

Returns a new instance of Broker.



32
33
34
35
# File 'lib/kodo/secrets/broker.rb', line 32

def initialize(store:, audit:)
  @store = store
  @audit = audit
end

Instance Method Details

#available?(name) ⇒ Boolean

Returns:

  • (Boolean)


71
72
73
74
75
76
77
78
79
# File 'lib/kodo/secrets/broker.rb', line 71

def available?(name)
  return true if @store.exists?(name)

  env_var = ENV_FALLBACKS[name]
  return false unless env_var

  value = ENV[env_var]
  !value.nil? && !value.empty?
end

#configured_secrets ⇒ Object



81
82
83
84
# File 'lib/kodo/secrets/broker.rb', line 81

def configured_secrets
  all_names = GRANTS.map(&:secret_name).uniq
  all_names.select { |name| available?(name) }
end

#fetch(name, requestor:) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/kodo/secrets/broker.rb', line 37

def fetch(name, requestor:)
  unless authorized?(name, requestor)
    @audit.log(
      event: 'secret_access_denied',
      detail: "secret:#{name} requestor:#{requestor}"
    )
    return nil
  end

  value = @store.get(name)
  return value if value

  env_var = ENV_FALLBACKS[name]
  env_value = ENV[env_var] if env_var
  return env_value if env_value && !env_value.empty?

  nil
end

#fetch!(name, requestor:) ⇒ Object

Raises:



56
57
58
59
60
61
# File 'lib/kodo/secrets/broker.rb', line 56

def fetch!(name, requestor:)
  value = fetch(name, requestor: requestor)
  raise Kodo::Error, "Secret not available: #{name}" unless value

  value
end

#store(name, value, source: 'user', validated: false) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/kodo/secrets/broker.rb', line 63

def store(name, value, source: 'user', validated: false)
  @store.put(name, value, source: source, validated: validated)
  @audit.log(
    event: 'secret_stored',
    detail: "secret:#{name} source:#{source} validated:#{validated}"
  )
end