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,4 +2,8 @@ class ApplicationController < ActionController::Base | ||
2 | # Prevent CSRF attacks by raising an exception. | 2 | # Prevent CSRF attacks by raising an exception. |
3 | # For APIs, you may want to use :null_session instead. | 3 | # For APIs, you may want to use :null_session instead. |
4 | protect_from_forgery with: :exception | 4 | protect_from_forgery with: :exception |
5 | + | ||
6 | + def check_cert | ||
7 | + end | ||
5 | end | 8 | end |
9 | +# vim: set et ts=2 sw=2: |
@@ -2,11 +2,14 @@ class DashboardController < ApplicationController | @@ -2,11 +2,14 @@ class DashboardController < ApplicationController | ||
2 | def index | 2 | def index |
3 | @lxd_host = LxdHost.find(1) | 3 | @lxd_host = LxdHost.find(1) |
4 | @cert = Certificate.find(1) | 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 | end | 13 | end |
11 | end | 14 | end |
12 | end | 15 | end |
@@ -3,7 +3,7 @@ require 'digest/md5' | @@ -3,7 +3,7 @@ require 'digest/md5' | ||
3 | 3 | ||
4 | class Certificate < ActiveRecord::Base | 4 | class Certificate < ActiveRecord::Base |
5 | def key | 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 | end | 7 | end |
8 | 8 | ||
9 | def cert | 9 | def cert |
@@ -11,11 +11,16 @@ class Certificate < ActiveRecord::Base | @@ -11,11 +11,16 @@ class Certificate < ActiveRecord::Base | ||
11 | end | 11 | end |
12 | 12 | ||
13 | def key_fpr | 13 | def key_fpr |
14 | - Digest::SHA1.hexdigest(key.to_der).upcase | 14 | + Digest::SHA256.hexdigest(key.to_der).upcase |
15 | end | 15 | end |
16 | 16 | ||
17 | def cert_fpr | 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 | end | 24 | end |
20 | end | 25 | end |
21 | # vim: set et ts=2 sw=2: | 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 | class Lxd::Certificate | 1 | class Lxd::Certificate |
2 | include ActiveModel::Model | 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 | end | 20 | end |
24 | end | 21 | end |
25 | # vim: set ts=2 sw=2: | 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 | <h1>Dashboard#index</h1> | 1 | <h1>Dashboard#index</h1> |
2 | <p><%= @lxd_host.class %></p> | 2 | <p><%= @lxd_host.class %></p> |
3 | <p><%= @cert.class %></p> | 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