blob: bb74c19ccb359168bc8c9a8d7dab60ba723da601 [file] [log] [blame]
Yoshie Muranaka532a4b02020-03-27 11:00:50 -07001<template>
2 <div>
3 <b-modal
4 id="generate-csr"
5 ref="modal"
6 size="lg"
7 no-stacking
8 :title="
9 $t('pageSslCertificates.modal.generateACertificateSigningRequest')
10 "
11 @ok="onOkGenerateCsrModal"
12 @cancel="resetForm"
13 @hidden="$v.$reset()"
14 >
Yoshie Muranakac77fdaf2020-05-04 09:33:51 -070015 <b-form id="generate-csr-form" novalidate @submit.prevent="handleSubmit">
Yoshie Muranaka532a4b02020-03-27 11:00:50 -070016 <b-container fluid>
17 <b-row>
18 <b-col lg="9">
19 <b-row>
20 <b-col lg="6">
21 <b-form-group
22 :label="
23 $t('pageSslCertificates.modal.certificateType') + ' *'
24 "
25 label-for="certificate-type"
26 >
27 <b-form-select
28 id="certificate-type"
29 v-model="form.certificateType"
30 :options="certificateOptions"
31 :state="getValidationState($v.form.certificateType)"
32 @input="$v.form.certificateType.$touch()"
33 >
34 <template v-slot:first>
35 <b-form-select-option :value="null" disabled>
36 {{ $t('global.form.selectAnOption') }}
37 </b-form-select-option>
38 </template>
39 </b-form-select>
40 <b-form-invalid-feedback role="alert">
41 {{ $t('global.form.fieldRequired') }}
42 </b-form-invalid-feedback>
43 </b-form-group>
44 </b-col>
45 <b-col lg="6">
46 <b-form-group
47 :label="$t('pageSslCertificates.modal.country') + ' *'"
48 label-for="country"
49 >
50 <b-form-select
51 id="country"
52 v-model="form.country"
53 :options="countryOptions"
54 :state="getValidationState($v.form.country)"
55 @input="$v.form.country.$touch()"
56 >
57 <template v-slot:first>
58 <b-form-select-option :value="null" disabled>
59 {{ $t('global.form.selectAnOption') }}
60 </b-form-select-option>
61 </template>
62 </b-form-select>
63 <b-form-invalid-feedback role="alert">
64 {{ $t('global.form.fieldRequired') }}
65 </b-form-invalid-feedback>
66 </b-form-group>
67 </b-col>
68 </b-row>
69 <b-row>
70 <b-col lg="6">
71 <b-form-group
72 :label="$t('pageSslCertificates.modal.state') + ' *'"
73 label-for="state"
74 >
75 <b-form-input
76 id="state"
77 v-model="form.state"
78 type="text"
79 :state="getValidationState($v.form.state)"
80 />
81 <b-form-invalid-feedback role="alert">
82 {{ $t('global.form.fieldRequired') }}
83 </b-form-invalid-feedback>
84 </b-form-group>
85 </b-col>
86 <b-col lg="6">
87 <b-form-group
88 :label="$t('pageSslCertificates.modal.city') + ' *'"
89 label-for="city"
90 >
91 <b-form-input
92 id="city"
93 v-model="form.city"
94 type="text"
95 :state="getValidationState($v.form.city)"
96 />
97 <b-form-invalid-feedback role="alert">
98 {{ $t('global.form.fieldRequired') }}
99 </b-form-invalid-feedback>
100 </b-form-group>
101 </b-col>
102 </b-row>
103 <b-row>
104 <b-col lg="6">
105 <b-form-group
106 :label="$t('pageSslCertificates.modal.companyName') + ' *'"
107 label-for="company-name"
108 >
109 <b-form-input
110 id="company-name"
111 v-model="form.companyName"
112 type="text"
113 :state="getValidationState($v.form.companyName)"
114 />
115 <b-form-invalid-feedback role="alert">
116 {{ $t('global.form.fieldRequired') }}
117 </b-form-invalid-feedback>
118 </b-form-group>
119 </b-col>
120 <b-col lg="6">
121 <b-form-group
122 :label="$t('pageSslCertificates.modal.companyUnit') + ' *'"
123 label-for="company-unit"
124 >
125 <b-form-input
126 id="company-unit"
127 v-model="form.companyUnit"
128 type="text"
129 :state="getValidationState($v.form.companyUnit)"
130 />
131 <b-form-invalid-feedback role="alert">
132 {{ $t('global.form.fieldRequired') }}
133 </b-form-invalid-feedback>
134 </b-form-group>
135 </b-col>
136 </b-row>
137 <b-row>
138 <b-col lg="6">
139 <b-form-group
140 :label="$t('pageSslCertificates.modal.commonName') + ' *'"
141 label-for="common-name"
142 >
143 <b-form-input
144 id="common-name"
145 v-model="form.commonName"
146 type="text"
147 :state="getValidationState($v.form.commonName)"
148 />
149 <b-form-invalid-feedback role="alert">
150 {{ $t('global.form.fieldRequired') }}
151 </b-form-invalid-feedback>
152 </b-form-group>
153 </b-col>
154 <b-col lg="6">
155 <b-form-group
156 :label="$t('pageSslCertificates.modal.challengePassword')"
157 label-for="challenge-password"
158 >
159 <b-form-input
160 id="challenge-password"
161 v-model="form.challengePassword"
162 type="text"
163 />
164 </b-form-group>
165 </b-col>
166 </b-row>
167 <b-row>
168 <b-col lg="6">
169 <b-form-group
170 :label="$t('pageSslCertificates.modal.contactPerson')"
171 label-for="contact-person"
172 >
173 <b-form-input
174 id="contact-person"
175 v-model="form.contactPerson"
176 type="text"
177 />
178 </b-form-group>
179 </b-col>
180 <b-col lg="6">
181 <b-form-group
182 :label="$t('pageSslCertificates.modal.emailAddress')"
183 label-for="email-address"
184 >
185 <b-form-input
186 id="email-address"
187 v-model="form.emailAddress"
188 type="text"
189 />
190 </b-form-group>
191 </b-col>
192 </b-row>
193 <b-row>
194 <b-col lg="12">
195 <b-form-group
196 :label="$t('pageSslCertificates.modal.alternateName')"
197 label-for="alternate-name"
198 >
199 <b-form-text id="alternate-name-help-block">
200 {{
201 $t('pageSslCertificates.modal.alternateNameHelperText')
202 }}
203 </b-form-text>
204 <b-form-tags
205 v-model="form.alternateName"
206 :remove-on-delete="true"
207 :tag-pills="true"
208 input-id="alternate-name"
209 size="lg"
210 separator=" "
211 :input-attrs="{
212 'aria-describedby': 'alternate-name-help-block'
213 }"
214 :duplicate-tag-text="
215 $t('pageSslCertificates.modal.duplicateAlternateName')
216 "
217 placeholder=""
218 >
219 <template v-slot:add-button-text>
220 {{ $t('global.action.add') }} <icon-add />
221 </template>
222 </b-form-tags>
223 </b-form-group>
224 </b-col>
225 </b-row>
226 </b-col>
227 <b-col lg="3">
228 <b-row>
229 <b-col lg="12">
230 <p class="col-form-label">
231 {{ $t('pageSslCertificates.modal.privateKey') }}
232 </p>
233 <b-form-group
234 :label="
235 $t('pageSslCertificates.modal.keyPairAlgorithm') + ' *'
236 "
237 label-for="key-pair-algorithm"
238 >
239 <b-form-select
240 id="key-pair-algorithm"
241 v-model="form.keyPairAlgorithm"
242 :options="keyPairAlgorithmOptions"
243 :state="getValidationState($v.form.keyPairAlgorithm)"
244 @input="$v.form.keyPairAlgorithm.$touch()"
245 >
246 <template v-slot:first>
247 <b-form-select-option :value="null" disabled>
248 {{ $t('global.form.selectAnOption') }}
249 </b-form-select-option>
250 </template>
251 </b-form-select>
252 <b-form-invalid-feedback role="alert">
253 {{ $t('global.form.fieldRequired') }}
254 </b-form-invalid-feedback>
255 </b-form-group>
256 </b-col>
257 </b-row>
258 <b-row>
259 <b-col lg="12">
260 <template v-if="$v.form.keyPairAlgorithm.$model === 'EC'">
261 <b-form-group
262 :label="$t('pageSslCertificates.modal.keyCurveId') + ' *'"
263 label-for="key-curve-id"
264 >
265 <b-form-select
266 id="key-curve-id"
267 v-model="form.keyCurveId"
268 :options="keyCurveIdOptions"
269 :state="getValidationState($v.form.keyCurveId)"
270 @input="$v.form.keyCurveId.$touch()"
271 >
272 <template v-slot:first>
273 <b-form-select-option :value="null" disabled>
274 {{ $t('global.form.selectAnOption') }}
275 </b-form-select-option>
276 </template>
277 </b-form-select>
278 <b-form-invalid-feedback role="alert">
279 {{ $t('global.form.fieldRequired') }}
280 </b-form-invalid-feedback>
281 </b-form-group>
282 </template>
283 <template v-if="$v.form.keyPairAlgorithm.$model === 'RSA'">
284 <b-form-group
285 :label="
286 $t('pageSslCertificates.modal.keyBitLength') + ' *'
287 "
288 label-for="key-bit-length"
289 >
290 <b-form-select
291 id="key-bit-length"
292 v-model="form.keyBitLength"
293 :options="keyBitLengthOptions"
294 :state="getValidationState($v.form.keyBitLength)"
295 @input="$v.form.keyBitLength.$touch()"
296 >
297 <template v-slot:first>
298 <b-form-select-option :value="null" disabled>
299 {{ $t('global.form.selectAnOption') }}
300 </b-form-select-option>
301 </template>
302 </b-form-select>
303 <b-form-invalid-feedback role="alert">
304 {{ $t('global.form.fieldRequired') }}
305 </b-form-invalid-feedback>
306 </b-form-group>
307 </template>
308 </b-col>
309 </b-row>
310 </b-col>
311 </b-row>
312 </b-container>
313 </b-form>
314 <template v-slot:modal-footer="{ ok, cancel }">
315 <b-button variant="secondary" @click="cancel()">
316 {{ $t('global.action.cancel') }}
317 </b-button>
318 <b-button
319 form="generate-csr-form"
320 type="submit"
321 variant="primary"
322 @click="ok()"
323 >
324 {{ $t('pageSslCertificates.generateCsr') }}
325 </b-button>
326 </template>
327 </b-modal>
328 <b-modal
329 id="csr-string"
330 no-stacking
331 size="lg"
332 :title="$t('pageSslCertificates.modal.certificateSigningRequest')"
333 @hidden="onHiddenCsrStringModal"
334 >
335 {{ csrString }}
336 <template v-slot:modal-footer>
337 <b-btn variant="secondary" @click="copyCsrString">
338 <template v-if="csrStringCopied">
339 <icon-checkmark />
340 {{ $t('global.status.copied') }}
341 </template>
342 <template v-else>
343 {{ $t('global.action.copy') }}
344 </template>
345 </b-btn>
346 <a
347 :href="`data:text/json;charset=utf-8,${csrString}`"
348 download="certificate.txt"
349 class="btn btn-primary"
350 >
351 {{ $t('global.action.download') }}
352 </a>
353 </template>
354 </b-modal>
355 </div>
356</template>
357
358<script>
359import IconAdd from '@carbon/icons-vue/es/add--alt/20';
360import IconCheckmark from '@carbon/icons-vue/es/checkmark/20';
361
362import { required, requiredIf } from 'vuelidate/lib/validators';
363
364import { COUNTRY_LIST } from './CsrCountryCodes';
365import { CERTIFICATE_TYPES } from '../../../store/modules/AccessControl/SslCertificatesStore';
366import BVToastMixin from '../../../components/Mixins/BVToastMixin';
367import VuelidateMixin from '../../../components/Mixins/VuelidateMixin.js';
368
369export default {
370 name: 'ModalGenerateCsr',
371 components: { IconAdd, IconCheckmark },
372 mixins: [BVToastMixin, VuelidateMixin],
373 data() {
374 return {
375 form: {
376 certificateType: null,
377 country: null,
378 state: null,
379 city: null,
380 companyName: null,
381 companyUnit: null,
382 commonName: null,
383 challengePassword: null,
384 contactPerson: null,
385 emailAddress: null,
386 alternateName: [],
387 keyPairAlgorithm: null,
388 keyCurveId: null,
389 keyBitLength: null
390 },
391 certificateOptions: CERTIFICATE_TYPES.reduce((arr, cert) => {
392 if (cert.type === 'TrustStore Certificate') return arr;
393 arr.push({
394 text: cert.label,
395 value: cert.type
396 });
397 return arr;
398 }, []),
399 countryOptions: COUNTRY_LIST.map(country => ({
400 text: country.label,
401 value: country.code
402 })),
403 keyPairAlgorithmOptions: ['EC', 'RSA'],
404 keyCurveIdOptions: ['prime256v1', 'secp521r1', 'secp384r1'],
405 keyBitLengthOptions: [2048],
406 csrString: '',
407 csrStringCopied: false
408 };
409 },
410 validations: {
411 form: {
412 certificateType: { required },
413 country: { required },
414 state: { required },
415 city: { required },
416 companyName: { required },
417 companyUnit: { required },
418 commonName: { required },
419 challengePassword: {},
420 contactPerson: {},
421 emailAddress: {},
422 alternateName: {},
423 keyPairAlgorithm: { required },
424 keyCurveId: {
425 reuired: requiredIf(function(form) {
426 return form.keyPairAlgorithm === 'EC';
427 })
428 },
429 keyBitLength: {
430 reuired: requiredIf(function(form) {
431 return form.keyPairAlgorithm === 'RSA';
432 })
433 }
434 }
435 },
436 methods: {
437 handleSubmit() {
438 this.$v.$touch();
439 if (this.$v.$invalid) return;
440 this.$store
441 .dispatch('sslCertificates/generateCsr', this.form)
442 .then(({ data: { CSRString } }) => {
443 this.csrString = CSRString;
444 this.$bvModal.show('csr-string');
445 this.$v.$reset();
446 });
447 },
448 resetForm() {
449 for (let key of Object.keys(this.form)) {
450 if (key === 'alternateName') {
451 this.form[key] = [];
452 } else {
453 this.form[key] = null;
454 }
455 }
456 },
457 onOkGenerateCsrModal(bvModalEvt) {
458 // prevent modal close
459 bvModalEvt.preventDefault();
460 this.handleSubmit();
461 },
462 onHiddenCsrStringModal() {
463 this.csrString = '';
464 this.resetForm();
465 },
466 copyCsrString(bvModalEvt) {
467 // prevent modal close
468 bvModalEvt.preventDefault();
469 navigator.clipboard.writeText(this.csrString).then(() => {
470 // Show copied text for 5 seconds
471 this.csrStringCopied = true;
472 setTimeout(() => {
473 this.csrStringCopied = false;
474 }, 5000 /*5 seconds*/);
475 });
476 }
477 }
478};
479</script>