Showing
11 changed files
with
241 additions
and
54 deletions
add-host-workflow.md
0 → 100644
1 | +# Workflow for adding a LXD host | |
2 | + | |
3 | +## User input | |
4 | + | |
5 | + * A symbolic name | |
6 | + * The LDX host base URL | |
7 | + * The password for certificate addition | |
8 | + | |
9 | +## workflow | |
10 | + | |
11 | + * Check our current client key. | |
12 | + * Recreate client key if we find no active valid key | |
13 | + * This also involves deactivating the old one and activate the new one. | |
14 | + * Get API version of the LXD host. (unauth) | |
15 | + * Bail out if not supported ... currently (only 1.0 is supported) | |
16 | + * Get Server info / well, this might also be done in the previous task. | |
17 | + * If unathorized add cert with password. | |
18 | + * I guess thats it. | |
19 | + | |
20 | +## stored | |
21 | + | |
22 | + * The new cert eventually | |
23 | + * The name and url of the LXD host | |
24 | + | |
25 | +# Workflow accessing LXD host | |
26 | + | |
27 | +## input | |
28 | + | |
29 | + * The name of the LXD host | |
30 | + | |
31 | +## workflow | |
32 | + | |
33 | + * Check our current client cert. | |
34 | + * If close to expiration create a new one and send it to | |
35 | + LXD host with the old one. | |
36 | + * If behind expiration ask for password | |
37 | + * Connect to LXD host using the current active cert. | ... | ... |
... | ... | @@ -2,4 +2,8 @@ class ApplicationController < ActionController::Base |
2 | 2 | # Prevent CSRF attacks by raising an exception. |
3 | 3 | # For APIs, you may want to use :null_session instead. |
4 | 4 | protect_from_forgery with: :exception |
5 | + | |
6 | + def check_cert | |
7 | + end | |
5 | 8 | end |
9 | +# vim: set et ts=2 sw=2: | ... | ... |
... | ... | @@ -2,11 +2,14 @@ class DashboardController < ApplicationController |
2 | 2 | def index |
3 | 3 | @lxd_host = LxdHost.find(1) |
4 | 4 | @cert = Certificate.find(1) |
5 | - @lxd = Lxd::Server.by_host @lxd_host, @cert | |
5 | + @api = Lxd::API.get @lxd_host, @cert | |
6 | + @lxd_config = Lxd::Config.get @api | |
6 | 7 | |
7 | - if @lxd.auth == 'untrusted' | |
8 | - Lxd::Certificate.new.save(@lxd_host, @cert) | |
9 | - @lxd = Lxd::Server.by_host @lxd_host, @cert | |
8 | + if @lxd_config.auth == 'untrusted' | |
9 | + # Here the controller has to ask for the password | |
10 | + cert = Lxd::Certificate.new api: @api | |
11 | + cert.save 'xxxxxxxxxx' | |
12 | + @lxd_config = Lxd::Config.get @api | |
10 | 13 | end |
11 | 14 | end |
12 | 15 | end | ... | ... |
... | ... | @@ -3,7 +3,7 @@ require 'digest/md5' |
3 | 3 | |
4 | 4 | class Certificate < ActiveRecord::Base |
5 | 5 | def key |
6 | - OpenSSL::PKey::RSA.new read_attribute(:key) if read_attribute(:key) | |
6 | + OpenSSL::PKey::EC.new read_attribute(:key) if read_attribute(:key) | |
7 | 7 | end |
8 | 8 | |
9 | 9 | def cert |
... | ... | @@ -11,11 +11,16 @@ class Certificate < ActiveRecord::Base |
11 | 11 | end |
12 | 12 | |
13 | 13 | def key_fpr |
14 | - Digest::SHA1.hexdigest(key.to_der).upcase | |
14 | + Digest::SHA256.hexdigest(key.to_der).upcase | |
15 | 15 | end |
16 | 16 | |
17 | 17 | def cert_fpr |
18 | - Digest::SHA1.hexdigest(cert.to_der).upcase | |
18 | + Digest::SHA256.hexdigest(cert.to_der).upcase | |
19 | + end | |
20 | + | |
21 | + private | |
22 | + | |
23 | + def _key | |
19 | 24 | end |
20 | 25 | end |
21 | 26 | # vim: set et ts=2 sw=2: | ... | ... |
app/models/lxd/api.rb
0 → 100644
1 | +module Lxd::API | |
2 | + def self.get host, certificate | |
3 | + uri = URI.parse host.uri | |
4 | + con = Net::HTTP.new uri.host, uri.port | |
5 | + con.use_ssl = true | |
6 | + con.cert = OpenSSL::X509::Certificate.new certificate.cert | |
7 | + con.key = OpenSSL::PKey::RSA.new certificate.key | |
8 | + con.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
9 | + | |
10 | + resp = self.call con, Net::HTTP::Get.new('/') | |
11 | + raise "unsupported api version" unless resp['metadata'].include? '/1.0' | |
12 | + Lxd::API::V1_0.new con | |
13 | + end | |
14 | + | |
15 | + def self.call con, req | |
16 | + resp = con.request req | |
17 | + raise "request failure: " + resp.code unless resp.code != 200 | |
18 | + JSON.parse resp.body | |
19 | + end | |
20 | + | |
21 | + def initialize con | |
22 | + @con = con | |
23 | + end | |
24 | + | |
25 | + def call req | |
26 | + handle_response(Lxd::API.call @con, req) | |
27 | + end | |
28 | + | |
29 | + def get uri | |
30 | + call Net::HTTP::Get.new uri | |
31 | + end | |
32 | + | |
33 | + def put uri, data={} | |
34 | + request = Net::HTTP::Put.new uri | |
35 | + request.body = data.to_json | |
36 | + call request | |
37 | + end | |
38 | + | |
39 | + def post uri, data={} | |
40 | + request = Net::HTTP::Post.new uri | |
41 | + request.body = data.to_json | |
42 | + call request | |
43 | + end | |
44 | +end | |
45 | +# vim: set ts=2 sw=2: | ... | ... |
app/models/lxd/api/v1_0.rb
0 → 100644
1 | +class Lxd::API::V1_0 | |
2 | + include Lxd::API | |
3 | + | |
4 | + def config | |
5 | + get '/1.0' | |
6 | + end | |
7 | + | |
8 | + def config= config={} | |
9 | + put '/1.0', config: config | |
10 | + end | |
11 | + | |
12 | + def certificates | |
13 | + get '/1.0/certificates'.map { |uri| | |
14 | + { | |
15 | + :uri => uri, | |
16 | + :cert => get(uri) | |
17 | + } | |
18 | + } | |
19 | + end | |
20 | + | |
21 | + def add_certificate cert={} | |
22 | + # TODO validate hash | |
23 | + post '/1.0/certificates', cert | |
24 | + end | |
25 | + | |
26 | + def handle_response resp | |
27 | + """ | |
28 | + 100 Operation created | |
29 | + 101 Started | |
30 | + 102 Stopped | |
31 | + 103 Running | |
32 | + 104 Cancelling | |
33 | + 105 Pending | |
34 | + 106 Starting | |
35 | + 107 Stopping | |
36 | + 108 Aborting | |
37 | + 109 Freezing | |
38 | + 110 Frozen | |
39 | + 111 Thawed | |
40 | + 200 Success | |
41 | + 400 Failure | |
42 | + 401 Cancelled | |
43 | + | |
44 | + | |
45 | + 100 to 199: resource state (started, stopped, ready, ...) | |
46 | + 200 to 399: positive action result | |
47 | + 400 to 599: negative action result | |
48 | + 600 to 999: future use | |
49 | + """ | |
50 | + raise "api error" if [400..500].include? resp['error_code'] | |
51 | + resp['metadata'] | |
52 | + end | |
53 | +end | |
54 | +# vim: set ts=2 sw=2: | ... | ... |
1 | 1 | class Lxd::Certificate |
2 | 2 | include ActiveModel::Model |
3 | 3 | |
4 | - def save(host, certificate) | |
5 | - all = Array.new; | |
4 | + attr_accessor :api, :type, :certificate, :fingerprint | |
6 | 5 | |
7 | - uri = URI.parse(host.uri + '/1.0/certificates') | |
8 | - http = Net::HTTP.new(uri.host, uri.port) | |
9 | - http.use_ssl = true | |
10 | - http.cert = OpenSSL::X509::Certificate.new(certificate.cert) | |
11 | - http.key = OpenSSL::PKey::RSA.new(certificate.key) | |
12 | - http.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
6 | + def self.all api | |
7 | + api.certificates.map { |cert| | |
8 | + Lxd::Certificate.new({api: api}.merge cert) | |
9 | + } | |
10 | + end | |
13 | 11 | |
14 | - request = Net::HTTP::Post.new(uri.request_uri) | |
15 | - request.body = { | |
16 | - :type => 'client', | |
17 | - :name => 'foo', | |
18 | - :password => '[where to get this from....]' | |
19 | - }.to_json | |
20 | - response = http.request(request) | |
12 | + def add password=nil, name='lex-deeit' | |
13 | + data = Hash.new | |
14 | + data[:type] = @type if @type else 'client' | |
15 | + data[:name] = name | |
16 | + data[:password] = password if password | |
17 | + data[:certificate] = @certificate if @certificate | |
21 | 18 | |
22 | - response.code | |
19 | + @api.add_certificate data | |
23 | 20 | end |
24 | 21 | end |
25 | 22 | # vim: set ts=2 sw=2: | ... | ... |
app/models/lxd/config.rb
0 → 100644
1 | +class Lxd::Config | |
2 | + include ActiveModel::Model | |
3 | + | |
4 | + attr_accessor :api, :api_extensions, :api_status, :api_version, :auth, | |
5 | + :config, :environment, :public | |
6 | + | |
7 | + def self.get api | |
8 | + Lxd::Config.new({api: api}.merge api.config) | |
9 | + end | |
10 | + | |
11 | + def save | |
12 | + @api.config = @config | |
13 | + end | |
14 | +end | |
15 | +# vim: set ts=2 sw=2: | ... | ... |
app/models/lxd/connection.rb
0 → 100644
1 | +class Lxd::Connection | |
2 | + attr_reader :con, :host, :port | |
3 | + | |
4 | + """ | |
5 | + /1.0 | |
6 | + /1.0/certificates | |
7 | + /1.0/certificates/<fingerprint> | |
8 | + /1.0/containers | |
9 | + /1.0/containers/<name> | |
10 | + /1.0/containers/<name>/exec | |
11 | + /1.0/containers/<name>/files | |
12 | + /1.0/containers/<name>/snapshots | |
13 | + /1.0/containers/<name>/snapshots/<name> | |
14 | + /1.0/containers/<name>/state | |
15 | + /1.0/containers/<name>/logs | |
16 | + /1.0/containers/<name>/logs/<logfile> | |
17 | + /1.0/events | |
18 | + /1.0/images | |
19 | + /1.0/images/<fingerprint> | |
20 | + /1.0/images/<fingerprint>/export | |
21 | + /1.0/images/aliases | |
22 | + /1.0/images/aliases/<name> | |
23 | + /1.0/networks | |
24 | + /1.0/networks/<name> | |
25 | + /1.0/operations | |
26 | + /1.0/operations/<uuid> | |
27 | + /1.0/operations/<uuid>/wait | |
28 | + /1.0/operations/<uuid>/websocket | |
29 | + /1.0/profiles | |
30 | + /1.0/profiles/<name> | |
31 | + """ | |
32 | + | |
33 | + def initialize host, certificate | |
34 | + uri = URI.parse host.uri | |
35 | + @host = uri.host | |
36 | + @port = uri.port | |
37 | + @con = Net::HTTP.new @host, @port | |
38 | + @con.use_ssl = true | |
39 | + @con.cert = OpenSSL::X509::Certificate.new certificate.cert | |
40 | + @con.key = OpenSSL::PKey::EC.new certificate.key | |
41 | + @con.verify_mode = OpenSSL::SSL:VERIFY_NONE | |
42 | + end | |
43 | + | |
44 | + def call | |
45 | + if not @api_version | |
46 | + @con.request(Net::HTTP::Get.new '/') | |
47 | + versions | |
48 | + end | |
49 | + end | |
50 | +# vim: set et ts=2 sw=2: | ... | ... |
app/models/lxd/server.rb
deleted
100644 → 0
1 | -class Lxd::Server | |
2 | - include ActiveModel::Model | |
3 | - | |
4 | - attr_accessor :api_extensions, :api_status, :api_version, :auth, :config, | |
5 | - :environment, :public | |
6 | - | |
7 | - def self.by_host(host, certificate) | |
8 | - all = Array.new; | |
9 | - | |
10 | - uri = URI.parse(host.uri + '/1.0') | |
11 | - http = Net::HTTP.new(uri.host, uri.port) | |
12 | - http.use_ssl = true | |
13 | - http.cert = OpenSSL::X509::Certificate.new(certificate.cert) | |
14 | - http.key = OpenSSL::PKey::RSA.new(certificate.key) | |
15 | - http.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
16 | - | |
17 | - request = Net::HTTP::Get.new(uri.request_uri) | |
18 | - response = http.request(request) | |
19 | - | |
20 | - Lxd::Server.new(JSON.parse(response.body)['metadata']) | |
21 | - end | |
22 | -end | |
23 | -# vim: set ts=2 sw=2: |
1 | 1 | <h1>Dashboard#index</h1> |
2 | 2 | <p><%= @lxd_host.class %></p> |
3 | 3 | <p><%= @cert.class %></p> |
4 | -<p><%= @lxd.class %></p> | |
5 | -<p><%= @lxd.api_extensions.inspect %></p> | |
6 | -<p><%= @lxd.api_status %></p> | |
7 | -<p><%= @lxd.api_version %></p> | |
8 | -<p><%= @lxd.auth %></p> | |
9 | -<p><%= @lxd.config.inspect %></p> | |
10 | -<p><%= @lxd.environment.inspect %></p> | |
11 | -<p><%= @lxd.public %></p> | |
4 | +<p><%= @lxd_config.class %></p> | |
5 | +<p><%= @lxd_config.api_extensions.inspect %></p> | |
6 | +<p><%= @lxd_config.api_status %></p> | |
7 | +<p><%= @lxd_config.api_version %></p> | |
8 | +<p><%= @lxd_config.auth %></p> | |
9 | +<p><%= @lxd_config.config.inspect %></p> | |
10 | +<p><%= @lxd_config.environment.inspect %></p> | |
11 | +<p><%= @lxd_config.public %></p> | ... | ... |
Please
register
or
login
to post a comment