diff --git a/src/locales/zh.json b/src/locales/zh.json index 72970816..389f26e8 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -1069,7 +1069,7 @@ "If OS is Linux, system will reset root password, if OS is Windows, system will reset Administrator password.": "如果操作系统是Linux,系统会修改root用户密码,如果是Windows,系统会修改Administrator用户密码。", "If an instance is using this flavor, deleting it will cause the instance's flavor data to be missing. Are you sure to delete {name}?": "若有云主机正在使用此 flavor,删除会导致云主机的 flavor 数据缺失,确定删除 {name} ?", "If checked, the network will be enable.": "如果选中,那么网络将被启用。", - "If it is an SNI type certificate, a domain name needs to be specified": "如果是 SNI 类型证书,需制定域名", + "If it is an SNI type certificate, a domain name needs to be specified": "如果是 SNI 类型证书,需指定域名", "If no gateway is specified, the first IP address will be defaulted.": "如果不指定网关IP,默认是第一个地址。", "If not provided, the roles assigned to the application credential will be the same as the roles in the current token.": "如果不选择,那么分配给应用凭证的角色将与当前用户的角色相同。", "If nova-compute on the host is disabled, it will be forbidden to be selected as the target host.": "如果计算节点上的nova-compute被禁用,将禁止其作为目标节点。", diff --git a/src/pages/network/containers/Certificate/Certificate.jsx b/src/pages/network/containers/Certificate/Certificate.jsx index 44be7cba..367a3ac5 100644 --- a/src/pages/network/containers/Certificate/Certificate.jsx +++ b/src/pages/network/containers/Certificate/Certificate.jsx @@ -20,7 +20,6 @@ import globalContainersStore, { import { checkPolicyRule } from 'resources/skyline/policy'; import globalSecretsStore, { SecretsStore } from 'stores/barbican/secrets'; import { certificateMode, certificateStatus } from 'resources/octavia/lb'; -import { getOptions } from 'utils/index'; import { parse } from 'qs'; import actionConfigs from './actions'; @@ -90,16 +89,20 @@ export class Certificate extends Base { title: t('Certificate Type'), dataIndex: 'mode', render: (value) => certificateMode[value] || value, + isHideable: true, }, { title: t('Expires At'), dataIndex: 'expiration', valueRender: 'toLocalTime', + isHideable: true, }, { title: t('Domain Name'), dataIndex: 'algorithm', render: (value) => value || '-', + hidden: this.currentMode === 'CA', + isHideable: true, }, { title: t('Status'), @@ -110,6 +113,7 @@ export class Certificate extends Base { title: t('Created At'), dataIndex: 'created', valueRender: 'toLocalTime', + isHideable: true, }, ]; return columns; @@ -121,11 +125,6 @@ export class Certificate extends Base { label: t('Name'), name: 'name', }, - { - label: t('Certificate Type'), - name: 'mode', - options: getOptions(certificateMode), - }, ]; return ret; } diff --git a/src/pages/network/containers/Certificate/Detail/Container/index.jsx b/src/pages/network/containers/Certificate/Detail/Container/index.jsx index 0fd91e83..b9a5c184 100644 --- a/src/pages/network/containers/Certificate/Detail/Container/index.jsx +++ b/src/pages/network/containers/Certificate/Detail/Container/index.jsx @@ -50,7 +50,7 @@ export class Detail extends Base { get tabs() { return [ { - title: t('Detail Info'), + title: t('BaseDetail'), key: 'detail_info', component: BaseDetail, }, diff --git a/src/pages/network/containers/Certificate/Detail/Secret/index.jsx b/src/pages/network/containers/Certificate/Detail/Secret/index.jsx index 6f38da92..afb61426 100644 --- a/src/pages/network/containers/Certificate/Detail/Secret/index.jsx +++ b/src/pages/network/containers/Certificate/Detail/Secret/index.jsx @@ -50,7 +50,7 @@ export class Detail extends Base { get tabs() { return [ { - title: t('Detail Info'), + title: t('BaseDetail'), key: 'detail_info', component: BaseDetail, }, diff --git a/src/pages/network/containers/Certificate/actions/Create.jsx b/src/pages/network/containers/Certificate/actions/Create.jsx index 74ff2c1a..726944ea 100644 --- a/src/pages/network/containers/Certificate/actions/Create.jsx +++ b/src/pages/network/containers/Certificate/actions/Create.jsx @@ -73,18 +73,11 @@ export class CreateAction extends ModalAction { validateCertificateContent = (rule, value) => { if (!value) return Promise.reject(); const keys = value.split(/\n/g); - const start = keys.shift(); - const end = keys.pop(); - const middleCorrect = keys.every((it, index) => { - if (index === keys.length - 1) { - return it.length <= 64; - } - return it.length === 64; - }); + const start = keys[0]; + const end = keys[keys.length - 1] || keys[keys.length - 2]; // Compatible with last blank line if ( start === '-----BEGIN CERTIFICATE-----' && - end === '-----END CERTIFICATE-----' && - middleCorrect + end === '-----END CERTIFICATE-----' ) { return Promise.resolve(); } @@ -98,18 +91,11 @@ export class CreateAction extends ModalAction { validateCertificateKeyPair = (rule, value) => { if (!value) return Promise.reject(); const keys = value.split(/\n/g); - const start = keys.shift(); - const end = keys.pop(); - const middleCorrect = keys.every((it, index) => { - if (index === keys.length - 1) { - return it.length <= 64; - } - return it.length === 64; - }); + const start = keys[0]; + const end = keys[keys.length - 1] || keys[keys.length - 2]; if ( start === '-----BEGIN RSA PRIVATE KEY-----' && - end === '-----END RSA PRIVATE KEY-----' && - middleCorrect + end === '-----END RSA PRIVATE KEY-----' ) { return Promise.resolve(); } diff --git a/src/pages/network/containers/LoadBalancers/Listener/Actions/CreateListener.jsx b/src/pages/network/containers/LoadBalancers/Listener/Actions/CreateListener.jsx index 1f13730b..36c5a874 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Actions/CreateListener.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Actions/CreateListener.jsx @@ -150,7 +150,9 @@ export class Create extends ModalAction { name: 'name', }, ], - columns: certificateColumns, + columns: certificateColumns.filter( + (it) => it.dataIndex !== 'algorithm' + ), display: protocol === 'TERMINATED_HTTPS' && ssl_parsing_method === 'two-way', }, @@ -167,7 +169,7 @@ export class Create extends ModalAction { required: true, data: this.SNICertificate, isLoading: this.containersStore.list.isLoading, - isMulti: false, + isMulti: true, filterParams: [ { label: t('Name'), @@ -217,9 +219,9 @@ export class Create extends ModalAction { data.client_authentication = 'MANDATORY'; } if (sni_container_refs) { - data.sni_container_refs = [ - sni_container_refs.selectedRows[0].container_ref, - ]; + data.sni_container_refs = sni_container_refs.selectedRows.map( + (it) => it.container_ref + ); } return this.store.create(data); }; diff --git a/src/pages/network/containers/LoadBalancers/Listener/Detail/BaseDetail.jsx b/src/pages/network/containers/LoadBalancers/Listener/Detail/BaseDetail.jsx index 6d0c1409..67ab5576 100644 --- a/src/pages/network/containers/LoadBalancers/Listener/Detail/BaseDetail.jsx +++ b/src/pages/network/containers/LoadBalancers/Listener/Detail/BaseDetail.jsx @@ -46,6 +46,10 @@ export class BaseDetail extends Base { return [this.PoolInfo, this.healthMonitor]; } + get rightCards() { + return [this.certificateInfo]; + } + get PoolInfo() { const { default_pool = {} } = this.detailData || {}; const { name, protocol, lb_algorithm, description } = default_pool; @@ -106,6 +110,67 @@ export class BaseDetail extends Base { options, }; } + + get certificateInfo() { + const options = [ + { + label: t('Server Certificate'), + dataIndex: 'serverCertificateId', + render: (value) => { + return value + ? this.getLinkRender( + 'certificateContainerDetail', + value, + { + id: value, + }, + null + ) + : '-'; + }, + }, + { + label: t('CA Certificate'), + dataIndex: 'caCertificateId', + render: (value) => { + return value + ? this.getLinkRender( + 'certificateSecretDetail', + value, + { + id: value, + }, + null + ) + : '-'; + }, + }, + { + label: t('SNI Certificate'), + dataIndex: 'sniCertificateId', + render: (value) => { + return value.length + ? value.map( + (it, index) => + this.getLinkRender( + 'certificateContainerDetail', + `${it}${index === value.length - 1 ? '' : ' , '}`, + { + id: it, + } + ), + null + ) + : '-'; + }, + }, + ]; + return { + title: t('certificate'), + options, + labelCol: 4, + }; + } } export default inject('rootStore')(observer(BaseDetail)); diff --git a/src/pages/network/containers/LoadBalancers/LoadBalancerInstance/actions/StepCreate/index.jsx b/src/pages/network/containers/LoadBalancers/LoadBalancerInstance/actions/StepCreate/index.jsx index 1846a6b3..d15d7fcd 100644 --- a/src/pages/network/containers/LoadBalancers/LoadBalancerInstance/actions/StepCreate/index.jsx +++ b/src/pages/network/containers/LoadBalancers/LoadBalancerInstance/actions/StepCreate/index.jsx @@ -120,9 +120,10 @@ export class StepCreate extends StepAction { listenerData.client_authentication = 'MANDATORY'; } if (listener_sni_enabled && listener_sni_container_refs) { - listenerData.sni_container_refs = [ - listener_sni_container_refs.selectedRows[0].container_ref, - ]; + listenerData.sni_container_refs = + listener_sni_container_refs.selectedRows.map( + (it) => it.container_ref + ); } } diff --git a/src/pages/network/containers/LoadBalancers/StepCreateComponents/ListenerStep/index.jsx b/src/pages/network/containers/LoadBalancers/StepCreateComponents/ListenerStep/index.jsx index 69748602..e8c47a68 100644 --- a/src/pages/network/containers/LoadBalancers/StepCreateComponents/ListenerStep/index.jsx +++ b/src/pages/network/containers/LoadBalancers/StepCreateComponents/ListenerStep/index.jsx @@ -152,7 +152,9 @@ export class ListenerStep extends Base { name: 'name', }, ], - columns: certificateColumns, + columns: certificateColumns.filter( + (it) => it.dataIndex !== 'algorithm' + ), display: listener_protocol === 'TERMINATED_HTTPS' && listener_ssl_parsing_method === 'two-way', @@ -170,7 +172,7 @@ export class ListenerStep extends Base { required: true, data: this.SNISecrets, isLoading: false, - isMulti: false, + isMulti: true, filterParams: [ { label: t('Name'), diff --git a/src/resources/octavia/lb.js b/src/resources/octavia/lb.js index 3a33134e..0448cb04 100644 --- a/src/resources/octavia/lb.js +++ b/src/resources/octavia/lb.js @@ -79,7 +79,7 @@ export const listenerProtocols = [ value: 'TCP', }, { - label: 'TERMINATED_HTTPS', + label: 'HTTPS', value: 'TERMINATED_HTTPS', }, { diff --git a/src/stores/octavia/listener.js b/src/stores/octavia/listener.js index d5ce9c05..3bb5d39d 100644 --- a/src/stores/octavia/listener.js +++ b/src/stores/octavia/listener.js @@ -47,7 +47,23 @@ export class ListenerStore extends Base { // } async detailDidFetch(item) { - const { default_pool_id } = item; + const { + default_pool_id, + default_tls_container_ref = '', + client_ca_tls_container_ref = '', + sni_container_refs = [], + } = item; + const [, serverId] = default_tls_container_ref.split('/containers/'); + const [, caId] = client_ca_tls_container_ref.split('/secrets/'); + const sniId = sni_container_refs.map((it) => { + const [, ssid] = it.split('/containers/'); + return ssid; + }); + Object.assign(item, { + serverCertificateId: serverId, + caCertificateId: caId, + sniCertificateId: sniId, + }); if (default_pool_id) { // pool attach listener or loadbalancer ? try {