1import api from '@/store/api'; 2import i18n from '@/i18n'; 3 4export const CERTIFICATE_TYPES = [ 5 { 6 type: 'HTTPS Certificate', 7 location: '/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/', 8 label: i18n.t('pageCertificates.httpsCertificate'), 9 }, 10 { 11 type: 'LDAP Certificate', 12 location: '/redfish/v1/AccountService/LDAP/Certificates/', 13 label: i18n.t('pageCertificates.ldapCertificate'), 14 }, 15 { 16 type: 'TrustStore Certificate', 17 location: '/redfish/v1/Managers/bmc/Truststore/Certificates/', 18 // Web UI will show 'CA Certificate' instead of 19 // 'TrustStore Certificate' after user testing revealed 20 // the term 'TrustStore Certificate' wasn't recognized/was unfamilar 21 label: i18n.t('pageCertificates.caCertificate'), 22 }, 23]; 24 25const getCertificateProp = (type, prop) => { 26 const certificate = CERTIFICATE_TYPES.find( 27 (certificate) => certificate.type === type, 28 ); 29 return certificate ? certificate[prop] : null; 30}; 31 32const CertificatesStore = { 33 namespaced: true, 34 state: { 35 allCertificates: [], 36 availableUploadTypes: [], 37 }, 38 getters: { 39 allCertificates: (state) => state.allCertificates, 40 availableUploadTypes: (state) => state.availableUploadTypes, 41 }, 42 mutations: { 43 setCertificates(state, certificates) { 44 state.allCertificates = certificates; 45 }, 46 setAvailableUploadTypes(state, availableUploadTypes) { 47 state.availableUploadTypes = availableUploadTypes; 48 }, 49 }, 50 actions: { 51 async getCertificates({ commit }) { 52 return await api 53 .get('/redfish/v1/CertificateService/CertificateLocations') 54 .then( 55 ({ 56 data: { 57 Links: { Certificates }, 58 }, 59 }) => Certificates.map((certificate) => certificate['@odata.id']), 60 ) 61 .then((certificateLocations) => { 62 const promises = certificateLocations.map((location) => 63 api.get(location), 64 ); 65 api.all(promises).then( 66 api.spread((...responses) => { 67 const certificates = responses.map(({ data }) => { 68 const { 69 Name, 70 ValidNotAfter, 71 ValidNotBefore, 72 Issuer = {}, 73 Subject = {}, 74 } = data; 75 return { 76 type: Name, 77 location: data['@odata.id'], 78 certificate: getCertificateProp(Name, 'label'), 79 issuedBy: Issuer.CommonName, 80 issuedTo: Subject.CommonName, 81 validFrom: new Date(ValidNotBefore), 82 validUntil: new Date(ValidNotAfter), 83 }; 84 }); 85 const availableUploadTypes = CERTIFICATE_TYPES.filter( 86 ({ type }) => 87 !certificates 88 .map((certificate) => certificate.type) 89 .includes(type), 90 ); 91 92 commit('setCertificates', certificates); 93 commit('setAvailableUploadTypes', availableUploadTypes); 94 }), 95 ); 96 }); 97 }, 98 async addNewCertificate({ dispatch }, { file, type }) { 99 return await api 100 .post(getCertificateProp(type, 'location'), file, { 101 headers: { 'Content-Type': 'application/x-pem-file' }, 102 }) 103 .then(() => dispatch('getCertificates')) 104 .then(() => 105 i18n.t('pageCertificates.toast.successAddCertificate', { 106 certificate: getCertificateProp(type, 'label'), 107 }), 108 ) 109 .catch((error) => { 110 console.log(error); 111 throw new Error(i18n.t('pageCertificates.toast.errorAddCertificate')); 112 }); 113 }, 114 async replaceCertificate( 115 { dispatch }, 116 { certificateString, location, type }, 117 ) { 118 const data = {}; 119 data.CertificateString = certificateString; 120 data.CertificateType = 'PEM'; 121 data.CertificateUri = { '@odata.id': location }; 122 123 return await api 124 .post( 125 '/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate', 126 data, 127 ) 128 .then(() => dispatch('getCertificates')) 129 .then(() => 130 i18n.t('pageCertificates.toast.successReplaceCertificate', { 131 certificate: getCertificateProp(type, 'label'), 132 }), 133 ) 134 .catch((error) => { 135 console.log(error); 136 throw new Error( 137 i18n.t('pageCertificates.toast.errorReplaceCertificate'), 138 ); 139 }); 140 }, 141 async deleteCertificate({ dispatch }, { type, location }) { 142 return await api 143 .delete(location) 144 .then(() => dispatch('getCertificates')) 145 .then(() => 146 i18n.t('pageCertificates.toast.successDeleteCertificate', { 147 certificate: getCertificateProp(type, 'label'), 148 }), 149 ) 150 .catch((error) => { 151 console.log(error); 152 throw new Error( 153 i18n.t('pageCertificates.toast.errorDeleteCertificate'), 154 ); 155 }); 156 }, 157 async generateCsr(_, userData) { 158 const { 159 certificateType, 160 country, 161 state, 162 city, 163 companyName, 164 companyUnit, 165 commonName, 166 keyPairAlgorithm, 167 keyBitLength, 168 keyCurveId, 169 challengePassword, 170 contactPerson, 171 emailAddress, 172 alternateName, 173 } = userData; 174 const data = {}; 175 176 data.CertificateCollection = { 177 '@odata.id': getCertificateProp(certificateType, 'location'), 178 }; 179 data.Country = country; 180 data.State = state; 181 data.City = city; 182 data.Organization = companyName; 183 data.OrganizationalUnit = companyUnit; 184 data.CommonName = commonName; 185 data.KeyPairAlgorithm = keyPairAlgorithm; 186 data.AlternativeNames = alternateName; 187 188 if (keyCurveId) data.KeyCurveId = keyCurveId; 189 if (keyBitLength) data.KeyBitLength = keyBitLength; 190 if (challengePassword) data.ChallengePassword = challengePassword; 191 if (contactPerson) data.ContactPerson = contactPerson; 192 if (emailAddress) data.Email = emailAddress; 193 194 return await api 195 .post( 196 '/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR', 197 data, 198 ) 199 //TODO: Success response also throws error so 200 // can't accurately show legitimate error in UI 201 .catch((error) => console.log(error)); 202 }, 203 }, 204}; 205 206export default CertificatesStore; 207