infra: custom SSL cert setup form (#54)

This fixes #33

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Ritchie Vincent 2019-12-06 19:22:53 +00:00 committed by Rohit Yadav
parent cadd7106a0
commit 3a82cc535f
3 changed files with 269 additions and 47 deletions

View File

@ -49,13 +49,13 @@ export function generateRouterMap (section) {
var route = {
name: child.name,
path: '/' + child.name,
hidden: child.hidden,
meta: {
title: child.title,
name: child.name,
keepAlive: true,
icon: child.icon,
docHelp: child.docHelp,
hidden: child.hidden,
permission: child.permission,
resourceType: child.resourceType,
params: child.params ? child.params : {},
@ -69,13 +69,13 @@ export function generateRouterMap (section) {
children: [
{
path: '/' + child.name + '/:id',
hidden: child.hidden,
meta: {
title: child.title,
name: child.name,
keepAlive: true,
icon: child.icon,
docHelp: child.docHelp,
hidden: child.hidden,
permission: child.permission,
resourceType: child.resourceType,
params: child.params ? child.params : {},
@ -96,6 +96,7 @@ export function generateRouterMap (section) {
map.children.push({
name: action.api,
icon: child.icon,
hidden: true,
path: '/action/' + action.api,
meta: {
title: child.title,
@ -103,8 +104,7 @@ export function generateRouterMap (section) {
keepAlive: true,
permission: [action.api]
},
component: action.component,
hidden: true
component: action.component
})
})
}

View File

@ -17,7 +17,7 @@
<template>
<div>
<a-card class="mobile-breadcrumb">
<a-card class="breadcrumb-card">
<a-row>
<a-col :span="14">
<breadcrumb style="padding-top: 6px" />
@ -402,7 +402,8 @@ export default {
// handle error
this.$notification.error({
message: 'Request Failed',
description: error.response.headers['x-description']
description: error.response.headers['x-description'],
duration: 0
})
if (error.response.status === 431) {
this.$router.push({ path: '/exception/404' })
@ -514,7 +515,7 @@ export default {
this.fetchData()
} else if (result.jobstatus === 2) {
this.fetchData()
} else {
} else if (result.jobstatus === 0) {
this.$message
.loading(this.$t(action.label) + ' in progress for ' + this.resource.name, 3)
.then(() => this.pollActionCompletion(jobId, action))
@ -636,7 +637,7 @@ export default {
<style scoped>
.mobile-breadcrumb {
.breadcrumb-card {
margin-left: -24px;
margin-right: -24px;
margin-top: -16px;

View File

@ -17,36 +17,125 @@
<template>
<a-row :gutter="24">
<a-col :md="18">
<a-card>
<breadcrumb />
</a-card>
</a-col>
<a-col
:md="6" >
<a-card>
<a-button
style="margin-left: 10px; float: right"
@click="fetchData()"
icon="reload"
:loading="loading"
type="primary">
{{ $t('Refresh') }}
</a-button>
<a-button
style="margin-left: 10px; float: right"
@click="sslFormVisible = true"
icon="safety-certificate">
{{ $t('SSL Certificate') }}
</a-button>
<a-modal
:title="$t('SSL Certificate')"
v-model="sslFormVisible"
@ok="handle">
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</a-modal>
<a-col :md="24">
<a-card class="breadcrumb-card">
<a-col :md="14">
<breadcrumb style="padding-top: 6px" />
</a-col>
<a-col :md="10">
<a-button
style="margin-left: 10px; float: right"
@click="fetchData()"
icon="reload"
:loading="loading"
type="primary">
{{ $t('Refresh') }}
</a-button>
<a-button
style="margin-left: 10px; float: right"
@click="sslFormVisible = true"
icon="safety-certificate">
{{ $t('SSL Certificate') }}
</a-button>
<a-modal
:title="$t('SSL Certificate')"
:visible="sslFormVisible"
:footer="null"
@cancel="sslModalClose">
<p>
Please submit a new X.509 compliant SSL certificate chain to be updated to each console proxy and secondary storage virtual instance:
</p>
<a-form @submit.prevent="handleSslFormSubmit" ref="sslForm" :form="form">
<a-form-item label="Root certificate" :required="true">
<a-textarea
id="rootCert"
rows="2"
placeholder="Root certificate"
:autoFocus="true"
name="rootCert"
v-decorator="[
'root',
{rules: [{ required: true, message: 'Required' }], validateTrigger:'change'}
]"
></a-textarea>
</a-form-item>
<transition-group name="fadeInUp" tag="div">
<a-form-item
v-for="(item, index) in intermediateCertificates"
:key="`key-${index}`"
class="intermediate-certificate"
:label="`Intermediate certificate ${index + 1}`">
<a-textarea
:id="`intermediateCert${index}`"
rows="2"
:placeholder="`Intermediate certificate ${index + 1}`"
:name="`intermediateCert${index}`"
v-decorator="[
`intermediate${index + 1}`,
{validateTrigger:'change'}
]"
></a-textarea>
</a-form-item>
</transition-group>
<a-form-item>
<a-button @click="addIntermediateCert">
<a-icon type="plus-circle" />
Add intermediate certificate
</a-button>
</a-form-item>
<a-form-item label="Server certificate" :required="true">
<a-textarea
id="serverCert"
rows="2"
placeholder="Server certificate"
name="serverCert"
v-decorator="[
'server',
{rules: [{ required: true, message: 'Required' }], validateTrigger:'change'}
]"
></a-textarea>
</a-form-item>
<a-form-item label="PKCS#8 Private Key" :required="true">
<a-textarea
id="pkcsKey"
rows="2"
placeholder="PKCS#8 Private Key"
name="pkcsKey"
v-decorator="[
'pkcs',
{rules: [{ required: true, message: 'Required' }], validateTrigger:'change'}
]"
></a-textarea>
</a-form-item>
<a-form-item label="DNS Domain Suffix (i.e., xyz.com)" :required="true">
<a-input
id="dnsSuffix"
placeholder="DNS Domain Suffix (i.e., xyz.com)"
name="dnsSuffix"
v-decorator="[
'dns',
{rules: [{ required: true, message: 'Required' }], validateTrigger:'change'}
]"
></a-input>
</a-form-item>
<a-form-item class="controls">
<a-button @click="this.sslModalClose" type="danger" class="close-button">
Cancel
</a-button>
<a-button type="primary" htmlType="submit" :loading="sslFormSubmitting">
Submit
</a-button>
</a-form-item>
</a-form>
</a-modal>
</a-col>
</a-card>
</a-col>
<a-col
@ -86,9 +175,15 @@ export default {
routes: {},
sections: ['zones', 'pods', 'clusters', 'hosts', 'storagepools', 'imagestores', 'systemvms', 'routers', 'cpusockets', 'managementservers', 'alerts'],
sslFormVisible: false,
stats: {}
stats: {},
intermediateCertificates: [],
sslFormSubmitting: false,
maxCerts: 0
}
},
beforeCreate () {
this.form = this.$form.createForm(this)
},
mounted () {
this.fetchData()
},
@ -115,17 +210,143 @@ export default {
this.loading = false
})
},
handleSslForm (e) {
console.log(e)
resetSslFormData () {
this.form.resetFields()
this.intermediateCertificates = []
this.sslFormSubmitting = false
this.sslFormVisible = false
},
sslModalClose () {
this.resetSslFormData()
},
addIntermediateCert () {
this.intermediateCertificates.push('')
},
pollActionCompletion (jobId, count) {
api('queryAsyncJobResult', { jobid: jobId }).then(json => {
const result = json.queryasyncjobresultresponse
if (result.jobstatus === 1 && this.maxCerts === count) {
console.log(result)
console.log(this.maxCerts)
console.log(count)
this.$message.success('Certificate Uploaded: ' + result.jobresult.customcertificate.message)
this.$notification.success({
message: 'Certificate Uploaded',
description: result.jobresult.customcertificate.message || 'Certificate successfully uploaded'
})
} else if (result.jobstatus === 2) {
this.$notification.error({
message: 'Certificate Upload Failed',
description: result.jobresult.errortext || 'Failed to update SSL Certificate. Failed to pass certificate validation check',
duration: 0
})
} else if (result.jobstatus === 0) {
this.$message
.loading('Certificate upload in progress: ' + count, 2)
.then(() => this.pollActionCompletion(jobId, count))
}
}).catch(e => {
console.log('Error encountered while fetching async job result' + e)
})
},
handleSslFormSubmit () {
this.sslFormSubmitting = true
this.form.validateFields(errors => {
if (errors) {
this.sslFormSubmitting = false
return
}
const formValues = this.form.getFieldsValue()
this.maxCerts = 2 + Object.keys(formValues).length
let count = 1
let data = {
id: count,
certificate: formValues.root,
domainsuffix: formValues.dns,
name: 'root'
}
api('uploadCustomCertificate', {}, 'POST', data).then(response => {
this.pollActionCompletion(response.uploadcustomcertificateresponse.jobid, count)
}).then(() => {
this.sslModalClose()
})
Object.keys(formValues).forEach(key => {
if (key.includes('intermediate')) {
count = count + 1
const data = {
id: count,
certificate: formValues[key],
domainsuffix: formValues.dns,
name: key
}
api('uploadCustomCertificate', {}, 'POST', data).then(response => {
this.pollActionCompletion(response.uploadcustomcertificateresponse.jobid, count)
}).then(() => {
this.sslModalClose()
})
}
})
count = count <= 2 ? 3 : count + 1
data = {
id: count,
certificate: formValues.server,
domainsuffix: formValues.dns,
privatekey: formValues.pkcs
}
api('uploadCustomCertificate', {}, 'POST', data).then(response => {
this.pollActionCompletion(response.uploadcustomcertificateresponse.jobid, count)
}).then(() => {
this.sslModalClose()
})
})
}
}
}
</script>
<style lang="less" scoped>
.chart-card-inner {
text-align: center;
white-space: nowrap;
overflow: hidden;
}
<style lang="scss" scoped>
.breadcrumb-card {
margin-left: -36px;
margin-right: -36px;
margin-top: -16px;
margin-bottom: 12px;
}
.chart-card-inner {
text-align: center;
white-space: nowrap;
overflow: hidden;
}
.intermediate-certificate {
opacity: 1;
transform: none;
transition: opacity 0.2s ease 0s, transform 0.5s ease;
will-change: transform;
}
.intermediate-certificate.fadeInUp-enter-active {
opacity: 0;
transform: translateY(10px);
transition: none;
}
.controls {
display: flex;
justify-content: flex-end;
}
.close-button {
margin-right: 20px;
}
.ant-form-item {
margin-bottom: 10px;
}
</style>