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 |
|||
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 |
|||
# vim: set et ts=2 sw=2: |
|||
@ -1,45 +1,51 @@ |
|||
module Lxd::API |
|||
def self.get host, certificate |
|||
def self.get host, certificate |
|||
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 |
|||
@con = con |
|||
end |
|||
|
|||
def call req |
|||
handle_response(Lxd::API.call @con, req) |
|||
handle_response(Lxd::API.call @con, req) |
|||
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 |
|||
# vim: set ts=2 sw=2: |
|||
# vim: set et ts=2 sw=2: |
|||
@ -1,54 +1,55 @@ |
|||
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 |
|||
# vim: set ts=2 sw=2: |
|||
# vim: set et ts=2 sw=2: |
|||
@ -1,22 +1,26 @@ |
|||
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 |
|||
# vim: set ts=2 sw=2: |
|||
# vim: set et ts=2 sw=2: |
|||
@ -1,3 +1,14 @@ |
|||
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 |
|||
# 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> |
|||
<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