Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add capability to manage SNIs & Certificates #127

Merged
merged 4 commits into from
Oct 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions src/html/certificates/form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<div class="container">
<h3 class="header">{{title}}</h3>

<div class="row">
<div class="col s5">
<div class="card-panel teal">
<p class="white-text">
A certificate object represents a public certificate/private key pair for an SSL certificate. These objects are used by Kong
to handle SSL/TLS termination for encrypted requests. Certificates are optionally associated with SNI
objects to tie a cert/key pair to one or more hostnames.
</p>

<p class="white-text">
Checkout <a href="https://getkong.org/docs/latest/admin-api/#add-certificate" target="_blank">Kong documentation</a> for the meaning of the form parameters.
</p>
</div>
</div>
<form name="addCertificate" class="col s7" novalidate ng-submit="save()">
<div class="row">

<div class="input-field col s12" ng-show="isEdit()">
<input id="id" ng-model="certificate.id" type="text" class="validate"
ng-class="{invalid: error.id}" ng-readonly="isEdit()" >
<label for="id" ng-class="{active:certificate.id}">ID</label>
<app-field-error error="error.id"></app-field-error>
</div>
<div class="input-field col s12">
<textarea autofocus id="cert" ng-model="certificate.cert" class="validate materialize-textarea"
ng-required="true" ng-class="{invalid: error.cert}" rows="4"></textarea>
<label for="cert" ng-class="{active:certificate.cert}">Cert</label>
<app-field-error error="error.cert"></app-field-error>
</div>
<div class="input-field col s12">
<textarea id="key" ng-model="certificate.key" class="validate materialize-textarea"
ng-required="true" ng-class="{invalid: error.key}" rows="4"></textarea>
<label for="key" ng-class="{active:certificate.key}">Key</label>
<app-field-error error="error.key"></app-field-error>
</div>
<div class="input-field col s12">
<input id="snis" ng-model="certificate.snis" type="text" class="validate"
ng-class="{invalid: error.snis}" ng-show="! isEdit()">
<ul ng-repeat="sni in certificate.snis" ng-show="isEdit()" ng-readonly="true" >
<li>{{sni}}</li>
</ul>
<label for="snis" ng-class="{active:certificate.snis}">SNIs</label>
<app-field-error error="error.snis"></app-field-error>
</div>

<div class="input-field col s6" >
<a href="#/snis/add/{{certificate.id}}" class="waves-effect waves-light btn" ng-show="isEdit()">
<i class="material-icons left">add_box</i>
Add SNI
</a>
</div>
<div class="input-field col s6">
<button type="submit" class="waves-effect waves-light btn right">
{{action}}
</button>
</div>

</div>
<input type="hidden" ng-model="certificate.id" value="{{certificate.id}}" />
</form>
</div>
</div>
76 changes: 76 additions & 0 deletions src/html/certificates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<div class="container" infinite-scroll="loadMore()" infinite-scroll-distance="5" infinite-scroll-use-document-bottom="true">

<ul ng-show="certificates.length >= 1" class="horizontal right">
<li>
<a href="#/certificates/add" class="btn-floating btn-large waves-effect waves-light">
<i class="material-icons">add</i>
</a>
</li>
</ul>

<h3 class="header">
Certificates
</h3>

<p class="flow-text center" ng-show="total === null" style="margin-top:50px;">
<app-loader></app-loader>
</p>

<div class ng-show="total === 0">
<p class="flow-text center">
You haven't defined any Certificates in Kong yet.
</p>
<p class="center">
<a href="#/certificates/add" class="waves-effect waves-light btn">
<i class="material-icons left">add_box</i>
Add Certificate
</a>
</p>
</div>

<table class="bordered" ng-show="total > 0">
<thead>
<tr>
<th>ID</th>
<th>Created</th>
<th>SNIs</th>
<th></th>
</tr>
</thead>

<tbody>
<tr ng-repeat="certificate in certificates">
<td>{{certificate.id}}</td>
<td>{{certificate.created_at | date}}</td>
<td>
<ul ng-repeat="sni in certificate.snis" >
<li>{{sni}}</li>
</ul>
</td>

<td class="right">
<a class="btn-floating waves-effect waves-light" href="#/certificates/{{certificate.id}}">
<i class="material-icons">mode_edit</i>
</a>
<a class="btn-floating waves-effect waves-light blue" href="#/snis/add/{{certificate.id}}">
<i class="material-icons">dns</i>
</a>
<a class="btn-floating waves-effect waves-light red modal-trigger" ng-click="showDeleteModal(certificate.id)">
<i class="material-icons">delete</i>
</a>
</td>
</tr>
</tbody>
</table>
</div>

<!-- Modal Structure -->
<div id="deleteCertificate" class="modal">
<div class="modal-content">
<h5>Do you really want to delete the Certificate "{{current.id}}"?</h5>
</div>
<div class="modal-footer">
<a class="waves-effect waves-green btn" ng-click="abortDelete()">Noooooo!</a>
<a class="waves-effect waves-red btn red" ng-click="performDelete()" style="margin-right:10px">Yes</a>
</div>
</div>
10 changes: 10 additions & 0 deletions src/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@
<i class="material-icons tooltipped" data-position="bottom" data-tooltip="Manage Plugins" data-delay="0">extension</i>
</a>
</li>
<li>
<a href="#/snis">
<i class="material-icons tooltipped" data-position="bottom" data-tooltip="Manage SNIS" data-delay="0">dns</i>
</a>
</li>
<li>
<a href="#/certificates">
<i class="material-icons tooltipped" data-position="bottom" data-tooltip="Manage Certificates" data-delay="0">https</i>
</a>
</li>
</ul>
</div>
</nav>
Expand Down
42 changes: 42 additions & 0 deletions src/html/snis/form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div class="container">
<h3 class="header">{{title}}</h3>

<div class="row">
<div class="col s5">
<div class="card-panel teal">
<p class="white-text">
An SNI object represents a many-to-one mapping of hostnames to a certificate. That is, a certificate object can have many hostnames associated with it; when Kong receives an SSL request, it uses the SNI field in the Client Hello to lookup the certificate object based on the SNI associated with the certificate.
</p>

<p class="white-text">
Checkout <a href="https://getkong.org/docs/latest/admin-api/#add-sni" target="_blank">Kong documentation</a> for the meaning of the form parameters.
</p>
</div>
</div>
<form name="addSni" class="col s7" novalidate ng-submit="save()">
<div class="row">
<div class="input-field col s12">
<input id="name" autofocus ng-required="true" ng-model="sni.name" type="text"
ng-class="{invalid: error.name}" ng-readonly="isEdit()" class="validate" >
<label for="name" ng-class="{active:sni.name}">Name</label>
<app-field-error error="error.name"></app-field-error>
</div>
<div class="input-field col s12">
<label class="active">SSL Certificate ID</label>
<select materialize-select required id="ssl_certificate_id"
ng-model="sni.ssl_certificate_id"
ng-options="cert.id as cert.id for cert in certificates"
>
</select>
<app-field-error error="error.ssl_certificate_id"></app-field-error>
</div>
<div class="input-field col s12">
<button type="submit" class="waves-effect waves-light btn right">
{{action}}
</button>
</div>
</div>
<input type="hidden" ng-model="sni.name" value="{{sni.name}}"/>
</form>
</div>
</div>
68 changes: 68 additions & 0 deletions src/html/snis/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<div class="container" infinite-scroll="loadMore()" infinite-scroll-distance="5" infinite-scroll-use-document-bottom="true">

<ul ng-show="snis.length >= 1" class="horizontal right">
<li>
<a href="#/snis/add" class="btn-floating btn-large waves-effect waves-light">
<i class="material-icons">add</i>
</a>
</li>
</ul>

<h3 class="header">
SNIs
</h3>

<p class="flow-text center" ng-show="total === null" style="margin-top:50px;">
<app-loader></app-loader>
</p>

<div class ng-show="total === 0">
<p class="flow-text center">
You haven't defined any SNI in Kong yet.
</p>
<p class="center">
<a href="#/snis/add" class="waves-effect waves-light btn">
<i class="material-icons left">add_box</i>
Add SNI
</a>
</p>
</div>

<table class="bordered" ng-show="total > 0">
<thead>
<tr>
<th>Name</th>
<th>SSL Certificate id</th>
<th>Created</th>
<th></th>
</tr>
</thead>

<tbody>
<tr ng-repeat="sni in snis">
<td>{{sni.name}}</td>
<td>{{sni.ssl_certificate_id}}</td>
<td>{{sni.created_at | date}}</td>
<td class="right">
<a class="btn-floating waves-effect waves-light" href="#/snis/{{sni.name}}">
<i class="material-icons">mode_edit</i>
</a>
<a class="btn-floating waves-effect waves-light red modal-trigger" ng-click="showDeleteModal(sni.name)">
<i class="material-icons">delete</i>
</a>
</td>
</tr>
</tbody>
</table>
</div>

<!-- Modal Structure -->
<div id="deleteSni" class="modal">
<div class="modal-content">
<h5>Do you really want to delete the SNI "{{current.name}}"?</h5>
</div>
<div class="modal-footer">
<a class="waves-effect waves-green btn" ng-click="abortDelete()">Noooooo!</a>
<a class="waves-effect waves-red btn red" ng-click="performDelete()" style="margin-right:10px">Yes</a>
</div>
</div>
49 changes: 49 additions & 0 deletions src/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,55 @@ var app = angular.module('app', ['ngRoute', 'ngCookies', 'ngAnimate', 'ngSanitiz
}]
}
})
.when('/snis', {
templateUrl: 'html/snis/index.html',
controller: 'SnisController',
resolve: {
isAppReady: isAppReady
}
})
.when('/snis/add', {
templateUrl: 'html/snis/form.html',
controller: 'SniController',
resolve: {
isAppReady: isAppReady
}
})
.when('/snis/:name', {
templateUrl: 'html/snis/form.html',
controller: 'SniController',
resolve: {
isAppReady: isAppReady,
}
})
.when('/snis/add/:certificate_id', {
templateUrl: 'html/snis/form.html',
controller: 'SniController',
resolve: {
isAppReady: isAppReady
}
})
.when('/certificates', {
templateUrl: 'html/certificates/index.html',
controller: 'CertificatesController',
resolve: {
isAppReady: isAppReady
}
})
.when('/certificates/add', {
templateUrl: 'html/certificates/form.html',
controller: 'CertificateController',
resolve: {
isAppReady: isAppReady
}
})
.when('/certificates/:id', {
templateUrl: 'html/certificates/form.html',
controller: 'CertificateController',
resolve: {
isAppReady: isAppReady,
}
})
.otherwise({redirectTo: '/'});
}])
.run(['$rootScope', 'Kong', '$location', function($rootScope, Kong, $location) {
Expand Down
46 changes: 46 additions & 0 deletions src/js/controllers/certificate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
angular.module('app').controller("CertificateController", ["$scope", "Kong", "$location", "$routeParams", "Alert", "$route", function ($scope, Kong, $location, $routeParams, Alert, $route) {

$scope.certificate = {};

onInit();

function onInit() {
if ($routeParams.id) {
Kong.get('/certificates/' + $routeParams.id).then( function(data) {
$scope.certificate = data;
});
$scope.title = "Edit Certificate";
$scope.action = "Save";
$scope.location = $location;
} else {
$scope.title = "Add a Certificate";
$scope.action = "Create";
}
}

$scope.isEdit = function () {
return $routeParams.id != null;
}

$scope.save = function () {
if ( $scope.isEdit() ) {
Kong.patch('/certificates/' + $scope.certificate.id, $scope.certificate).then(function () {
Alert.success('Certificate updated');
$scope.error = {};
}, function (response) {
$scope.error = response.data;
});
} else {
Kong.post('/certificates', $scope.certificate).then(function () {
Alert.success('Certificate created');
// clearing inputs.
$scope.certificate = {};

// clearing errors.
$scope.error = {};
}, function (response) {
$scope.error = response.data;
});
}
};
}]);
Loading