diff --git a/backend/src/server/routes/v1/certificate-profiles-router.ts b/backend/src/server/routes/v1/certificate-profiles-router.ts index f85f8a677..7d4e04773 100644 --- a/backend/src/server/routes/v1/certificate-profiles-router.ts +++ b/backend/src/server/routes/v1/certificate-profiles-router.ts @@ -168,6 +168,12 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid autoRenew: z.boolean(), renewBeforeDays: z.number().optional() }) + .optional(), + acmeConfig: z + .object({ + id: z.string(), + directoryUrl: z.string() + }) .optional() }).array(), totalCount: z.number() diff --git a/backend/src/services/certificate-profile/certificate-profile-dal.ts b/backend/src/services/certificate-profile/certificate-profile-dal.ts index f8f511ab4..5296cb172 100644 --- a/backend/src/services/certificate-profile/certificate-profile-dal.ts +++ b/backend/src/services/certificate-profile/certificate-profile-dal.ts @@ -274,6 +274,11 @@ export const certificateProfileDALFactory = (db: TDbClient) => { `${TableName.PkiCertificateProfile}.apiConfigId`, `${TableName.PkiApiEnrollmentConfig}.id` ) + .leftJoin( + TableName.PkiAcmeEnrollmentConfig, + `${TableName.PkiCertificateProfile}.acmeConfigId`, + `${TableName.PkiAcmeEnrollmentConfig}.id` + ) .select(selectAllTableCols(TableName.PkiCertificateProfile)) .select( db.ref("id").withSchema(TableName.PkiEstEnrollmentConfig).as("estId"), @@ -285,7 +290,8 @@ export const certificateProfileDALFactory = (db: TDbClient) => { 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.ref("renewBeforeDays").withSchema(TableName.PkiApiEnrollmentConfig).as("apiRenewBeforeDays"), + db.ref("id").withSchema(TableName.PkiAcmeEnrollmentConfig).as("acmeId") ); const results = (await query @@ -312,6 +318,12 @@ export const certificateProfileDALFactory = (db: TDbClient) => { } : undefined; + const acmeConfig = result.acmeId + ? { + id: result.acmeId as string + } + : undefined; + const baseProfile = { id: result.id, projectId: result.projectId, @@ -325,7 +337,8 @@ export const certificateProfileDALFactory = (db: TDbClient) => { createdAt: result.createdAt, updatedAt: result.updatedAt, estConfig, - apiConfig + apiConfig, + acmeConfig }; return baseProfile as TCertificateProfileWithConfigs; diff --git a/backend/src/services/certificate-profile/certificate-profile-service.ts b/backend/src/services/certificate-profile/certificate-profile-service.ts index f1cee1761..8adbf2c45 100644 --- a/backend/src/services/certificate-profile/certificate-profile-service.ts +++ b/backend/src/services/certificate-profile/certificate-profile-service.ts @@ -627,10 +627,9 @@ export const certificateProfileServiceFactory = ({ ...converted, estConfig: decryptedEstConfig, apiConfig: profileWithConfigs.apiConfig, - acmeConfig: - profile.enrollmentType === EnrollmentType.ACME - ? { id: profile.id, directoryUrl: buildUrl(profile.id, "/directory") } - : undefined + acmeConfig: profileWithConfigs.acmeConfig + ? { ...profileWithConfigs.acmeConfig, directoryUrl: buildUrl(profile.id, "/directory") } + : undefined }; return result; diff --git a/backend/src/services/enrollment-config/enrollment-config-types.ts b/backend/src/services/enrollment-config/enrollment-config-types.ts index ff017e409..ed2f921c4 100644 --- a/backend/src/services/enrollment-config/enrollment-config-types.ts +++ b/backend/src/services/enrollment-config/enrollment-config-types.ts @@ -37,6 +37,4 @@ export interface TApiConfigData { renewBeforeDays?: number; } -export interface TAcmeConfigData { - eabSecret: string; -} +export interface TAcmeConfigData {} diff --git a/frontend/src/hooks/api/certificateProfiles/queries.tsx b/frontend/src/hooks/api/certificateProfiles/queries.tsx index 19859b02f..1e0fe3b9b 100644 --- a/frontend/src/hooks/api/certificateProfiles/queries.tsx +++ b/frontend/src/hooks/api/certificateProfiles/queries.tsx @@ -10,7 +10,8 @@ import { TGetProfileCertificatesDTO, TGetProfileMetricsDTO, TListCertificateProfilesDTO, - TProfileCertificate + TProfileCertificate, + TRevealAcmeEabSecretDTO } from "./types"; export const certificateProfileKeys = { @@ -41,6 +42,11 @@ export const certificateProfileKeys = { "metrics", profileId, params + ], + revealAcmeEabSecret: (profileId: string) => [ + "certificate-profiles", + "reveal-acme-eab-secret", + profileId ] }; @@ -112,6 +118,20 @@ export const useGetCertificateProfileBySlug = ({ }); }; +export const useRevealAcmeEabSecret = ({ profileId }: TRevealAcmeEabSecretDTO) => { + return useQuery({ + queryKey: certificateProfileKeys.revealAcmeEabSecret(profileId), + queryFn: async () => { + const { data } = await apiRequest.get<{ + eabKid: string; + eabSecret: string; + }>(`/api/v1/pki/certificate-profiles/${profileId}/acme/eab-secret/reveal`); + return data; + }, + enabled: Boolean(profileId) + }); +}; + export const useGetProfileCertificates = ({ profileId, offset = 0, diff --git a/frontend/src/hooks/api/certificateProfiles/types.ts b/frontend/src/hooks/api/certificateProfiles/types.ts index 94d8d0c6d..7acb6fef9 100644 --- a/frontend/src/hooks/api/certificateProfiles/types.ts +++ b/frontend/src/hooks/api/certificateProfiles/types.ts @@ -36,6 +36,10 @@ export type TCertificateProfileWithDetails = TCertificateProfile & { autoRenew: boolean; renewBeforeDays?: number; }; + acmeConfig?: { + id: string; + directoryUrl: string; + }; }; export type TCreateCertificateProfileDTO = { @@ -95,6 +99,10 @@ export type TGetCertificateProfileBySlugDTO = { slug: string; }; +export type TRevealAcmeEabSecretDTO = { + profileId: string; +}; + export type TProfileCertificate = { id: string; serialNumber: string; diff --git a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/RevealAcmeEabSecretModal.tsx b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/RevealAcmeEabSecretModal.tsx index 729b3e896..7156fc7e4 100644 --- a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/RevealAcmeEabSecretModal.tsx +++ b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/RevealAcmeEabSecretModal.tsx @@ -1,6 +1,16 @@ -import { FormLabel, IconButton, Input, Modal, ModalContent } from "@app/components/v2"; +import { + Alert, + AlertDescription, + FormLabel, + IconButton, + Input, + Modal, + ModalContent, + Spinner +} from "@app/components/v2"; import { useToggle } from "@app/hooks"; import { TCertificateProfileWithDetails } from "@app/hooks/api/certificateProfiles"; +import { useRevealAcmeEabSecret } from "@app/hooks/api/certificateProfiles/queries"; import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -14,10 +24,12 @@ export const RevealAcmeEabSecretModal = ({ isOpen, onClose, profile }: Props) => const [isAcmeDirectoryUrlCopied, setIsAcmeDirectoryUrlCopied] = useToggle(false); const [isEabKidCopied, setIsEabKidCopied] = useToggle(false); const [isEabSecretCopied, setIsEabSecretCopied] = useToggle(false); + const revealAcmeEabSecret = useRevealAcmeEabSecret({ profileId: profile.id }); + const { data, isLoading, isError, error } = revealAcmeEabSecret; + + const { directoryUrl } = profile.acmeConfig!; + const { eabKid, eabSecret } = data ?? { eabKid: "", eabSecret: "" }; - const acmeDirectoryUrl = "http://FIXME.com/directory"; - const eabKid = profile.id; - const eabSecret = "FIXME"; return ( title="Reveal EAB Secret" subTitle="To issue certificates automatically, your ACME client needs the following details." > - -
- - { - navigator.clipboard.writeText(acmeDirectoryUrl); - setIsAcmeDirectoryUrlCopied.on(); - }} - className="w-10" - > - - -
+ {isLoading && ( +
+ +
+ )} + {isError && ( + + Failed to reveal EAB secret: {error.message} + + )} + {data && ( + <> + +
+ + { + navigator.clipboard.writeText(directoryUrl); + setIsAcmeDirectoryUrlCopied.on(); + }} + className="w-10" + > + + +
- -
- - { - navigator.clipboard.writeText(eabKid); - setIsEabKidCopied.on(); - }} - className="w-10" - > - - -
+ +
+ + { + navigator.clipboard.writeText(eabKid); + setIsEabKidCopied.on(); + }} + className="w-10" + > + + +
- -
- - { - navigator.clipboard.writeText(eabSecret); - setIsEabSecretCopied.on(); - }} - className="w-10" - > - - -
+ +
+ + { + navigator.clipboard.writeText(eabSecret); + setIsEabSecretCopied.on(); + }} + className="w-10" + > + + +
+ + )}
);