diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 8970b3152..d853f7412 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -1169,8 +1169,9 @@ export const CERTIFICATE_TEMPLATES = { commonName: "The regular expression string to use for validating common names", subjectAlternativeName: "The regular expression string to use for validating subject alternative names", ttl: "The max TTL for the template", - keyUsages: "The key usage constraint or default value", - extendedKeyUsages: "The extended key usage constraint or default value" + keyUsages: "The key usage constraint or default value for when template is used during certificate issuance", + extendedKeyUsages: + "The extended key usage constraint or default value for when template is used during certificate issuance" }, GET: { certificateTemplateId: "The ID of the certificate template to get" @@ -1183,8 +1184,10 @@ export const CERTIFICATE_TEMPLATES = { commonName: "The updated regular expression string for validating common names", subjectAlternativeName: "The updated regular expression string for validating subject alternative names", ttl: "The updated max TTL for the template", - keyUsages: "The updated key usage constraint or default value", - extendedKeyUsages: "The updated extended key usage constraint or default value" + keyUsages: + "The updated key usage constraint or default value for when template is used during certificate issuance", + extendedKeyUsages: + "The updated extended key usage constraint or default value for when template is used during certificate issuance" }, DELETE: { certificateTemplateId: "The ID of the certificate template to delete" diff --git a/docs/documentation/platform/pki/certificates.mdx b/docs/documentation/platform/pki/certificates.mdx index a4f1ba02c..4976b5e18 100644 --- a/docs/documentation/platform/pki/certificates.mdx +++ b/docs/documentation/platform/pki/certificates.mdx @@ -60,6 +60,8 @@ In the following steps, we explore how to issue a X.509 certificate under a CA. - Common Name (CN): A regular expression used to validate the common name in certificate requests. - Alternative Names (SANs): A regular expression used to validate subject alternative names in certificate requests. - TTL: The maximum Time-to-Live (TTL) for certificates issued using this template. + - Key Usage: The key usage constraint or default value for certificates issued using this template. + - Extended Key Usage: The extended key usage constraint or default value for certificates issued using this template. To create a certificate, head to your Project > Internal PKI > Certificates and press **Issue** under the Certificates section. @@ -76,13 +78,16 @@ In the following steps, we explore how to issue a X.509 certificate under a CA. - Common Name (CN): The (common) name for the certificate like `service.acme.com`. - Alternative Names (SANs): A comma-delimited list of Subject Alternative Names (SANs) for the certificate; these can be host names or email addresses like `app1.acme.com, app2.acme.com`. - TTL: The lifetime of the certificate in seconds. - + - Key Usage: The key usage extension of the certificate. + - Extended Key Usage: The extended key usage extension of the certificate. + Note that Infisical PKI supports issuing certificates without certificate templates as well. If this is desired, then you can set the **Certificate Template** field to **None** and specify the **Issuing CA** and optional **Certificate Collection** fields; the rest of the fields for the issued certificate remain the same. - + That said, we recommend using certificate templates to enforce policies and attach expiration monitoring on issued certificates. + Once you have created the certificate from step 1, you'll be presented with the certificate details including the **Certificate Body**, **Certificate Chain**, and **Private Key**. @@ -105,7 +110,7 @@ In the following steps, we explore how to issue a X.509 certificate under a CA. With certificate templates, you can specify, for example, that issued certificates must have a common name (CN) adhering to a specific format like .*.acme.com or perhaps that the max TTL cannot be more than 1 year. To create a certificate template, make an API request to the [Create Certificate Template](/api-reference/endpoints/certificate-templates/create) API endpoint, specifying the issuing CA. - + ### Sample request ```bash Request @@ -132,6 +137,7 @@ In the following steps, we explore how to issue a X.509 certificate under a CA. ttl: "...", } ``` + To create a certificate under the certificate template, make an API request to the [Issue Certificate](/api-reference/endpoints/certificates/issue-cert) API endpoint, @@ -164,7 +170,7 @@ In the following steps, we explore how to issue a X.509 certificate under a CA. Note that Infisical PKI supports issuing certificates without certificate templates as well. If this is desired, then you can set the **Certificate Template** field to **None** and specify the **Issuing CA** and optional **Certificate Collection** fields; the rest of the fields for the issued certificate remain the same. - + That said, we recommend using certificate templates to enforce policies and attach expiration monitoring on issued certificates. @@ -197,6 +203,7 @@ In the following steps, we explore how to issue a X.509 certificate under a CA. serialNumber: "..." } ``` + diff --git a/docs/images/platform/pki/certificate/cert-issue-modal.png b/docs/images/platform/pki/certificate/cert-issue-modal.png index f73462c8f..352c4979c 100644 Binary files a/docs/images/platform/pki/certificate/cert-issue-modal.png and b/docs/images/platform/pki/certificate/cert-issue-modal.png differ diff --git a/docs/images/platform/pki/certificate/cert-template-modal.png b/docs/images/platform/pki/certificate/cert-template-modal.png index f3995b6e4..2f6c88166 100644 Binary files a/docs/images/platform/pki/certificate/cert-template-modal.png and b/docs/images/platform/pki/certificate/cert-template-modal.png differ diff --git a/frontend/src/hooks/api/certificates/constants.tsx b/frontend/src/hooks/api/certificates/constants.tsx index 2f2972bbc..0384ea6cd 100644 --- a/frontend/src/hooks/api/certificates/constants.tsx +++ b/frontend/src/hooks/api/certificates/constants.tsx @@ -1,4 +1,10 @@ -import { CertKeyAlgorithm, CertStatus, CrlReason } from "./enums"; +import { + CertExtendedKeyUsage, + CertKeyAlgorithm, + CertKeyUsage, + CertStatus, + CrlReason +} from "./enums"; export const certStatusToNameMap: { [K in CertStatus]: string } = { [CertStatus.ACTIVE]: "Active", @@ -69,3 +75,24 @@ export const crlReasons = [ }, { label: crlReasonToNameMap[CrlReason.A_A_COMPROMISE], value: CrlReason.A_A_COMPROMISE } ]; + +export const KEY_USAGES_OPTIONS = [ + { value: CertKeyUsage.DIGITAL_SIGNATURE, label: "Digital Signature" }, + { value: CertKeyUsage.KEY_ENCIPHERMENT, label: "Key Encipherment" }, + { value: CertKeyUsage.NON_REPUDIATION, label: "Non Repudiation" }, + { value: CertKeyUsage.DATA_ENCIPHERMENT, label: "Data Encipherment" }, + { value: CertKeyUsage.KEY_AGREEMENT, label: "Key Agreement" }, + { value: CertKeyUsage.KEY_CERT_SIGN, label: "Certificate Sign" }, + { value: CertKeyUsage.CRL_SIGN, label: "CRL Sign" }, + { value: CertKeyUsage.ENCIPHER_ONLY, label: "Encipher Only" }, + { value: CertKeyUsage.DECIPHER_ONLY, label: "Decipher Only" } +] as const; + +export const EXTENDED_KEY_USAGES_OPTIONS = [ + { value: CertExtendedKeyUsage.CLIENT_AUTH, label: "Client Auth" }, + { value: CertExtendedKeyUsage.SERVER_AUTH, label: "Server Auth" }, + { value: CertExtendedKeyUsage.EMAIL_PROTECTION, label: "Email Protection" }, + { value: CertExtendedKeyUsage.OCSP_SIGNING, label: "OCSP Signing" }, + { value: CertExtendedKeyUsage.CODE_SIGNING, label: "Code Signing" }, + { value: CertExtendedKeyUsage.TIMESTAMPING, label: "Timestamping" } +] as const; diff --git a/frontend/src/hooks/api/certificates/enums.tsx b/frontend/src/hooks/api/certificates/enums.tsx index d0da0273a..566da7506 100644 --- a/frontend/src/hooks/api/certificates/enums.tsx +++ b/frontend/src/hooks/api/certificates/enums.tsx @@ -22,3 +22,24 @@ export enum CrlReason { PRIVILEGE_WITHDRAWN = "PRIVILEGE_WITHDRAWN", A_A_COMPROMISE = "A_A_COMPROMISE" } + +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 CertExtendedKeyUsage { + CLIENT_AUTH = "clientAuth", + SERVER_AUTH = "serverAuth", + CODE_SIGNING = "codeSigning", + EMAIL_PROTECTION = "emailProtection", + TIMESTAMPING = "timeStamping", + OCSP_SIGNING = "ocspSigning" +} diff --git a/frontend/src/hooks/api/certificates/types.ts b/frontend/src/hooks/api/certificates/types.ts index be341f675..a9bcf5fbc 100644 --- a/frontend/src/hooks/api/certificates/types.ts +++ b/frontend/src/hooks/api/certificates/types.ts @@ -1,4 +1,4 @@ -import { CertStatus } from "./enums"; +import { CertExtendedKeyUsage, CertKeyUsage, CertStatus } from "./enums"; export type TCertificate = { id: string; @@ -25,45 +25,3 @@ export type TRevokeCertDTO = { serialNumber: string; revocationReason: string; }; - -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 const KEY_USAGES_OPTIONS = [ - { value: CertKeyUsage.DIGITAL_SIGNATURE, label: "Digital Signature" }, - { value: CertKeyUsage.KEY_ENCIPHERMENT, label: "Key Encipherment" }, - { value: CertKeyUsage.NON_REPUDIATION, label: "Non Repudiation" }, - { value: CertKeyUsage.DATA_ENCIPHERMENT, label: "Data Encipherment" }, - { value: CertKeyUsage.KEY_AGREEMENT, label: "Key Agreement" }, - { value: CertKeyUsage.KEY_CERT_SIGN, label: "Certificate Sign" }, - { value: CertKeyUsage.CRL_SIGN, label: "CRL Sign" }, - { value: CertKeyUsage.ENCIPHER_ONLY, label: "Encipher Only" }, - { value: CertKeyUsage.DECIPHER_ONLY, label: "Decipher Only" } -] as const; - -export enum CertExtendedKeyUsage { - CLIENT_AUTH = "clientAuth", - SERVER_AUTH = "serverAuth", - CODE_SIGNING = "codeSigning", - EMAIL_PROTECTION = "emailProtection", - TIMESTAMPING = "timeStamping", - OCSP_SIGNING = "ocspSigning" -} - -export const EXTENDED_KEY_USAGES_OPTIONS = [ - { value: CertExtendedKeyUsage.CLIENT_AUTH, label: "Client Auth" }, - { value: CertExtendedKeyUsage.SERVER_AUTH, label: "Server Auth" }, - { value: CertExtendedKeyUsage.EMAIL_PROTECTION, label: "Email Protection" }, - { value: CertExtendedKeyUsage.OCSP_SIGNING, label: "OCSP Signing" }, - { value: CertExtendedKeyUsage.CODE_SIGNING, label: "Code Signing" }, - { value: CertExtendedKeyUsage.TIMESTAMPING, label: "Timestamping" } -] as const; diff --git a/frontend/src/views/Project/CertificatesPage/components/CertificatesTab/components/CertificateModal.tsx b/frontend/src/views/Project/CertificatesPage/components/CertificatesTab/components/CertificateModal.tsx index 10f8f7ea4..f14ed7aa2 100644 --- a/frontend/src/views/Project/CertificatesPage/components/CertificatesTab/components/CertificateModal.tsx +++ b/frontend/src/views/Project/CertificatesPage/components/CertificatesTab/components/CertificateModal.tsx @@ -34,11 +34,10 @@ import { } from "@app/hooks/api"; import { caTypeToNameMap } from "@app/hooks/api/ca/constants"; import { - CertExtendedKeyUsage, - CertKeyUsage, EXTENDED_KEY_USAGES_OPTIONS, KEY_USAGES_OPTIONS -} from "@app/hooks/api/certificates/types"; +} from "@app/hooks/api/certificates/constants"; +import { CertExtendedKeyUsage, CertKeyUsage } from "@app/hooks/api/certificates/enums"; import { UsePopUpState } from "@app/hooks/usePopUp"; import { CertificateContent } from "./CertificateContent"; @@ -428,7 +427,7 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { -
Key Usages
+
Key Usage
{ render={({ field: { onChange, value }, fieldState: { error } }) => { return ( @@ -472,7 +471,7 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { render={({ field: { onChange, value }, fieldState: { error } }) => { return ( diff --git a/frontend/src/views/Project/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx b/frontend/src/views/Project/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx index 3ead118bf..c7fba88b7 100644 --- a/frontend/src/views/Project/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx +++ b/frontend/src/views/Project/CertificatesPage/components/CertificatesTab/components/CertificateTemplateModal.tsx @@ -34,11 +34,10 @@ import { } from "@app/hooks/api"; import { caTypeToNameMap } from "@app/hooks/api/ca/constants"; import { - CertExtendedKeyUsage, - CertKeyUsage, EXTENDED_KEY_USAGES_OPTIONS, KEY_USAGES_OPTIONS -} from "@app/hooks/api/certificates/types"; +} from "@app/hooks/api/certificates/constants"; +import { CertExtendedKeyUsage, CertKeyUsage } from "@app/hooks/api/certificates/enums"; import { UsePopUpState } from "@app/hooks/usePopUp"; const validateTemplateRegexField = z @@ -395,7 +394,7 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro -
Key Usages
+
Key Usage
{ return ( @@ -438,7 +437,7 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro render={({ field: { onChange, value }, fieldState: { error } }) => { return (