mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-09 15:38:03 -05:00
Remove ACMESANType usage on redundant issuance param
This commit is contained in:
@@ -11,12 +11,7 @@ import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
|||||||
import { addNoCacheHeaders } from "@app/server/lib/caching";
|
import { addNoCacheHeaders } from "@app/server/lib/caching";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
import {
|
import { CertKeyAlgorithm, CertSignatureAlgorithm, CrlReason } from "@app/services/certificate/certificate-types";
|
||||||
ACMESANType,
|
|
||||||
CertKeyAlgorithm,
|
|
||||||
CertSignatureAlgorithm,
|
|
||||||
CrlReason
|
|
||||||
} from "@app/services/certificate/certificate-types";
|
|
||||||
import { CaType } from "@app/services/certificate-authority/certificate-authority-enums";
|
import { CaType } from "@app/services/certificate-authority/certificate-authority-enums";
|
||||||
import { validateCaDateField } from "@app/services/certificate-authority/certificate-authority-validators";
|
import { validateCaDateField } from "@app/services/certificate-authority/certificate-authority-validators";
|
||||||
import {
|
import {
|
||||||
@@ -129,18 +124,6 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => {
|
|||||||
.optional(),
|
.optional(),
|
||||||
signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm).optional(),
|
signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm).optional(),
|
||||||
keyAlgorithm: z.nativeEnum(CertKeyAlgorithm).optional(),
|
keyAlgorithm: z.nativeEnum(CertKeyAlgorithm).optional(),
|
||||||
subjectAlternativeNames: z
|
|
||||||
.array(
|
|
||||||
z.object({
|
|
||||||
type: z.nativeEnum(ACMESANType),
|
|
||||||
value: z
|
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.min(1, "SAN value cannot be empty")
|
|
||||||
.max(255, "SAN value must be less than 255 characters")
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.optional(),
|
|
||||||
ttl: z
|
ttl: z
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
@@ -199,19 +182,9 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => {
|
|||||||
useOrderFlow = caType !== CaType.INTERNAL;
|
useOrderFlow = caType !== CaType.INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes?.subjectAlternativeNames?.length || useOrderFlow) {
|
if (useOrderFlow) {
|
||||||
let acmeAltNames: Array<{ type: ACMESANType; value: string }> | undefined = attributes?.subjectAlternativeNames;
|
|
||||||
if (useOrderFlow && !attributes?.subjectAlternativeNames && attributes?.altNames?.length) {
|
|
||||||
acmeAltNames = attributes.altNames.map((alt: { type: CertSubjectAlternativeNameType; value: string }) => ({
|
|
||||||
type: (alt.type === CertSubjectAlternativeNameType.DNS_NAME
|
|
||||||
? ACMESANType.DNS
|
|
||||||
: ACMESANType.IP) as ACMESANType,
|
|
||||||
value: alt.value
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
const certificateOrderObject = {
|
const certificateOrderObject = {
|
||||||
altNames: acmeAltNames || [],
|
altNames: attributes?.altNames || [],
|
||||||
validity: { ttl: attributes?.ttl || "" },
|
validity: { ttl: attributes?.ttl || "" },
|
||||||
commonName: attributes?.commonName,
|
commonName: attributes?.commonName,
|
||||||
keyUsages: attributes?.keyUsages,
|
keyUsages: attributes?.keyUsages,
|
||||||
@@ -579,7 +552,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => {
|
|||||||
profileId: z.string().uuid(),
|
profileId: z.string().uuid(),
|
||||||
subjectAlternativeNames: z.array(
|
subjectAlternativeNames: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
type: z.nativeEnum(ACMESANType),
|
type: z.nativeEnum(CertSubjectAlternativeNameType),
|
||||||
value: z
|
value: z
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { ms } from "@app/lib/ms";
|
|||||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
import { ACMESANType, CertKeyAlgorithm, CertSignatureAlgorithm } from "@app/services/certificate/certificate-types";
|
import { CertKeyAlgorithm, CertSignatureAlgorithm } from "@app/services/certificate/certificate-types";
|
||||||
import { validateCaDateField } from "@app/services/certificate-authority/certificate-authority-validators";
|
import { validateCaDateField } from "@app/services/certificate-authority/certificate-authority-validators";
|
||||||
import {
|
import {
|
||||||
CertExtendedKeyUsageType,
|
CertExtendedKeyUsageType,
|
||||||
@@ -305,7 +305,7 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
|
|||||||
profileId: z.string().uuid(),
|
profileId: z.string().uuid(),
|
||||||
subjectAlternativeNames: z.array(
|
subjectAlternativeNames: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
type: z.nativeEnum(ACMESANType),
|
type: z.nativeEnum(CertSubjectAlternativeNameType),
|
||||||
value: z
|
value: z
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ export const certificateIssuanceQueueFactory = ({
|
|||||||
|
|
||||||
const [, generatedCsr] = await acme.crypto.createCsr(
|
const [, generatedCsr] = await acme.crypto.createCsr(
|
||||||
{
|
{
|
||||||
altNames: altNames || [],
|
altNames: altNames ? [...altNames] : [],
|
||||||
commonName: commonName || ""
|
commonName: commonName || ""
|
||||||
},
|
},
|
||||||
skLeaf
|
skLeaf
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { TPkiAcmeAccountDALFactory } from "@app/ee/services/pki-acme/pki-acme-ac
|
|||||||
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
|
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
|
||||||
import { TCertificateSecretDALFactory } from "@app/services/certificate/certificate-secret-dal";
|
import { TCertificateSecretDALFactory } from "@app/services/certificate/certificate-secret-dal";
|
||||||
import { ACMESANType, CertStatus } from "@app/services/certificate/certificate-types";
|
import { CertStatus } from "@app/services/certificate/certificate-types";
|
||||||
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||||
import { CaStatus } from "@app/services/certificate-authority/certificate-authority-enums";
|
import { CaStatus } from "@app/services/certificate-authority/certificate-authority-enums";
|
||||||
import { TInternalCertificateAuthorityServiceFactory } from "@app/services/certificate-authority/internal/internal-certificate-authority-service";
|
import { TInternalCertificateAuthorityServiceFactory } from "@app/services/certificate-authority/internal/internal-certificate-authority-service";
|
||||||
@@ -19,7 +19,8 @@ import {
|
|||||||
CertExtendedKeyUsageType,
|
CertExtendedKeyUsageType,
|
||||||
CertIncludeType,
|
CertIncludeType,
|
||||||
CertKeyUsageType,
|
CertKeyUsageType,
|
||||||
CertSubjectAttributeType
|
CertSubjectAttributeType,
|
||||||
|
CertSubjectAlternativeNameType
|
||||||
} from "@app/services/certificate-common/certificate-constants";
|
} from "@app/services/certificate-common/certificate-constants";
|
||||||
import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal";
|
import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal";
|
||||||
import { EnrollmentType, IssuerType } from "@app/services/certificate-profile/certificate-profile-types";
|
import { EnrollmentType, IssuerType } from "@app/services/certificate-profile/certificate-profile-types";
|
||||||
@@ -853,7 +854,7 @@ describe("CertificateV3Service", () => {
|
|||||||
|
|
||||||
describe("orderCertificateFromProfile", () => {
|
describe("orderCertificateFromProfile", () => {
|
||||||
const mockCertificateOrder = {
|
const mockCertificateOrder = {
|
||||||
altNames: [{ type: ACMESANType.DNS, value: "example.com" }],
|
altNames: [{ type: CertSubjectAlternativeNameType.DNS_NAME, value: "example.com" }],
|
||||||
validity: { ttl: "30d" },
|
validity: { ttl: "30d" },
|
||||||
commonName: "example.com",
|
commonName: "example.com",
|
||||||
keyUsages: [CertKeyUsageType.DIGITAL_SIGNATURE],
|
keyUsages: [CertKeyUsageType.DIGITAL_SIGNATURE],
|
||||||
|
|||||||
@@ -1054,7 +1054,7 @@ export const certificateV3ServiceFactory = ({
|
|||||||
tx
|
tx
|
||||||
});
|
});
|
||||||
|
|
||||||
const certificateRecord = await certificateDAL.findById(certResult.certificateId);
|
const certificateRecord = await certificateDAL.findById(certResult.certificateId, tx);
|
||||||
if (!certificateRecord) {
|
if (!certificateRecord) {
|
||||||
throw new NotFoundError({ message: "Certificate was issued but could not be found in database" });
|
throw new NotFoundError({ message: "Certificate was issued but could not be found in database" });
|
||||||
}
|
}
|
||||||
@@ -1307,25 +1307,7 @@ export const certificateV3ServiceFactory = ({
|
|||||||
commonName: certificateOrder.commonName,
|
commonName: certificateOrder.commonName,
|
||||||
keyUsages: certificateOrder.keyUsages,
|
keyUsages: certificateOrder.keyUsages,
|
||||||
extendedKeyUsages: certificateOrder.extendedKeyUsages,
|
extendedKeyUsages: certificateOrder.extendedKeyUsages,
|
||||||
subjectAlternativeNames: certificateOrder.altNames?.map((san) => {
|
subjectAlternativeNames: certificateOrder.altNames,
|
||||||
let certType: CertSubjectAlternativeNameType;
|
|
||||||
switch (san.type) {
|
|
||||||
case "dns":
|
|
||||||
certType = CertSubjectAlternativeNameType.DNS_NAME;
|
|
||||||
break;
|
|
||||||
case "ip":
|
|
||||||
certType = CertSubjectAlternativeNameType.IP_ADDRESS;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new BadRequestError({
|
|
||||||
message: `Unsupported Subject Alternative Name type: ${san.type as string}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
type: certType,
|
|
||||||
value: san.value
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
validity: certificateOrder.validity,
|
validity: certificateOrder.validity,
|
||||||
notBefore: certificateOrder.notBefore,
|
notBefore: certificateOrder.notBefore,
|
||||||
notAfter: certificateOrder.notAfter,
|
notAfter: certificateOrder.notAfter,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { TProjectPermission } from "@app/lib/types";
|
import { TProjectPermission } from "@app/lib/types";
|
||||||
|
|
||||||
import { ACMESANType } from "../certificate/certificate-types";
|
|
||||||
import {
|
import {
|
||||||
CertExtendedKeyUsageType,
|
CertExtendedKeyUsageType,
|
||||||
CertKeyUsageType,
|
CertKeyUsageType,
|
||||||
@@ -45,7 +44,7 @@ export type TOrderCertificateFromProfileDTO = {
|
|||||||
profileId: string;
|
profileId: string;
|
||||||
certificateOrder: {
|
certificateOrder: {
|
||||||
altNames: Array<{
|
altNames: Array<{
|
||||||
type: ACMESANType;
|
type: CertSubjectAlternativeNameType;
|
||||||
value: string;
|
value: string;
|
||||||
}>;
|
}>;
|
||||||
validity: {
|
validity: {
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ export {
|
|||||||
useRevokeCert,
|
useRevokeCert,
|
||||||
useUpdateRenewalConfig
|
useUpdateRenewalConfig
|
||||||
} from "./mutations";
|
} from "./mutations";
|
||||||
export { useGetCert, useGetCertBody, useGetCertificateRequest } from "./queries";
|
export { useGetCert, useGetCertBody } from "./queries";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useQuery } from "@tanstack/react-query";
|
|||||||
|
|
||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
|
||||||
import { TCertificate, TCertificateRequestDetails } from "./types";
|
import { TCertificate } from "./types";
|
||||||
|
|
||||||
export const certKeys = {
|
export const certKeys = {
|
||||||
getCertById: (serialNumber: string) => [{ serialNumber }, "cert"],
|
getCertById: (serialNumber: string) => [{ serialNumber }, "cert"],
|
||||||
@@ -59,23 +59,3 @@ export const useGetCertBundle = (serialNumber: string) => {
|
|||||||
enabled: Boolean(serialNumber)
|
enabled: Boolean(serialNumber)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetCertificateRequest = (requestId: string, projectSlug: string) => {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: certKeys.getCertificateRequest(requestId, projectSlug),
|
|
||||||
queryFn: async () => {
|
|
||||||
const { data } = await apiRequest.get<TCertificateRequestDetails>(
|
|
||||||
`/api/v3/pki/certificates/requests/${requestId}`,
|
|
||||||
{
|
|
||||||
params: { projectSlug }
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
enabled: Boolean(requestId) && Boolean(projectSlug),
|
|
||||||
refetchInterval: (query) => {
|
|
||||||
// Only refetch if status is pending
|
|
||||||
return query.state.data?.status === "pending" ? 5000 : false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
import { useEffect } from "react";
|
|
||||||
import { faCheck, faExclamationTriangle, faSpinner } from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
|
|
||||||
import { useProject } from "@app/context";
|
|
||||||
import { useGetCertificateRequest } from "@app/hooks/api/certificates";
|
|
||||||
|
|
||||||
type CertificateInfo = {
|
|
||||||
id: string;
|
|
||||||
serialNumber: string;
|
|
||||||
commonName: string;
|
|
||||||
notAfter: string;
|
|
||||||
[key: string]: unknown;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
requestId: string;
|
|
||||||
onCertificateIssued?: (certificate: CertificateInfo) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const CertificateRequestTracker = ({ requestId, onCertificateIssued }: Props) => {
|
|
||||||
const { currentProject } = useProject();
|
|
||||||
|
|
||||||
const { data: requestData, isLoading } = useGetCertificateRequest(
|
|
||||||
requestId,
|
|
||||||
currentProject?.slug || ""
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (requestData?.status === "issued" && requestData.certificate && onCertificateIssued) {
|
|
||||||
onCertificateIssued(requestData.certificate);
|
|
||||||
}
|
|
||||||
}, [requestData, onCertificateIssued]);
|
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<FontAwesomeIcon icon={faSpinner} className="animate-spin text-primary" />
|
|
||||||
<span className="text-sm text-mineshaft-400">Loading request status...</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getStatusIcon = () => {
|
|
||||||
switch (requestData?.status) {
|
|
||||||
case "pending":
|
|
||||||
return <FontAwesomeIcon icon={faSpinner} className="animate-spin text-yellow-500" />;
|
|
||||||
case "issued":
|
|
||||||
return <FontAwesomeIcon icon={faCheck} className="text-green-500" />;
|
|
||||||
case "failed":
|
|
||||||
return <FontAwesomeIcon icon={faExclamationTriangle} className="text-red-500" />;
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStatusMessage = () => {
|
|
||||||
switch (requestData?.status) {
|
|
||||||
case "pending":
|
|
||||||
return "Certificate request is being processed...";
|
|
||||||
case "issued":
|
|
||||||
return "Certificate has been issued successfully!";
|
|
||||||
case "failed":
|
|
||||||
return `Certificate request failed: ${requestData.errorMessage || "Unknown error"}`;
|
|
||||||
default:
|
|
||||||
return "Unknown status";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
{getStatusIcon()}
|
|
||||||
<span className="text-sm font-medium text-mineshaft-300">
|
|
||||||
Certificate Request ID: {requestId}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="text-sm text-mineshaft-400">
|
|
||||||
Status: <span className="font-medium capitalize">{requestData?.status || "Unknown"}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="text-sm text-mineshaft-400">{getStatusMessage()}</div>
|
|
||||||
|
|
||||||
{requestData?.status === "issued" && requestData.certificate && (
|
|
||||||
<div className="mt-4 rounded-md border border-green-500/30 bg-green-900/20 p-3">
|
|
||||||
<div className="text-sm text-green-400">
|
|
||||||
<strong>Certificate Details:</strong>
|
|
||||||
<br />
|
|
||||||
Serial Number: {requestData.certificate.serialNumber}
|
|
||||||
<br />
|
|
||||||
Common Name: {requestData.certificate.commonName}
|
|
||||||
<br />
|
|
||||||
Valid Until: {new Date(requestData.certificate.notAfter).toLocaleDateString()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{requestData?.status === "failed" && requestData.errorMessage && (
|
|
||||||
<div className="mt-4 rounded-md border border-red-500/30 bg-red-900/20 p-3">
|
|
||||||
<div className="text-sm text-red-400">
|
|
||||||
<strong>Error Details:</strong>
|
|
||||||
<br />
|
|
||||||
{requestData.errorMessage}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user