26 changed files with 270 additions and 330 deletions
-
1.gitignore
-
27app/controllers/application_controller.rb
-
94app/controllers/certificates_controller.rb
-
22app/controllers/dashboard_controller.rb
-
33app/controllers/lxd_hosts_controller.rb
-
35app/models/certificate.rb
-
70app/models/lxd/api.rb
-
105app/models/lxd/api/v1_0.rb
-
36app/models/lxd/certificate.rb
-
13app/models/lxd_host.rb
-
29app/views/certificates/_form.html.erb
-
6app/views/certificates/edit.html.erb
-
31app/views/certificates/index.html.erb
-
4app/views/certificates/index.json.jbuilder
-
5app/views/certificates/new.html.erb
-
19app/views/certificates/show.html.erb
-
1app/views/certificates/show.json.jbuilder
-
18app/views/dashboard/index.html.erb
-
13app/views/lxd_hosts/auth.html.erb
-
13config/certificate.yml
-
3config/environments/development.rb
-
3config/environments/production.rb
-
3config/environments/test.rb
-
3config/routes.rb
-
6db/migrate/20160425195446_delete_password_from_lxd_hosts.rb
-
7db/schema.rb
@ -1,94 +0,0 @@ |
|||||
require 'openssl' |
|
||||
|
|
||||
class CertificatesController < ApplicationController |
|
||||
before_action :set_certificate, only: [:show, :edit, :update, :destroy] |
|
||||
|
|
||||
# GET /certificates |
|
||||
# GET /certificates.json |
|
||||
def index |
|
||||
@certificates = Certificate.all |
|
||||
end |
|
||||
|
|
||||
# GET /certificates/1 |
|
||||
# GET /certificates/1.json |
|
||||
def show |
|
||||
end |
|
||||
|
|
||||
# GET /certificates/new |
|
||||
def new |
|
||||
@certificate = Certificate.new |
|
||||
end |
|
||||
|
|
||||
# GET /certificates/1/edit |
|
||||
def edit |
|
||||
end |
|
||||
|
|
||||
# POST /certificates |
|
||||
# POST /certificates.json |
|
||||
def create |
|
||||
@certificate = Certificate.new(certificate_params) |
|
||||
|
|
||||
key = OpenSSL::PKey::RSA.new 4096 |
|
||||
name = OpenSSL::X509::Name.parse 'CN=lex-deeit/DC=weird-web-workers/DC=org' |
|
||||
|
|
||||
cert = OpenSSL::X509::Certificate.new |
|
||||
cert.version = 2 |
|
||||
cert.serial = 0 |
|
||||
cert.not_before = Time.now |
|
||||
cert.not_after = Time.now + 3600 |
|
||||
|
|
||||
cert.public_key = key.public_key |
|
||||
cert.subject = name |
|
||||
cert.sign key, OpenSSL::Digest::SHA256.new |
|
||||
|
|
||||
@certificate.key = key.to_pem |
|
||||
@certificate.cert = cert.to_pem |
|
||||
|
|
||||
respond_to do |format| |
|
||||
if @certificate.save |
|
||||
format.html { redirect_to @certificate, notice: 'Certificate was successfully created.' } |
|
||||
format.json { render :show, status: :created, location: @certificate } |
|
||||
else |
|
||||
format.html { render :new } |
|
||||
format.json { render json: @certificate.errors, status: :unprocessable_entity } |
|
||||
end |
|
||||
end |
|
||||
end |
|
||||
|
|
||||
# PATCH/PUT /certificates/1 |
|
||||
# PATCH/PUT /certificates/1.json |
|
||||
def update |
|
||||
respond_to do |format| |
|
||||
if @certificate.update(certificate_params) |
|
||||
format.html { redirect_to @certificate, notice: 'Certificate was successfully updated.' } |
|
||||
format.json { render :show, status: :ok, location: @certificate } |
|
||||
else |
|
||||
format.html { render :edit } |
|
||||
format.json { render json: @certificate.errors, status: :unprocessable_entity } |
|
||||
end |
|
||||
end |
|
||||
end |
|
||||
|
|
||||
# DELETE /certificates/1 |
|
||||
# DELETE /certificates/1.json |
|
||||
def destroy |
|
||||
@certificate.destroy |
|
||||
respond_to do |format| |
|
||||
format.html { redirect_to certificates_url, notice: 'Certificate was successfully destroyed.' } |
|
||||
format.json { head :no_content } |
|
||||
end |
|
||||
end |
|
||||
|
|
||||
private |
|
||||
# Use callbacks to share common setup or constraints between actions. |
|
||||
def set_certificate |
|
||||
@certificate = Certificate.find(params[:id]) |
|
||||
end |
|
||||
|
|
||||
# Never trust parameters from the scary internet, only allow the white list through. |
|
||||
def certificate_params |
|
||||
params.require(:certificate).permit(:key, :cert, :active) |
|
||||
end |
|
||||
end |
|
||||
|
|
||||
# vim: set et ts=2 sw=2: |
|
||||
@ -1,16 +1,18 @@ |
|||||
class DashboardController < ApplicationController |
class DashboardController < ApplicationController |
||||
def index |
def index |
||||
@lxd_host = LxdHost.find(1) |
|
||||
@cert = Certificate.find(1) |
|
||||
@api = Lxd::API.get @lxd_host, @cert |
|
||||
@lxd_config = Lxd::Config.get @api |
|
||||
|
check_cert |
||||
|
@lxd_hosts = LxdHost.all |
||||
|
|
||||
if @lxd_config.auth == 'untrusted' |
|
||||
# Here the controller has to ask for the password |
|
||||
cert = Lxd::Certificate.new api: @api |
|
||||
cert.save 'xxxxxxxxxx' |
|
||||
@lxd_config = Lxd::Config.get @api |
|
||||
end |
|
||||
|
@lxd_hosts.map { |host| |
||||
|
host.cert = @cert |
||||
|
if host.config.auth == 'untrusted' |
||||
|
session[:return_to] = request.env["REQUEST_URI"] |
||||
|
redirect_to controller: 'lxd_hosts', action: 'auth', id: host.id |
||||
|
return |
||||
|
end |
||||
|
} |
||||
|
|
||||
|
@certificates = Lxd::Certificate.all @lxd_hosts.first.api |
||||
end |
end |
||||
end |
end |
||||
# vim: set et ts=2 sw=2: |
# vim: set et ts=2 sw=2: |
||||
@ -1,45 +1,51 @@ |
|||||
module Lxd::API |
module Lxd::API |
||||
def self.get host, certificate |
|
||||
|
def self.get host, certificate |
||||
uri = URI.parse host.uri |
uri = URI.parse host.uri |
||||
con = Net::HTTP.new uri.host, uri.port |
|
||||
con.use_ssl = true |
|
||||
con.cert = OpenSSL::X509::Certificate.new certificate.cert |
|
||||
con.key = OpenSSL::PKey::RSA.new certificate.key |
|
||||
con.verify_mode = OpenSSL::SSL::VERIFY_NONE |
|
||||
|
|
||||
resp = self.call con, Net::HTTP::Get.new('/') |
|
||||
raise "unsupported api version" unless resp['metadata'].include? '/1.0' |
|
||||
Lxd::API::V1_0.new con |
|
||||
end |
|
||||
|
|
||||
def self.call con, req |
|
||||
resp = con.request req |
|
||||
raise "request failure: " + resp.code unless resp.code != 200 |
|
||||
JSON.parse resp.body |
|
||||
end |
|
||||
|
con = Net::HTTP.new uri.host, uri.port |
||||
|
con.use_ssl = true |
||||
|
con.cert = OpenSSL::X509::Certificate.new certificate.cert |
||||
|
con.key = OpenSSL::PKey::RSA.new certificate.key |
||||
|
con.verify_mode = OpenSSL::SSL::VERIFY_NONE |
||||
|
|
||||
|
resp = self.call con, Net::HTTP::Get.new('/') |
||||
|
raise "unsupported api version" unless resp['metadata'].include? '/1.0' |
||||
|
Lxd::API::V1_0.new con |
||||
|
end |
||||
|
|
||||
|
def self.call con, req |
||||
|
resp = con.request req |
||||
|
raise "request failure: " + resp.code unless resp.code != 200 |
||||
|
JSON.parse resp.body |
||||
|
end |
||||
|
|
||||
def initialize con |
def initialize con |
||||
@con = con |
@con = con |
||||
end |
end |
||||
|
|
||||
def call req |
def call req |
||||
handle_response(Lxd::API.call @con, req) |
|
||||
|
handle_response(Lxd::API.call @con, req) |
||||
end |
end |
||||
|
|
||||
def get uri |
|
||||
call Net::HTTP::Get.new uri |
|
||||
end |
|
||||
|
def get uri |
||||
|
call Net::HTTP::Get.new uri |
||||
|
end |
||||
|
|
||||
def put uri, data={} |
|
||||
request = Net::HTTP::Put.new uri |
|
||||
request.body = data.to_json |
|
||||
call request |
|
||||
end |
|
||||
|
def put uri, data={} |
||||
|
request = Net::HTTP::Put.new uri |
||||
|
request.body = data.to_json |
||||
|
call request |
||||
|
end |
||||
|
|
||||
|
def post uri, data={} |
||||
|
request = Net::HTTP::Post.new uri |
||||
|
request.body = data.to_json |
||||
|
call request |
||||
|
end |
||||
|
|
||||
def post uri, data={} |
|
||||
request = Net::HTTP::Post.new uri |
|
||||
request.body = data.to_json |
|
||||
call request |
|
||||
end |
|
||||
|
def delete uri, data={} |
||||
|
request = Net::HTTP::Delete.new uri |
||||
|
request.body = data.to_json |
||||
|
call request |
||||
|
end |
||||
end |
end |
||||
# vim: set ts=2 sw=2: |
|
||||
|
# vim: set et ts=2 sw=2: |
||||
@ -1,54 +1,55 @@ |
|||||
class Lxd::API::V1_0 |
class Lxd::API::V1_0 |
||||
include Lxd::API |
|
||||
|
|
||||
def config |
|
||||
get '/1.0' |
|
||||
end |
|
||||
|
|
||||
def config= config={} |
|
||||
put '/1.0', config: config |
|
||||
end |
|
||||
|
|
||||
def certificates |
|
||||
get '/1.0/certificates'.map { |uri| |
|
||||
{ |
|
||||
:uri => uri, |
|
||||
:cert => get(uri) |
|
||||
} |
|
||||
} |
|
||||
end |
|
||||
|
|
||||
def add_certificate cert={} |
|
||||
# TODO validate hash |
|
||||
post '/1.0/certificates', cert |
|
||||
end |
|
||||
|
|
||||
def handle_response resp |
|
||||
""" |
|
||||
100 Operation created |
|
||||
101 Started |
|
||||
102 Stopped |
|
||||
103 Running |
|
||||
104 Cancelling |
|
||||
105 Pending |
|
||||
106 Starting |
|
||||
107 Stopping |
|
||||
108 Aborting |
|
||||
109 Freezing |
|
||||
110 Frozen |
|
||||
111 Thawed |
|
||||
200 Success |
|
||||
400 Failure |
|
||||
401 Cancelled |
|
||||
|
|
||||
|
|
||||
100 to 199: resource state (started, stopped, ready, ...) |
|
||||
200 to 399: positive action result |
|
||||
400 to 599: negative action result |
|
||||
600 to 999: future use |
|
||||
""" |
|
||||
raise "api error" if [400..500].include? resp['error_code'] |
|
||||
resp['metadata'] |
|
||||
end |
|
||||
|
include Lxd::API |
||||
|
|
||||
|
def config |
||||
|
get '/1.0' |
||||
|
end |
||||
|
|
||||
|
def config= config={} |
||||
|
put '/1.0', config: config |
||||
|
end |
||||
|
|
||||
|
def certificates |
||||
|
get('/1.0/certificates').map { |uri| |
||||
|
{ :uri => uri }.merge get(uri) |
||||
|
} |
||||
|
end |
||||
|
|
||||
|
def add_certificate data={} |
||||
|
# TODO validate hash |
||||
|
post '/1.0/certificates', data |
||||
|
end |
||||
|
|
||||
|
def delete_certificate fingerprint |
||||
|
delete '/1.0/certificates/' + fingerprint |
||||
|
end |
||||
|
|
||||
|
def handle_response resp |
||||
|
""" |
||||
|
100 Operation created |
||||
|
101 Started |
||||
|
102 Stopped |
||||
|
103 Running |
||||
|
104 Cancelling |
||||
|
105 Pending |
||||
|
106 Starting |
||||
|
107 Stopping |
||||
|
108 Aborting |
||||
|
109 Freezing |
||||
|
110 Frozen |
||||
|
111 Thawed |
||||
|
200 Success |
||||
|
400 Failure |
||||
|
401 Cancelled |
||||
|
|
||||
|
|
||||
|
100 to 199: resource state (started, stopped, ready, ...) |
||||
|
200 to 399: positive action result |
||||
|
400 to 599: negative action result |
||||
|
600 to 999: future use |
||||
|
""" |
||||
|
raise "api error: (" + resp['error_code'].to_s + ") " + resp['error'] if resp['error_code'] and resp['error_code'] != 403 |
||||
|
resp['metadata'] |
||||
|
end |
||||
end |
end |
||||
# vim: set ts=2 sw=2: |
|
||||
|
# vim: set et ts=2 sw=2: |
||||
@ -1,22 +1,26 @@ |
|||||
class Lxd::Certificate |
class Lxd::Certificate |
||||
include ActiveModel::Model |
|
||||
|
include ActiveModel::Model |
||||
|
|
||||
attr_accessor :api, :type, :certificate, :fingerprint |
|
||||
|
attr_accessor :api, :uri, :type, :certificate, :fingerprint |
||||
|
|
||||
def self.all api |
|
||||
api.certificates.map { |cert| |
|
||||
Lxd::Certificate.new({api: api}.merge cert) |
|
||||
} |
|
||||
end |
|
||||
|
def self.all api |
||||
|
api.certificates.map { |cert| |
||||
|
Lxd::Certificate.new({api: api}.merge cert) |
||||
|
} |
||||
|
end |
||||
|
|
||||
def add password=nil, name='lex-deeit' |
|
||||
data = Hash.new |
|
||||
data[:type] = @type if @type else 'client' |
|
||||
data[:name] = name |
|
||||
data[:password] = password if password |
|
||||
data[:certificate] = @certificate if @certificate |
|
||||
|
def add password=nil, name='lex-deeit' |
||||
|
data = Hash.new |
||||
|
data[:type] = if @type then @type else 'client' end |
||||
|
data[:name] = name |
||||
|
data[:password] = password if password |
||||
|
data[:certificate] = @certificate if @certificate |
||||
|
|
||||
@api.add_certificate data |
|
||||
end |
|
||||
|
@api.add_certificate data |
||||
|
end |
||||
|
|
||||
|
def delete |
||||
|
@api.delete_certificate @fingerprint |
||||
|
end |
||||
end |
end |
||||
# vim: set ts=2 sw=2: |
|
||||
|
# vim: set et ts=2 sw=2: |
||||
@ -1,3 +1,14 @@ |
|||||
class LxdHost < ActiveRecord::Base |
class LxdHost < ActiveRecord::Base |
||||
has_secure_password |
|
||||
|
def cert=(cert) |
||||
|
@cert = cert |
||||
|
end |
||||
|
|
||||
|
def api |
||||
|
Lxd::API.get self, @cert |
||||
|
end |
||||
|
|
||||
|
def config |
||||
|
Lxd::Config.get api |
||||
|
end |
||||
end |
end |
||||
|
# vim: ts=2 sw=2: |
||||
@ -1,29 +0,0 @@ |
|||||
<%= form_for(@certificate) do |f| %> |
|
||||
<% if @certificate.errors.any? %> |
|
||||
<div id="error_explanation"> |
|
||||
<h2><%= pluralize(@certificate.errors.count, "error") %> prohibited this certificate from being saved:</h2> |
|
||||
|
|
||||
<ul> |
|
||||
<% @certificate.errors.full_messages.each do |message| %> |
|
||||
<li><%= message %></li> |
|
||||
<% end %> |
|
||||
</ul> |
|
||||
</div> |
|
||||
<% end %> |
|
||||
|
|
||||
<div class="field"> |
|
||||
<%= f.label :key %><br> |
|
||||
<%= f.text_area :key %> |
|
||||
</div> |
|
||||
<div class="field"> |
|
||||
<%= f.label :cert %><br> |
|
||||
<%= f.text_area :cert %> |
|
||||
</div> |
|
||||
<div class="field"> |
|
||||
<%= f.label :active %><br> |
|
||||
<%= f.check_box :active %> |
|
||||
</div> |
|
||||
<div class="actions"> |
|
||||
<%= f.submit %> |
|
||||
</div> |
|
||||
<% end %> |
|
||||
@ -1,6 +0,0 @@ |
|||||
<h1>Editing Certificate</h1> |
|
||||
|
|
||||
<%= render 'form' %> |
|
||||
|
|
||||
<%= link_to 'Show', @certificate %> | |
|
||||
<%= link_to 'Back', certificates_path %> |
|
||||
@ -1,31 +0,0 @@ |
|||||
<p id="notice"><%= notice %></p> |
|
||||
|
|
||||
<h1>Listing Certificates</h1> |
|
||||
|
|
||||
<table> |
|
||||
<thead> |
|
||||
<tr> |
|
||||
<th>Key</th> |
|
||||
<th>Cert</th> |
|
||||
<th>Active</th> |
|
||||
<th colspan="3"></th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
|
|
||||
<tbody> |
|
||||
<% @certificates.each do |certificate| %> |
|
||||
<tr> |
|
||||
<td><%= certificate.key_fpr.scan(/../).join(':') %></td> |
|
||||
<td><%= certificate.cert_fpr.scan(/../).join(':') %></td> |
|
||||
<td><%= certificate.active %></td> |
|
||||
<td><%= link_to 'Show', certificate %></td> |
|
||||
<td><%= link_to 'Edit', edit_certificate_path(certificate) %></td> |
|
||||
<td><%= link_to 'Destroy', certificate, method: :delete, data: { confirm: 'Are you sure?' } %></td> |
|
||||
</tr> |
|
||||
<% end %> |
|
||||
</tbody> |
|
||||
</table> |
|
||||
|
|
||||
<br> |
|
||||
|
|
||||
<%= link_to 'New Certificate', new_certificate_path %> |
|
||||
@ -1,4 +0,0 @@ |
|||||
json.array!(@certificates) do |certificate| |
|
||||
json.extract! certificate, :id, :key, :cert, :active |
|
||||
json.url certificate_url(certificate, format: :json) |
|
||||
end |
|
||||
@ -1,5 +0,0 @@ |
|||||
<h1>New Certificate</h1> |
|
||||
|
|
||||
<%= render 'form' %> |
|
||||
|
|
||||
<%= link_to 'Back', certificates_path %> |
|
||||
@ -1,19 +0,0 @@ |
|||||
<p id="notice"><%= notice %></p> |
|
||||
|
|
||||
<p> |
|
||||
<strong>Key:</strong> |
|
||||
<%= @certificate.key %> |
|
||||
</p> |
|
||||
|
|
||||
<p> |
|
||||
<strong>Cert:</strong> |
|
||||
<%= @certificate.cert %> |
|
||||
</p> |
|
||||
|
|
||||
<p> |
|
||||
<strong>Active:</strong> |
|
||||
<%= @certificate.active %> |
|
||||
</p> |
|
||||
|
|
||||
<%= link_to 'Edit', edit_certificate_path(@certificate) %> | |
|
||||
<%= link_to 'Back', certificates_path %> |
|
||||
@ -1 +0,0 @@ |
|||||
json.extract! @certificate, :id, :key, :cert, :active, :created_at, :updated_at |
|
||||
@ -1,11 +1,9 @@ |
|||||
<h1>Dashboard#index</h1> |
<h1>Dashboard#index</h1> |
||||
<p><%= @lxd_host.class %></p> |
|
||||
<p><%= @cert.class %></p> |
|
||||
<p><%= @lxd_config.class %></p> |
|
||||
<p><%= @lxd_config.api_extensions.inspect %></p> |
|
||||
<p><%= @lxd_config.api_status %></p> |
|
||||
<p><%= @lxd_config.api_version %></p> |
|
||||
<p><%= @lxd_config.auth %></p> |
|
||||
<p><%= @lxd_config.config.inspect %></p> |
|
||||
<p><%= @lxd_config.environment.inspect %></p> |
|
||||
<p><%= @lxd_config.public %></p> |
|
||||
|
<p><%= @cert.cert_fpr %></p> |
||||
|
<p>Serial: <%= @cert.cert.serial %></p> |
||||
|
<% @lxd_hosts.each do |host| -%> |
||||
|
<p><%= host.config.inspect %></p> |
||||
|
<% end -%> |
||||
|
<% @certificates.each do |cert| -%> |
||||
|
<p><%= cert.fingerprint %></p> |
||||
|
<% end -%> |
||||
@ -0,0 +1,13 @@ |
|||||
|
<h1>Authenticate Lxd Host: <%= @lxd_host.name %></h1> |
||||
|
|
||||
|
<p>...<%= @data.inspect %></p> |
||||
|
|
||||
|
<%= form_for :lxd_hosts, url: { action: "add_key" }, method: 'put' do |f| %> |
||||
|
<div class="field"> |
||||
|
<%= f.label :password %><br> |
||||
|
<%= f.password_field :password %> |
||||
|
</div> |
||||
|
<div class="actions"> |
||||
|
<%= f.submit %> |
||||
|
</div> |
||||
|
<% end %> |
||||
@ -0,0 +1,13 @@ |
|||||
|
--- |
||||
|
default: &default |
||||
|
x509_base: 'DC=weird-web-workers/DC=org' |
||||
|
|
||||
|
development: |
||||
|
<<: *default |
||||
|
|
||||
|
test: |
||||
|
<<: *default |
||||
|
|
||||
|
production: |
||||
|
<<: *default |
||||
|
# vim: set et ts=2 sw=2: |
||||
@ -0,0 +1,6 @@ |
|||||
|
class DeletePasswordFromLxdHosts < ActiveRecord::Migration |
||||
|
def change |
||||
|
remove_column :lxd_hosts, :password_digest |
||||
|
end |
||||
|
end |
||||
|
# vim: set ts=2 sw=2: |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue