Commit c496fc34eae75ca6ed38645eda5aafb9fb54a757

Authored by Georg Hopp
1 parent f8a80693

Start some real code...

  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:
... ...
  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:
... ...
  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:
... ...
  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:
... ...
  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:
... ...
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