misc: improved docs and added support for curl clients

This commit is contained in:
Sheen Capadngan
2024-08-27 02:05:35 +08:00
parent 00f86cfd00
commit 0809da33e0
6 changed files with 27 additions and 18 deletions
@@ -11,7 +11,15 @@ export const registerCertificateEstRouter = async (server: FastifyZodProvider) =
// add support for CSR bodies // add support for CSR bodies
server.addContentTypeParser("application/pkcs10", { parseAs: "string" }, (_, body, done) => { server.addContentTypeParser("application/pkcs10", { parseAs: "string" }, (_, body, done) => {
try { try {
done(null, (body as string).replace(/\n/g, "").replace(/ /g, "")); let csrBody = body as string;
// some EST clients send CSRs in PEM format and some in base64 format
// for CSRs sent in PEM, we leave them as is
// for CSRs sent in base64, we preprocess them to remove new lines and spaces
if (!csrBody.includes("BEGIN CERTIFICATE REQUEST")) {
csrBody = csrBody.replace(/\n/g, "").replace(/ /g, "");
}
done(null, csrBody);
} catch (err) { } catch (err) {
const error = err as Error; const error = err as Error;
done(error, undefined); done(error, undefined);
@@ -16,7 +16,9 @@ export const convertRawCertsToPkcs7 = (rawCertificate: ArrayBuffer[]) => {
}); });
const derBuffer = cmsContent.toSchema().toBER(false); const derBuffer = cmsContent.toSchema().toBER(false);
const base64Pkcs7 = Buffer.from(derBuffer).toString("base64"); const base64Pkcs7 = Buffer.from(derBuffer)
.toString("base64")
.replace(/(.{64})/g, "$1\n"); // we add a linebreak for CURL clients
return base64Pkcs7; return base64Pkcs7;
}; };
@@ -158,7 +158,9 @@ export const certificateEstServiceFactory = ({
return new x509.X509Certificate(cert); return new x509.X509Certificate(cert);
}); });
if (!caCerts) throw new BadRequestError({ message: "Failed to parse certificate chain" }); if (!caCerts) {
throw new BadRequestError({ message: "Failed to parse certificate chain" });
}
const leafCertificate = decodeURIComponent(sslClientCert).match( const leafCertificate = decodeURIComponent(sslClientCert).match(
/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g /-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g
@@ -213,14 +215,11 @@ export const certificateEstServiceFactory = ({
.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g) .match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g)
?.map((cert) => new x509.X509Certificate(cert)); ?.map((cert) => new x509.X509Certificate(cert));
if (!certificates) throw new BadRequestError({ message: "Failed to parse certificate chain" }); if (!certificates) {
throw new BadRequestError({ message: "Failed to parse certificate chain" });
const caCertificate = new x509.X509Certificate(caCert);
if (!(await isCertChainValid([caCertificate, ...certificates]))) {
throw new BadRequestError({ message: "Invalid certificate chain" });
} }
const caCertificate = new x509.X509Certificate(caCert);
return convertRawCertsToPkcs7([caCertificate.rawData, ...certificates.map((cert) => cert.rawData)]); return convertRawCertsToPkcs7([caCertificate.rawData, ...certificates.map((cert) => cert.rawData)]);
}; };
@@ -30,11 +30,6 @@ export const isCertChainValid = async (certificates: x509.X509Certificate[]) =>
return true; return true;
} }
// check for self-signed
if (certificates.length === 2 && certificates[0].equal(certificates[1])) {
return true;
}
const leafCert = certificates[0]; const leafCert = certificates[0];
const chain = new x509.X509ChainBuilder({ const chain = new x509.X509ChainBuilder({
certificates: certificates.slice(1) certificates: certificates.slice(1)
+9 -1
View File
@@ -37,7 +37,7 @@ These endpoints are exposed on port 8443 under the .well-known/est path e.g.
- **Certificate Authority Chain** - This is the certificate chain used to validate your devices' manufacturing/pre-installed certificates. This will be used to authenticate your devices with Infisical's EST server. - **Certificate Authority Chain** - This is the certificate chain used to validate your devices' manufacturing/pre-installed certificates. This will be used to authenticate your devices with Infisical's EST server.
- **Passphrase** - This is also used to authenticate your devices with Infisical's EST server. When configuring the clients, use the value defined here as the EST password. - **Passphrase** - This is also used to authenticate your devices with Infisical's EST server. When configuring the clients, use the value defined here as the EST password.
For security reasons, Infisical authenticates EST clients using both client certificate authentication (against the configured certificate authority chain) and passphrase authentication. For security reasons, Infisical authenticates EST clients using both client certificate and passphrase.
4. Once the configuration of enrollment options is completed, a new **EST Label** field appears in the enrollment settings. This is the value to use as label in the URL when configuring the connection of EST clients to Infisical. 4. Once the configuration of enrollment options is completed, a new **EST Label** field appears in the enrollment settings. This is the value to use as label in the URL when configuring the connection of EST clients to Infisical.
![est enrollment modal create](/images/platform/pki/est/template-enrollment-est-label.png) ![est enrollment modal create](/images/platform/pki/est/template-enrollment-est-label.png)
@@ -47,3 +47,11 @@ These endpoints are exposed on port 8443 under the .well-known/est path e.g.
- https://app.infisical.com:8443/.well-known/est/f110f308-9888-40ab-b228-237b12de8b96/cacerts - https://app.infisical.com:8443/.well-known/est/f110f308-9888-40ab-b228-237b12de8b96/cacerts
- https://app.infisical.com:8443/.well-known/est/f110f308-9888-40ab-b228-237b12de8b96/simpleenroll - https://app.infisical.com:8443/.well-known/est/f110f308-9888-40ab-b228-237b12de8b96/simpleenroll
- https://app.infisical.com:8443/.well-known/est/f110f308-9888-40ab-b228-237b12de8b96/simplereenroll - https://app.infisical.com:8443/.well-known/est/f110f308-9888-40ab-b228-237b12de8b96/simplereenroll
## Setting up EST clients
- To use the EST passphrase in your clients, configure it as the EST password. The EST username can be set to any arbitrary value.
- Use the appropriate client certificates for invoking the EST endpoints.
- For `simpleenroll`, use the bootstrapped/manufacturer client certificate.
- For `simplereenroll`, use a valid EST-issued client certificate.
- When configuring the PKCS#12 objects for the client certificates, only include the leaf certificate and the private key.
@@ -3,8 +3,6 @@ import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import z from "zod"; import z from "zod";
// import { faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
// import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { import {
Button, Button,
@@ -180,7 +178,6 @@ export const CertificateTemplateEnrollmentModal = ({ popUp, handlePopUpToggle }:
type={isPassphraseFocused ? "text" : "password"} type={isPassphraseFocused ? "text" : "password"}
onFocus={() => setIsPassphraseFocused.on()} onFocus={() => setIsPassphraseFocused.on()}
onBlur={() => setIsPassphraseFocused.off()} onBlur={() => setIsPassphraseFocused.off()}
// rightIcon={<FontAwesomeIcon icon={faEyeSlash} />}
/> />
</FormControl> </FormControl>
)} )}