Class: OsCtld::SendReceive::KeyChain

Inherits:
Object
  • Object
show all
Includes:
OsCtl::Lib::Utils::Log, Lockable
Defined in:
lib/osctld/send_receive/key_chain.rb

Defined Under Namespace

Classes: Key

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Lockable

#exclusively, included, #inclusively, #init_lock, #lock, #unlock

Constructor Details

#initialize(pool) ⇒ KeyChain

Returns a new instance of KeyChain.



56
57
58
59
60
# File 'lib/osctld/send_receive/key_chain.rb', line 56

def initialize(pool)
  init_lock
  @pool = pool
  @keys = []
end

Instance Attribute Details

#keysObject (readonly, protected)

Returns the value of attribute keys.



239
240
241
# File 'lib/osctld/send_receive/key_chain.rb', line 239

def keys
  @keys
end

#poolObject (readonly, protected)

Returns the value of attribute pool.



239
240
241
# File 'lib/osctld/send_receive/key_chain.rb', line 239

def pool
  @pool
end

Instance Method Details

#assets(add) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/osctld/send_receive/key_chain.rb', line 62

def assets(add)
  add.file(
    private_key_path,
    desc: 'Identity private key',
    user: 0,
    group: 0,
    mode: 0o400,
    optional: true
  )
  add.file(
    public_key_path,
    desc: 'Identity public key',
    user: 0,
    group: 0,
    mode: 0o400,
    optional: true
  )
  add.file(
    key_chain_path,
    desc: 'Keys authorized to send containers to this node',
    user: 0,
    group: 0,
    mode: 0o400,
    optional: true
  )
end

#authorize_key(name, pubkey, opts = {}) ⇒ Object

Parameters:

  • name (String)
  • pubkey (String)
  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :from (String)
  • :ctid (String)
  • :passphrase (String)
  • :single_use (Boolean)


156
157
158
159
160
161
162
# File 'lib/osctld/send_receive/key_chain.rb', line 156

def authorize_key(name, pubkey, opts = {})
  exclusively do
    raise ArgumentError, 'key exists' if keys.detect { |v| v.name == name }

    keys << Key.new(name, pubkey, opts)
  end
end

#deploy(io) ⇒ Object

Parameters:

  • io (IO)


101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/osctld/send_receive/key_chain.rb', line 101

def deploy(io)
  inclusively do
    keys.each do |key|
      options = [
        "command=\"#{File.join(SendReceive::HOOK)} #{pool.name} #{key.name}\"",
        'restrict'
      ]

      io.puts("#{options.join(',')} #{key.pubkey}")
    end
  end
end

#exportObject



209
210
211
# File 'lib/osctld/send_receive/key_chain.rb', line 209

def export
  inclusively { keys.map(&:dump) }
end

#find_key(pubkey, hosts, passphrase) ⇒ Key?

Find key by pubkey, client address/hostnames and passphrase

Parameters:

  • pubkey (String)
  • hosts (Array<String>)
  • passphrase (String)

Returns:



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/osctld/send_receive/key_chain.rb', line 133

def find_key(pubkey, hosts, passphrase)
  inclusively do
    keys.detect do |k|
      next if k.pubkey != pubkey || k.passphrase != passphrase

      if k.from
        k.from.any? do |pattern|
          hosts.any? { |v| File.fnmatch?(pattern, v) }
        end
      else
        true
      end
    end
  end
end

#get_key(name) ⇒ Key?

Find key by name

Parameters:

  • name (String)

Returns:



122
123
124
125
126
# File 'lib/osctld/send_receive/key_chain.rb', line 122

def get_key(name)
  inclusively do
    keys.detect { |v| v.name == name }
  end
end

#key_chain_pathObject



229
230
231
# File 'lib/osctld/send_receive/key_chain.rb', line 229

def key_chain_path
  File.join(pool.conf_path, 'send-receive', 'keychain.yml')
end

#key_exist?(name) ⇒ Boolean

Parameters:

  • name (String)

Returns:

  • (Boolean)


115
116
117
# File 'lib/osctld/send_receive/key_chain.rb', line 115

def key_exist?(name)
  inclusively { !keys.detect { |v| v.name == name }.nil? }
end

#log_typeObject



233
234
235
# File 'lib/osctld/send_receive/key_chain.rb', line 233

def log_type
  "#{pool.name}:key-chain"
end

#private_key_pathObject



221
222
223
# File 'lib/osctld/send_receive/key_chain.rb', line 221

def private_key_path
  File.join(pool.conf_path, 'send-receive', 'key')
end

#public_key_pathObject



225
226
227
# File 'lib/osctld/send_receive/key_chain.rb', line 225

def public_key_path
  "#{private_key_path}.pub"
end

#revoke_key(name) ⇒ Object

Parameters:

  • name (String)


165
166
167
168
169
# File 'lib/osctld/send_receive/key_chain.rb', line 165

def revoke_key(name)
  exclusively do
    keys.delete_if { |v| v.name == name }
  end
end

#saveObject



213
214
215
216
217
218
219
# File 'lib/osctld/send_receive/key_chain.rb', line 213

def save
  exclusively do
    File.open(key_chain_path, 'w', 0o400) do |f|
      f.write(OsCtl::Lib::ConfigFile.dump_yaml(keys.map(&:dump)))
    end
  end
end

#setupObject



89
90
91
92
93
94
95
96
97
98
# File 'lib/osctld/send_receive/key_chain.rb', line 89

def setup
  exclusively do
    keys.clear
    return unless File.exist?(key_chain_path)

    OsCtl::Lib::ConfigFile.load_yaml_file(key_chain_path).each do |v|
      keys << Key.load(v)
    end
  end
end

#started_using_key(name) ⇒ Boolean

Returns true if the key has been updated.

Parameters:

  • name (String)

Returns:

  • (Boolean)

    true if the key has been updated



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/osctld/send_receive/key_chain.rb', line 173

def started_using_key(name)
  ret = false

  exclusively do
    key = keys.detect { |v| v.name == name }

    if key && key.single_use?
      ret = true
      key.in_use = true
      save
    end
  end

  ret
end

#stopped_using_key(name) ⇒ Boolean

Returns true if the key has been deleted.

Parameters:

  • name (String)

Returns:

  • (Boolean)

    true if the key has been deleted



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/osctld/send_receive/key_chain.rb', line 191

def stopped_using_key(name)
  ret = false

  exclusively do
    i = keys.index { |v| v.name == name }

    if i && keys[i].single_use?
      ret = true
      keys.delete_at(i)
      save
    end
  end

  log(:info, "Removed single-use key #{name}") if ret

  ret
end