misc: key usages setup

This commit is contained in:
Sheen Capadngan
2024-09-10 21:42:41 +08:00
parent a8fd83652d
commit 1c749c84f2
11 changed files with 199 additions and 20 deletions
@@ -0,0 +1,40 @@
import { Knex } from "knex";
import { CertKeyUsage } from "@app/services/certificate/certificate-types";
import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
const hasKeyUsagesCol = await knex.schema.hasColumn(TableName.CertificateTemplate, "keyUsages");
const hasExtendedKeyUsagesCol = await knex.schema.hasColumn(TableName.CertificateTemplate, "extendedKeyUsages");
await knex.schema.alterTable(TableName.CertificateTemplate, (tb) => {
if (!hasKeyUsagesCol) {
tb.specificType("keyUsages", "text[]");
}
if (!hasExtendedKeyUsagesCol) {
tb.specificType("extendedKeyUsages", "text[]");
}
});
if (!hasKeyUsagesCol) {
await knex(TableName.CertificateTemplate).update({
keyUsages: [CertKeyUsage.DIGITAL_SIGNATURE, CertKeyUsage.KEY_ENCIPHERMENT]
});
}
}
export async function down(knex: Knex): Promise<void> {
const hasKeyUsagesCol = await knex.schema.hasColumn(TableName.CertificateTemplate, "keyUsages");
const hasExtendedKeyUsagesCol = await knex.schema.hasColumn(TableName.CertificateTemplate, "extendedKeyUsages");
await knex.schema.alterTable(TableName.CertificateTemplate, (t) => {
if (hasKeyUsagesCol) {
t.dropColumn("keyUsages");
}
if (hasExtendedKeyUsagesCol) {
t.dropColumn("extendedKeyUsages");
}
});
}
@@ -16,7 +16,9 @@ export const CertificateTemplatesSchema = z.object({
subjectAlternativeName: z.string(),
ttl: z.string(),
createdAt: z.date(),
updatedAt: z.date()
updatedAt: z.date(),
keyUsages: z.string().array().nullable().optional(),
extendedKeyUsages: z.string().array().nullable().optional()
});
export type TCertificateTemplates = z.infer<typeof CertificateTemplatesSchema>;
@@ -7,6 +7,7 @@ import { CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { CertKeyUsage } from "@app/services/certificate/certificate-types";
import { sanitizedCertificateTemplate } from "@app/services/certificate-template/certificate-template-schema";
import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators";
@@ -74,7 +75,12 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
ttl: z
.string()
.refine((val) => ms(val) > 0, "TTL must be a positive number")
.describe(CERTIFICATE_TEMPLATES.CREATE.ttl)
.describe(CERTIFICATE_TEMPLATES.CREATE.ttl),
keyUsages: z
.nativeEnum(CertKeyUsage)
.array()
.optional()
.default([CertKeyUsage.DIGITAL_SIGNATURE, CertKeyUsage.KEY_ENCIPHERMENT])
}),
response: {
200: sanitizedCertificateTemplate
@@ -130,7 +136,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
.string()
.refine((val) => ms(val) > 0, "TTL must be a positive number")
.optional()
.describe(CERTIFICATE_TEMPLATES.UPDATE.ttl)
.describe(CERTIFICATE_TEMPLATES.UPDATE.ttl),
keyUsages: z.nativeEnum(CertKeyUsage).array().optional()
}),
params: z.object({
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.UPDATE.certificateTemplateId)
@@ -50,7 +50,9 @@ export const certificateTemplateDALFactory = (db: TDbClient) => {
)
.first();
return certTemplate;
if (certTemplate) {
return { ...certTemplate, keyUsages: certTemplate.keyUsages || [] };
}
} catch (error) {
throw new DatabaseError({ error, name: "Get certificate template by ID" });
}
@@ -13,6 +13,7 @@ export const sanitizedCertificateTemplate = CertificateTemplatesSchema.pick({
}).merge(
z.object({
projectId: z.string(),
caName: z.string()
caName: z.string(),
keyUsages: z.string().array()
})
);
@@ -57,7 +57,8 @@ export const certificateTemplateServiceFactory = ({
actorId,
actorAuthMethod,
actor,
actorOrgId
actorOrgId,
keyUsages
}: TCreateCertTemplateDTO) => {
const ca = await certificateAuthorityDAL.findById(caId);
if (!ca) {
@@ -86,7 +87,8 @@ export const certificateTemplateServiceFactory = ({
name,
commonName,
subjectAlternativeName,
ttl
ttl,
keyUsages
},
tx
);
@@ -113,7 +115,8 @@ export const certificateTemplateServiceFactory = ({
actorId,
actorAuthMethod,
actor,
actorOrgId
actorOrgId,
keyUsages
}: TUpdateCertTemplateDTO) => {
const certTemplate = await certificateTemplateDAL.getById(id);
if (!certTemplate) {
@@ -153,7 +156,8 @@ export const certificateTemplateServiceFactory = ({
commonName,
subjectAlternativeName,
name,
ttl
ttl,
keyUsages
},
tx
);
@@ -1,4 +1,5 @@
import { TProjectPermission } from "@app/lib/types";
import { CertKeyUsage } from "@app/services/certificate/certificate-types";
export type TCreateCertTemplateDTO = {
caId: string;
@@ -7,6 +8,7 @@ export type TCreateCertTemplateDTO = {
commonName: string;
subjectAlternativeName: string;
ttl: string;
keyUsages: CertKeyUsage[];
} & Omit<TProjectPermission, "projectId">;
export type TUpdateCertTemplateDTO = {
@@ -17,6 +19,7 @@ export type TUpdateCertTemplateDTO = {
commonName?: string;
subjectAlternativeName?: string;
ttl?: string;
keyUsages?: CertKeyUsage[];
} & Omit<TProjectPermission, "projectId">;
export type TGetCertTemplateDTO = {
@@ -12,6 +12,18 @@ export enum CertKeyAlgorithm {
ECDSA_P384 = "EC_secp384r1"
}
export enum CertKeyUsage {
DIGITAL_SIGNATURE = "digitalSignature",
KEY_ENCIPHERMENT = "keyEncipherment",
NON_REPUDIATION = "nonRepudiation",
DATA_ENCIPHERMENT = "dataEncipherment",
KEY_AGREEMENT = "keyAgreement",
KEY_CERT_SIGN = "keyCertSign",
CRL_SIGN = "cRLSign",
ENCIPHER_ONLY = "encipherOnly",
DECIPHER_ONLY = "decipherOnly"
}
export enum CrlReason {
UNSPECIFIED = "UNSPECIFIED",
KEY_COMPROMISE = "KEY_COMPROMISE",