misc: addressed PR feedback regarding audit logs and endpoint structure

This commit is contained in:
Sheen Capadngan
2024-08-19 16:15:43 +08:00
parent abdcb95a8f
commit 00039ba0e4
12 changed files with 145 additions and 96 deletions

View File

@@ -1374,6 +1374,12 @@ interface CreateCertificateTemplate {
type: EventType.CREATE_CERTIFICATE_TEMPLATE;
metadata: {
certificateTemplateId: string;
caId: string;
pkiCollectionId?: string;
name: string;
commonName: string;
subjectAlternativeName: string;
ttl: string;
};
}
@@ -1388,6 +1394,12 @@ interface UpdateCertificateTemplate {
type: EventType.UPDATE_CERTIFICATE_TEMPLATE;
metadata: {
certificateTemplateId: string;
caId: string;
pkiCollectionId?: string;
name: string;
commonName: string;
subjectAlternativeName: string;
ttl: string;
};
}

View File

@@ -1,24 +1,14 @@
import ms from "ms";
import { z } from "zod";
import { CertificateTemplatesSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
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 { sanitizedCertificateTemplate } from "@app/services/certificate-template/certificate-template-schema";
import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators";
const sanitizedCertificateTemplate = CertificateTemplatesSchema.pick({
id: true,
caId: true,
name: true,
commonName: true,
subjectAlternativeName: true,
pkiCollectionId: true,
ttl: true
});
export const registerCertificateTemplateRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
@@ -31,14 +21,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
}),
response: {
200: z.object({
certificateTemplate: sanitizedCertificateTemplate.merge(
z.object({
projectId: z.string(),
caName: z.string()
})
)
})
200: sanitizedCertificateTemplate
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -62,7 +45,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
}
});
return { certificateTemplate };
return certificateTemplate;
}
});
@@ -87,9 +70,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
.describe(CERTIFICATE_TEMPLATES.CREATE.ttl)
}),
response: {
200: z.object({
certificateTemplate: sanitizedCertificateTemplate
})
200: sanitizedCertificateTemplate
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -108,12 +89,18 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
event: {
type: EventType.CREATE_CERTIFICATE_TEMPLATE,
metadata: {
certificateTemplateId: certificateTemplate.id
certificateTemplateId: certificateTemplate.id,
caId: certificateTemplate.caId,
pkiCollectionId: certificateTemplate.pkiCollectionId as string,
name: certificateTemplate.name,
commonName: certificateTemplate.commonName,
subjectAlternativeName: certificateTemplate.subjectAlternativeName,
ttl: certificateTemplate.ttl
}
}
});
return { certificateTemplate };
return certificateTemplate;
}
});
@@ -142,9 +129,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.UPDATE.certificateTemplateId)
}),
response: {
200: z.object({
certificateTemplate: sanitizedCertificateTemplate
})
200: sanitizedCertificateTemplate
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -164,12 +149,18 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
event: {
type: EventType.UPDATE_CERTIFICATE_TEMPLATE,
metadata: {
certificateTemplateId: certificateTemplate.id
certificateTemplateId: certificateTemplate.id,
caId: certificateTemplate.caId,
pkiCollectionId: certificateTemplate.pkiCollectionId as string,
name: certificateTemplate.name,
commonName: certificateTemplate.commonName,
subjectAlternativeName: certificateTemplate.subjectAlternativeName,
ttl: certificateTemplate.ttl
}
}
});
return { certificateTemplate };
return certificateTemplate;
}
});
@@ -184,9 +175,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
}),
response: {
200: z.object({
certificateTemplate: sanitizedCertificateTemplate
})
200: sanitizedCertificateTemplate
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
@@ -210,7 +199,7 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
}
});
return { certificateTemplate };
return certificateTemplate;
}
});
};

View File

@@ -4,7 +4,6 @@ import { z } from "zod";
import {
CertificateAuthoritiesSchema,
CertificatesSchema,
CertificateTemplatesSchema,
PkiAlertsSchema,
PkiCollectionsSchema,
ProjectKeysSchema
@@ -16,6 +15,7 @@ import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { CaStatus } from "@app/services/certificate-authority/certificate-authority-types";
import { sanitizedCertificateTemplate } from "@app/services/certificate-template/certificate-template-schema";
import { ProjectFilterType } from "@app/services/project/project-types";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
@@ -472,17 +472,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}),
response: {
200: z.object({
certificateTemplates: z.array(
CertificateTemplatesSchema.pick({
id: true,
name: true
}).merge(
z.object({
caName: z.string(),
caId: z.string()
})
)
)
certificateTemplates: sanitizedCertificateTemplate.array()
})
}
},

View File

@@ -1,5 +1,6 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols } from "@app/lib/knex";
export type TCertificateTemplateDALFactory = ReturnType<typeof certificateTemplateDALFactory>;
@@ -8,37 +9,48 @@ export const certificateTemplateDALFactory = (db: TDbClient) => {
const certificateTemplateOrm = ormify(db, TableName.CertificateTemplate);
const getCertTemplatesByProjectId = async (projectId: string) => {
const certTemplates = await db
.replicaNode()(TableName.CertificateTemplate)
.join(
TableName.CertificateAuthority,
`${TableName.CertificateAuthority}.id`,
`${TableName.CertificateTemplate}.caId`
)
.where(`${TableName.CertificateAuthority}.projectId`, "=", projectId)
.select(selectAllTableCols(TableName.CertificateTemplate))
.select(db.ref("friendlyName").as("caName").withSchema(TableName.CertificateAuthority));
try {
const certTemplates = await db
.replicaNode()(TableName.CertificateTemplate)
.join(
TableName.CertificateAuthority,
`${TableName.CertificateAuthority}.id`,
`${TableName.CertificateTemplate}.caId`
)
.where(`${TableName.CertificateAuthority}.projectId`, "=", projectId)
.select(selectAllTableCols(TableName.CertificateTemplate))
.select(
db.ref("friendlyName").as("caName").withSchema(TableName.CertificateAuthority),
db.ref("projectId").withSchema(TableName.CertificateAuthority)
);
return certTemplates;
return certTemplates;
} catch (error) {
throw new DatabaseError({ error, name: "Get certificate templates by project ID" });
}
};
const getById = async (id: string) => {
const certTemplate = await db
.replicaNode()(TableName.CertificateTemplate)
.join(
TableName.CertificateAuthority,
`${TableName.CertificateAuthority}.id`,
`${TableName.CertificateTemplate}.caId`
)
.where(`${TableName.CertificateTemplate}.id`, "=", id)
.select(selectAllTableCols(TableName.CertificateTemplate))
.select(
db.ref("projectId").withSchema(TableName.CertificateAuthority),
db.ref("friendlyName").as("caName").withSchema(TableName.CertificateAuthority)
)
.first();
try {
const certTemplate = await db
.replicaNode()(TableName.CertificateTemplate)
.join(
TableName.CertificateAuthority,
`${TableName.CertificateAuthority}.id`,
`${TableName.CertificateTemplate}.caId`
)
.where(`${TableName.CertificateTemplate}.id`, "=", id)
.select(selectAllTableCols(TableName.CertificateTemplate))
.select(
db.ref("projectId").withSchema(TableName.CertificateAuthority),
db.ref("friendlyName").as("caName").withSchema(TableName.CertificateAuthority)
)
.first();
return certTemplate;
return certTemplate;
} catch (error) {
throw new DatabaseError({ error, name: "Get certificate template by ID" });
}
};
return { ...certificateTemplateOrm, getCertTemplatesByProjectId, getById };

View File

@@ -0,0 +1,18 @@
import z from "zod";
import { CertificateTemplatesSchema } from "@app/db/schemas";
export const sanitizedCertificateTemplate = CertificateTemplatesSchema.pick({
id: true,
caId: true,
name: true,
commonName: true,
subjectAlternativeName: true,
pkiCollectionId: true,
ttl: true
}).merge(
z.object({
projectId: z.string(),
caName: z.string()
})
);

View File

@@ -57,7 +57,7 @@ export const certificateTemplateServiceFactory = ({
ProjectPermissionSub.CertificateTemplates
);
const certificateTemplate = await certificateTemplateDAL.create({
const { id } = await certificateTemplateDAL.create({
caId,
pkiCollectionId,
name,
@@ -66,7 +66,14 @@ export const certificateTemplateServiceFactory = ({
ttl
});
return { ...certificateTemplate, projectId: ca.projectId };
const certificateTemplate = await certificateTemplateDAL.getById(id);
if (!certificateTemplate) {
throw new NotFoundError({
message: "Certificate template not found"
});
}
return certificateTemplate;
};
const updateCertTemplate = async ({
@@ -111,7 +118,7 @@ export const certificateTemplateServiceFactory = ({
}
}
const updatedCertTemplate = await certificateTemplateDAL.updateById(certTemplate.id, {
await certificateTemplateDAL.updateById(certTemplate.id, {
caId,
pkiCollectionId,
commonName,
@@ -120,7 +127,14 @@ export const certificateTemplateServiceFactory = ({
ttl
});
return { ...updatedCertTemplate, projectId: certTemplate.projectId };
const updatedTemplate = await certificateTemplateDAL.getById(id);
if (!updatedTemplate) {
throw new NotFoundError({
message: "Certificate template not found"
});
}
return updatedTemplate;
};
const deleteCertTemplate = async ({ id, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteCertTemplateDTO) => {
@@ -144,9 +158,9 @@ export const certificateTemplateServiceFactory = ({
ProjectPermissionSub.CertificateTemplates
);
const deletedCertTemplate = await certificateTemplateDAL.deleteById(certTemplate.id);
await certificateTemplateDAL.deleteById(certTemplate.id);
return { ...deletedCertTemplate, projectId: certTemplate.projectId };
return certTemplate;
};
const getCertTemplate = async ({ id, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertTemplateDTO) => {

View File

@@ -683,6 +683,12 @@ interface CreateCertificateTemplate {
type: EventType.CREATE_CERTIFICATE_TEMPLATE;
metadata: {
certificateTemplateId: string;
caId: string;
pkiCollectionId?: string;
name: string;
commonName: string;
subjectAlternativeName: string;
ttl: string;
};
}
@@ -697,6 +703,12 @@ interface UpdateCertificateTemplate {
type: EventType.UPDATE_CERTIFICATE_TEMPLATE;
metadata: {
certificateTemplateId: string;
caId: string;
pkiCollectionId?: string;
name: string;
commonName: string;
subjectAlternativeName: string;
ttl: string;
};
}

View File

@@ -15,9 +15,7 @@ export const useCreateCertTemplate = () => {
const queryClient = useQueryClient();
return useMutation<TCertificateTemplate, {}, TCreateCertificateTemplateDTO>({
mutationFn: async (data) => {
const {
data: { certificateTemplate }
} = await apiRequest.post<{ certificateTemplate: TCertificateTemplate }>(
const { data: certificateTemplate } = await apiRequest.post<TCertificateTemplate>(
"/api/v1/pki/certificate-templates",
data
);
@@ -33,9 +31,7 @@ export const useUpdateCertTemplate = () => {
const queryClient = useQueryClient();
return useMutation<TCertificateTemplate, {}, TUpdateCertificateTemplateDTO>({
mutationFn: async (data) => {
const {
data: { certificateTemplate }
} = await apiRequest.patch<{ certificateTemplate: TCertificateTemplate }>(
const { data: certificateTemplate } = await apiRequest.patch<TCertificateTemplate>(
`/api/v1/pki/certificate-templates/${data.id}`,
data
);

View File

@@ -12,9 +12,7 @@ export const useGetCertTemplate = (id: string) => {
return useQuery({
queryKey: certTemplateKeys.getCertTemplateById(id),
queryFn: async () => {
const {
data: { certificateTemplate }
} = await apiRequest.get<{ certificateTemplate: TCertificateTemplate }>(
const { data: certificateTemplate } = await apiRequest.get<TCertificateTemplate>(
`/api/v1/pki/certificate-templates/${id}`
);
return certificateTemplate;

View File

@@ -1,13 +1,8 @@
export type TCertificateTemplateListEntry = {
id: string;
name: string;
caName: string;
caId: string;
};
export type TCertificateTemplate = {
id: string;
caId: string;
caName: string;
projectId: string;
pkiCollectionId?: string;
name: string;
commonName: string;

View File

@@ -5,7 +5,7 @@ import { apiRequest } from "@app/config/request";
import { CaStatus } from "../ca/enums";
import { TCertificateAuthority } from "../ca/types";
import { TCertificate } from "../certificates/types";
import { TCertificateTemplateListEntry } from "../certificateTemplates/types";
import { TCertificateTemplate } from "../certificateTemplates/types";
import { TGroupMembership } from "../groups/types";
import { identitiesKeys } from "../identities/queries";
import { IdentityMembership } from "../identities/types";
@@ -649,7 +649,7 @@ export const useListWorkspaceCertificateTemplates = ({ workspaceId }: { workspac
queryFn: async () => {
const {
data: { certificateTemplates }
} = await apiRequest.get<{ certificateTemplates: TCertificateTemplateListEntry[] }>(
} = await apiRequest.get<{ certificateTemplates: TCertificateTemplate[] }>(
`/api/v2/workspace/${workspaceId}/certificate-templates`
);

View File

@@ -408,6 +408,19 @@ export const LogsTableRow = ({ auditLog }: Props) => {
);
case EventType.CREATE_CERTIFICATE_TEMPLATE:
case EventType.UPDATE_CERTIFICATE_TEMPLATE:
return (
<Td>
<p>{`Certificate Template ID: ${event.metadata.certificateTemplateId}`}</p>
<p>{`Certificate Authority ID: ${event.metadata.caId}`}</p>
<p>{`Name: ${event.metadata.name}`}</p>
<p>{`Common Name: ${event.metadata.commonName}`}</p>
<p>{`Subject Alternative Name: ${event.metadata.subjectAlternativeName}`}</p>
<p>{`TTL: ${event.metadata.ttl}`}</p>
{event.metadata.pkiCollectionId && (
<p>{`Collection ID: ${event.metadata.pkiCollectionId}`}</p>
)}
</Td>
);
case EventType.GET_CERTIFICATE_TEMPLATE:
case EventType.DELETE_CERTIFICATE_TEMPLATE:
return (