mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 21:40:31 +00:00
Merge pull request #2497 from scott-ray-wilson/kms-feature
Feature: KMS MVP
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export * from "./mutations";
|
||||
export * from "./queries";
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,90 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { encodeBase64 } from "tweetnacl-util";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
import { cmekKeys } from "@app/hooks/api/cmeks/queries";
|
||||
import {
|
||||
TCmekDecrypt,
|
||||
TCmekDecryptResponse,
|
||||
TCmekEncrypt,
|
||||
TCmekEncryptResponse,
|
||||
TCreateCmek,
|
||||
TDeleteCmek,
|
||||
TUpdateCmek
|
||||
} from "@app/hooks/api/cmeks/types";
|
||||
|
||||
export const useCreateCmek = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (payload: TCreateCmek) => {
|
||||
const { data } = await apiRequest.post("/api/v1/kms/keys", payload);
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectId }) => {
|
||||
queryClient.invalidateQueries(cmekKeys.getCmeksByProjectId({ projectId }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateCmek = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ keyId, name, description, isDisabled }: TUpdateCmek) => {
|
||||
const { data } = await apiRequest.patch(`/api/v1/kms/keys/${keyId}`, {
|
||||
name,
|
||||
description,
|
||||
isDisabled
|
||||
});
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectId }) => {
|
||||
queryClient.invalidateQueries(cmekKeys.getCmeksByProjectId({ projectId }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteCmek = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ keyId }: TDeleteCmek) => {
|
||||
const { data } = await apiRequest.delete(`/api/v1/kms/keys/${keyId}`);
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectId }) => {
|
||||
queryClient.invalidateQueries(cmekKeys.getCmeksByProjectId({ projectId }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useCmekEncrypt = () => {
|
||||
return useMutation({
|
||||
mutationFn: async ({ keyId, plaintext, isBase64Encoded }: TCmekEncrypt) => {
|
||||
const { data } = await apiRequest.post<TCmekEncryptResponse>(
|
||||
`/api/v1/kms/keys/${keyId}/encrypt`,
|
||||
{
|
||||
plaintext: isBase64Encoded ? plaintext : encodeBase64(Buffer.from(plaintext))
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useCmekDecrypt = () => {
|
||||
return useMutation({
|
||||
mutationFn: async ({ keyId, ciphertext }: TCmekDecrypt) => {
|
||||
const { data } = await apiRequest.post<TCmekDecryptResponse>(
|
||||
`/api/v1/kms/keys/${keyId}/decrypt`,
|
||||
{
|
||||
ciphertext
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
import { CmekOrderBy, TListProjectCmeksDTO, TProjectCmeksList } from "@app/hooks/api/cmeks/types";
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
|
||||
export const cmekKeys = {
|
||||
all: ["cmek"] as const,
|
||||
lists: () => [...cmekKeys.all, "list"] as const,
|
||||
getCmeksByProjectId: ({ projectId, ...filters }: TListProjectCmeksDTO) =>
|
||||
[...cmekKeys.lists(), projectId, filters] as const
|
||||
};
|
||||
|
||||
export const useGetCmeksByProjectId = (
|
||||
{
|
||||
projectId,
|
||||
offset = 0,
|
||||
limit = 100,
|
||||
orderBy = CmekOrderBy.Name,
|
||||
orderDirection = OrderByDirection.ASC,
|
||||
search = ""
|
||||
}: TListProjectCmeksDTO,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
TProjectCmeksList,
|
||||
unknown,
|
||||
TProjectCmeksList,
|
||||
ReturnType<typeof cmekKeys.getCmeksByProjectId>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: cmekKeys.getCmeksByProjectId({
|
||||
projectId,
|
||||
offset,
|
||||
limit,
|
||||
orderBy,
|
||||
orderDirection,
|
||||
search
|
||||
}),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TProjectCmeksList>("/api/v1/kms/keys", {
|
||||
params: { projectId, offset, limit, search, orderBy, orderDirection }
|
||||
});
|
||||
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(projectId) && (options?.enabled ?? true),
|
||||
keepPreviousData: true,
|
||||
...options
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
|
||||
export type TCmek = {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
encryptionAlgorithm: EncryptionAlgorithm;
|
||||
projectId: string;
|
||||
isDisabled: boolean;
|
||||
isReserved: boolean;
|
||||
orgId: string;
|
||||
version: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
type ProjectRef = { projectId: string };
|
||||
type KeyRef = { keyId: string };
|
||||
|
||||
export type TCreateCmek = Pick<TCmek, "name" | "description" | "encryptionAlgorithm"> & ProjectRef;
|
||||
export type TUpdateCmek = KeyRef &
|
||||
Partial<Pick<TCmek, "name" | "description" | "isDisabled">> &
|
||||
ProjectRef;
|
||||
export type TDeleteCmek = KeyRef & ProjectRef;
|
||||
|
||||
export type TCmekEncrypt = KeyRef & { plaintext: string; isBase64Encoded?: boolean };
|
||||
export type TCmekDecrypt = KeyRef & { ciphertext: string };
|
||||
|
||||
export type TProjectCmeksList = {
|
||||
keys: TCmek[];
|
||||
totalCount: number;
|
||||
};
|
||||
|
||||
export type TListProjectCmeksDTO = {
|
||||
projectId: string;
|
||||
offset?: number;
|
||||
limit?: number;
|
||||
orderBy?: CmekOrderBy;
|
||||
orderDirection?: OrderByDirection;
|
||||
search?: string;
|
||||
};
|
||||
|
||||
export type TCmekEncryptResponse = {
|
||||
ciphertext: string;
|
||||
};
|
||||
|
||||
export type TCmekDecryptResponse = {
|
||||
plaintext: string;
|
||||
};
|
||||
|
||||
export enum CmekOrderBy {
|
||||
Name = "name"
|
||||
}
|
||||
|
||||
export enum EncryptionAlgorithm {
|
||||
AES_GCM_256 = "aes-256-gcm",
|
||||
AES_GCM_128 = "aes-128-gcm"
|
||||
}
|
||||
@@ -8,9 +8,9 @@ import { AddExternalKmsType, KmsType } from "./types";
|
||||
export const useAddExternalKms = (orgId: string) => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ slug, description, provider }: AddExternalKmsType) => {
|
||||
mutationFn: async ({ name, description, provider }: AddExternalKmsType) => {
|
||||
const { data } = await apiRequest.post("/api/v1/external-kms", {
|
||||
slug,
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
});
|
||||
@@ -28,14 +28,14 @@ export const useUpdateExternalKms = (orgId: string) => {
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
kmsId,
|
||||
slug,
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
}: {
|
||||
kmsId: string;
|
||||
} & AddExternalKmsType) => {
|
||||
const { data } = await apiRequest.patch(`/api/v1/external-kms/${kmsId}`, {
|
||||
slug,
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
});
|
||||
|
||||
@@ -46,7 +46,7 @@ export const useGetActiveProjectKms = (projectId: string) => {
|
||||
} = await apiRequest.get<{
|
||||
secretManagerKmsKey: {
|
||||
id: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
isExternal: string;
|
||||
};
|
||||
}>(`/api/v1/workspace/${projectId}/kms`);
|
||||
|
||||
@@ -5,7 +5,7 @@ export type Kms = {
|
||||
id: string;
|
||||
description: string;
|
||||
orgId: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
external: {
|
||||
id: string;
|
||||
status: string;
|
||||
@@ -21,7 +21,7 @@ export type KmsListEntry = {
|
||||
isDisabled: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
externalKms: {
|
||||
provider: string;
|
||||
status: string;
|
||||
@@ -88,7 +88,7 @@ export const ExternalKmsInputSchema = z.discriminatedUnion("type", [
|
||||
]);
|
||||
|
||||
export const AddExternalKmsSchema = z.object({
|
||||
slug: z
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
|
||||
@@ -122,6 +122,6 @@ export type TOrgIdentitiesList = {
|
||||
};
|
||||
|
||||
export enum OrgIdentityOrderBy {
|
||||
Name = "name",
|
||||
Role = "role"
|
||||
Name = "name"
|
||||
// Role = "role"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user