Merge pull request #4792 from Infisical/pki/enableSubscribers

Enable creation of PKI Subscribers and Templates using the UI
This commit is contained in:
carlosmonastyrski
2025-10-31 21:17:24 -03:00
committed by GitHub
9 changed files with 83 additions and 59 deletions
@@ -42,8 +42,8 @@ export type TCreateCertificateTemplateDTO = {
subjectAlternativeName: string; subjectAlternativeName: string;
ttl: string; ttl: string;
projectId: string; projectId: string;
keyUsages: CertKeyUsage[]; keyUsages: string[];
extendedKeyUsages: CertExtendedKeyUsage[]; extendedKeyUsages: string[];
}; };
export type TUpdateCertificateTemplateDTO = { export type TUpdateCertificateTemplateDTO = {
@@ -55,8 +55,8 @@ export type TUpdateCertificateTemplateDTO = {
subjectAlternativeName?: string; subjectAlternativeName?: string;
ttl?: string; ttl?: string;
projectId: string; projectId: string;
keyUsages?: CertKeyUsage[]; keyUsages?: string[];
extendedKeyUsages?: CertExtendedKeyUsage[]; extendedKeyUsages?: string[];
}; };
export type TDeleteCertificateTemplateDTO = { export type TDeleteCertificateTemplateDTO = {
@@ -71,8 +71,8 @@ export type TCreateCertificateTemplateV2DTO = {
subjectAlternativeName: string; subjectAlternativeName: string;
ttl: string; ttl: string;
projectId: string; projectId: string;
keyUsages: CertKeyUsage[]; keyUsages: string[];
extendedKeyUsages: CertExtendedKeyUsage[]; extendedKeyUsages: string[];
}; };
export type TUpdateCertificateTemplateV2DTO = { export type TUpdateCertificateTemplateV2DTO = {
@@ -83,8 +83,8 @@ export type TUpdateCertificateTemplateV2DTO = {
subjectAlternativeName?: string; subjectAlternativeName?: string;
ttl?: string; ttl?: string;
projectId: string; projectId: string;
keyUsages?: CertKeyUsage[]; keyUsages?: string[];
extendedKeyUsages?: CertExtendedKeyUsage[]; extendedKeyUsages?: string[];
}; };
export type TDeleteCertificateTemplateV2DTO = { export type TDeleteCertificateTemplateV2DTO = {
@@ -47,8 +47,8 @@ export type TCreatePkiSubscriberDTO = {
commonName: string; commonName: string;
ttl?: string; ttl?: string;
subjectAlternativeNames: string[]; subjectAlternativeNames: string[];
keyUsages: CertKeyUsage[]; keyUsages: string[];
extendedKeyUsages: CertExtendedKeyUsage[]; extendedKeyUsages: string[];
enableAutoRenewal?: boolean; enableAutoRenewal?: boolean;
autoRenewalPeriodInDays?: number; autoRenewalPeriodInDays?: number;
properties?: TPkiSubscriberProperties; properties?: TPkiSubscriberProperties;
@@ -63,8 +63,8 @@ export type TUpdatePkiSubscriberDTO = {
status?: PkiSubscriberStatus; status?: PkiSubscriberStatus;
ttl?: string; ttl?: string;
subjectAlternativeNames?: string[]; subjectAlternativeNames?: string[];
keyUsages?: CertKeyUsage[]; keyUsages?: string[];
extendedKeyUsages?: CertExtendedKeyUsage[]; extendedKeyUsages?: string[];
enableAutoRenewal?: boolean; enableAutoRenewal?: boolean;
autoRenewalPeriodInDays?: number; autoRenewalPeriodInDays?: number;
properties?: TPkiSubscriberProperties; properties?: TPkiSubscriberProperties;
@@ -172,10 +172,14 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro
ttl, ttl,
keyUsages: Object.entries(keyUsages) keyUsages: Object.entries(keyUsages)
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key as CertKeyUsage), .map(([key]) =>
key === CertKeyUsage.CRL_SIGN
? "cRLSign"
: key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
),
extendedKeyUsages: Object.entries(extendedKeyUsages) extendedKeyUsages: Object.entries(extendedKeyUsages)
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key as CertExtendedKeyUsage) .map(([key]) => key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()))
}); });
createNotification({ createNotification({
@@ -193,10 +197,14 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro
ttl, ttl,
keyUsages: Object.entries(keyUsages) keyUsages: Object.entries(keyUsages)
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key as CertKeyUsage), .map(([key]) =>
key === CertKeyUsage.CRL_SIGN
? "cRLSign"
: key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
),
extendedKeyUsages: Object.entries(extendedKeyUsages) extendedKeyUsages: Object.entries(extendedKeyUsages)
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key as CertExtendedKeyUsage) .map(([key]) => key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()))
}); });
createNotification({ createNotification({
@@ -7,8 +7,7 @@ import { Button, DeleteActionModal } from "@app/components/v2";
import { import {
ProjectPermissionCertificateActions, ProjectPermissionCertificateActions,
ProjectPermissionSub, ProjectPermissionSub,
useProject, useProject
useSubscription
} from "@app/context"; } from "@app/context";
import { useDeleteCert } from "@app/hooks/api"; import { useDeleteCert } from "@app/hooks/api";
import { usePopUp } from "@app/hooks/usePopUp"; import { usePopUp } from "@app/hooks/usePopUp";
@@ -24,10 +23,10 @@ import { CertificatesTable } from "./CertificatesTable";
export const CertificatesSection = () => { export const CertificatesSection = () => {
const { currentProject } = useProject(); const { currentProject } = useProject();
const { subscription } = useSubscription();
const { mutateAsync: deleteCert } = useDeleteCert(); const { mutateAsync: deleteCert } = useDeleteCert();
const isLegacyTemplatesEnabled = subscription.pkiLegacyTemplates; // TODO: Use subscription.pkiLegacyTemplates to block legacy templates creation
const isLegacyTemplatesEnabled = true;
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
"certificateIssuance", "certificateIssuance",
@@ -36,8 +36,7 @@ import { Badge } from "@app/components/v3";
import { import {
ProjectPermissionCertificateActions, ProjectPermissionCertificateActions,
ProjectPermissionSub, ProjectPermissionSub,
useProject, useProject
useSubscription
} from "@app/context"; } from "@app/context";
import { useListWorkspaceCertificates, useUpdateRenewalConfig } from "@app/hooks/api"; import { useListWorkspaceCertificates, useUpdateRenewalConfig } from "@app/hooks/api";
import { caSupportsCapability } from "@app/hooks/api/ca/constants"; import { caSupportsCapability } from "@app/hooks/api/ca/constants";
@@ -175,7 +174,6 @@ const PER_PAGE_INIT = 25;
export const CertificatesTable = ({ handlePopUpOpen }: Props) => { export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [perPage, setPerPage] = useState(PER_PAGE_INIT); const [perPage, setPerPage] = useState(PER_PAGE_INIT);
const { subscription } = useSubscription();
const { currentProject } = useProject(); const { currentProject } = useProject();
const { data, isPending } = useListWorkspaceCertificates({ const { data, isPending } = useListWorkspaceCertificates({
@@ -185,7 +183,8 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
}); });
const { mutateAsync: updateRenewalConfig } = useUpdateRenewalConfig(); const { mutateAsync: updateRenewalConfig } = useUpdateRenewalConfig();
const isLegacyTemplatesEnabled = subscription.pkiLegacyTemplates; // TODO: Use subscription.pkiLegacyTemplates to block legacy templates creation
const isLegacyTemplatesEnabled = true;
const { data: caData } = useListCasByProjectId(currentProject?.id ?? ""); const { data: caData } = useListCasByProjectId(currentProject?.id ?? "");
@@ -351,8 +351,14 @@ export const PkiSubscriberModal = ({ popUp, handlePopUpToggle }: Props) => {
commonName, commonName,
subjectAlternativeNames: subjectAlternativeNamesList, subjectAlternativeNames: subjectAlternativeNamesList,
ttl, ttl,
keyUsages: keyUsagesList, keyUsages: keyUsagesList.map((key) =>
extendedKeyUsages: extendedKeyUsagesList, key === CertKeyUsage.CRL_SIGN
? "cRLSign"
: key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
),
extendedKeyUsages: extendedKeyUsagesList.map((key) =>
key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
),
enableAutoRenewal, enableAutoRenewal,
autoRenewalPeriodInDays, autoRenewalPeriodInDays,
properties: Object.keys(properties).length > 0 ? properties : undefined properties: Object.keys(properties).length > 0 ? properties : undefined
@@ -365,8 +371,14 @@ export const PkiSubscriberModal = ({ popUp, handlePopUpToggle }: Props) => {
commonName, commonName,
subjectAlternativeNames: subjectAlternativeNamesList, subjectAlternativeNames: subjectAlternativeNamesList,
ttl, ttl,
keyUsages: keyUsagesList, keyUsages: keyUsagesList.map((key) =>
extendedKeyUsages: extendedKeyUsagesList, key === CertKeyUsage.CRL_SIGN
? "cRLSign"
: key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
),
extendedKeyUsages: extendedKeyUsagesList.map((key) =>
key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
),
enableAutoRenewal, enableAutoRenewal,
autoRenewalPeriodInDays, autoRenewalPeriodInDays,
properties: Object.keys(properties).length > 0 ? properties : undefined properties: Object.keys(properties).length > 0 ? properties : undefined
@@ -7,8 +7,7 @@ import { Button, DeleteActionModal } from "@app/components/v2";
import { import {
ProjectPermissionPkiSubscriberActions, ProjectPermissionPkiSubscriberActions,
ProjectPermissionSub, ProjectPermissionSub,
useProject, useProject
useSubscription
} from "@app/context"; } from "@app/context";
import { useDeletePkiSubscriber, useUpdatePkiSubscriber } from "@app/hooks/api"; import { useDeletePkiSubscriber, useUpdatePkiSubscriber } from "@app/hooks/api";
import { PkiSubscriberStatus } from "@app/hooks/api/pkiSubscriber/types"; import { PkiSubscriberStatus } from "@app/hooks/api/pkiSubscriber/types";
@@ -19,10 +18,10 @@ import { PkiSubscribersTable } from "./PkiSubscribersTable";
export const PkiSubscriberSection = () => { export const PkiSubscriberSection = () => {
const { currentProject } = useProject(); const { currentProject } = useProject();
const { subscription } = useSubscription();
const projectId = currentProject.id; const projectId = currentProject.id;
const canCreateLegacySubscribers = subscription.pkiLegacyTemplates; // TODO: Use subscription.pkiLegacyTemplates to block legacy templates creation
const canCreateLegacySubscribers = true;
const { mutateAsync: deletePkiSubscriber } = useDeletePkiSubscriber(); const { mutateAsync: deletePkiSubscriber } = useDeletePkiSubscriber();
const { mutateAsync: updatePkiSubscriber } = useUpdatePkiSubscriber(); const { mutateAsync: updatePkiSubscriber } = useUpdatePkiSubscriber();
@@ -114,30 +114,29 @@ export const PkiTemplateListPage = () => {
/> />
</div> </div>
<div className="container mx-auto mb-6 max-w-8xl rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"> <div className="container mx-auto mb-6 max-w-8xl rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
{subscription?.pkiLegacyTemplates && ( {/* TODO: Use subscription.pkiLegacyTemplates to block legacy templates creation */}
<div className="mb-4 flex justify-between"> <div className="mb-4 flex justify-between">
<p className="text-xl font-medium text-mineshaft-100">Templates</p> <p className="text-xl font-medium text-mineshaft-100">Templates</p>
<div className="flex w-full justify-end"> <div className="flex w-full justify-end">
<ProjectPermissionCan <ProjectPermissionCan
I={ProjectPermissionPkiTemplateActions.Create} I={ProjectPermissionPkiTemplateActions.Create}
a={ProjectPermissionSub.CertificateTemplates} a={ProjectPermissionSub.CertificateTemplates}
> >
{(isAllowed) => ( {(isAllowed) => (
<Button <Button
colorSchema="primary" colorSchema="primary"
type="submit" type="submit"
leftIcon={<FontAwesomeIcon icon={faPlus} />} leftIcon={<FontAwesomeIcon icon={faPlus} />}
onClick={() => handlePopUpOpen("certificateTemplate")} onClick={() => handlePopUpOpen("certificateTemplate")}
isDisabled={!isAllowed} isDisabled={!isAllowed}
className="ml-4" className="ml-4"
> >
Add Template Add Template
</Button> </Button>
)} )}
</ProjectPermissionCan> </ProjectPermissionCan>
</div>
</div> </div>
)} </div>
<TableContainer> <TableContainer>
<Table> <Table>
<THead> <THead>
@@ -140,10 +140,14 @@ export const PkiTemplateForm = ({ certTemplate, handlePopUpToggle }: Props) => {
ttl, ttl,
keyUsages: Object.entries(keyUsages) keyUsages: Object.entries(keyUsages)
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key as CertKeyUsage), .map(([key]) =>
key === CertKeyUsage.CRL_SIGN
? "cRLSign"
: key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
),
extendedKeyUsages: Object.entries(extendedKeyUsages) extendedKeyUsages: Object.entries(extendedKeyUsages)
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key as CertExtendedKeyUsage) .map(([key]) => key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()))
}); });
createNotification({ createNotification({
@@ -160,10 +164,14 @@ export const PkiTemplateForm = ({ certTemplate, handlePopUpToggle }: Props) => {
ttl, ttl,
keyUsages: Object.entries(keyUsages) keyUsages: Object.entries(keyUsages)
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key as CertKeyUsage), .map(([key]) =>
key === CertKeyUsage.CRL_SIGN
? "cRLSign"
: key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
),
extendedKeyUsages: Object.entries(extendedKeyUsages) extendedKeyUsages: Object.entries(extendedKeyUsages)
.filter(([, value]) => value) .filter(([, value]) => value)
.map(([key]) => key as CertExtendedKeyUsage) .map(([key]) => key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()))
}); });
createNotification({ createNotification({