Implement PLESK, SSL Services

This commit is contained in:
Deon George
2011-12-17 10:31:35 +11:00
parent cb18209369
commit c8fd44f844
29 changed files with 1038 additions and 438 deletions

View File

@@ -0,0 +1,59 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class provides Admin SSL functions
*
* @package OSB
* @subpackage SSL
* @category Controllers/Admin
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Controller_Admin_SSL extends Controller_TemplateDefault_Admin {
protected $secure_actions = array(
'list'=>TRUE,
'update'=>TRUE,
);
public function action_list() {
Block::add(array(
'title'=>_('SSL Services'),
'body'=>Table::display(
ORM::factory('ssl_ca')->find_all(),
25,
array(
'id'=>array('label'=>'ID','url'=>'admin/ssl/update/'),
'sign_cert'=>array('label'=>'Cert'),
'issuer()'=>array('label'=>'Issuer'),
'expires()'=>array('label'=>'Expires'),
),
array(
'page'=>TRUE,
'type'=>'select',
'form'=>'admin/ssl/update',
)),
));
}
public function action_update() {
$id = $this->request->param('id');
$so = ORM::factory('ssl_ca',$id);
if (! $so->loaded())
Request::current()->redirect('welcome/index');
if ($_POST) {
if (! $so->values($_POST)->update()->saved())
throw new Kohana_Exception('Failed to save updates to plugin data for record :record',array(':record'=>$so->id()));
}
Block::add(array(
'title'=>sprintf('%s %s:%s',_('Update SSL Service'),$so->id,$so->display('sign_cert')),
'body'=>View::factory('ssl/admin/update')
->set('so',$so)
->set('mediapath',Route::get('default/media'))
));
}
}
?>

View File

@@ -0,0 +1,25 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class provides OSB SSL task capabilities.
*
* @package OSB
* @subpackage SSL
* @category Controllers/Task
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Controller_Task_SSL extends Controller_Task {
/**
* Renew a certificate
*/
public function action_renew() {
// @todo, Change this to be a SSL id, maybe list all the certs expiring
$id = $this->request->param('id');
$so = ORM::factory('service',$id);
$so->plugin()->renew();
}
}
?>

View File

@@ -0,0 +1,51 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class provides User SSL functions
*
* @package OSB
* @subpackage SSL
* @category Controllers/Admin
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Controller_User_SSL extends Controller_TemplateDefault_User {
protected $secure_actions = array(
'download'=>FALSE,
);
public function action_download() {
$id = $_POST['sid'];
$so = ORM::factory('service',$id);
if (! $so->loaded())
Request::current()->redirect('welcome/index');
$passwd = $_POST['passwd'];
if (strlen($passwd) < Kohana::config('ssl.minpass_length')) {
SystemMessage::add(array(
'title'=>_('Validation failed'),
'type'=>'error',
'body'=>_('Your requested password is too short.'),
));
Request::current()->redirect('user/service/view/'.$so->id);
}
if (! $so->loaded() OR ! Auth::instance()->authorised($so->account_id,$so->affiliate_id)) {
$this->template->content = 'Unauthorised or doesnt exist?';
return FALSE;
}
$file = Kohana::config('config.tmpdir').'/'.$so->name().'.pkcs12';
openssl_pkcs12_export_to_file($so->plugin()->cert,$file,$so->plugin()->pk,$passwd,array('extracerts'=>$so->plugin()->cacerts()));
$x = file_get_contents($file);
unlink($file);
$this->response->headers('Content-Type','application/pks12');
$this->response->headers('Content-Disposition','attachment; filename="'.basename($file).'"');
$this->response->body($x);
$this->auto_render = FALSE;
}
}
?>

View File

@@ -0,0 +1,23 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class supports SSL products
*
* @package OSB
* @subpackage Product/SSL
* @category Models
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Model_Product_Plugin_SSL extends Model_Product_Plugin {
protected $_table_name = 'ssl';
// Our required abstract methods
public function feature_summary() {
// @todo This view should render based on the the results of this::allowance();
return View::factory('product/plugin/ssl/feature_summary')
->set('po',$this);
}
}
?>

View File

@@ -0,0 +1,145 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class supports Services
*
* @package OSB
* @subpackage SSL
* @category Models
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Model_Service_Plugin_SSL extends Model_Service_Plugin {
protected $_table_name = 'service__ssl';
protected $_updated_column = FALSE;
// Relationships
protected $_belongs_to = array(
'service'=>array(),
);
protected $_has_one = array(
'ssl_ca'=>array('far_key'=>'ssl_ca_id','foreign_key'=>'id'),
'ssl'=>array('far_key'=>'ssl_id','foreign_key'=>'id'),
);
protected $_display_filters = array(
'csr'=>array(
array('SSL::csrsubject',array(':value')),
),
);
// Required abstract functions
public function service_view() {
return View::factory('service/user/plugin/ssl/view')
->set('so',$this);
}
public function name() {
return $this->display('csr');
}
// @todo This needs to be validated for this model
public function product() {
if ($this->provided_adsl_plan_id)
return $this->adsl_plan;
else
return $this->service->product->plugin();
}
public function valid_from() {
return SSL::from($this->cert);
}
public function valid_to() {
return SSL::expire($this->cert);
}
public function serial_num() {
return SSL::serial($this->cert);
}
public function hash() {
return SSL::hash($this->cert);
}
public function version() {
return SSL::version($this->cert);
}
/**
* Get specific service details for use in other modules
* For Example: Invoice
*
* @todo Make the rendered items configurable
* @todo Change this method name, now that it is public
*/
// @todo This needs to be validated for this model
public function _details($type) {
switch ($type) {
case 'invoice_detail_items':
return array(
_('Service Address')=>$this->service_address ? $this->display('service_address') : '>NotSet<',
_('Contract Until')=>$this->contract_date_end(),
);
break;
default:
return parent::$_details($type);
}
}
// @todo This needs to be validated for this model
public function admin_update() {
return View::factory('service/admin/plugin/ssl/update')
->set('mediapath',Route::get('default/media'))
->set('so',$this);
}
public function download_button() {
if (! preg_match('/client/',$this->ssl->extensions))
return '';
// @todo Do some password validation
$output = Form::open('user/ssl/download');
$output .= Form::hidden('sid',$this->service->id);
$output .= _('Choose a password').': '.Form::password('passwd','').'<br/><br/>';
$output .= Form::submit('download','Download',array('class'=>'form_button'));
return $output;
}
public function cacerts() {
$return = array();
$x = $this->ssl_ca_id;
while ($x) {
$sco = ORM::factory('ssl_ca',$x);
array_push($return,$sco->sign_cert);
$x = $sco->parent_ssl_ca_id;
}
return $return;
}
public function renew() {
$d = SSL::details($this->cert);
$ssl_conf = Kohana::config('ssl');
// If our certificate is not old enough skip
if ($d['validTo_time_t'] > time()+$ssl_conf['min_renew_days']*86400)
return FALSE;
$res = openssl_csr_sign($this->csr,$this->ssl_ca->sign_cert,$this->ssl_ca->sign_pk,$this->ssl->days,array(
'config'=>$ssl_conf['config'],
'x509_extensions'=>$this->ssl->extensions,
),time());
if (openssl_x509_export($res,$cert)) {
$this->cert = $cert;
$this->save();
return TRUE;
} else
throw new Kohana_Exception('Error Creating SSL Certificate :error',array(':error'=>openssl_error_string()));
}
}
?>

View File

@@ -0,0 +1,16 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class supports SSL
*
* @package OSB
* @subpackage SSL
* @category Models
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Model_SSL extends ORMOSB {
protected $_updated_column = FALSE;
}
?>

View File

@@ -0,0 +1,37 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class supports SSL
*
* @package OSB
* @subpackage SSL
* @category Models
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class Model_SSL_CA extends ORMOSB {
protected $_updated_column = FALSE;
// Relationships
protected $_belongs_to = array(
);
protected $_has_one = array(
);
protected $_display_filters = array(
'sign_cert'=>array(
array('SSL::subject',array(':value')),
),
);
public function expires() {
return SSL::expire($this->sign_cert);
}
public function issuer() {
return SSL::issuer($this->sign_cert);
}
}
?>

View File

@@ -0,0 +1,63 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* This class is for access to SSL information
*
* @package OSB
* @subpackage System
* @category Helpers
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
class SSL {
public static function instance() {
return new SSL;
}
public static function details($key) {
return openssl_x509_parse($key);
}
public static function issuer($key) {
$k = static::details($key);
return $k['issuer']['CN'];
}
public static function from($key) {
$k = static::details($key);
return Config::date($k['validFrom_time_t']);
}
public static function expire($key) {
$k = static::details($key);
return Config::date($k['validTo_time_t']);
}
public static function hash($key) {
$k = static::details($key);
return $k['hash'];
}
public static function serial($key) {
$k = static::details($key);
return $k['serialNumber'];
}
public static function subject($key) {
$k = static::details($key);
return $k['subject']['CN'];
}
public static function version($key) {
$k = static::details($key);
return $k['version'];
}
public static function csrsubject($csr) {
$c = openssl_csr_get_subject($csr);
return $c['CN'];
}
}
?>

View File

@@ -0,0 +1,23 @@
<?php defined('SYSPATH') or die('No direct access allowed.');
/**
* OSB Configuration - SSL Config Items
*
* @package OSB
* @subpackage System
* @category Configuration
* @author Deon George
* @copyright (c) 2010 Open Source Billing
* @license http://dev.osbill.net/license.html
*/
return array(
// Days before certificates can be renewed.
'min_renew_days' => 7,
// Min password length for exports
'minpass_length' => 4,
// Location to openssl config
'config' => 'appliation/config/openssl.cnf',
);
?>

View File

@@ -0,0 +1,11 @@
<!-- //@todo To translate -->
<table class="box-full">
<tr>
<td style="width: 40%;">Validity Days</td>
<td class="data" style="width: 60%;" colspan="2"><?php echo $po->display('days'); ?></td>
</tr>
<tr>
<td>Type</td>
<td class="data"><?php echo $po->display('extensions'); ?></td>
</tr>
</table>

View File

@@ -0,0 +1,14 @@
<table border="0">
<tr>
<td style="width: 40%;">CSR</td>
<td style="width: 60%;"><?php echo FORM::textarea('plugin[csr]',$so->service->plugin()->csr,array('cols'=>64,'rows'=>13)); ?></td>
</td>
<tr>
<td>PK</td>
<td><?php echo FORM::textarea('plugin[pk]',$so->service->plugin()->pk,array('cols'=>64,'rows'=>13)); ?></td>
</td>
<tr>
<td>Cert</td>
<td><?php echo FORM::textarea('plugin[cert]',$so->service->plugin()->cert,array('cols'=>64,'rows'=>13)); ?></td>
</td>
</table>

View File

@@ -0,0 +1,44 @@
<!-- //@todo To translate -->
<table class="box-full">
<tr>
<td class="head" colspan="3">Service Details</td>
</tr>
<tr>
<td colspan="3">&nbsp;</td>
</tr>
<tr>
<td>
<table width="100%">
<tr>
<td style="width: 25%;">Service Name</td>
<td style="width: 75%;" class="data"><?php echo $so->display('csr'); ?></td>
</tr>
<tr>
<td>Valid From</td>
<td class="data"><?php echo $so->valid_from(); ?></td>
</tr>
<tr>
<td>Valid To</td>
<td class="data"><?php echo $so->valid_to(); ?></td>
</tr>
<tr>
<td>Serial Number</td>
<td class="data"><?php echo $so->serial_num(); ?></td>
</tr>
<tr>
<td>Version</td>
<td class="data"><?php echo $so->version(); ?></td>
</tr>
<tr>
<td>Hash</td>
<td class="data"><?php echo $so->hash(); ?></td>
</tr>
<tr>
<td>Certificate</td>
<td class="data"><pre><?php echo $so->display('cert'); ?></pre></td>
</tr>
</table>
</td>
<td style="text-align: right;"><?php echo $so->download_button(); ?></td>
</tr>
</table>

View File

@@ -0,0 +1,41 @@
<?php echo Form::open(); ?>
<table border="0">
<tr>
<td>Subject</td>
<td class="data"><?php echo SSL::subject($so->sign_cert); ?></td>
</tr>
<tr>
<td>Issuer</td>
<td class="data"><?php echo SSL::issuer($so->sign_cert); ?></td>
</tr>
<tr>
<td>Valid From</td>
<td class="data"><?php echo SSL::from($so->sign_cert); ?></td>
</tr>
<tr>
<td>Valid To</td>
<td class="data"><?php echo SSL::expire($so->sign_cert); ?></td>
</tr>
<tr>
<td>Serial Num</td>
<td class="data"><?php echo SSL::serial($so->sign_cert); ?></td>
</tr>
<tr>
<td>Hash</td>
<td class="data"><?php echo SSL::hash($so->sign_cert); ?></td>
</tr>
<tr>
<td>Version</td>
<td class="data"><?php echo SSL::version($so->sign_cert); ?></td>
</tr>
<tr>
<td style="width: 40%;">Private Key</td>
<td style="width: 60%;"><?php echo FORM::textarea('sign_pk',$so->sign_pk,array('cols'=>64,'rows'=>13)); ?></td>
</tr>
<tr>
<td>Certificate</td>
<td><?php echo FORM::textarea('sign_cert',$so->sign_cert,array('cols'=>64,'rows'=>13)); ?></td>
</tr>
<table>
<?php echo Form::submit('submit',_('Update'),array('class'=>'form_button')); ?>
<?php echo Form::close(); ?>