mirror of https://github.com/certd/certd
fix: 上传商用证书,直接粘贴文本报错的问题;修复无法上传ec加密证书的bug
parent
0e07ae6ce8
commit
5750bb7067
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="pem-input">
|
||||
<FileInput v-bind="fileInput" class="mb-5" type="primary" text="选择文件" @change="onChange" />
|
||||
<a-textarea v-bind="textarea" v-model:value="textRef"></a-textarea>
|
||||
<a-textarea v-bind="textarea" :value="modelValue" @update:value="emitValue"></a-textarea>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -17,7 +17,6 @@ const props = defineProps<{
|
|||
}>();
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
const textRef = ref();
|
||||
|
||||
function emitValue(value: string) {
|
||||
emit("update:modelValue", value);
|
||||
|
@ -39,16 +38,6 @@ function onChange(e: any) {
|
|||
};
|
||||
fileReader.readAsText(file); // 以文本形式读取文件
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
value => {
|
||||
textRef.value = value;
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
|
@ -122,3 +122,11 @@ export async function GetCert(pipelineId: number): Promise<CertInfo> {
|
|||
params: { id: pipelineId },
|
||||
});
|
||||
}
|
||||
|
||||
export async function ReadCertDetail(crt: string): Promise<any> {
|
||||
return await request({
|
||||
url: certApiPrefix + "/readCertDetail",
|
||||
method: "post",
|
||||
data: { crt },
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="tsx" setup>
|
||||
import { computed, inject } from "vue";
|
||||
import { computed, inject, watch, ref } from "vue";
|
||||
import { useCertUpload } from "./use";
|
||||
import { getAllDomainsFromCrt } from "/@/views/certd/pipeline/utils";
|
||||
|
||||
|
@ -27,19 +27,36 @@ const emit = defineEmits(["updated", "update:modelValue"]);
|
|||
|
||||
const { openUpdateCertDialog } = useCertUpload();
|
||||
|
||||
const domain = computed(() => {
|
||||
if (!props.modelValue?.crt) {
|
||||
return "";
|
||||
}
|
||||
const domains = getAllDomainsFromCrt(props.modelValue?.crt);
|
||||
const domainsRef = ref([]);
|
||||
|
||||
return domains[0];
|
||||
watch(
|
||||
() => {
|
||||
return props.modelValue?.crt;
|
||||
},
|
||||
async crt => {
|
||||
if (crt) {
|
||||
domainsRef.value = await getAllDomainsFromCrt(crt);
|
||||
} else {
|
||||
domainsRef.value = [];
|
||||
}
|
||||
|
||||
emit("updated", { domains: domainsRef.value });
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
const domain = computed(() => {
|
||||
if (domainsRef.value && domainsRef.value.length > 0) {
|
||||
return domainsRef.value[0];
|
||||
}
|
||||
|
||||
return "";
|
||||
});
|
||||
|
||||
function onUpdated(res: { uploadCert: any }) {
|
||||
async function onUpdated(res: { uploadCert: any }) {
|
||||
emit("update:modelValue", res.uploadCert);
|
||||
const domains = getAllDomainsFromCrt(res.uploadCert.crt);
|
||||
emit("updated", { domains });
|
||||
}
|
||||
|
||||
const pipeline: any = inject("pipeline");
|
||||
|
|
|
@ -135,7 +135,7 @@ export function useCertUpload() {
|
|||
},
|
||||
async doSubmit({ form }: any) {
|
||||
const cert = form.uploadCert;
|
||||
const domains = getAllDomainsFromCrt(cert.crt);
|
||||
const domains = await getAllDomainsFromCrt(cert.crt);
|
||||
|
||||
const notifications = [];
|
||||
if (form.notification != null) {
|
||||
|
|
|
@ -2,8 +2,7 @@ import { forEach } from "lodash-es";
|
|||
import { mySuiteApi } from "/@/views/certd/suite/mine/api";
|
||||
import { notification } from "ant-design-vue";
|
||||
import { useSettingStore } from "/@/store/settings";
|
||||
//@ts-ignore
|
||||
import forge from "node-forge";
|
||||
import { ReadCertDetail } from "./api";
|
||||
export function eachStages(list: any[], exec: (item: any, runnableType: string) => void, runnableType: string = "stage") {
|
||||
if (!list || list.length <= 0) {
|
||||
return;
|
||||
|
@ -70,33 +69,16 @@ export async function checkPipelineLimit() {
|
|||
}
|
||||
}
|
||||
|
||||
export function readCertDetail(crt: string) {
|
||||
const detail = forge.pki.certificateFromPem(crt);
|
||||
const expires = detail.notAfter;
|
||||
return { detail, expires };
|
||||
export async function readCertDetail(crt: string) {
|
||||
return await ReadCertDetail(crt);
|
||||
}
|
||||
|
||||
export function getAllDomainsFromCrt(crt: string) {
|
||||
const { detail } = readCertDetail(crt);
|
||||
const domains = [];
|
||||
|
||||
// 1. 提取SAN中的DNS名称
|
||||
const sanExtension = detail.extensions.find((ext: any) => ext.name === "subjectAltName");
|
||||
if (sanExtension) {
|
||||
sanExtension.altNames.forEach((altName: any) => {
|
||||
if (altName.type === 2) {
|
||||
// type=2 表示DNS名称
|
||||
domains.push(altName.value);
|
||||
}
|
||||
});
|
||||
export async function getAllDomainsFromCrt(crt: string) {
|
||||
const { detail } = await readCertDetail(crt);
|
||||
const altNames = detail.domains.altNames;
|
||||
const commonName = detail.domains.commonName;
|
||||
if (altNames.includes(commonName)) {
|
||||
return altNames;
|
||||
}
|
||||
|
||||
// 2. 如果没有SAN,回退到CN(通用名称)
|
||||
if (domains.length === 0) {
|
||||
const cnAttr = detail.subject.attributes.find((attr: any) => attr.name === "commonName");
|
||||
if (cnAttr) {
|
||||
domains.push(cnAttr.value);
|
||||
}
|
||||
}
|
||||
return domains;
|
||||
return [commonName, ...altNames];
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||
import {Body, Controller, Inject, Post, Provide, Query} from '@midwayjs/core';
|
||||
import { PipelineService } from '../../../modules/pipeline/service/pipeline-service.js';
|
||||
import { BaseController, Constants } from '@certd/lib-server';
|
||||
import { StorageService } from '../../../modules/pipeline/service/storage-service.js';
|
||||
import {CertReader} from "@certd/plugin-cert";
|
||||
|
||||
@Provide()
|
||||
@Controller('/api/pi/cert')
|
||||
|
@ -18,4 +19,14 @@ export class CertController extends BaseController {
|
|||
const privateVars = await this.storeService.getPipelinePrivateVars(id);
|
||||
return this.ok(privateVars.cert);
|
||||
}
|
||||
|
||||
|
||||
@Post('/readCertDetail', { summary: Constants.per.authOnly })
|
||||
async readCertDetail(@Body('crt') crt: string) {
|
||||
if (!crt) {
|
||||
throw new Error('crt is required');
|
||||
}
|
||||
const certDetail = CertReader.readCertDetail(crt)
|
||||
return this.ok(certDetail);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue