mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 18:27:36 +00:00
Expose directory url
This commit is contained in:
@@ -168,6 +168,12 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
|
|||||||
autoRenew: z.boolean(),
|
autoRenew: z.boolean(),
|
||||||
renewBeforeDays: z.number().optional()
|
renewBeforeDays: z.number().optional()
|
||||||
})
|
})
|
||||||
|
.optional(),
|
||||||
|
acmeConfig: z
|
||||||
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
directoryUrl: z.string()
|
||||||
|
})
|
||||||
.optional()
|
.optional()
|
||||||
}).array(),
|
}).array(),
|
||||||
totalCount: z.number()
|
totalCount: z.number()
|
||||||
|
|||||||
@@ -274,6 +274,11 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
|||||||
`${TableName.PkiCertificateProfile}.apiConfigId`,
|
`${TableName.PkiCertificateProfile}.apiConfigId`,
|
||||||
`${TableName.PkiApiEnrollmentConfig}.id`
|
`${TableName.PkiApiEnrollmentConfig}.id`
|
||||||
)
|
)
|
||||||
|
.leftJoin(
|
||||||
|
TableName.PkiAcmeEnrollmentConfig,
|
||||||
|
`${TableName.PkiCertificateProfile}.acmeConfigId`,
|
||||||
|
`${TableName.PkiAcmeEnrollmentConfig}.id`
|
||||||
|
)
|
||||||
.select(selectAllTableCols(TableName.PkiCertificateProfile))
|
.select(selectAllTableCols(TableName.PkiCertificateProfile))
|
||||||
.select(
|
.select(
|
||||||
db.ref("id").withSchema(TableName.PkiEstEnrollmentConfig).as("estId"),
|
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("encryptedCaChain").withSchema(TableName.PkiEstEnrollmentConfig).as("estEncryptedCaChain"),
|
||||||
db.ref("id").withSchema(TableName.PkiApiEnrollmentConfig).as("apiId"),
|
db.ref("id").withSchema(TableName.PkiApiEnrollmentConfig).as("apiId"),
|
||||||
db.ref("autoRenew").withSchema(TableName.PkiApiEnrollmentConfig).as("apiAutoRenew"),
|
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
|
const results = (await query
|
||||||
@@ -312,6 +318,12 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
const acmeConfig = result.acmeId
|
||||||
|
? {
|
||||||
|
id: result.acmeId as string
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const baseProfile = {
|
const baseProfile = {
|
||||||
id: result.id,
|
id: result.id,
|
||||||
projectId: result.projectId,
|
projectId: result.projectId,
|
||||||
@@ -325,7 +337,8 @@ export const certificateProfileDALFactory = (db: TDbClient) => {
|
|||||||
createdAt: result.createdAt,
|
createdAt: result.createdAt,
|
||||||
updatedAt: result.updatedAt,
|
updatedAt: result.updatedAt,
|
||||||
estConfig,
|
estConfig,
|
||||||
apiConfig
|
apiConfig,
|
||||||
|
acmeConfig
|
||||||
};
|
};
|
||||||
|
|
||||||
return baseProfile as TCertificateProfileWithConfigs;
|
return baseProfile as TCertificateProfileWithConfigs;
|
||||||
|
|||||||
@@ -627,10 +627,9 @@ export const certificateProfileServiceFactory = ({
|
|||||||
...converted,
|
...converted,
|
||||||
estConfig: decryptedEstConfig,
|
estConfig: decryptedEstConfig,
|
||||||
apiConfig: profileWithConfigs.apiConfig,
|
apiConfig: profileWithConfigs.apiConfig,
|
||||||
acmeConfig:
|
acmeConfig: profileWithConfigs.acmeConfig
|
||||||
profile.enrollmentType === EnrollmentType.ACME
|
? { ...profileWithConfigs.acmeConfig, directoryUrl: buildUrl(profile.id, "/directory") }
|
||||||
? { id: profile.id, directoryUrl: buildUrl(profile.id, "/directory") }
|
: undefined
|
||||||
: undefined
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -37,6 +37,4 @@ export interface TApiConfigData {
|
|||||||
renewBeforeDays?: number;
|
renewBeforeDays?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TAcmeConfigData {
|
export interface TAcmeConfigData {}
|
||||||
eabSecret: string;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import {
|
|||||||
TGetProfileCertificatesDTO,
|
TGetProfileCertificatesDTO,
|
||||||
TGetProfileMetricsDTO,
|
TGetProfileMetricsDTO,
|
||||||
TListCertificateProfilesDTO,
|
TListCertificateProfilesDTO,
|
||||||
TProfileCertificate
|
TProfileCertificate,
|
||||||
|
TRevealAcmeEabSecretDTO
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export const certificateProfileKeys = {
|
export const certificateProfileKeys = {
|
||||||
@@ -41,6 +42,11 @@ export const certificateProfileKeys = {
|
|||||||
"metrics",
|
"metrics",
|
||||||
profileId,
|
profileId,
|
||||||
params
|
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 = ({
|
export const useGetProfileCertificates = ({
|
||||||
profileId,
|
profileId,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ export type TCertificateProfileWithDetails = TCertificateProfile & {
|
|||||||
autoRenew: boolean;
|
autoRenew: boolean;
|
||||||
renewBeforeDays?: number;
|
renewBeforeDays?: number;
|
||||||
};
|
};
|
||||||
|
acmeConfig?: {
|
||||||
|
id: string;
|
||||||
|
directoryUrl: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TCreateCertificateProfileDTO = {
|
export type TCreateCertificateProfileDTO = {
|
||||||
@@ -95,6 +99,10 @@ export type TGetCertificateProfileBySlugDTO = {
|
|||||||
slug: string;
|
slug: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TRevealAcmeEabSecretDTO = {
|
||||||
|
profileId: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type TProfileCertificate = {
|
export type TProfileCertificate = {
|
||||||
id: string;
|
id: string;
|
||||||
serialNumber: string;
|
serialNumber: string;
|
||||||
|
|||||||
+89
-63
@@ -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 { useToggle } from "@app/hooks";
|
||||||
import { TCertificateProfileWithDetails } from "@app/hooks/api/certificateProfiles";
|
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 { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
@@ -14,10 +24,12 @@ export const RevealAcmeEabSecretModal = ({ isOpen, onClose, profile }: Props) =>
|
|||||||
const [isAcmeDirectoryUrlCopied, setIsAcmeDirectoryUrlCopied] = useToggle(false);
|
const [isAcmeDirectoryUrlCopied, setIsAcmeDirectoryUrlCopied] = useToggle(false);
|
||||||
const [isEabKidCopied, setIsEabKidCopied] = useToggle(false);
|
const [isEabKidCopied, setIsEabKidCopied] = useToggle(false);
|
||||||
const [isEabSecretCopied, setIsEabSecretCopied] = 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 (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
@@ -31,67 +43,81 @@ export const RevealAcmeEabSecretModal = ({ isOpen, onClose, profile }: Props) =>
|
|||||||
title="Reveal EAB Secret"
|
title="Reveal EAB Secret"
|
||||||
subTitle="To issue certificates automatically, your ACME client needs the following details."
|
subTitle="To issue certificates automatically, your ACME client needs the following details."
|
||||||
>
|
>
|
||||||
<FormLabel
|
{isLoading && (
|
||||||
label="ACME Directory URL"
|
<div className="flex items-center justify-center py-4">
|
||||||
tooltipText="The ACME directory URL for your ACME client to issue certificates."
|
<Spinner size="sm" />
|
||||||
/>
|
</div>
|
||||||
<div className="flex gap-2">
|
)}
|
||||||
<Input value={acmeDirectoryUrl} disabled />
|
{isError && (
|
||||||
<IconButton
|
<Alert variant="danger">
|
||||||
ariaLabel="copy"
|
<AlertDescription>Failed to reveal EAB secret: {error.message}</AlertDescription>
|
||||||
variant="outline_bg"
|
</Alert>
|
||||||
colorSchema="secondary"
|
)}
|
||||||
onClick={() => {
|
{data && (
|
||||||
navigator.clipboard.writeText(acmeDirectoryUrl);
|
<>
|
||||||
setIsAcmeDirectoryUrlCopied.on();
|
<FormLabel
|
||||||
}}
|
label="ACME Directory URL"
|
||||||
className="w-10"
|
tooltipText="The ACME directory URL for your ACME client to issue certificates."
|
||||||
>
|
/>
|
||||||
<FontAwesomeIcon icon={isAcmeDirectoryUrlCopied ? faCheck : faCopy} />
|
<div className="flex gap-2">
|
||||||
</IconButton>
|
<Input value={directoryUrl} disabled />
|
||||||
</div>
|
<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
|
<FormLabel
|
||||||
label="EAB KID"
|
label="EAB KID"
|
||||||
className="mt-4"
|
className="mt-4"
|
||||||
tooltipText="The EAB Key Identifier (KID) for your ACME client to authenticate when registering a new account."
|
tooltipText="The EAB Key Identifier (KID) for your ACME client to authenticate when registering a new account."
|
||||||
/>
|
/>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Input value={eabKid} disabled />
|
<Input value={eabKid} disabled />
|
||||||
<IconButton
|
<IconButton
|
||||||
ariaLabel="copy"
|
ariaLabel="copy"
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
colorSchema="secondary"
|
colorSchema="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigator.clipboard.writeText(eabKid);
|
navigator.clipboard.writeText(eabKid);
|
||||||
setIsEabKidCopied.on();
|
setIsEabKidCopied.on();
|
||||||
}}
|
}}
|
||||||
className="w-10"
|
className="w-10"
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={isEabKidCopied ? faCheck : faCopy} />
|
<FontAwesomeIcon icon={isEabKidCopied ? faCheck : faCopy} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormLabel
|
<FormLabel
|
||||||
label="EAB Secret"
|
label="EAB Secret"
|
||||||
className="mt-4"
|
className="mt-4"
|
||||||
tooltipText="The EAB Secret for your ACME client to authenticate when registering a new account."
|
tooltipText="The EAB Secret for your ACME client to authenticate when registering a new account."
|
||||||
/>
|
/>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<Input value={eabSecret} isDisabled />
|
<Input value={eabSecret} isDisabled />
|
||||||
<IconButton
|
<IconButton
|
||||||
ariaLabel="copy"
|
ariaLabel="copy"
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
colorSchema="secondary"
|
colorSchema="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigator.clipboard.writeText(eabSecret);
|
navigator.clipboard.writeText(eabSecret);
|
||||||
setIsEabSecretCopied.on();
|
setIsEabSecretCopied.on();
|
||||||
}}
|
}}
|
||||||
className="w-10"
|
className="w-10"
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={isEabSecretCopied ? faCheck : faCopy} />
|
<FontAwesomeIcon icon={isEabSecretCopied ? faCheck : faCopy} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user