mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 13:56:43 +00:00
Merge pull request #1939 from Infisical/cert-mgmt
Certificate Management (Internal PKI)
This commit is contained in:
@@ -26,7 +26,6 @@ export const eventToNameMap: { [K in EventType]: string } = {
|
||||
[EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Create universal auth client secret",
|
||||
[EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Revoke universal auth client secret",
|
||||
[EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS]: "Get universal auth client secrets",
|
||||
[EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth",
|
||||
[EventType.CREATE_ENVIRONMENT]: "Create environment",
|
||||
[EventType.UPDATE_ENVIRONMENT]: "Update environment",
|
||||
[EventType.DELETE_ENVIRONMENT]: "Delete environment",
|
||||
@@ -43,7 +42,21 @@ export const eventToNameMap: { [K in EventType]: string } = {
|
||||
[EventType.UPDATE_SECRET_IMPORT]: "Update secret import",
|
||||
[EventType.DELETE_SECRET_IMPORT]: "Delete secret import",
|
||||
[EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS]: "Update denied permissions",
|
||||
[EventType.UPDATE_USER_WORKSPACE_ROLE]: "Update user role"
|
||||
[EventType.UPDATE_USER_WORKSPACE_ROLE]: "Update user role",
|
||||
[EventType.CREATE_CA]: "Create CA",
|
||||
[EventType.GET_CA]: "Get CA",
|
||||
[EventType.UPDATE_CA]: "Update CA",
|
||||
[EventType.DELETE_CA]: "Delete CA",
|
||||
[EventType.GET_CA_CSR]: "Get CA CSR",
|
||||
[EventType.GET_CA_CERT]: "Get CA certificate",
|
||||
[EventType.SIGN_INTERMEDIATE]: "Sign intermediate",
|
||||
[EventType.IMPORT_CA_CERT]: "Import CA certificate",
|
||||
[EventType.GET_CA_CRL]: "Get CA CRL",
|
||||
[EventType.ISSUE_CERT]: "Issue certificate",
|
||||
[EventType.GET_CERT]: "Get certificate",
|
||||
[EventType.DELETE_CERT]: "Delete certificate",
|
||||
[EventType.REVOKE_CERT]: "Revoke certificate",
|
||||
[EventType.GET_CERT_BODY]: "Get certificate body"
|
||||
};
|
||||
|
||||
export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
|
||||
|
||||
@@ -56,5 +56,19 @@ export enum EventType {
|
||||
UPDATE_SECRET_IMPORT = "update-secret-import",
|
||||
DELETE_SECRET_IMPORT = "delete-secret-import",
|
||||
UPDATE_USER_WORKSPACE_ROLE = "update-user-workspace-role",
|
||||
UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS = "update-user-workspace-denied-permissions"
|
||||
UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS = "update-user-workspace-denied-permissions",
|
||||
CREATE_CA = "create-certificate-authority",
|
||||
GET_CA = "get-certificate-authority",
|
||||
UPDATE_CA = "update-certificate-authority",
|
||||
DELETE_CA = "delete-certificate-authority",
|
||||
GET_CA_CSR = "get-certificate-authority-csr",
|
||||
GET_CA_CERT = "get-certificate-authority-cert",
|
||||
SIGN_INTERMEDIATE = "sign-intermediate",
|
||||
IMPORT_CA_CERT = "import-certificate-authority-cert",
|
||||
GET_CA_CRL = "get-certificate-authority-crl",
|
||||
ISSUE_CERT = "issue-cert",
|
||||
GET_CERT = "get-cert",
|
||||
DELETE_CERT = "delete-cert",
|
||||
REVOKE_CERT = "revoke-cert",
|
||||
GET_CERT_BODY = "get-cert-body"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { CaStatus } from "../ca";
|
||||
import { IdentityTrustedIp } from "../identities/types";
|
||||
import { ActorType, EventType, UserAgentType } from "./enums";
|
||||
|
||||
@@ -462,6 +463,125 @@ interface UpdateUserDeniedPermissions {
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateCa {
|
||||
type: EventType.CREATE_CA;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetCa {
|
||||
type: EventType.GET_CA;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateCa {
|
||||
type: EventType.UPDATE_CA;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
status: CaStatus;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteCa {
|
||||
type: EventType.DELETE_CA;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetCaCsr {
|
||||
type: EventType.GET_CA_CSR;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetCaCert {
|
||||
type: EventType.GET_CA_CERT;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface SignIntermediate {
|
||||
type: EventType.SIGN_INTERMEDIATE;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface ImportCaCert {
|
||||
type: EventType.IMPORT_CA_CERT;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetCaCrl {
|
||||
type: EventType.GET_CA_CRL;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IssueCert {
|
||||
type: EventType.ISSUE_CERT;
|
||||
metadata: {
|
||||
caId: string;
|
||||
dn: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetCert {
|
||||
type: EventType.GET_CERT;
|
||||
metadata: {
|
||||
certId: string;
|
||||
cn: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteCert {
|
||||
type: EventType.DELETE_CERT;
|
||||
metadata: {
|
||||
certId: string;
|
||||
cn: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface RevokeCert {
|
||||
type: EventType.REVOKE_CERT;
|
||||
metadata: {
|
||||
certId: string;
|
||||
cn: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetCertBody {
|
||||
type: EventType.GET_CERT_BODY;
|
||||
metadata: {
|
||||
certId: string;
|
||||
cn: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type Event =
|
||||
| GetSecretsEvent
|
||||
| GetSecretEvent
|
||||
@@ -504,7 +624,21 @@ export type Event =
|
||||
| UpdateSecretImportEvent
|
||||
| DeleteSecretImportEvent
|
||||
| UpdateUserRole
|
||||
| UpdateUserDeniedPermissions;
|
||||
| UpdateUserDeniedPermissions
|
||||
| CreateCa
|
||||
| GetCa
|
||||
| UpdateCa
|
||||
| DeleteCa
|
||||
| GetCaCsr
|
||||
| GetCaCert
|
||||
| SignIntermediate
|
||||
| ImportCaCert
|
||||
| GetCaCrl
|
||||
| IssueCert
|
||||
| GetCert
|
||||
| DeleteCert
|
||||
| RevokeCert
|
||||
| GetCertBody;
|
||||
|
||||
export type AuditLog = {
|
||||
id: string;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { CaStatus,CaType } from "./enums";
|
||||
|
||||
export const caTypeToNameMap: { [K in CaType]: string } = {
|
||||
[CaType.ROOT]: "Root",
|
||||
[CaType.INTERMEDIATE]: "Intermediate"
|
||||
};
|
||||
|
||||
export const caStatusToNameMap: { [K in CaStatus]: string } = {
|
||||
[CaStatus.ACTIVE]: "Active",
|
||||
[CaStatus.DISABLED]: "Disabled",
|
||||
[CaStatus.PENDING_CERTIFICATE]: "Pending Certificate"
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
export enum CaType {
|
||||
ROOT = "root",
|
||||
INTERMEDIATE = "intermediate"
|
||||
}
|
||||
|
||||
export enum CaStatus {
|
||||
ACTIVE = "active",
|
||||
DISABLED = "disabled",
|
||||
PENDING_CERTIFICATE = "pending-certificate"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
export { CaStatus, CaType } from "./enums";
|
||||
export {
|
||||
useCreateCa,
|
||||
useCreateCertificate,
|
||||
useDeleteCa,
|
||||
useImportCaCertificate,
|
||||
useSignIntermediate,
|
||||
useUpdateCa
|
||||
} from "./mutations";
|
||||
export { useGetCaById, useGetCaCert, useGetCaCrl,useGetCaCsr } from "./queries";
|
||||
@@ -0,0 +1,108 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { workspaceKeys } from "../workspace/queries";
|
||||
import {
|
||||
TCertificateAuthority,
|
||||
TCreateCaDTO,
|
||||
TCreateCertificateDTO,
|
||||
TCreateCertificateResponse,
|
||||
TDeleteCaDTO,
|
||||
TImportCaCertificateDTO,
|
||||
TImportCaCertificateResponse,
|
||||
TSignIntermediateDTO,
|
||||
TSignIntermediateResponse,
|
||||
TUpdateCaDTO
|
||||
} from "./types";
|
||||
|
||||
export const useCreateCa = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificateAuthority, {}, TCreateCaDTO>({
|
||||
mutationFn: async (body) => {
|
||||
const {
|
||||
data: { ca }
|
||||
} = await apiRequest.post<{ ca: TCertificateAuthority }>("/api/v1/pki/ca/", body);
|
||||
return ca;
|
||||
},
|
||||
onSuccess: (_, { projectSlug }) => {
|
||||
queryClient.invalidateQueries(workspaceKeys.getWorkspaceCas({ projectSlug }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateCa = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificateAuthority, {}, TUpdateCaDTO>({
|
||||
mutationFn: async ({ caId, projectSlug, ...body }) => {
|
||||
const {
|
||||
data: { ca }
|
||||
} = await apiRequest.patch<{ ca: TCertificateAuthority }>(`/api/v1/pki/ca/${caId}`, body);
|
||||
return ca;
|
||||
},
|
||||
onSuccess: (_, { projectSlug }) => {
|
||||
queryClient.invalidateQueries(workspaceKeys.getWorkspaceCas({ projectSlug }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteCa = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificateAuthority, {}, TDeleteCaDTO>({
|
||||
mutationFn: async ({ caId }) => {
|
||||
const {
|
||||
data: { ca }
|
||||
} = await apiRequest.delete<{ ca: TCertificateAuthority }>(`/api/v1/pki/ca/${caId}`);
|
||||
return ca;
|
||||
},
|
||||
onSuccess: (_, { projectSlug }) => {
|
||||
queryClient.invalidateQueries(workspaceKeys.getWorkspaceCas({ projectSlug }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useSignIntermediate = () => {
|
||||
// TODO: consider renaming
|
||||
return useMutation<TSignIntermediateResponse, {}, TSignIntermediateDTO>({
|
||||
mutationFn: async (body) => {
|
||||
const { data } = await apiRequest.post<TSignIntermediateResponse>(
|
||||
`/api/v1/pki/ca/${body.caId}/sign-intermediate`,
|
||||
body
|
||||
);
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useImportCaCertificate = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TImportCaCertificateResponse, {}, TImportCaCertificateDTO>({
|
||||
mutationFn: async ({ caId, ...body }) => {
|
||||
const { data } = await apiRequest.post<TImportCaCertificateResponse>(
|
||||
`/api/v1/pki/ca/${caId}/import-certificate`,
|
||||
body
|
||||
);
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectSlug }) => {
|
||||
queryClient.invalidateQueries(workspaceKeys.getWorkspaceCas({ projectSlug }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// consider rename to issue certificate
|
||||
export const useCreateCertificate = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCreateCertificateResponse, {}, TCreateCertificateDTO>({
|
||||
mutationFn: async ({ caId, ...body }) => {
|
||||
const { data } = await apiRequest.post<TCreateCertificateResponse>(
|
||||
`/api/v1/pki/ca/${caId}/issue-certificate`,
|
||||
body
|
||||
);
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectSlug }) => {
|
||||
queryClient.invalidateQueries(workspaceKeys.forWorkspaceCertificates(projectSlug));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { TCertificateAuthority } from "./types";
|
||||
|
||||
export const caKeys = {
|
||||
getCaById: (caId: string) => [{ caId }, "ca"],
|
||||
getCaCert: (caId: string) => [{ caId }, "ca-cert"],
|
||||
getCaCsr: (caId: string) => [{ caId }, "ca-csr"],
|
||||
getCaCrl: (caId: string) => [{ caId }, "ca-crl"]
|
||||
};
|
||||
|
||||
export const useGetCaById = (caId: string) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getCaById(caId),
|
||||
queryFn: async () => {
|
||||
const {
|
||||
data: { ca }
|
||||
} = await apiRequest.get<{ ca: TCertificateAuthority }>(`/api/v1/pki/ca/${caId}`);
|
||||
return ca;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetCaCert = (caId: string) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getCaCert(caId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
certificate: string;
|
||||
certificateChain: string;
|
||||
serialNumber: string;
|
||||
}>(`/api/v1/pki/ca/${caId}/certificate`);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetCaCsr = (caId: string) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getCaCsr(caId),
|
||||
queryFn: async () => {
|
||||
const {
|
||||
data: { csr }
|
||||
} = await apiRequest.get<{
|
||||
csr: string;
|
||||
}>(`/api/v1/pki/ca/${caId}/csr`);
|
||||
return csr;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetCaCrl = (caId: string) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getCaCrl(caId),
|
||||
queryFn: async () => {
|
||||
const {
|
||||
data: { crl }
|
||||
} = await apiRequest.get<{
|
||||
crl: string;
|
||||
}>(`/api/v1/pki/ca/${caId}/crl`);
|
||||
return crl;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
import { CertKeyAlgorithm } from "../certificates/enums";
|
||||
import { CaStatus, CaType } from "./enums";
|
||||
|
||||
export type TCertificateAuthority = {
|
||||
id: string;
|
||||
parentCaId?: string;
|
||||
projectId: string;
|
||||
type: CaType;
|
||||
status: CaStatus;
|
||||
friendlyName: string;
|
||||
organization: string;
|
||||
ou: string;
|
||||
country: string;
|
||||
province: string;
|
||||
locality: string;
|
||||
commonName: string;
|
||||
dn: string;
|
||||
maxPathLength?: number;
|
||||
notAfter?: string;
|
||||
notBefore?: string;
|
||||
keyAlgorithm: CertKeyAlgorithm;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type TCreateCaDTO = {
|
||||
projectSlug: string;
|
||||
type: string;
|
||||
friendlyName?: string;
|
||||
organization: string;
|
||||
ou: string;
|
||||
country: string;
|
||||
province: string;
|
||||
locality: string;
|
||||
commonName: string;
|
||||
notAfter?: string;
|
||||
maxPathLength: number;
|
||||
keyAlgorithm: CertKeyAlgorithm;
|
||||
};
|
||||
|
||||
export type TUpdateCaDTO = {
|
||||
projectSlug: string;
|
||||
caId: string;
|
||||
status?: CaStatus;
|
||||
};
|
||||
|
||||
export type TDeleteCaDTO = {
|
||||
projectSlug: string;
|
||||
caId: string;
|
||||
};
|
||||
|
||||
export type TSignIntermediateDTO = {
|
||||
caId: string;
|
||||
csr: string;
|
||||
maxPathLength: number;
|
||||
notBefore?: string;
|
||||
notAfter?: string;
|
||||
};
|
||||
|
||||
export type TSignIntermediateResponse = {
|
||||
certificate: string;
|
||||
certificateChain: string;
|
||||
issuingCaCertificate: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
|
||||
export type TImportCaCertificateDTO = {
|
||||
caId: string;
|
||||
projectSlug: string;
|
||||
certificate: string;
|
||||
certificateChain: string;
|
||||
};
|
||||
|
||||
export type TImportCaCertificateResponse = {
|
||||
message: string;
|
||||
caId: string;
|
||||
};
|
||||
|
||||
export type TCreateCertificateDTO = {
|
||||
projectSlug: string;
|
||||
caId: string;
|
||||
friendlyName?: string;
|
||||
commonName: string;
|
||||
ttl: string; // string compatible with ms
|
||||
notBefore?: string;
|
||||
notAfter?: string;
|
||||
};
|
||||
|
||||
export type TCreateCertificateResponse = {
|
||||
certificate: string;
|
||||
issuingCertificate: string;
|
||||
certificateChain: string;
|
||||
privateKey: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
import { CertKeyAlgorithm, CertStatus,CrlReason } from "./enums";
|
||||
|
||||
export const certStatusToNameMap: { [K in CertStatus]: string } = {
|
||||
[CertStatus.ACTIVE]: "Active",
|
||||
[CertStatus.REVOKED]: "Revoked"
|
||||
};
|
||||
|
||||
export const certKeyAlgorithmToNameMap: { [K in CertKeyAlgorithm]: string } = {
|
||||
[CertKeyAlgorithm.RSA_2048]: "RSA 2048",
|
||||
[CertKeyAlgorithm.RSA_4096]: "RSA 4096",
|
||||
[CertKeyAlgorithm.ECDSA_P256]: "ECDSA P256",
|
||||
[CertKeyAlgorithm.ECDSA_P384]: "ECDSA P384"
|
||||
};
|
||||
|
||||
export const certKeyAlgorithms = [
|
||||
{ label: certKeyAlgorithmToNameMap[CertKeyAlgorithm.RSA_2048], value: CertKeyAlgorithm.RSA_2048 },
|
||||
{ label: certKeyAlgorithmToNameMap[CertKeyAlgorithm.RSA_4096], value: CertKeyAlgorithm.RSA_4096 },
|
||||
{
|
||||
label: certKeyAlgorithmToNameMap[CertKeyAlgorithm.ECDSA_P256],
|
||||
value: CertKeyAlgorithm.ECDSA_P256
|
||||
},
|
||||
{
|
||||
label: certKeyAlgorithmToNameMap[CertKeyAlgorithm.ECDSA_P384],
|
||||
value: CertKeyAlgorithm.ECDSA_P384
|
||||
}
|
||||
];
|
||||
|
||||
export const crlReasonToNameMap: { [K in CrlReason]: string } = {
|
||||
[CrlReason.UNSPECIFIED]: "Unspecified",
|
||||
[CrlReason.KEY_COMPROMISE]: "Key Compromise",
|
||||
[CrlReason.CA_COMPROMISE]: "CA Compromise",
|
||||
[CrlReason.AFFILIATION_CHANGED]: "Affiliation Changed",
|
||||
[CrlReason.SUPERSEDED]: "Superseded",
|
||||
[CrlReason.CESSATION_OF_OPERATION]: "Cessation of Operation",
|
||||
[CrlReason.CERTIFICATE_HOLD]: "Certificate Hold",
|
||||
// [CrlReason.REMOVE_FROM_CRL]: "Remove from CRL",
|
||||
[CrlReason.PRIVILEGE_WITHDRAWN]: "Privilege Withdrawn",
|
||||
[CrlReason.A_A_COMPROMISE]: "A/A Compromise"
|
||||
};
|
||||
|
||||
export const crlReasons = [
|
||||
{ label: crlReasonToNameMap[CrlReason.UNSPECIFIED], value: CrlReason.UNSPECIFIED },
|
||||
{ label: crlReasonToNameMap[CrlReason.KEY_COMPROMISE], value: CrlReason.KEY_COMPROMISE },
|
||||
{ label: crlReasonToNameMap[CrlReason.CA_COMPROMISE], value: CrlReason.CA_COMPROMISE },
|
||||
{
|
||||
label: crlReasonToNameMap[CrlReason.AFFILIATION_CHANGED],
|
||||
value: CrlReason.AFFILIATION_CHANGED
|
||||
},
|
||||
{ label: crlReasonToNameMap[CrlReason.SUPERSEDED], value: CrlReason.SUPERSEDED },
|
||||
{
|
||||
label: crlReasonToNameMap[CrlReason.CESSATION_OF_OPERATION],
|
||||
value: CrlReason.CESSATION_OF_OPERATION
|
||||
},
|
||||
{ label: crlReasonToNameMap[CrlReason.CERTIFICATE_HOLD], value: CrlReason.CERTIFICATE_HOLD },
|
||||
{
|
||||
label: crlReasonToNameMap[CrlReason.PRIVILEGE_WITHDRAWN],
|
||||
value: CrlReason.PRIVILEGE_WITHDRAWN
|
||||
},
|
||||
{ label: crlReasonToNameMap[CrlReason.A_A_COMPROMISE], value: CrlReason.A_A_COMPROMISE }
|
||||
];
|
||||
@@ -0,0 +1,24 @@
|
||||
export enum CertStatus {
|
||||
ACTIVE = "active",
|
||||
REVOKED = "revoked"
|
||||
}
|
||||
|
||||
export enum CertKeyAlgorithm {
|
||||
RSA_2048 = "RSA_2048",
|
||||
RSA_4096 = "RSA_4096",
|
||||
ECDSA_P256 = "EC_prime256v1",
|
||||
ECDSA_P384 = "EC_secp384r1"
|
||||
}
|
||||
|
||||
export enum CrlReason {
|
||||
UNSPECIFIED = "UNSPECIFIED",
|
||||
KEY_COMPROMISE = "KEY_COMPROMISE",
|
||||
CA_COMPROMISE = "CA_COMPROMISE",
|
||||
AFFILIATION_CHANGED = "AFFILIATION_CHANGED",
|
||||
SUPERSEDED = "SUPERSEDED",
|
||||
CESSATION_OF_OPERATION = "CESSATION_OF_OPERATION",
|
||||
CERTIFICATE_HOLD = "CERTIFICATE_HOLD",
|
||||
// REMOVE_FROM_CRL = "REMOVE_FROM_CRL",
|
||||
PRIVILEGE_WITHDRAWN = "PRIVILEGE_WITHDRAWN",
|
||||
A_A_COMPROMISE = "A_A_COMPROMISE"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export { useDeleteCert, useRevokeCert } from "./mutations";
|
||||
export { useGetCert, useGetCertBody } from "./queries";
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { workspaceKeys } from "../workspace/queries";
|
||||
import { TCertificate, TDeleteCertDTO, TRevokeCertDTO } from "./types";
|
||||
|
||||
export const useDeleteCert = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificate, {}, TDeleteCertDTO>({
|
||||
mutationFn: async ({ serialNumber }) => {
|
||||
const {
|
||||
data: { certificate }
|
||||
} = await apiRequest.delete<{ certificate: TCertificate }>(
|
||||
`/api/v1/pki/certificates/${serialNumber}`
|
||||
);
|
||||
return certificate;
|
||||
},
|
||||
onSuccess: (_, { projectSlug }) => {
|
||||
queryClient.invalidateQueries(workspaceKeys.forWorkspaceCertificates(projectSlug));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useRevokeCert = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificate, {}, TRevokeCertDTO>({
|
||||
mutationFn: async ({ serialNumber, revocationReason }) => {
|
||||
const {
|
||||
data: { certificate }
|
||||
} = await apiRequest.post<{ certificate: TCertificate }>(
|
||||
`/api/v1/pki/certificates/${serialNumber}/revoke`,
|
||||
{
|
||||
revocationReason
|
||||
}
|
||||
);
|
||||
return certificate;
|
||||
},
|
||||
onSuccess: (_, { projectSlug }) => {
|
||||
queryClient.invalidateQueries(workspaceKeys.forWorkspaceCertificates(projectSlug));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { TCertificate } from "./types";
|
||||
|
||||
export const certKeys = {
|
||||
getCertById: (serialNumber: string) => [{ serialNumber }, "cert"],
|
||||
getCertBody: (serialNumber: string) => [{ serialNumber }, "certBody"]
|
||||
};
|
||||
|
||||
export const useGetCert = (serialNumber: string) => {
|
||||
return useQuery({
|
||||
queryKey: certKeys.getCertById(serialNumber),
|
||||
queryFn: async () => {
|
||||
const {
|
||||
data: { certificate }
|
||||
} = await apiRequest.get<{ certificate: TCertificate }>(
|
||||
`/api/v1/pki/certificates/${serialNumber}`
|
||||
);
|
||||
return certificate;
|
||||
},
|
||||
enabled: Boolean(serialNumber)
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetCertBody = (serialNumber: string) => {
|
||||
return useQuery({
|
||||
queryKey: certKeys.getCertBody(serialNumber),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
certificate: string;
|
||||
certificateChain: string;
|
||||
serialNumber: string;
|
||||
}>(`/api/v1/pki/certificates/${serialNumber}/certificate`);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(serialNumber)
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { CertStatus } from "./enums";
|
||||
|
||||
export type TCertificate = {
|
||||
id: string;
|
||||
caId: string;
|
||||
status: CertStatus;
|
||||
friendlyName: string;
|
||||
commonName: string;
|
||||
serialNumber: string;
|
||||
notBefore: string;
|
||||
notAfter: string;
|
||||
};
|
||||
|
||||
export type TDeleteCertDTO = {
|
||||
projectSlug: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
|
||||
export type TRevokeCertDTO = {
|
||||
projectSlug: string;
|
||||
serialNumber: string;
|
||||
revocationReason: string;
|
||||
};
|
||||
@@ -5,6 +5,8 @@ export * from "./auditLogs";
|
||||
export * from "./auditLogStreams";
|
||||
export * from "./auth";
|
||||
export * from "./bots";
|
||||
export * from "./ca";
|
||||
export * from "./certificates";
|
||||
export * from "./dynamicSecret";
|
||||
export * from "./dynamicSecretLease";
|
||||
export * from "./groups";
|
||||
|
||||
@@ -25,14 +25,15 @@ export type SubscriptionPlan = {
|
||||
ldap: boolean;
|
||||
groups: boolean;
|
||||
status:
|
||||
| "incomplete"
|
||||
| "incomplete_expired"
|
||||
| "trialing"
|
||||
| "active"
|
||||
| "past_due"
|
||||
| "canceled"
|
||||
| "unpaid"
|
||||
| null;
|
||||
| "incomplete"
|
||||
| "incomplete_expired"
|
||||
| "trialing"
|
||||
| "active"
|
||||
| "past_due"
|
||||
| "canceled"
|
||||
| "unpaid"
|
||||
| null;
|
||||
trial_end: number | null;
|
||||
has_used_trial: boolean;
|
||||
caCrl: boolean;
|
||||
};
|
||||
|
||||
@@ -21,6 +21,8 @@ export {
|
||||
useGetWorkspaceIntegrations,
|
||||
useGetWorkspaceSecrets,
|
||||
useGetWorkspaceUsers,
|
||||
useListWorkspaceCas,
|
||||
useListWorkspaceCertificates,
|
||||
useListWorkspaceGroups,
|
||||
useNameWorkspaceSecrets,
|
||||
useRenameWorkspace,
|
||||
@@ -28,5 +30,4 @@ export {
|
||||
useUpdateIdentityWorkspaceRole,
|
||||
useUpdateUserWorkspaceRole,
|
||||
useUpdateWsEnvironment,
|
||||
useUpgradeProject
|
||||
} from "./queries";
|
||||
useUpgradeProject} from "./queries";
|
||||
|
||||
@@ -2,6 +2,9 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { CaStatus } from "../ca/enums";
|
||||
import { TCertificateAuthority } from "../ca/types";
|
||||
import { TCertificate } from "../certificates/types";
|
||||
import { TGroupMembership } from "../groups/types";
|
||||
import { IdentityMembership } from "../identities/types";
|
||||
import { IntegrationAuth } from "../integrationAuth/types";
|
||||
@@ -40,7 +43,23 @@ export const workspaceKeys = {
|
||||
getWorkspaceIdentityMemberships: (workspaceId: string) =>
|
||||
[{ workspaceId }, "workspace-identity-memberships"] as const,
|
||||
getWorkspaceGroupMemberships: (workspaceId: string) =>
|
||||
[{ workspaceId }, "workspace-groups"] as const
|
||||
[{ workspaceId }, "workspace-groups"] as const,
|
||||
getWorkspaceCas: ({ projectSlug }: { projectSlug: string }) =>
|
||||
[{ projectSlug }, "workspace-cas"] as const,
|
||||
specificWorkspaceCas: ({ projectSlug, status }: { projectSlug: string; status?: CaStatus }) =>
|
||||
[...workspaceKeys.getWorkspaceCas({ projectSlug }), { status }] as const,
|
||||
allWorkspaceCertificates: () => ["workspace-certificates"] as const,
|
||||
forWorkspaceCertificates: (slug: string) =>
|
||||
[...workspaceKeys.allWorkspaceCertificates(), slug] as const,
|
||||
specificWorkspaceCertificates: ({
|
||||
slug,
|
||||
offset,
|
||||
limit
|
||||
}: {
|
||||
slug: string;
|
||||
offset: number;
|
||||
limit: number;
|
||||
}) => [...workspaceKeys.forWorkspaceCertificates(slug), { offset, limit }] as const
|
||||
};
|
||||
|
||||
const fetchWorkspaceById = async (workspaceId: string) => {
|
||||
@@ -485,3 +504,70 @@ export const useListWorkspaceGroups = (projectSlug: string) => {
|
||||
enabled: true
|
||||
});
|
||||
};
|
||||
|
||||
export const useListWorkspaceCas = ({
|
||||
projectSlug,
|
||||
status
|
||||
}: {
|
||||
projectSlug: string;
|
||||
status?: CaStatus;
|
||||
}) => {
|
||||
return useQuery({
|
||||
queryKey: workspaceKeys.specificWorkspaceCas({
|
||||
projectSlug,
|
||||
status
|
||||
}),
|
||||
queryFn: async () => {
|
||||
const params = new URLSearchParams({
|
||||
...(status && { status })
|
||||
});
|
||||
|
||||
const {
|
||||
data: { cas }
|
||||
} = await apiRequest.get<{ cas: TCertificateAuthority[] }>(
|
||||
`/api/v2/workspace/${projectSlug}/cas`,
|
||||
{
|
||||
params
|
||||
}
|
||||
);
|
||||
return cas;
|
||||
},
|
||||
enabled: Boolean(projectSlug)
|
||||
});
|
||||
};
|
||||
|
||||
export const useListWorkspaceCertificates = ({
|
||||
projectSlug,
|
||||
offset,
|
||||
limit
|
||||
}: {
|
||||
projectSlug: string;
|
||||
offset: number;
|
||||
limit: number;
|
||||
}) => {
|
||||
return useQuery({
|
||||
queryKey: workspaceKeys.specificWorkspaceCertificates({
|
||||
slug: projectSlug,
|
||||
offset,
|
||||
limit
|
||||
}),
|
||||
queryFn: async () => {
|
||||
const params = new URLSearchParams({
|
||||
offset: String(offset),
|
||||
limit: String(limit)
|
||||
});
|
||||
|
||||
const {
|
||||
data: { certificates, totalCount }
|
||||
} = await apiRequest.get<{ certificates: TCertificate[]; totalCount: number }>(
|
||||
`/api/v2/workspace/${projectSlug}/certificates`,
|
||||
{
|
||||
params
|
||||
}
|
||||
);
|
||||
|
||||
return { certificates, totalCount };
|
||||
},
|
||||
enabled: Boolean(projectSlug)
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user