1/** 2 * Controller for Certificate Management 3 * 4 * @module app/access-control 5 * @exports certificateController 6 * @name certificateController 7 */ 8 9window.angular && (function(angular) { 10 'use strict'; 11 12 angular.module('app.configuration').controller('certificateController', [ 13 '$scope', 'APIUtils', '$q', 'Constants', 'toastService', '$timeout', 14 '$uibModal', 15 function( 16 $scope, APIUtils, $q, Constants, toastService, $timeout, $uibModal) { 17 $scope.loading = false; 18 $scope.certificates = []; 19 $scope.availableCertificateTypes = []; 20 $scope.allCertificateTypes = Constants.CERTIFICATE_TYPES; 21 $scope.newCertificate = {}; 22 $scope.newCSR = {}; 23 $scope.keyBitLength = Constants.CERTIFICATE.KEY_BIT_LENGTH; 24 $scope.keyPairAlgorithm = Constants.CERTIFICATE.KEY_PAIR_ALGORITHM; 25 $scope.keyCurveId = Constants.CERTIFICATE.KEY_CURVE_ID; 26 $scope.countryList = Constants.COUNTRIES; 27 28 $scope.$on('$viewContentLoaded', () => { 29 getBmcTime(); 30 }) 31 32 $scope.loadCertificates = function() { 33 $scope.certificates = []; 34 $scope.availableCertificateTypes = Constants.CERTIFICATE_TYPES; 35 $scope.loading = true; 36 // Use Certificate Service to get the locations of all the certificates, 37 // then add a promise for fetching each certificate 38 APIUtils.getCertificateLocations().then( 39 function(data) { 40 var promises = []; 41 var locations = data.Links.Certificates; 42 for (var i in locations) { 43 var location = locations[i]; 44 promises.push(getCertificatePromise(location['@odata.id'])); 45 } 46 $q.all(promises) 47 .catch(function(error) { 48 toastService.error('Failed to load certificates.'); 49 console.log(JSON.stringify(error)); 50 }) 51 .finally(function() { 52 $scope.loading = false; 53 $scope.certificates.sort(function(a, b) { 54 if (a.Name > b.Name) { 55 return 1; 56 } 57 if (a.Name < b.Name) { 58 return -1; 59 } 60 if (a.Issuer.CommonName > b.Issuer.CommonName) { 61 return 1; 62 } 63 if (a.Issuer.CommonName < b.Issuer.CommonName) { 64 return -1; 65 } 66 return (Date.parse(a.ValidNotBefore) > 67 Date.parse(b.ValidNotBefore)) ? 68 1 : 69 -1; 70 }); 71 }); 72 }, 73 function(error) { 74 $scope.loading = false; 75 $scope.availableCertificateTypes = []; 76 toastService.error('Failed to load certificates.'); 77 console.log(JSON.stringify(error)); 78 }); 79 }; 80 81 $scope.uploadCertificate = function() { 82 if ($scope.newCertificate.file.name.split('.').pop() !== 'pem') { 83 toastService.error('Certificate must be a .pem file.'); 84 return; 85 } 86 APIUtils 87 .addNewCertificate( 88 $scope.newCertificate.file, $scope.newCertificate.selectedType) 89 .then( 90 function(data) { 91 toastService.success( 92 $scope.newCertificate.selectedType.name + 93 ' was uploaded.'); 94 $scope.newCertificate = {}; 95 $scope.loadCertificates(); 96 }, 97 function(error) { 98 toastService.error( 99 $scope.newCertificate.selectedType.name + 100 ' failed upload.'); 101 console.log(JSON.stringify(error)); 102 }); 103 }; 104 105 var getCertificatePromise = function(url) { 106 var promise = APIUtils.getCertificate(url).then(function(data) { 107 var certificate = data; 108 isExpiring(certificate); 109 updateAvailableTypes(certificate); 110 $scope.certificates.push(certificate); 111 }); 112 return promise; 113 }; 114 115 var isExpiring = function(certificate) { 116 // convert certificate time to epoch time 117 // if ValidNotAfter is less than or equal to 30 days from bmc time 118 // (2592000000), isExpiring. If less than or equal to 0, is expired. 119 // dividing bmc time by 1000 converts epoch milliseconds to seconds 120 var difference = (new Date(certificate.ValidNotAfter).getTime()) - 121 ($scope.bmcTime) / 1000; 122 if (difference <= 0) { 123 certificate.isExpired = true; 124 } else if (difference <= 2592000000) { 125 certificate.isExpiring = true; 126 } else { 127 certificate.isExpired = false; 128 certificate.isExpiring = false; 129 } 130 }; 131 132 // add optional name 133 $scope.names = []; 134 $scope.addOptionalRow = function() { 135 $scope.names.push({Value: ''}) 136 }; 137 138 // remove optional name row 139 $scope.deleteOptionalRow = function(index) { 140 $scope.names.splice(index, 1); 141 if ($scope.names.length == 0) { 142 $scope.names = []; 143 } 144 }; 145 146 // create a CSR object to send to the backend 147 $scope.getCSRCode = function() { 148 var addCSR = {}; 149 let alternativeNames = $scope.names.map(name => name.Value); 150 151 // if user provided a first alternative name then push to alternative 152 // names array 153 $scope.newCSR.firstAlternativeName ? 154 alternativeNames.push($scope.newCSR.firstAlternativeName) : 155 $scope.newCSR.firstAlternativeName = ''; 156 157 addCSR.CertificateCollection = { 158 '@odata.id': $scope.newCSR.certificateCollection.location 159 }; 160 addCSR.CommonName = $scope.newCSR.commonName; 161 addCSR.ContactPerson = $scope.newCSR.contactPerson || ''; 162 addCSR.City = $scope.newCSR.city; 163 addCSR.AlternativeNames = alternativeNames || []; 164 addCSR.ChallengePassword = $scope.newCSR.challengePassword || ''; 165 addCSR.Email = $scope.newCSR.emailAddress || ''; 166 addCSR.Country = $scope.newCSR.countryCode.code; 167 addCSR.Organization = $scope.newCSR.organization; 168 addCSR.OrganizationalUnit = $scope.newCSR.companyUnit; 169 addCSR.KeyCurveId = $scope.newCSR.keyCurveId || ''; 170 addCSR.KeyBitLength = $scope.newCSR.keyBitLength 171 addCSR.KeyPairAlgorithm = $scope.newCSR.keyPairAlgorithm || ''; 172 addCSR.State = $scope.newCSR.state; 173 174 APIUtils.createCSRCertificate(addCSR).then( 175 function(data) { 176 $scope.csrCode = data; 177 openDownloadCsrModal(); 178 }, 179 function(error) { 180 toastService.error('Unable to generate CSR. Try again.'); 181 console.log(JSON.stringify(error)); 182 }) 183 }; 184 185 function openDownloadCsrModal() { 186 const modalTemplateCsrDownload = 187 require('./certificate-modal-csr-download.html'); 188 $uibModal 189 .open({ 190 template: modalTemplateCsrDownload, 191 windowTopClass: 'uib-modal', 192 scope: $scope, 193 ariaLabelledBy: 'modal_label', 194 size: 'lg', 195 }) 196 .result.catch(function() { 197 resetCSRModal(); 198 }); 199 }; 200 201 $scope.addCertModal = function() { 202 openAddCertModal(); 203 }; 204 205 function openAddCertModal() { 206 const modalTemplateAddCert = 207 require('./certificate-modal-add-cert.html'); 208 $uibModal 209 .open({ 210 template: modalTemplateAddCert, 211 windowTopClass: 'uib-modal', 212 scope: $scope, 213 ariaLabelledBy: 'modal_label', 214 }) 215 .result.catch(function() { 216 // do nothing 217 }); 218 }; 219 220 $scope.addCsrModal = function() { 221 openCsrModal(); 222 }; 223 224 function openCsrModal() { 225 const modalTemplateCsrGen = require('./certificate-modal-csr-gen.html'); 226 $uibModal 227 .open({ 228 template: modalTemplateCsrGen, 229 windowTopClass: 'uib-modal', 230 scope: $scope, 231 ariaLabelledBy: 'modal_label', 232 size: 'lg', 233 }) 234 .result.catch(function() { 235 resetCSRModal(); 236 }); 237 }; 238 239 // resetting the modal when user clicks cancel/closes the 240 // modal 241 const resetCSRModal = function() { 242 $scope.newCSR.certificateCollection = $scope.selectOption; 243 $scope.newCSR.commonName = ''; 244 $scope.newCSR.contactPerson = ''; 245 $scope.newCSR.city = ''; 246 $scope.names = []; 247 $scope.newCSR.challengePassword = ''; 248 $scope.newCSR.emailAddress = ''; 249 $scope.newCSR.countryCode = ''; 250 $scope.newCSR.keyCurveId = ''; 251 $scope.newCSR.firstAlternativeName = ''; 252 $scope.newCSR.keyBitLength = $scope.selectOption; 253 $scope.newCSR.keyPairAlgorithm = $scope.selectOption; 254 $scope.newCSR.organization = ''; 255 $scope.newCSR.companyUnit = ''; 256 $scope.newCSR.state = ''; 257 }; 258 259 // copies the CSR code 260 $scope.copySuccess = function(event) { 261 $scope.copied = true; 262 $timeout(function() { 263 $scope.copied = false; 264 }, 5000); 265 }; 266 $scope.copyFailed = function(err) { 267 console.log(JSON.stringify(err)); 268 }; 269 270 271 var getBmcTime = function() { 272 APIUtils.getBMCTime().then(function(data) { 273 $scope.bmcTime = data.data.Elapsed; 274 }); 275 276 return $scope.bmcTime; 277 }; 278 279 var updateAvailableTypes = function(certificate) { 280 $scope.availableCertificateTypes = 281 $scope.availableCertificateTypes.filter(function(type) { 282 if (type.Description == 'TrustStore Certificate') { 283 return true; 284 } 285 return type.Description !== certificate.Description; 286 }); 287 }; 288 289 $scope.getDays = function(endDate) { 290 // finds number of days until certificate expiration 291 // dividing bmc time by 1000 converts milliseconds to seconds 292 var ms = (new Date(endDate).getTime()) - ($scope.bmcTime) / 1000; 293 return Math.floor(ms / (24 * 60 * 60 * 1000)); 294 }; 295 296 $scope.loadCertificates(); 297 } 298 ]); 299})(angular); 300