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