mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-11 14:28:56 +00:00
PKI UI improvements
This commit is contained in:
@@ -121,9 +121,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
|
||||
limit: z.coerce.number().min(1).max(100).default(20),
|
||||
search: z.string().optional(),
|
||||
enrollmentType: z.nativeEnum(EnrollmentType).optional(),
|
||||
caId: z.string().uuid().optional(),
|
||||
includeMetrics: z.coerce.boolean().optional().default(false),
|
||||
expiringDays: z.coerce.number().min(1).max(365).optional().default(7)
|
||||
caId: z.string().uuid().optional()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -195,10 +193,6 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
|
||||
params: z.object({
|
||||
id: z.string().uuid()
|
||||
}),
|
||||
querystring: z.object({
|
||||
includeMetrics: z.coerce.boolean().optional().default(false),
|
||||
expiringDays: z.coerce.number().min(1).max(365).optional().default(7)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
certificateProfile: PkiCertificateProfilesSchema.extend({
|
||||
@@ -232,16 +226,6 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
|
||||
autoRenew: z.boolean(),
|
||||
renewBeforeDays: z.number().optional()
|
||||
})
|
||||
.optional(),
|
||||
metrics: z
|
||||
.object({
|
||||
profileId: z.string(),
|
||||
totalCertificates: z.number(),
|
||||
activeCertificates: z.number(),
|
||||
expiredCertificates: z.number(),
|
||||
expiringCertificates: z.number(),
|
||||
revokedCertificates: z.number()
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
})
|
||||
@@ -257,20 +241,6 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
|
||||
profileId: req.params.id
|
||||
});
|
||||
|
||||
let result = certificateProfile;
|
||||
|
||||
if (req.query.includeMetrics) {
|
||||
const metrics = await server.services.certificateProfile.getProfileMetrics({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
profileId: req.params.id,
|
||||
expiringDays: req.query.expiringDays
|
||||
});
|
||||
result = { ...certificateProfile, metrics };
|
||||
}
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
projectId: certificateProfile.projectId,
|
||||
@@ -283,7 +253,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
|
||||
}
|
||||
});
|
||||
|
||||
return { certificateProfile: result };
|
||||
return { certificateProfile };
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ const PkiSyncCertificateSchema = z.object({
|
||||
updatedAt: z.date(),
|
||||
certificateSerialNumber: z.string().optional(),
|
||||
certificateCommonName: z.string().optional(),
|
||||
certificateAltNames: z.string().optional(),
|
||||
certificateStatus: z.string().optional(),
|
||||
certificateNotBefore: z.date().optional(),
|
||||
certificateNotAfter: z.date().optional(),
|
||||
|
||||
@@ -10,10 +10,8 @@ import {
|
||||
TCertificateProfile,
|
||||
TCertificateProfileCertificate,
|
||||
TCertificateProfileInsert,
|
||||
TCertificateProfileMetrics,
|
||||
TCertificateProfileUpdate,
|
||||
TCertificateProfileWithConfigs,
|
||||
TCertificateProfileWithRawMetrics
|
||||
TCertificateProfileWithConfigs
|
||||
} from "./certificate-profile-types";
|
||||
|
||||
export type TCertificateProfileDALFactory = ReturnType<typeof certificateProfileDALFactory>;
|
||||
@@ -203,21 +201,11 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
search?: string;
|
||||
enrollmentType?: EnrollmentType;
|
||||
caId?: string;
|
||||
includeMetrics?: boolean;
|
||||
expiringDays?: number;
|
||||
} = {},
|
||||
tx?: Knex
|
||||
): Promise<TCertificateProfile[] | TCertificateProfileWithRawMetrics[] | TCertificateProfileWithConfigs[]> => {
|
||||
): Promise<TCertificateProfile[] | TCertificateProfileWithConfigs[]> => {
|
||||
try {
|
||||
const {
|
||||
offset = 0,
|
||||
limit = 20,
|
||||
search,
|
||||
enrollmentType,
|
||||
caId,
|
||||
includeMetrics = false,
|
||||
expiringDays = 7
|
||||
} = options;
|
||||
const { offset = 0, limit = 20, search, enrollmentType, caId } = options;
|
||||
|
||||
let baseQuery = (tx || db)(TableName.PkiCertificateProfile).where(
|
||||
`${TableName.PkiCertificateProfile}.projectId`,
|
||||
@@ -242,7 +230,7 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
baseQuery = baseQuery.where(`${TableName.PkiCertificateProfile}.caId`, caId);
|
||||
}
|
||||
|
||||
let query = baseQuery
|
||||
const query = baseQuery
|
||||
.leftJoin(
|
||||
TableName.PkiEstEnrollmentConfig,
|
||||
`${TableName.PkiCertificateProfile}.estConfigId`,
|
||||
@@ -267,52 +255,6 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
db.ref("renewBeforeDays").withSchema(TableName.PkiApiEnrollmentConfig).as("apiRenewBeforeDays")
|
||||
);
|
||||
|
||||
if (includeMetrics) {
|
||||
query = query.leftJoin(
|
||||
TableName.Certificate,
|
||||
`${TableName.PkiCertificateProfile}.id`,
|
||||
`${TableName.Certificate}.profileId`
|
||||
);
|
||||
|
||||
const now = new Date();
|
||||
const expiringDate = new Date();
|
||||
expiringDate.setDate(now.getDate() + expiringDays);
|
||||
|
||||
query = query
|
||||
.select(
|
||||
selectAllTableCols(TableName.PkiCertificateProfile),
|
||||
db.ref("id").withSchema(TableName.PkiEstEnrollmentConfig).as("estId"),
|
||||
db
|
||||
.ref("disableBootstrapCaValidation")
|
||||
.withSchema(TableName.PkiEstEnrollmentConfig)
|
||||
.as("estDisableBootstrapCaValidation"),
|
||||
db.ref("hashedPassphrase").withSchema(TableName.PkiEstEnrollmentConfig).as("estHashedPassphrase"),
|
||||
db.ref("encryptedCaChain").withSchema(TableName.PkiEstEnrollmentConfig).as("estEncryptedCaChain"),
|
||||
db.ref("id").withSchema(TableName.PkiApiEnrollmentConfig).as("apiId"),
|
||||
db.ref("autoRenew").withSchema(TableName.PkiApiEnrollmentConfig).as("apiAutoRenew"),
|
||||
db.ref("renewBeforeDays").withSchema(TableName.PkiApiEnrollmentConfig).as("apiRenewBeforeDays"),
|
||||
db.raw("COUNT(certificates.id) as total_certificates"),
|
||||
db.raw(
|
||||
'COUNT(CASE WHEN certificates."revokedAt" IS NULL AND certificates."notAfter" > ? THEN 1 END) as active_certificates',
|
||||
[expiringDate]
|
||||
),
|
||||
db.raw(
|
||||
'COUNT(CASE WHEN certificates."revokedAt" IS NULL AND certificates."notAfter" <= ? THEN 1 END) as expired_certificates',
|
||||
[now]
|
||||
),
|
||||
db.raw(
|
||||
'COUNT(CASE WHEN certificates."revokedAt" IS NULL AND certificates."notAfter" > ? AND certificates."notAfter" <= ? THEN 1 END) as expiring_certificates',
|
||||
[now, expiringDate]
|
||||
),
|
||||
db.raw('COUNT(CASE WHEN certificates."revokedAt" IS NOT NULL THEN 1 END) as revoked_certificates')
|
||||
)
|
||||
.groupBy(
|
||||
`${TableName.PkiCertificateProfile}.id`,
|
||||
`${TableName.PkiEstEnrollmentConfig}.id`,
|
||||
`${TableName.PkiApiEnrollmentConfig}.id`
|
||||
);
|
||||
}
|
||||
|
||||
const results = (await query
|
||||
.orderBy(`${TableName.PkiCertificateProfile}.createdAt`, "desc")
|
||||
.offset(offset)
|
||||
@@ -353,17 +295,6 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
apiConfig
|
||||
};
|
||||
|
||||
if (includeMetrics) {
|
||||
return {
|
||||
...baseProfile,
|
||||
total_certificates: result.total_certificates,
|
||||
active_certificates: result.active_certificates,
|
||||
expired_certificates: result.expired_certificates,
|
||||
expiring_certificates: result.expiring_certificates,
|
||||
revoked_certificates: result.revoked_certificates
|
||||
} as TCertificateProfileWithRawMetrics & TCertificateProfileWithConfigs;
|
||||
}
|
||||
|
||||
return baseProfile as TCertificateProfileWithConfigs;
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -485,45 +416,6 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getProfileMetrics = async (
|
||||
profileId: string,
|
||||
expiringDays: number = 7,
|
||||
tx?: Knex
|
||||
): Promise<TCertificateProfileMetrics> => {
|
||||
try {
|
||||
const now = new Date();
|
||||
const expiringDate = new Date();
|
||||
expiringDate.setDate(now.getDate() + expiringDays);
|
||||
|
||||
const metrics = await (tx || db)(TableName.Certificate)
|
||||
.where("profileId", profileId)
|
||||
.select(
|
||||
db.raw("COUNT(*) as total_certificates"),
|
||||
db.raw('COUNT(CASE WHEN "revokedAt" IS NULL AND "notAfter" > ? THEN 1 END) as active_certificates', [
|
||||
expiringDate
|
||||
]),
|
||||
db.raw('COUNT(CASE WHEN "revokedAt" IS NULL AND "notAfter" <= ? THEN 1 END) as expired_certificates', [now]),
|
||||
db.raw(
|
||||
'COUNT(CASE WHEN "revokedAt" IS NULL AND "notAfter" > ? AND "notAfter" <= ? THEN 1 END) as expiring_certificates',
|
||||
[now, expiringDate]
|
||||
),
|
||||
db.raw('COUNT(CASE WHEN "revokedAt" IS NOT NULL THEN 1 END) as revoked_certificates')
|
||||
)
|
||||
.first();
|
||||
|
||||
return {
|
||||
profileId,
|
||||
totalCertificates: parseInt(String((metrics as Record<string, unknown>)?.total_certificates || 0), 10),
|
||||
activeCertificates: parseInt(String((metrics as Record<string, unknown>)?.active_certificates || 0), 10),
|
||||
expiredCertificates: parseInt(String((metrics as Record<string, unknown>)?.expired_certificates || 0), 10),
|
||||
expiringCertificates: parseInt(String((metrics as Record<string, unknown>)?.expiring_certificates || 0), 10),
|
||||
revokedCertificates: parseInt(String((metrics as Record<string, unknown>)?.revoked_certificates || 0), 10)
|
||||
};
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "Get certificate profile metrics" });
|
||||
}
|
||||
};
|
||||
|
||||
const isProfileInUse = async (profileId: string, tx?: Knex) => {
|
||||
try {
|
||||
const doc = await (tx || db)(TableName.Certificate).where("profileId", profileId).count("*").first();
|
||||
@@ -546,7 +438,6 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
||||
countByProjectId,
|
||||
findByNameAndProjectId,
|
||||
getCertificatesByProfile,
|
||||
getProfileMetrics,
|
||||
isProfileInUse
|
||||
};
|
||||
};
|
||||
|
||||
@@ -127,8 +127,3 @@ export const listCertificatesByProfileSchema = z.object({
|
||||
status: z.enum(["active", "expired", "revoked"]).optional(),
|
||||
search: z.string().optional()
|
||||
});
|
||||
|
||||
export const getCertificateProfileMetricsSchema = z.object({
|
||||
profileId: z.string().uuid(),
|
||||
expiringDays: z.coerce.number().min(1).max(365).default(30)
|
||||
});
|
||||
|
||||
@@ -47,7 +47,6 @@ describe("CertificateProfileService", () => {
|
||||
findByNameAndProjectId: vi.fn(),
|
||||
findByIdWithConfigs: vi.fn(),
|
||||
getCertificatesByProfile: vi.fn(),
|
||||
getProfileMetrics: vi.fn(),
|
||||
isProfileInUse: vi.fn(),
|
||||
transaction: vi.fn(),
|
||||
find: vi.fn(),
|
||||
@@ -493,9 +492,7 @@ describe("CertificateProfileService", () => {
|
||||
limit: 20,
|
||||
search: undefined,
|
||||
enrollmentType: undefined,
|
||||
caId: undefined,
|
||||
includeMetrics: false,
|
||||
expiringDays: 30
|
||||
caId: undefined
|
||||
});
|
||||
});
|
||||
|
||||
@@ -515,51 +512,7 @@ describe("CertificateProfileService", () => {
|
||||
limit: 5,
|
||||
search: "test",
|
||||
enrollmentType: EnrollmentType.API,
|
||||
caId: "ca-123",
|
||||
includeMetrics: false,
|
||||
expiringDays: 30
|
||||
});
|
||||
});
|
||||
|
||||
it("should list profiles with metrics when includeMetrics is true", async () => {
|
||||
const mockProfilesWithMetrics = [
|
||||
{
|
||||
...sampleProfile,
|
||||
total_certificates: 10,
|
||||
active_certificates: 8,
|
||||
expired_certificates: 1,
|
||||
expiring_certificates: 1,
|
||||
revoked_certificates: 0
|
||||
}
|
||||
];
|
||||
(mockCertificateProfileDAL.findByProjectId as any).mockResolvedValue(mockProfilesWithMetrics);
|
||||
|
||||
const result = await service.listProfiles({
|
||||
...mockActor,
|
||||
projectId: "project-123",
|
||||
includeMetrics: true,
|
||||
expiringDays: 15
|
||||
});
|
||||
|
||||
expect(result.profiles).toHaveLength(1);
|
||||
expect(result.profiles[0]).toHaveProperty("metrics");
|
||||
expect(result.profiles[0].metrics).toEqual({
|
||||
profileId: sampleProfile.id,
|
||||
totalCertificates: 10,
|
||||
activeCertificates: 8,
|
||||
expiredCertificates: 1,
|
||||
expiringCertificates: 1,
|
||||
revokedCertificates: 0
|
||||
});
|
||||
|
||||
expect(mockCertificateProfileDAL.findByProjectId).toHaveBeenCalledWith("project-123", {
|
||||
offset: 0,
|
||||
limit: 20,
|
||||
search: undefined,
|
||||
enrollmentType: undefined,
|
||||
caId: undefined,
|
||||
includeMetrics: true,
|
||||
expiringDays: 15
|
||||
caId: "ca-123"
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -659,54 +612,6 @@ describe("CertificateProfileService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("getProfileMetrics", () => {
|
||||
const mockMetrics = {
|
||||
profileId: "profile-123",
|
||||
totalCertificates: 10,
|
||||
activeCertificates: 8,
|
||||
expiredCertificates: 1,
|
||||
expiringCertificates: 2,
|
||||
revokedCertificates: 1
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
(mockCertificateProfileDAL.findById as any).mockResolvedValue(sampleProfile);
|
||||
(mockCertificateProfileDAL.getProfileMetrics as any).mockResolvedValue(mockMetrics);
|
||||
});
|
||||
|
||||
it("should get profile metrics successfully", async () => {
|
||||
const result = await service.getProfileMetrics({
|
||||
...mockActor,
|
||||
profileId: "profile-123"
|
||||
});
|
||||
|
||||
expect(result).toEqual(mockMetrics);
|
||||
expect(mockCertificateProfileDAL.findById).toHaveBeenCalledWith("profile-123");
|
||||
expect(mockCertificateProfileDAL.getProfileMetrics).toHaveBeenCalledWith("profile-123", 30);
|
||||
});
|
||||
|
||||
it("should get profile metrics with custom expiring days", async () => {
|
||||
await service.getProfileMetrics({
|
||||
...mockActor,
|
||||
profileId: "profile-123",
|
||||
expiringDays: 60
|
||||
});
|
||||
|
||||
expect(mockCertificateProfileDAL.getProfileMetrics).toHaveBeenCalledWith("profile-123", 60);
|
||||
});
|
||||
|
||||
it("should throw NotFoundError when profile not found", async () => {
|
||||
(mockCertificateProfileDAL.findById as any).mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
service.getProfileMetrics({
|
||||
...mockActor,
|
||||
profileId: "profile-123"
|
||||
})
|
||||
).rejects.toThrow(NotFoundError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("comprehensive certificate profile scenarios", () => {
|
||||
describe("profile configuration validation", () => {
|
||||
it("should validate EST enrollment configuration", async () => {
|
||||
@@ -929,53 +834,6 @@ describe("CertificateProfileService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("metrics and monitoring", () => {
|
||||
it("should calculate profile metrics correctly", async () => {
|
||||
const detailedMetrics = {
|
||||
profileId: "profile-123",
|
||||
totalCertificates: 50,
|
||||
activeCertificates: 40,
|
||||
expiredCertificates: 5,
|
||||
expiringCertificates: 3,
|
||||
revokedCertificates: 2
|
||||
};
|
||||
|
||||
(mockCertificateProfileDAL.findById as any).mockResolvedValue(sampleProfile);
|
||||
(mockCertificateProfileDAL.getProfileMetrics as any).mockResolvedValue(detailedMetrics);
|
||||
|
||||
const result = await service.getProfileMetrics({
|
||||
...mockActor,
|
||||
profileId: "profile-123",
|
||||
expiringDays: 14
|
||||
});
|
||||
|
||||
expect(result).toEqual(detailedMetrics);
|
||||
expect(mockCertificateProfileDAL.getProfileMetrics).toHaveBeenCalledWith("profile-123", 14);
|
||||
});
|
||||
|
||||
it("should handle zero certificate metrics", async () => {
|
||||
const emptyMetrics = {
|
||||
profileId: "profile-123",
|
||||
totalCertificates: 0,
|
||||
activeCertificates: 0,
|
||||
expiredCertificates: 0,
|
||||
expiringCertificates: 0,
|
||||
revokedCertificates: 0
|
||||
};
|
||||
|
||||
(mockCertificateProfileDAL.findById as any).mockResolvedValue(sampleProfile);
|
||||
(mockCertificateProfileDAL.getProfileMetrics as any).mockResolvedValue(emptyMetrics);
|
||||
|
||||
const result = await service.getProfileMetrics({
|
||||
...mockActor,
|
||||
profileId: "profile-123"
|
||||
});
|
||||
|
||||
expect(result.totalCertificates).toBe(0);
|
||||
expect(result.activeCertificates).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("error scenarios", () => {
|
||||
it("should handle database connection errors gracefully", async () => {
|
||||
(mockCertificateProfileDAL.findById as any).mockRejectedValue(new Error("Database connection failed"));
|
||||
|
||||
@@ -27,10 +27,8 @@ import {
|
||||
TCertificateProfile,
|
||||
TCertificateProfileCertificate,
|
||||
TCertificateProfileInsert,
|
||||
TCertificateProfileMetrics,
|
||||
TCertificateProfileUpdate,
|
||||
TCertificateProfileWithConfigs,
|
||||
TCertificateProfileWithRawMetrics
|
||||
TCertificateProfileWithConfigs
|
||||
} from "./certificate-profile-types";
|
||||
|
||||
const validateAndEncryptPemCaChain = async (
|
||||
@@ -361,18 +359,14 @@ export const certificateProfileServiceFactory = ({
|
||||
actorId,
|
||||
actorAuthMethod,
|
||||
actorOrgId,
|
||||
profileId,
|
||||
includeMetrics = false,
|
||||
expiringDays = 30
|
||||
profileId
|
||||
}: {
|
||||
actor: ActorType;
|
||||
actorId: string;
|
||||
actorAuthMethod: ActorAuthMethod;
|
||||
actorOrgId: string;
|
||||
profileId: string;
|
||||
includeMetrics?: boolean;
|
||||
expiringDays?: number;
|
||||
}): Promise<TCertificateProfile & { metrics?: TCertificateProfileMetrics }> => {
|
||||
}): Promise<TCertificateProfile> => {
|
||||
const profile = await certificateProfileDAL.findById(profileId);
|
||||
if (!profile) {
|
||||
throw new NotFoundError({ message: "Certificate profile not found" });
|
||||
@@ -393,14 +387,6 @@ export const certificateProfileServiceFactory = ({
|
||||
|
||||
const converted = convertDalToService(profile);
|
||||
|
||||
if (includeMetrics) {
|
||||
const metrics = await certificateProfileDAL.getProfileMetrics(profileId, expiringDays);
|
||||
return {
|
||||
...converted,
|
||||
metrics
|
||||
};
|
||||
}
|
||||
|
||||
return converted;
|
||||
};
|
||||
|
||||
@@ -506,9 +492,7 @@ export const certificateProfileServiceFactory = ({
|
||||
limit = 20,
|
||||
search,
|
||||
enrollmentType,
|
||||
caId,
|
||||
includeMetrics = false,
|
||||
expiringDays = 30
|
||||
caId
|
||||
}: {
|
||||
actor: ActorType;
|
||||
actorId: string;
|
||||
@@ -520,10 +504,8 @@ export const certificateProfileServiceFactory = ({
|
||||
search?: string;
|
||||
enrollmentType?: EnrollmentType;
|
||||
caId?: string;
|
||||
includeMetrics?: boolean;
|
||||
expiringDays?: number;
|
||||
}): Promise<{
|
||||
profiles: (TCertificateProfileWithConfigs & { metrics?: TCertificateProfileMetrics })[];
|
||||
profiles: TCertificateProfileWithConfigs[];
|
||||
totalCount: number;
|
||||
}> => {
|
||||
const { permission } = await permissionService.getProjectPermission({
|
||||
@@ -544,9 +526,7 @@ export const certificateProfileServiceFactory = ({
|
||||
limit,
|
||||
search,
|
||||
enrollmentType,
|
||||
caId,
|
||||
includeMetrics,
|
||||
expiringDays
|
||||
caId
|
||||
});
|
||||
|
||||
const totalCount = await certificateProfileDAL.countByProjectId(projectId, {
|
||||
@@ -591,27 +571,12 @@ export const certificateProfileServiceFactory = ({
|
||||
}
|
||||
|
||||
const converted = convertDalToService(profileWithConfigs);
|
||||
let result: TCertificateProfileWithConfigs & { metrics?: TCertificateProfileMetrics } = {
|
||||
const result: TCertificateProfileWithConfigs = {
|
||||
...converted,
|
||||
estConfig: decryptedEstConfig,
|
||||
apiConfig: profileWithConfigs.apiConfig
|
||||
};
|
||||
|
||||
if (includeMetrics) {
|
||||
const profileWithMetrics = profile as TCertificateProfileWithRawMetrics;
|
||||
result = {
|
||||
...result,
|
||||
metrics: {
|
||||
profileId: converted.id,
|
||||
totalCertificates: parseInt(String(profileWithMetrics.total_certificates || 0), 10),
|
||||
activeCertificates: parseInt(String(profileWithMetrics.active_certificates || 0), 10),
|
||||
expiredCertificates: parseInt(String(profileWithMetrics.expired_certificates || 0), 10),
|
||||
expiringCertificates: parseInt(String(profileWithMetrics.expiring_certificates || 0), 10),
|
||||
revokedCertificates: parseInt(String(profileWithMetrics.revoked_certificates || 0), 10)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
})
|
||||
);
|
||||
@@ -709,43 +674,6 @@ export const certificateProfileServiceFactory = ({
|
||||
return certificates;
|
||||
};
|
||||
|
||||
const getProfileMetrics = async ({
|
||||
actor,
|
||||
actorId,
|
||||
actorAuthMethod,
|
||||
actorOrgId,
|
||||
profileId,
|
||||
expiringDays = 30
|
||||
}: {
|
||||
actor: ActorType;
|
||||
actorId: string;
|
||||
actorAuthMethod: ActorAuthMethod;
|
||||
actorOrgId: string;
|
||||
profileId: string;
|
||||
expiringDays?: number;
|
||||
}): Promise<TCertificateProfileMetrics> => {
|
||||
const profile = await certificateProfileDAL.findById(profileId);
|
||||
if (!profile) {
|
||||
throw new NotFoundError({ message: "Certificate profile not found" });
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission({
|
||||
actor,
|
||||
actorId,
|
||||
projectId: profile.projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId,
|
||||
actionProjectType: ActionProjectType.CertificateManager
|
||||
});
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionCertificateProfileActions.Read,
|
||||
ProjectPermissionSub.CertificateProfiles
|
||||
);
|
||||
|
||||
const metrics = await certificateProfileDAL.getProfileMetrics(profileId, expiringDays);
|
||||
return metrics;
|
||||
};
|
||||
|
||||
const getEstConfigurationByProfile = async (
|
||||
params:
|
||||
| {
|
||||
@@ -818,7 +746,6 @@ export const certificateProfileServiceFactory = ({
|
||||
listProfiles,
|
||||
deleteProfile,
|
||||
getProfileCertificates,
|
||||
getProfileMetrics,
|
||||
getEstConfigurationByProfile
|
||||
};
|
||||
};
|
||||
|
||||
@@ -54,18 +54,8 @@ export type TCertificateProfileWithConfigs = TCertificateProfile & {
|
||||
autoRenew: boolean;
|
||||
renewBeforeDays?: number;
|
||||
};
|
||||
metrics?: TCertificateProfileMetrics;
|
||||
};
|
||||
|
||||
export interface TCertificateProfileMetrics {
|
||||
profileId: string;
|
||||
totalCertificates: number;
|
||||
activeCertificates: number;
|
||||
expiredCertificates: number;
|
||||
expiringCertificates: number;
|
||||
revokedCertificates: number;
|
||||
}
|
||||
|
||||
export interface TCertificateProfileCertificate {
|
||||
id: string;
|
||||
serialNumber: string;
|
||||
@@ -76,11 +66,3 @@ export interface TCertificateProfileCertificate {
|
||||
revokedAt: Date | null;
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
export type TCertificateProfileWithRawMetrics = TCertificateProfile & {
|
||||
total_certificates?: string;
|
||||
active_certificates?: string;
|
||||
expired_certificates?: string;
|
||||
expiring_certificates?: string;
|
||||
revoked_certificates?: string;
|
||||
};
|
||||
|
||||
@@ -180,6 +180,7 @@ export const certificateSyncDALFactory = (db: TDbClient) => {
|
||||
certificateDetails: (TCertificateSyncs & {
|
||||
certificateSerialNumber?: string;
|
||||
certificateCommonName?: string;
|
||||
certificateAltNames?: string;
|
||||
certificateStatus?: string;
|
||||
certificateNotBefore?: Date;
|
||||
certificateNotAfter?: Date;
|
||||
@@ -211,6 +212,7 @@ export const certificateSyncDALFactory = (db: TDbClient) => {
|
||||
.select(
|
||||
db.ref("serialNumber").withSchema(TableName.Certificate).as("certificateSerialNumber"),
|
||||
db.ref("commonName").withSchema(TableName.Certificate).as("certificateCommonName"),
|
||||
db.ref("altNames").withSchema(TableName.Certificate).as("certificateAltNames"),
|
||||
db.ref("status").withSchema(TableName.Certificate).as("certificateStatus"),
|
||||
db.ref("notBefore").withSchema(TableName.Certificate).as("certificateNotBefore"),
|
||||
db.ref("notAfter").withSchema(TableName.Certificate).as("certificateNotAfter"),
|
||||
@@ -229,6 +231,7 @@ export const certificateSyncDALFactory = (db: TDbClient) => {
|
||||
const certificateDetails = (await query) as (TCertificateSyncs & {
|
||||
certificateSerialNumber?: string;
|
||||
certificateCommonName?: string;
|
||||
certificateAltNames?: string;
|
||||
certificateStatus?: string;
|
||||
certificateNotBefore?: Date;
|
||||
certificateNotAfter?: Date;
|
||||
|
||||
+1
-1
@@ -520,7 +520,7 @@ export const awsCertificateManagerPkiSyncFactory = ({
|
||||
try {
|
||||
// Small delay to ensure AWS ACM has processed the certificate import
|
||||
await new Promise<void>((resolve) => {
|
||||
setTimeout(() => resolve(), 100);
|
||||
setTimeout(() => resolve(), 500);
|
||||
});
|
||||
|
||||
await withRateLimitRetry(
|
||||
|
||||
@@ -606,6 +606,7 @@ export const pkiSyncServiceFactory = ({
|
||||
updatedAt: detail.updatedAt,
|
||||
certificateSerialNumber: detail.certificateSerialNumber || undefined,
|
||||
certificateCommonName: detail.certificateCommonName || undefined,
|
||||
certificateAltNames: detail.certificateAltNames || undefined,
|
||||
certificateStatus: detail.certificateStatus || undefined,
|
||||
certificateNotBefore: detail.certificateNotBefore || undefined,
|
||||
certificateNotAfter: detail.certificateNotAfter || undefined,
|
||||
|
||||
@@ -170,13 +170,14 @@ export type TPkiSyncCertificate = {
|
||||
lastSyncedAt?: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
certificate?: {
|
||||
serialNumber: string;
|
||||
commonName: string;
|
||||
status: string;
|
||||
notBefore: Date;
|
||||
notAfter: Date;
|
||||
};
|
||||
certificateSerialNumber?: string;
|
||||
certificateCommonName?: string;
|
||||
certificateAltNames?: string;
|
||||
certificateStatus?: string;
|
||||
certificateNotBefore?: Date;
|
||||
certificateNotAfter?: Date;
|
||||
pkiSyncName?: string;
|
||||
pkiSyncDestination?: string;
|
||||
};
|
||||
|
||||
export type TPkiSyncRaw = NonNullable<Awaited<ReturnType<TPkiSyncDALFactory["findById"]>>>;
|
||||
|
||||
Reference in New Issue
Block a user