mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Expose directory url
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -37,6 +37,4 @@ export interface TApiConfigData {
|
||||
renewBeforeDays?: number;
|
||||
}
|
||||
|
||||
export interface TAcmeConfigData {
|
||||
eabSecret: string;
|
||||
}
|
||||
export interface TAcmeConfigData {}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
@@ -31,67 +43,81 @@ export const RevealAcmeEabSecretModal = ({ isOpen, onClose, profile }: Props) =>
|
||||
title="Reveal EAB Secret"
|
||||
subTitle="To issue certificates automatically, your ACME client needs the following details."
|
||||
>
|
||||
<FormLabel
|
||||
label="ACME Directory URL"
|
||||
tooltipText="The ACME directory URL for your ACME client to issue certificates."
|
||||
/>
|
||||
<div className="flex gap-2">
|
||||
<Input value={acmeDirectoryUrl} disabled />
|
||||
<IconButton
|
||||
ariaLabel="copy"
|
||||
variant="outline_bg"
|
||||
colorSchema="secondary"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(acmeDirectoryUrl);
|
||||
setIsAcmeDirectoryUrlCopied.on();
|
||||
}}
|
||||
className="w-10"
|
||||
>
|
||||
<FontAwesomeIcon icon={isAcmeDirectoryUrlCopied ? faCheck : faCopy} />
|
||||
</IconButton>
|
||||
</div>
|
||||
{isLoading && (
|
||||
<div className="flex items-center justify-center py-4">
|
||||
<Spinner size="sm" />
|
||||
</div>
|
||||
)}
|
||||
{isError && (
|
||||
<Alert variant="danger">
|
||||
<AlertDescription>Failed to reveal EAB secret: {error.message}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
{data && (
|
||||
<>
|
||||
<FormLabel
|
||||
label="ACME Directory URL"
|
||||
tooltipText="The ACME directory URL for your ACME client to issue certificates."
|
||||
/>
|
||||
<div className="flex gap-2">
|
||||
<Input value={directoryUrl} disabled />
|
||||
<IconButton
|
||||
ariaLabel="copy"
|
||||
variant="outline_bg"
|
||||
colorSchema="secondary"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(directoryUrl);
|
||||
setIsAcmeDirectoryUrlCopied.on();
|
||||
}}
|
||||
className="w-10"
|
||||
>
|
||||
<FontAwesomeIcon icon={isAcmeDirectoryUrlCopied ? faCheck : faCopy} />
|
||||
</IconButton>
|
||||
</div>
|
||||
|
||||
<FormLabel
|
||||
label="EAB KID"
|
||||
className="mt-4"
|
||||
tooltipText="The EAB Key Identifier (KID) for your ACME client to authenticate when registering a new account."
|
||||
/>
|
||||
<div className="flex gap-2">
|
||||
<Input value={eabKid} disabled />
|
||||
<IconButton
|
||||
ariaLabel="copy"
|
||||
variant="outline_bg"
|
||||
colorSchema="secondary"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(eabKid);
|
||||
setIsEabKidCopied.on();
|
||||
}}
|
||||
className="w-10"
|
||||
>
|
||||
<FontAwesomeIcon icon={isEabKidCopied ? faCheck : faCopy} />
|
||||
</IconButton>
|
||||
</div>
|
||||
<FormLabel
|
||||
label="EAB KID"
|
||||
className="mt-4"
|
||||
tooltipText="The EAB Key Identifier (KID) for your ACME client to authenticate when registering a new account."
|
||||
/>
|
||||
<div className="flex gap-2">
|
||||
<Input value={eabKid} disabled />
|
||||
<IconButton
|
||||
ariaLabel="copy"
|
||||
variant="outline_bg"
|
||||
colorSchema="secondary"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(eabKid);
|
||||
setIsEabKidCopied.on();
|
||||
}}
|
||||
className="w-10"
|
||||
>
|
||||
<FontAwesomeIcon icon={isEabKidCopied ? faCheck : faCopy} />
|
||||
</IconButton>
|
||||
</div>
|
||||
|
||||
<FormLabel
|
||||
label="EAB Secret"
|
||||
className="mt-4"
|
||||
tooltipText="The EAB Secret for your ACME client to authenticate when registering a new account."
|
||||
/>
|
||||
<div className="flex gap-2">
|
||||
<Input value={eabSecret} isDisabled />
|
||||
<IconButton
|
||||
ariaLabel="copy"
|
||||
variant="outline_bg"
|
||||
colorSchema="secondary"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(eabSecret);
|
||||
setIsEabSecretCopied.on();
|
||||
}}
|
||||
className="w-10"
|
||||
>
|
||||
<FontAwesomeIcon icon={isEabSecretCopied ? faCheck : faCopy} />
|
||||
</IconButton>
|
||||
</div>
|
||||
<FormLabel
|
||||
label="EAB Secret"
|
||||
className="mt-4"
|
||||
tooltipText="The EAB Secret for your ACME client to authenticate when registering a new account."
|
||||
/>
|
||||
<div className="flex gap-2">
|
||||
<Input value={eabSecret} isDisabled />
|
||||
<IconButton
|
||||
ariaLabel="copy"
|
||||
variant="outline_bg"
|
||||
colorSchema="secondary"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(eabSecret);
|
||||
setIsEabSecretCopied.on();
|
||||
}}
|
||||
className="w-10"
|
||||
>
|
||||
<FontAwesomeIcon icon={isEabSecretCopied ? faCheck : faCopy} />
|
||||
</IconButton>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user