initial commit
This commit is contained in:
94
lemur/static/app/angular/certificates/certificate/certificate.js
vendored
Normal file
94
lemur/static/app/angular/certificates/certificate/certificate.js
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('lemur')
|
||||
.config(function config($routeProvider) {
|
||||
$routeProvider.when('/certificates/create', {
|
||||
templateUrl: '/angular/certificates/certificate/certificateWizard.tpl.html',
|
||||
controller: 'CertificateCreateController'
|
||||
});
|
||||
|
||||
$routeProvider.when('/certificates/:id/edit', {
|
||||
templateUrl: '/angular/certificates/certificate/edit.tpl.html',
|
||||
controller: 'CertificateEditController'
|
||||
});
|
||||
})
|
||||
|
||||
.controller('CertificateEditController', function ($scope, $routeParams, CertificateApi, CertificateService, MomentService) {
|
||||
CertificateApi.get($routeParams.id).then(function (certificate) {
|
||||
$scope.certificate = certificate;
|
||||
});
|
||||
|
||||
$scope.momentService = MomentService;
|
||||
$scope.save = CertificateService.update;
|
||||
|
||||
})
|
||||
|
||||
.controller('CertificateCreateController', function ($scope, $modal, CertificateApi, CertificateService, AccountService, ELBService, AuthorityService, MomentService, LemurRestangular) {
|
||||
$scope.certificate = LemurRestangular.restangularizeElement(null, {}, 'certificates');
|
||||
|
||||
$scope.save = function (certificate) {
|
||||
var loadingModal = $modal.open({backdrop: 'static', template: '<wave-spinner></wave-spinner>', windowTemplateUrl: 'angular/loadingModal.html', size: 'large'});
|
||||
CertificateService.create(certificate).then(function (response) {
|
||||
loadingModal.close();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.templates = [
|
||||
{
|
||||
'name': 'Client Certificate',
|
||||
'description': '',
|
||||
'extensions': {
|
||||
'basicConstraints': {},
|
||||
'keyUsage': {
|
||||
'isCritical': true,
|
||||
'useDigitalSignature': true
|
||||
},
|
||||
'extendedKeyUsage': {
|
||||
'isCritical': true,
|
||||
'useClientAuthentication': true
|
||||
},
|
||||
'subjectKeyIdentifier': {
|
||||
'includeSKI': true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Server Certificate',
|
||||
'description': '',
|
||||
'extensions' : {
|
||||
'basicConstraints': {},
|
||||
'keyUsage': {
|
||||
'isCritical': true,
|
||||
'useKeyEncipherment': true,
|
||||
'useDigitalSignature': true
|
||||
},
|
||||
'extendedKeyUsage': {
|
||||
'isCritical': true,
|
||||
'useServerAuthentication': true
|
||||
},
|
||||
'subjectKeyIdentifier': {
|
||||
'includeSKI': true
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
$scope.openNotBefore = function($event) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
|
||||
$scope.openNotBefore.isOpen = true;
|
||||
};
|
||||
|
||||
$scope.openNotAfter = function($event) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
|
||||
$scope.openNotAfter.isOpen = true;
|
||||
|
||||
};
|
||||
|
||||
$scope.elbService = ELBService;
|
||||
$scope.authorityService = AuthorityService;
|
||||
$scope.accountService = AccountService;
|
||||
});
|
@ -0,0 +1,20 @@
|
||||
<h2 class="featurette-heading">Create a certificate <span class="text-muted"><small>encrypt all the things
|
||||
</small></span></h2>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<a href="/#/certificates/" class="btn btn-danger pull-right">Cancel</a>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form name="createForm" class="form-horizontal" role="form" ng-submit="submitCreate()" novalidate>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="submit" ng-disabled="createForm.$invalid" class="btn btn-success pull-right"><span
|
||||
ng-show="!loading"> Create </span><span ng-show="loading">Creating <i ng-show="loading"
|
||||
class="fa fa-cog fa-spin"></i></span>
|
||||
</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,17 @@
|
||||
<h2 class="featurette-heading"><span ng-show="!certificate.id">Create</span><span ng-show="certificate.id">Edit</span> Certificate <span class="text-muted"><small>encrypt all the things
|
||||
<div>
|
||||
<wizard on-finish="save(certificate)" template="angular/wizard.html">
|
||||
<wz-step title="Tracking" canexit="trackingForm.$valid">
|
||||
<ng-include src="'angular/certificates/certificate/tracking.tpl.html'"></ng-include>
|
||||
</wz-step>
|
||||
<wz-step title="Distinguished Name" canenter="exitTracking" canexit="exitDN">
|
||||
<ng-include src="'angular/certificates/certificate/distinguishedName.tpl.html'"></ng-include>
|
||||
</wz-step>
|
||||
<wz-step title="Options" canenter="enterValidation">
|
||||
<ng-include src="'angular/certificates/certificate/options.tpl.html'"></ng-include>
|
||||
</wz-step>
|
||||
<wz-step title="Destinations" canenter="enterValidation">
|
||||
<ng-include src="'angular/certificates/certificate/destinations.tpl.html'"></ng-include>
|
||||
</wz-step>
|
||||
</wizard>
|
||||
</div>
|
@ -0,0 +1,62 @@
|
||||
<p>Destinations are purely optional, if you think the created certificate will be used in AWS select one or more accounts and Lemur will upload it for you.</p>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Accounts
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="text" ng-model="certificate.selectedAccount" placeholder="Account Name"
|
||||
typeahead="account.label for account in accountService.findAccountsByName($viewValue)" typeahead-loading="loadingAccounts"
|
||||
class="form-control input-md" typeahead-on-select="certificate.attachAccount($item)" typeahead-min-wait="50"
|
||||
tooltip="Lemur can upload the certificate to any AWS account."
|
||||
tooltip-trigger="focus" tooltip-placement="top">
|
||||
<span class="input-group-btn">
|
||||
<button ng-model="accounts.show" class="btn btn-md btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
|
||||
<span class="badge">{{ certificate.accounts.length || 0 }}</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<table class="table">
|
||||
<tr ng-repeat="account in certificate.accounts track by $index">
|
||||
<td><a class="btn btn-sm btn-info" href="#/accounts/{{ account.id }}/certificates">{{ account.label }}</a></td>
|
||||
<td><span class="text-muted">{{ account.comments }}</span></td>
|
||||
<td>
|
||||
<button type="button" ng-click="certificate.removeAccount($index)" class="btn btn-danger btn-sm pull-right">Remove</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!--<div ng-show="certificate.accounts" class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
ELBs
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="text" ng-model="certificate.selectedELB" placeholder="ELB Name"
|
||||
typeahead="elb.name for elb in elbService.findELBByName($viewValue)" typeahead-loading="loadingAccounts"
|
||||
class="form-control col-md-4" typeahead-min-wait="50"
|
||||
tooltip="Lemur can upload a certificate to one or more ELBs"
|
||||
tooltip-trigger="focus" tooltip-placement="top"/>
|
||||
<input class="form-control col-md-2" type="integer" ng-model="certificate.selectedPort" placeholder="Port"/>
|
||||
<select class="form-control col-md-2" ng-options="item for item in ['https', 'tcp']"></select>
|
||||
<span class="input-group-btn">
|
||||
<button ng-click="certificate.attachELB()" class="btn btn-info">Add</button>
|
||||
</span>
|
||||
</div>
|
||||
<table class="table">
|
||||
<tr ng-repeat="elb in certificate.elbs track by $index">
|
||||
<td><a class="btn btn-sm btn-info" href="#/accounts/{{ elb.id }}/elbs">{{ elb.name }}</a></td>
|
||||
<td>{{ elb.region }}</td>
|
||||
<td>{{ elb.scheme }}</td>
|
||||
<td>{{ elb.vpcId }}</td>
|
||||
<td>{{ elb.listener.scheme }}</td>
|
||||
<td>{{ elb.listener.port }}</td>
|
||||
<td>
|
||||
<button type="button" ng-click="certificate.removeELB($index)" class="btn btn-danger btn-sm pull-right">remove</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>-->
|
||||
</div>
|
@ -0,0 +1,55 @@
|
||||
<form name="dnForm" novalidate>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': dnForm.country.$invalid, 'has-success': !dnForm.country.$invalid&&dnForm.country.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Country
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="country" ng-model="certificate.country" placeholder="Country" class="form-control" ng-init="certificate.country = 'US'" required/>
|
||||
<p ng-show="dnForm.country.$invalid && !dnForm.country.$pristine" class="help-block">You must enter a country</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': dnForm.state.$invalid, 'has-success': !dnForm.$invalid&&dnForm.state.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
State
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="state" ng-model="certificate.state" placeholder="State" class="form-control" ng-init="certificate.state = 'CA'" required/>
|
||||
<p ng-show="dnForm.state.$invalid && !dnForm.state.$pristine" class="help-block">You must enter a state</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': dnForm.location.$invalid, 'has-success': !dnForm.$invalid&&dnForm.location.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Location
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="location" ng-model="certificate.location" placeholder="Location" class="form-control" ng-init="certificate.location = 'Los Gatos'"required/>
|
||||
<p ng-show="dnForm.location.$invalid && !dnForm.location.$pristine" class="help-block">You must enter a location</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': dnForm.organization.$invalid, 'has-success': !dnForm.$invalid&&dnForm.organization.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Organization
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="organization" ng-model="certificate.organization" placeholder="Organization" class="form-control" ng-init="certificate.organization = 'Netflix'" required/>
|
||||
<p ng-show="dnForm.organization.$invalid && !dnForm.organization.$pristine" class="help-block">You must enter a organization</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': dnForm.organizationalUnit.$invalid, 'has-success': !dnForm.$invalid&&dnForm.organizationalUnit.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Organizational Unit
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="organizationalUnit" ng-model="certificate.organizationalUnit" placeholder="Organizational Unit" class="form-control" ng-init="certificate.organizationalUnit = 'Operations'"required/>
|
||||
<p ng-show="dnForm.organization.$invalid && !dnForm.organizationalUnit.$pristine" class="help-block">You must enter a organizational unit</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -0,0 +1,224 @@
|
||||
<form name="optionsForm" novalidate>
|
||||
<div class="form-horizontal">
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Subject Alternate Names
|
||||
</label>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" ng-model="certificate.subAltType" ng-options="item for item in ['DNSName', 'IPAddress', 'uniformResourceIdentifier', 'directoryName','rfc822Name', 'registeredID', 'otherName', 'x400Address', 'EDIPartyName']"></select>
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
<div class="input-group">
|
||||
<input tooltip-trigger="focus" tooltip-placement="top" tooltip="String or Base64-encoded DER ASN.1 structure for the value" class="form-control" name="value" ng-model="certificate.subAltValue" placeholder="Value" class="form-control" required/>
|
||||
<span class="input-group-btn">
|
||||
<button ng-click="certificate.attachSubAltName()" class="btn btn-info">Add</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-8 col-sm-offset-2">
|
||||
<table class="table">
|
||||
<tr ng-repeat="alt in certificate.extensions.subAltNames.names track by $index">
|
||||
<td>{{ alt.nameType }}</td>
|
||||
<td>{{ alt.value }}</td>
|
||||
<td>
|
||||
<button type="button" ng-click="certificate.removeSubAltName($index)" class="btn btn-danger btn-sm pull-right">Remove</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Key Usage
|
||||
</label>
|
||||
<div class="col-sm-3">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useDigitalSignature">Digital Signature
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useNonRepudiation">Non Repudiation
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useKeyEncipherment">Key Encipherment
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useDataEncipherment">Data Encipherment
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useKeyAgreement">Key Agreement
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useKeyCertSign">Key Certificate Signature
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useCRLSign">CRL Sign
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useEncipherOnly">Encipher Only
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.keyUsage.useDecipherOnly">Decipher Only
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Extended Key Usage
|
||||
</label>
|
||||
<div class="col-sm-3">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.extendedKeyUsage.useServerAuthentication">Server Authentication
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.extendedKeyUsage.useEmail">Email
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.extendedKeyUsage.useTimestamping">Timestamping
|
||||
</label>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.extendedKeyUsage.useEapOverLAN">EAP Over LAN
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.extendedKeyUsage.useEapOverPPP">EAP Over PPP
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.extendedKeyUsage.useSmartCardLogon">Smartcard Logon
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.extendedKeyUsage.useOCSPSigning">OCSP Signing
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Authority Key Identifier
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label tooltip-trigger="mouseenter" tooltip-placement="top" tooltip="Put Issuer's keyIdentifier in this extension" >
|
||||
<input type="checkbox" ng-model="certificate.extensions.authorityKeyIdentifier.useKeyIdentifier">Key Identifier
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label tooltip-trigger="mouseenter" tooltip-placement="top" tooltip="Put Issuer's Name and Serial number" >
|
||||
<input type="checkbox" ng-model="certificate.extensions.authorityIdentifier.useAuthorityCert">Authority Certificate
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Authority Information Access
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label tooltip-trigger="mouseenter" tooltip-placement="top" tooltip="Ask CA to include/not include AIA extension" >
|
||||
<input type="checkbox" ng-model="certificate.extensions.certificateInfoAccess.includeAIA">Include AIA
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Subject Key Identifier
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label tooltip-trigger="mouseenter" tooltip-placement="top" tooltip="Ask CA to include/not include Subject Key Identifier" >
|
||||
<input type="checkbox" ng-model="certificate.extensions.subjectKeyIdentifier.includeSKI">Include SKI
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
cRL Distribution Points
|
||||
</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" ng-model="certificate.extensions.cRLDistributionPoints.includeCRLDP" ng-options="item for item in ['yes', 'no', 'default']"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Custom
|
||||
</label>
|
||||
<div class="col-sm-2">
|
||||
<input tooltip-trigger="focus" tooltip-placement="top" tooltip="OID for the custom extension e.g. 1.12.123.12.10" class="form-control" name="oid" ng-model="certificate.customOid" placeholder="Oid" class="form-control" required/>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<select tooltip-trigger="focus" tooltip-placement="top" tooltip="Encoding for value" class="form-control col-sm-2" ng-model="certificate.customEncoding" ng-options="item for item in ['b64asn1', 'string', 'ia5string']"></select>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<input tooltip-trigger="focus" tooltip-placement="top" tooltip="String or Base64-encoded DER ASN.1 structure for the value" class="form-control" name="value" ng-model="certificate.customValue" placeholder="Value" class="form-control" required/>
|
||||
<span class="input-group-btn">
|
||||
<button ng-click="certificate.attachCustom()" class="btn btn-info">Add</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="certificate.extensions.custom.isCritical">Critical
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-8 col-sm-offset-2">
|
||||
<table class="table">
|
||||
<tr ng-repeat="custom in certificate.extensions.custom track by $index">
|
||||
<td>{{ custom.oid }}</td>
|
||||
<td>{{ custom.encoding }}</td>
|
||||
<td>{{ custom.value }}</td>
|
||||
<td>{{ custom.isCritical}}</td>
|
||||
<td>
|
||||
<button type="button" ng-click="certificate.removeCustom($index)" class="btn btn-danger btn-sm pull-right">Remove</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
@ -0,0 +1,103 @@
|
||||
<form name="trackingForm" novalidate>
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': trackingForm.ownerEmail.$invalid, 'has-success': !trackingForm.$invalid&&trackingForm.ownerEmail.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Owner
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" name="ownerEmail" ng-model="certificate.owner" placeholder="TeamDL@netflix.com" tooltip="This is the certificates team distribution list or main point of contact" class="form-control" required/>
|
||||
<p ng-show="trackingForm.ownerEmail.$invalid && !trackingForm.ownerEmail.$pristine" class="help-block">You must enter an Certificate owner</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': trackingForm.description.$invalid, 'has-success': !trackingForm.$invalid&&trackingForm.description.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Description
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea name="description" ng-model="certificate.description" placeholder="Something elegant" class="form-control" ng-pattern="/^[\w\-\s]+$/" required></textarea>
|
||||
<p ng-show="trackingForm.description.$invalid && !trackingForm.description.$pristine" class="help-block">You must give a short description about this authority will be used for, this description should only include alphanumeric characters</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Certificate Authority
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group col-sm-12">
|
||||
<input tooltip="If you are unsure which authority you need; you most likely want to use 'verisign'" type="text" ng-model="certificate.selectedAuthority" placeholder="Authority Name" typeahead-on-select="certificate.attachAuthority($item)"
|
||||
typeahead="authority.name for authority in authorityService.findAuthorityByName($viewValue)" typeahead-loading="loadingAuthorities"
|
||||
class="form-control" typeahead-wait-ms="100" typeahead-template-url="angular/authorities/authority/select.tpl.html">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="certificate.authority.name == 'verisign'">
|
||||
<div class="form-group" ng-class="{'has-error': !certificate.extensions.subAltNames.names.length&&!certificate.extensions.subAltNames.names , 'has-success': certificate.extensions.subAltNames.names||certificate.subAltValue}">
|
||||
<label class="control-label col-sm-2">Domain(s)</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group input-group-option">
|
||||
<input tooltip="If you request multiple domains a SAN certificate will be created" type="text" name="domain" ng-model="certificate.subAltValue" placeholder="Domain..." class="form-control" required/>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" ng-click="certificate.attachSubAltName()">Add</button>
|
||||
</span>
|
||||
</div>
|
||||
<table ng-show="certificate.extensions.subAltNames.names" class="table">
|
||||
<tr ng-repeat="domain in certificate.extensions.subAltNames.names track by $index">
|
||||
<td>{{ domain.value }}</td>
|
||||
<td>
|
||||
<button type="button" ng-click="certificate.removeSubAltName($index)" class="btn btn-danger btn-sm pull-right">Remove</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="certificate.authority && certificate.authority.name != 'verisign'" class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Certificate Template
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" ng-change="certificate.useTemplate()" name="certificateTemplate" ng-model="certificate.template" ng-options="template.name for template in templates"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="certificate.authority && certificate.authority.name != 'verisign'" class="form-group"
|
||||
ng-class="{'has-error': trackingForm.commonName.$invalid, 'has-success': !trackingForm.$invalid&&trackingForm.commonName.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Common Name
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input name="commonName" ng-model="certificate.commonName" placeholder="Common Name" class="form-control" required/>
|
||||
<p ng-show="trackingForm.commonName.$invalid && !trackingForm.commonName.$pristine" class="help-block">You must enter a common name</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Validity Range
|
||||
</label>
|
||||
<div class="col-sm-4">
|
||||
<div>
|
||||
<div class="input-group">
|
||||
<input tooltip="Starting Date (yyyy/MM/dd)" class="form-control" datepicker-popup="yyyy/MM/dd" is-open="$parent.openNotBefore.isOpen" min-date="certificate.authority.notBefore" max-date="certificate.authority.maxDate" ng-model="certificate.validityStart" />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" ng-click="openNotBefore($event)"><i class="glyphicon glyphicon-calendar"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-center col-sm-2"><label><span class="glyphicon glyphicon-resize-horizontal"></span></label></span>
|
||||
<div class="col-sm-4">
|
||||
<div>
|
||||
<div class="input-group">
|
||||
<input tooltip="Ending Date (yyyy/MM/dd)" class="form-control" datepicker-popup="yyyy/MM/dd" is-open="$parent.openNotAfter.isOpen" min-date="certificate.authority.notBefore" max-date="certificate.authority.maxDate" ng-model="certificate.validityEnd" />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" ng-click="openNotAfter($event)"><i class="glyphicon glyphicon-calendar"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
26
lemur/static/app/angular/certificates/certificate/upload.js
vendored
Normal file
26
lemur/static/app/angular/certificates/certificate/upload.js
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('lemur')
|
||||
|
||||
.config(function config($routeProvider) {
|
||||
$routeProvider.when('/certificates/upload', {
|
||||
templateUrl: '/angular/certificates/certificate/upload.tpl.html',
|
||||
controller: 'CertificatesUploadController'
|
||||
});
|
||||
})
|
||||
|
||||
.controller('CertificatesUploadController', function ($scope, CertificateService, LemurRestangular, AccountService, ELBService) {
|
||||
$scope.certificate = LemurRestangular.restangularizeElement(null, {}, 'certificates');
|
||||
$scope.upload = CertificateService.upload;
|
||||
|
||||
$scope.accountService = AccountService;
|
||||
$scope.elbService = ELBService;
|
||||
|
||||
|
||||
$scope.attachELB = function (elb) {
|
||||
$scope.certificate.attachELB(elb);
|
||||
ELBService.getListeners(elb).then(function (listeners) {
|
||||
$scope.certificate.elb.listeners = listeners;
|
||||
});
|
||||
};
|
||||
});
|
@ -0,0 +1,136 @@
|
||||
<h2 class="featurette-heading">Upload a certificate <span class="text-muted"><small>encrypt all the things
|
||||
</small></span></h2>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<a href="/#/certificates/" class="btn btn-danger pull-right">Cancel</a>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form name="uploadForm" class="form-horizontal" role="form" novalidate>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': uploadForm.owner.$invalid, 'has-success': !uploadForm.owner.$invalid&&uploadForm.owner.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Owner
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input type="email" name="owner" ng-model="certificate.owner" placeholder="owner@netflix.com"
|
||||
class="form-control" required/>
|
||||
|
||||
<p ng-show="uploadForm.owner.$invalid && !uploadForm.owner.$pristine" class="help-block">Enter a valid
|
||||
email.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': uploadForm.publicCert.$invalid, 'has-success': !uploadForm.publicCert.$invalid&&uploadForm.publicCert.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Public Certificate
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<textarea name="publicCert" ng-model="certificate.publicCert" placeholder="PEM encoded string..."
|
||||
class="form-control" ng-pattern="/^-----BEGIN CERTIFICATE-----/" required></textarea>
|
||||
|
||||
<p ng-show="uploadForm.publicCert.$invalid && !uploadForm.publicCert.$pristine" class="help-block">Enter
|
||||
a valid certificate.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': uploadForm.privateKey.$invalid&&uploadForm.privateKey.$dirty, 'has-success': !uploadForm.privateKey.$invalid&&uploadForm.privateKey.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Private Key
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<textarea name="privateKey" ng-model="certificate.privateKey" placeholder="PEM encoded string..."
|
||||
class="form-control" ng-pattern="/^-----BEGIN RSA PRIVATE KEY-----/"></textarea>
|
||||
|
||||
<p ng-show="uploadForm.privateKey.$invalid && !uploadForm.privateKey.$pristine" class="help-block">Enter
|
||||
a valid certificate.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group"
|
||||
ng-class="{'has-error': uploadForm.owner.$invalid&&uploadform.intermediateCert.$dirty, 'has-success': !uploadForm.intermediateCert.$invalid&&uploadForm.intermediateCert.$dirty}">
|
||||
<label class="control-label col-sm-2">
|
||||
Intermediate Certificate
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<textarea name="intermediateCert" ng-model="certificate.intermediateCert"
|
||||
placeholder="PEM encoded string..." class="form-control"
|
||||
ng-pattern="/^-----BEGIN CERTIFICATE-----/"></textarea>
|
||||
|
||||
<p ng-show="uploadForm.intermediateCert.$invalid && !uploadForm.intemediateCert.$pristine"
|
||||
class="help-block">Enter a valid certificate.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
Accounts
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="text" ng-model="certificate.selectedAccount" placeholder="Account Name"
|
||||
typeahead="account.label for account in accountService.findAccountsByName($viewValue)" typeahead-loading="loadingAccounts"
|
||||
class="form-control" typeahead-on-select="certificate.attachAccount($item)" typeahead-min-wait="50"
|
||||
tooltip="Lemur can upload the certificate to any AWS account."
|
||||
tooltip-trigger="focus" tooltip-placement="top">
|
||||
<span class="input-group-btn">
|
||||
<button ng-model="certificate.accounts" class="btn btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
|
||||
<span class="badge">{{ certificate.accounts.length || 0 }}</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<table ng-show="certificate.accounts" class="table">
|
||||
<tr ng-repeat="account in certificate.accounts track by $index">
|
||||
<td><a class="btn btn-sm btn-info" href="#/accounts/{{ account.id }}/certificates">{{ account.label }}</a></td>
|
||||
<td><span class="text-muted">{{ account.comments }}</span></td>
|
||||
<td>
|
||||
<button type="button" ng-click="certificate.removeAccount($index)" class="btn btn-danger btn-sm pull-right">
|
||||
Remove
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!--<div class="form-group">
|
||||
<label class="control-label col-sm-2">
|
||||
ELBs
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="text" ng-model="certificate.selectedELB" placeholder="ELB Name"
|
||||
typeahead="elb.name for elb in elbService.findELBByName($viewValue)" typeahead-loading="loadingAccounts"
|
||||
class="form-control" typeahead-on-select="attachELB($item)" typeahead-min-wait="50"
|
||||
tooltip="Lemur can upload a certificate to one or more ELBs searching will be limited to the accounts selected above"
|
||||
tooltip-trigger="focus" tooltip-placement="top">
|
||||
<span class="input-group-btn">
|
||||
<button ng-model="certificate.elbs" class="btn btn-default" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">
|
||||
<span class="badge">{{ certificate.elbs.length || 0 }}</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<table ng-show="certificate.elbs" class="table">
|
||||
<tr ng-repeat="elb in certificate.elbs track by $index">
|
||||
<td><a class="btn btn-sm btn-info" href="#/accounts/{{ elb.id }}/elbs">{{ elb.name }}</a></td>
|
||||
<td>{{ elb.region }}</td>
|
||||
<td>{{ elb.scheme }}</td>
|
||||
<td>{{ elb.vpcId }}</td>
|
||||
<td><a class="btn btn-info" ng-model="elb.showListeners" btn-checkbox btn-checkbox-true="1" btn-checkbox-false="0">View Listeners</a></td>
|
||||
<td>
|
||||
<button type="button" ng-click="certificate.removeAccount($index)" class="btn btn-danger btn-sm pull-right">
|
||||
Remove
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>-->
|
||||
</form>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<button type="submit" ng-click="upload(certificate)" ng-disabled="uploadForm.$invalid" class="btn btn-success pull-right">Upload</button>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
238
lemur/static/app/angular/certificates/services.js
vendored
Normal file
238
lemur/static/app/angular/certificates/services.js
vendored
Normal file
@ -0,0 +1,238 @@
|
||||
/**
|
||||
* Created by kglisson on 1/19/15.
|
||||
*/
|
||||
angular.module('lemur')
|
||||
.service('CertificateApi', function (LemurRestangular, DomainService) {
|
||||
LemurRestangular.extendModel('certificates', function (obj) {
|
||||
return angular.extend(obj, {
|
||||
attachAuthority: function (authority) {
|
||||
this.authority = authority;
|
||||
this.authority.maxDate = moment(this.authority.notAfter).subtract(1, 'days').format('YYYY/MM/DD');
|
||||
},
|
||||
attachSubAltName: function () {
|
||||
if (this.extensions === undefined) {
|
||||
this.extensions = {};
|
||||
}
|
||||
|
||||
if (this.extensions.subAltNames === undefined) {
|
||||
this.extensions.subAltNames = {'names': []};
|
||||
}
|
||||
|
||||
if (!angular.isString(this.subAltType)) {
|
||||
this.subAltType = 'CNAME';
|
||||
}
|
||||
|
||||
if (angular.isString(this.subAltValue) && angular.isString(this.subAltType)) {
|
||||
this.extensions.subAltNames.names.push({'nameType': this.subAltType, 'value': this.subAltValue});
|
||||
this.findDuplicates();
|
||||
}
|
||||
|
||||
this.subAltType = null;
|
||||
this.subAltValue = null;
|
||||
},
|
||||
removeSubAltName: function (index) {
|
||||
this.extensions.subAltNames.names.splice(index, 1);
|
||||
this.findDuplicates();
|
||||
},
|
||||
attachCustom: function () {
|
||||
if (this.extensions === undefined || this.extensions.custom === undefined) {
|
||||
this.extensions = {'custom': []};
|
||||
}
|
||||
|
||||
if (angular.isString(this.customOid) && angular.isString(this.customEncoding) && angular.isString(this.customValue)) {
|
||||
this.extensions.custom.push(
|
||||
{
|
||||
'oid': this.customOid,
|
||||
'isCritical': this.customIsCritical,
|
||||
'encoding': this.customEncoding,
|
||||
'value': this.customValue
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.customOid = null;
|
||||
this.customIsCritical = null;
|
||||
this.customEncoding = null;
|
||||
this.customValue = null;
|
||||
},
|
||||
removeCustom: function (index) {
|
||||
this.extensions.custom.splice(index, 1);
|
||||
},
|
||||
attachAccount: function (account) {
|
||||
this.selectedAccount = null;
|
||||
if (this.accounts === undefined) {
|
||||
this.accounts = [];
|
||||
}
|
||||
this.accounts.push(account);
|
||||
},
|
||||
removeAccount: function (index) {
|
||||
this.accounts.splice(index, 1);
|
||||
},
|
||||
attachELB: function (elb) {
|
||||
this.selectedELB = null;
|
||||
if (this.elbs === undefined) {
|
||||
this.elbs = [];
|
||||
}
|
||||
this.elbs.push(elb);
|
||||
},
|
||||
removeELB: function (index) {
|
||||
this.elbs.splice(index, 1);
|
||||
},
|
||||
findDuplicates: function () {
|
||||
DomainService.findDomainByName(this.extensions.subAltNames[0]).then(function (domains) { //We should do a better job of searchin multiple domains
|
||||
this.duplicates = domains.total;
|
||||
});
|
||||
},
|
||||
useTemplate: function () {
|
||||
this.extensions = this.template.extensions;
|
||||
}
|
||||
});
|
||||
});
|
||||
return LemurRestangular.all('certificates');
|
||||
})
|
||||
.service('CertificateService', function ($location, CertificateApi, toaster) {
|
||||
var CertificateService = this;
|
||||
CertificateService.findCertificatesByName = function (filterValue) {
|
||||
return CertificateApi.getList({'filter[name]': filterValue})
|
||||
.then(function (certificates) {
|
||||
return certificates;
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.getARNs = function (certificate) {
|
||||
certificate.arns = [];
|
||||
_.each(certificate.accounts, function (account) {
|
||||
certificate.arns.push('arn:aws:iam::' + account.accountNumber + ':server-certificate/' + certificate.name);
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.create = function (certificate) {
|
||||
certificate.attachSubAltName();
|
||||
return CertificateApi.post(certificate).then(
|
||||
function (response) {
|
||||
toaster.pop({
|
||||
type: 'success',
|
||||
title: certificate.name,
|
||||
body: 'Successfully created!'
|
||||
});
|
||||
$location.path('/certificates');
|
||||
},
|
||||
function (response) {
|
||||
toaster.pop({
|
||||
type: 'error',
|
||||
title: certificate.name,
|
||||
body: 'Was not created! ' + response.data.message
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
CertificateService.update = function (certificate) {
|
||||
certificate.put().then(function () {
|
||||
toaster.pop({
|
||||
type: 'success',
|
||||
title: certificate.name,
|
||||
body: 'Successfully updated!'
|
||||
});
|
||||
$location.path('certificates');
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.upload = function (certificate) {
|
||||
CertificateApi.customPOST(certificate, "upload").then(
|
||||
function (response) {
|
||||
toaster.pop({
|
||||
type: 'success',
|
||||
title: certificate.name,
|
||||
body: 'Successfully uploaded!'
|
||||
});
|
||||
$location.path('/certificates');
|
||||
},
|
||||
function (response) {
|
||||
toaster.pop({
|
||||
type: 'error',
|
||||
title: certificate.name,
|
||||
body: 'Failed to upload ' + response.data.message
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.loadPrivateKey = function (certificate) {
|
||||
certificate.customGET('key').then(
|
||||
function (response) {
|
||||
if (response.key === null) {
|
||||
toaster.pop({
|
||||
type: 'warning',
|
||||
title: certificate.name,
|
||||
body: 'No private key found!'
|
||||
});
|
||||
} else {
|
||||
certificate.privateKey = response.key;
|
||||
}
|
||||
},
|
||||
function (response) {
|
||||
toaster.pop({
|
||||
type: 'error',
|
||||
title: certificate.name,
|
||||
body: 'You do not have permission to view this key!'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.getAuthority = function (certificate) {
|
||||
certificate.customGET('authority').then(function (authority) {
|
||||
certificate.authority = authority;
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.getCreator = function (certificate) {
|
||||
certificate.customGET('creator').then(function (creator) {
|
||||
certificate.creator = creator;
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.getAccounts = function (certificate) {
|
||||
certificate.getList('accounts').then(function (accounts) {
|
||||
certificate.accounts = accounts;
|
||||
CertificateService.getARNs(certificate);
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.getListeners = function (certificate) {
|
||||
certificate.getList('listeners').then(function (listeners) {
|
||||
certificate.listeners = listeners;
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.getELBs = function (certificate) {
|
||||
certificate.getList('listeners').then(function (elbs) {
|
||||
certificate.elbs = elbs;
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.getDomains = function (certificate) {
|
||||
certificate.getList('domains').then(function (domains) {
|
||||
certificate.domains = domains;
|
||||
});
|
||||
};
|
||||
|
||||
CertificateService.updateActive = function (certificate) {
|
||||
certificate.put().then(
|
||||
function () {
|
||||
toaster.pop({
|
||||
type: 'success',
|
||||
title: certificate.name,
|
||||
body: 'Successfully updated!'
|
||||
});
|
||||
},
|
||||
function (response) {
|
||||
toaster.pop({
|
||||
type: 'error',
|
||||
title: certificate.name,
|
||||
body: 'Was not updated! ' + response.data.message
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return CertificateService;
|
||||
});
|
63
lemur/static/app/angular/certificates/view/view.js
vendored
Normal file
63
lemur/static/app/angular/certificates/view/view.js
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('lemur')
|
||||
|
||||
.config(function config($routeProvider) {
|
||||
$routeProvider.when('/certificates', {
|
||||
templateUrl: '/angular/certificates/view/view.tpl.html',
|
||||
controller: 'CertificatesViewController'
|
||||
});
|
||||
})
|
||||
|
||||
.controller('CertificatesViewController', function ($q, $scope, CertificateApi, CertificateService, MomentService, ngTableParams) {
|
||||
$scope.filter = {};
|
||||
$scope.certificateTable = new ngTableParams({
|
||||
page: 1, // show first page
|
||||
count: 10, // count per page
|
||||
sorting: {
|
||||
id: 'desc' // initial sorting
|
||||
},
|
||||
filter: $scope.filter
|
||||
}, {
|
||||
total: 0, // length of data
|
||||
getData: function ($defer, params) {
|
||||
CertificateApi.getList(params.url())
|
||||
.then(function (data) {
|
||||
// TODO we should attempt to resolve all of these in parallel
|
||||
_.each(data, function (certificate) {
|
||||
CertificateService.getDomains(certificate);
|
||||
CertificateService.getAccounts(certificate);
|
||||
CertificateService.getListeners(certificate);
|
||||
CertificateService.getAuthority(certificate);
|
||||
CertificateService.getCreator(certificate);
|
||||
});
|
||||
params.total(data.total);
|
||||
$defer.resolve(data);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$scope.certificateService = CertificateService;
|
||||
$scope.momentService = MomentService;
|
||||
|
||||
$scope.remove = function (certificate) {
|
||||
certificate.remove().then(function () {
|
||||
$scope.certificateTable.reload();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.getCertificateStatus = function () {
|
||||
var def = $q.defer();
|
||||
def.resolve([{'title': 'Active', 'id': true}, {'title': 'Inactive', 'id': false}])
|
||||
return def;
|
||||
};
|
||||
|
||||
$scope.show = {title: 'Current User', value: 'currentUser'};
|
||||
|
||||
$scope.fields = [{title: 'Current User', value: 'currentUser'}, {title: 'All', value: 'all'}];
|
||||
|
||||
|
||||
$scope.toggleFilter = function (params) {
|
||||
params.settings().$scope.show_filter = !params.settings().$scope.show_filter;
|
||||
};
|
||||
});
|
142
lemur/static/app/angular/certificates/view/view.tpl.html
Normal file
142
lemur/static/app/angular/certificates/view/view.tpl.html
Normal file
@ -0,0 +1,142 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2 class="featurette-heading">Certificates
|
||||
<span class="text-muted"><small>Cipher text says what?</small></span></h2>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="btn-group pull-right">
|
||||
<a data-placement="left" data-title="Create Certificate" bs-tooltip href="#/certificates/create"
|
||||
class="btn btn-primary">
|
||||
Create
|
||||
</a>
|
||||
<a data-placement="left" data-title="Upload Certificate" bs-tooltip href="#/certificates/upload"
|
||||
class="btn btn-info">
|
||||
Upload
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button ng-click="toggleFilter(certificateTable)" class="btn btn-default">Filter</button>
|
||||
</div>
|
||||
<!--<select class="form-control" ng-model="show" ng-options="item.value as item.title for item in fields"></select>-->
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table ng-table="certificateTable" class="table" show-filter="false" template-pagination="angular/pager.html">
|
||||
<tbody>
|
||||
<tr ng-class="{'even-row': $even }" ng-repeat-start="certificate in $data track by $index">
|
||||
<td data-title="'Name'" sortable="'name'" filter="{ 'name': 'text' }">
|
||||
<ul class="list-unstyled">
|
||||
<li>{{ certificate.name }}</li>
|
||||
<li><span class="text-muted">{{ certificate.owner }}</span></li>
|
||||
</ul>
|
||||
</td>
|
||||
<td data-title="'Accounts'" filter="{ 'account': 'select' }" filter-date="getAccountDropDown()">
|
||||
<div class="btn-group">
|
||||
<a href="#/accounts/{{ account.id }}/edit" class="btn btn-sm btn-default" ng-repeat="account in certificate.accounts">{{ account.label }}</a>
|
||||
</div>
|
||||
</td>
|
||||
<td data-title="'Active'" filter="{ 'active': 'select' }" filter-data="getCertificateStatus()">
|
||||
<form>
|
||||
<switch ng-change="certificateService.updateActive(certificate)" id="status" name="status" ng-model="certificate.active" class="green small"></switch>
|
||||
</form>
|
||||
</td>
|
||||
<td data-title="'Issuer'" sortable="'issuer'" filter="{ 'issuer': 'text' }">
|
||||
{{ certificate.authority.name || certificate.issuer }}
|
||||
</td>
|
||||
<td data-title="'Common Name'" filter="{ 'cn': 'text'}">
|
||||
{{ certificate.cn }}
|
||||
</td>
|
||||
<td data-title="''">
|
||||
<div class="btn-group-vertical pull-right">
|
||||
<button ng-model="certificate.toggle" class="btn btn-sm btn-info" btn-checkbox btn-checkbox-true="1" butn-checkbox-false="0">View</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="warning" ng-show="certificate.toggle" ng-repeat-end>
|
||||
<td colspan="5">
|
||||
<div class="col-md-6">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">
|
||||
<strong>Creator</strong>
|
||||
<span class="pull-right">
|
||||
{{ certificate.creator.email }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Not Before</strong>
|
||||
<span class="pull-right" tooltip="{{ certificate.notBefore }}">
|
||||
{{ momentService.createMoment(certificate.notBefore) }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Not After</strong>
|
||||
<span class="pull-right" tooltip="{{ certificate.notAfter }}">
|
||||
{{ momentService.createMoment(certificate.notAfter) }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>San</strong>
|
||||
<span class="pull-right">
|
||||
<i class="glyphicon glyphicon-ok" ng-show="certificate.san == 'true'"></i>
|
||||
<i class="glyphicon glyphicon-remove" ng-show="certificate.san == 'false'"></i>
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Bits</strong>
|
||||
<span class="pull-right">{{ certificate.bits }}</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Serial</strong>
|
||||
<span class="pull-right">{{ certificate.serial }}</span>
|
||||
</li>
|
||||
<li tooltip="Lemur will attempt to check a certificates validity, this is used to track whether a certificate as been revoked" class="list-group-item">
|
||||
<strong>Validity</strong>
|
||||
<span class="pull-right">
|
||||
<span ng-show="!certificate.status" class="label label-warning">Unknown</span>
|
||||
<span ng-show="certificate.status == 'revoked'" class="label label-danger">Revoked</span>
|
||||
<span ng-show="certificate.status == 'valid'" class="label label-success">Valid</span>
|
||||
</span>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Description</strong>
|
||||
<span class="pull-right">{{ certificate.description }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<h4>Domains</h4>
|
||||
<div class="list-group">
|
||||
<a href="#/domains/{{ domain.id }}" class="list-group-item" ng-repeat="domain in certificate.domains">{{ domain.name }}</a>
|
||||
</div>
|
||||
<h4 ng-show="certificate.accounts.total">ARNs</h4>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item" ng-repeat="arn in certificate.arns">{{ arn }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<tabset justified="true" class="col-md-6">
|
||||
<tab heading="Chain">
|
||||
<p>
|
||||
<pre style="width: 550px">{{ certificate.chain }}</pre>
|
||||
</p>
|
||||
</tab>
|
||||
<tab heading="Public Certificate">
|
||||
<p>
|
||||
<pre style="width: 550px">{{ certificate.body }}</pre>
|
||||
</p>
|
||||
</tab>
|
||||
<tab ng-click="certificateService.loadPrivateKey(certificate)">
|
||||
<tab-heading>
|
||||
Private Key
|
||||
</tab-heading>
|
||||
<p>
|
||||
<pre style="width: 550px">{{ certificate.privateKey }}</pre>
|
||||
</p>
|
||||
</tab>
|
||||
</tabset>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user