mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
fix: kms endpoints to rerutn credentialsHash
This commit is contained in:
@@ -3,35 +3,27 @@ import { z } from "zod";
|
||||
import { ExternalKmsSchema, KmsKeysSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import {
|
||||
ExternalKmsAwsSchema,
|
||||
ExternalKmsGcpSchema,
|
||||
KmsProviders,
|
||||
SanitizedExternalKmsAwsSchema,
|
||||
SanitizedExternalKmsGcpSchema,
|
||||
TExternalKmsInputSchema,
|
||||
TExternalKmsInputUpdateSchema
|
||||
} from "@app/ee/services/external-kms/providers/model";
|
||||
import { crypto } from "@app/lib/crypto/cryptography";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
const sanitizedExternalSchema = KmsKeysSchema.extend({
|
||||
external: ExternalKmsSchema.pick({
|
||||
id: true,
|
||||
status: true,
|
||||
statusDetails: true,
|
||||
provider: true
|
||||
})
|
||||
});
|
||||
|
||||
const sanitizedExternalSchemaForGetById = KmsKeysSchema.extend({
|
||||
external: ExternalKmsSchema.pick({
|
||||
externalKms: ExternalKmsSchema.pick({
|
||||
id: true,
|
||||
status: true,
|
||||
statusDetails: true,
|
||||
provider: true
|
||||
}).extend({
|
||||
// for GCP, we don't return the credential object as it is sensitive data that should not be exposed
|
||||
providerInput: z.union([ExternalKmsAwsSchema, ExternalKmsGcpSchema.pick({ gcpRegion: true, keyName: true })])
|
||||
configuration: z.union([SanitizedExternalKmsAwsSchema, SanitizedExternalKmsGcpSchema]),
|
||||
credentialsHash: z.string().optional()
|
||||
})
|
||||
});
|
||||
|
||||
@@ -59,9 +51,7 @@ export const registerExternalKmsEndpoints = <
|
||||
id: z.string().trim().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
externalKms: sanitizedExternalSchemaForGetById
|
||||
})
|
||||
200: sanitizedExternalSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
@@ -93,7 +83,16 @@ export const registerExternalKmsEndpoints = <
|
||||
}
|
||||
});
|
||||
|
||||
return { externalKms };
|
||||
const {
|
||||
external: { providerInput: configuration, ...externalKmsData },
|
||||
...rest
|
||||
} = externalKms;
|
||||
|
||||
const credentialsHash = crypto.nativeCrypto
|
||||
.createHash("sha256")
|
||||
.update(externalKmsData.encryptedProviderInputs)
|
||||
.digest("hex");
|
||||
return { ...rest, externalKms: { ...externalKmsData, configuration, credentialsHash } };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -110,9 +109,7 @@ export const registerExternalKmsEndpoints = <
|
||||
configuration: createSchema
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
externalKms: sanitizedExternalSchema
|
||||
})
|
||||
200: sanitizedExternalSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
@@ -152,7 +149,15 @@ export const registerExternalKmsEndpoints = <
|
||||
}
|
||||
});
|
||||
|
||||
return { externalKms };
|
||||
const {
|
||||
external: { providerInput: externalKmsConfiguration, ...externalKmsData },
|
||||
...rest
|
||||
} = externalKms;
|
||||
const credentialsHash = crypto.nativeCrypto
|
||||
.createHash("sha256")
|
||||
.update(externalKmsData.encryptedProviderInputs)
|
||||
.digest("hex");
|
||||
return { ...rest, externalKms: { ...externalKmsData, configuration: externalKmsConfiguration, credentialsHash } };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -169,12 +174,10 @@ export const registerExternalKmsEndpoints = <
|
||||
body: z.object({
|
||||
name: z.string().min(1).trim().toLowerCase().optional(),
|
||||
description: z.string().trim().optional(),
|
||||
configuration: updateSchema
|
||||
configuration: updateSchema.optional()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
externalKms: sanitizedExternalSchema
|
||||
})
|
||||
200: sanitizedExternalSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
@@ -215,7 +218,15 @@ export const registerExternalKmsEndpoints = <
|
||||
}
|
||||
});
|
||||
|
||||
return { externalKms };
|
||||
const {
|
||||
external: { providerInput: externalKmsConfiguration, ...externalKmsData },
|
||||
...rest
|
||||
} = externalKms;
|
||||
const credentialsHash = crypto.nativeCrypto
|
||||
.createHash("sha256")
|
||||
.update(externalKmsData.encryptedProviderInputs)
|
||||
.digest("hex");
|
||||
return { ...rest, externalKms: { ...externalKmsData, configuration: externalKmsConfiguration, credentialsHash } };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -230,9 +241,7 @@ export const registerExternalKmsEndpoints = <
|
||||
id: z.string().trim().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
externalKms: sanitizedExternalSchema
|
||||
})
|
||||
200: sanitizedExternalSchema
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
@@ -264,7 +273,16 @@ export const registerExternalKmsEndpoints = <
|
||||
}
|
||||
});
|
||||
|
||||
return { externalKms };
|
||||
const {
|
||||
external: { providerInput: configuration, ...externalKmsData },
|
||||
...rest
|
||||
} = externalKms;
|
||||
const credentialsHash = crypto.nativeCrypto
|
||||
.createHash("sha256")
|
||||
.update(externalKmsData.encryptedProviderInputs)
|
||||
.digest("hex");
|
||||
|
||||
return { ...rest, externalKms: { ...externalKmsData, configuration, credentialsHash } };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -24,7 +24,13 @@ import {
|
||||
} from "./external-kms-types";
|
||||
import { AwsKmsProviderFactory } from "./providers/aws-kms";
|
||||
import { GcpKmsProviderFactory } from "./providers/gcp-kms";
|
||||
import { ExternalKmsAwsSchema, ExternalKmsGcpSchema, KmsProviders, TExternalKmsGcpSchema } from "./providers/model";
|
||||
import {
|
||||
ExternalKmsAwsSchema,
|
||||
ExternalKmsGcpSchema,
|
||||
KmsProviders,
|
||||
TExternalKmsAwsSchema,
|
||||
TExternalKmsGcpSchema
|
||||
} from "./providers/model";
|
||||
|
||||
type TExternalKmsServiceFactoryDep = {
|
||||
externalKmsDAL: TExternalKmsDALFactory;
|
||||
@@ -72,6 +78,7 @@ export const externalKmsServiceFactory = ({
|
||||
const kmsName = name ? slugify(name) : slugify(alphaNumericNanoId(8).toLowerCase());
|
||||
|
||||
let sanitizedProviderInput = "";
|
||||
let sanitizedProviderInputObject: TExternalKmsAwsSchema | TExternalKmsGcpSchema;
|
||||
switch (provider.type) {
|
||||
case KmsProviders.Aws:
|
||||
{
|
||||
@@ -88,6 +95,7 @@ export const externalKmsServiceFactory = ({
|
||||
try {
|
||||
// if missing kms key this generate a new kms key id and returns new provider input
|
||||
const newProviderInput = await externalKms.generateInputKmsKey();
|
||||
sanitizedProviderInputObject = newProviderInput;
|
||||
sanitizedProviderInput = JSON.stringify(newProviderInput);
|
||||
|
||||
await externalKms.validateConnection();
|
||||
@@ -109,6 +117,7 @@ export const externalKmsServiceFactory = ({
|
||||
const externalKms = await GcpKmsProviderFactory({ inputs: provider.inputs });
|
||||
try {
|
||||
await externalKms.validateConnection();
|
||||
sanitizedProviderInputObject = provider.inputs;
|
||||
sanitizedProviderInput = JSON.stringify(provider.inputs);
|
||||
} catch (error) {
|
||||
if (error instanceof BadRequestError) {
|
||||
@@ -155,7 +164,10 @@ export const externalKmsServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
return { ...kms, external: externalKmsCfg };
|
||||
return {
|
||||
...kms,
|
||||
external: { ...externalKmsCfg, providerInput: sanitizedProviderInputObject }
|
||||
};
|
||||
});
|
||||
|
||||
return externalKms;
|
||||
@@ -195,6 +207,7 @@ export const externalKmsServiceFactory = ({
|
||||
if (!externalKmsDoc) throw new NotFoundError({ message: `External KMS with ID '${kmsId}' not found` });
|
||||
|
||||
let sanitizedProviderInput = "";
|
||||
let sanitizedProviderInputObject: TExternalKmsAwsSchema | TExternalKmsGcpSchema;
|
||||
const { encryptor: orgDataKeyEncryptor, decryptor: orgDataKeyDecryptor } =
|
||||
await kmsService.createCipherPairWithDataKey({
|
||||
type: KmsDataKey.Organization,
|
||||
@@ -215,6 +228,7 @@ export const externalKmsServiceFactory = ({
|
||||
const externalKms = await AwsKmsProviderFactory({ inputs: updatedProviderInput });
|
||||
try {
|
||||
await externalKms.validateConnection();
|
||||
sanitizedProviderInputObject = updatedProviderInput;
|
||||
sanitizedProviderInput = JSON.stringify(updatedProviderInput);
|
||||
} catch (error) {
|
||||
if (error instanceof BadRequestError) {
|
||||
@@ -238,6 +252,7 @@ export const externalKmsServiceFactory = ({
|
||||
const externalKms = await GcpKmsProviderFactory({ inputs: updatedProviderInput });
|
||||
try {
|
||||
await externalKms.validateConnection();
|
||||
sanitizedProviderInputObject = updatedProviderInput;
|
||||
sanitizedProviderInput = JSON.stringify(updatedProviderInput);
|
||||
} catch (error) {
|
||||
if (error instanceof BadRequestError) {
|
||||
@@ -266,14 +281,17 @@ export const externalKmsServiceFactory = ({
|
||||
}
|
||||
|
||||
const externalKms = await externalKmsDAL.transaction(async (tx) => {
|
||||
const kms = await kmsDAL.updateById(
|
||||
kmsDoc.id,
|
||||
{
|
||||
description,
|
||||
name: kmsName
|
||||
},
|
||||
tx
|
||||
);
|
||||
let kms = kmsDoc;
|
||||
if (kmsName || description) {
|
||||
kms = await kmsDAL.updateById(
|
||||
kmsDoc.id,
|
||||
{
|
||||
description,
|
||||
name: kmsName
|
||||
},
|
||||
tx
|
||||
);
|
||||
}
|
||||
if (encryptedProviderInputs) {
|
||||
const externalKmsCfg = await externalKmsDAL.updateById(
|
||||
externalKmsDoc.id,
|
||||
@@ -282,9 +300,9 @@ export const externalKmsServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
return { ...kms, external: externalKmsCfg };
|
||||
return { ...kms, external: { ...externalKmsCfg, providerInput: sanitizedProviderInputObject } };
|
||||
}
|
||||
return { ...kms, external: externalKmsDoc };
|
||||
return { ...kms, external: { ...externalKmsDoc, providerInput: sanitizedProviderInputObject } };
|
||||
});
|
||||
|
||||
return externalKms;
|
||||
@@ -305,9 +323,40 @@ export const externalKmsServiceFactory = ({
|
||||
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
|
||||
if (!externalKmsDoc) throw new NotFoundError({ message: `External KMS with ID '${kmsId}' not found` });
|
||||
|
||||
let decryptedProviderInputObject: TExternalKmsAwsSchema | TExternalKmsGcpSchema;
|
||||
|
||||
const { decryptor: orgDataKeyDecryptor } = await kmsService.createCipherPairWithDataKey({
|
||||
type: KmsDataKey.Organization,
|
||||
orgId: actorOrgId
|
||||
});
|
||||
|
||||
const decryptedProviderInputBlob = orgDataKeyDecryptor({
|
||||
cipherTextBlob: externalKmsDoc.encryptedProviderInputs
|
||||
});
|
||||
|
||||
switch (externalKmsDoc.provider) {
|
||||
case KmsProviders.Aws: {
|
||||
const decryptedProviderInput = await ExternalKmsAwsSchema.parseAsync(
|
||||
JSON.parse(decryptedProviderInputBlob.toString())
|
||||
);
|
||||
decryptedProviderInputObject = decryptedProviderInput;
|
||||
break;
|
||||
}
|
||||
case KmsProviders.Gcp: {
|
||||
const decryptedProviderInput = await ExternalKmsGcpSchema.parseAsync(
|
||||
JSON.parse(decryptedProviderInputBlob.toString())
|
||||
);
|
||||
|
||||
decryptedProviderInputObject = decryptedProviderInput;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const externalKms = await externalKmsDAL.transaction(async (tx) => {
|
||||
const kms = await kmsDAL.deleteById(kmsDoc.id, tx);
|
||||
return { ...kms, external: externalKmsDoc };
|
||||
return { ...kms, external: { ...externalKmsDoc, providerInput: decryptedProviderInputObject } };
|
||||
});
|
||||
|
||||
return externalKms;
|
||||
|
||||
@@ -19,27 +19,31 @@ export enum KmsGcpKeyFetchAuthType {
|
||||
Kms = "kmsId"
|
||||
}
|
||||
|
||||
const AwsConnectionAssumeRoleCredentialsSchema = z.object({
|
||||
assumeRoleArn: z.string().trim().min(1).describe("AWS user role to be assumed by infisical"),
|
||||
externalId: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
.optional()
|
||||
.describe("AWS assume role external id for furthur security in authentication")
|
||||
});
|
||||
|
||||
const AwsConnectionAccessTokenCredentialsSchema = z.object({
|
||||
accessKey: z.string().trim().min(1).describe("AWS user account access key"),
|
||||
secretKey: z.string().trim().min(1).describe("AWS user account secret key")
|
||||
});
|
||||
|
||||
export const ExternalKmsAwsSchema = z.object({
|
||||
credential: z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal(KmsAwsCredentialType.AccessKey),
|
||||
data: z.object({
|
||||
accessKey: z.string().trim().min(1).describe("AWS user account access key"),
|
||||
secretKey: z.string().trim().min(1).describe("AWS user account secret key")
|
||||
})
|
||||
data: AwsConnectionAccessTokenCredentialsSchema
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal(KmsAwsCredentialType.AssumeRole),
|
||||
data: z.object({
|
||||
assumeRoleArn: z.string().trim().min(1).describe("AWS user role to be assumed by infisical"),
|
||||
externalId: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
.optional()
|
||||
.describe("AWS assume role external id for furthur security in authentication")
|
||||
})
|
||||
data: AwsConnectionAssumeRoleCredentialsSchema
|
||||
})
|
||||
])
|
||||
.describe("AWS credential information to connect"),
|
||||
@@ -52,6 +56,19 @@ export const ExternalKmsAwsSchema = z.object({
|
||||
});
|
||||
export type TExternalKmsAwsSchema = z.infer<typeof ExternalKmsAwsSchema>;
|
||||
|
||||
export const SanitizedExternalKmsAwsSchema = ExternalKmsAwsSchema.extend({
|
||||
credential: z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal(KmsAwsCredentialType.AccessKey),
|
||||
data: AwsConnectionAccessTokenCredentialsSchema.pick({ accessKey: true })
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal(KmsAwsCredentialType.AssumeRole),
|
||||
data: AwsConnectionAssumeRoleCredentialsSchema.pick({})
|
||||
})
|
||||
])
|
||||
});
|
||||
|
||||
export const ExternalKmsGcpCredentialSchema = z.object({
|
||||
type: z.literal(KmsGcpCredentialType.ServiceAccount),
|
||||
project_id: z.string().min(1),
|
||||
@@ -75,6 +92,8 @@ export const ExternalKmsGcpSchema = z.object({
|
||||
});
|
||||
export type TExternalKmsGcpSchema = z.infer<typeof ExternalKmsGcpSchema>;
|
||||
|
||||
export const SanitizedExternalKmsGcpSchema = ExternalKmsGcpSchema.pick({ gcpRegion: true, keyName: true });
|
||||
|
||||
const ExternalKmsGcpClientSchema = ExternalKmsGcpSchema.pick({ gcpRegion: true }).extend({
|
||||
credential: ExternalKmsGcpCredentialSchema
|
||||
});
|
||||
|
||||
@@ -15,12 +15,12 @@ import {
|
||||
export const useAddExternalKms = (orgId: string) => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ name, description, provider }: AddExternalKmsType) => {
|
||||
const providerPath = provider.type === ExternalKmsProvider.Aws ? "aws" : "gcp";
|
||||
mutationFn: async ({ name, description, configuration }: AddExternalKmsType) => {
|
||||
const providerPath = configuration.type === ExternalKmsProvider.Aws ? "aws" : "gcp";
|
||||
const { data } = await apiRequest.post(`/api/v1/external-kms/${providerPath}`, {
|
||||
name,
|
||||
description,
|
||||
configuration: provider.inputs
|
||||
configuration: configuration.inputs
|
||||
});
|
||||
|
||||
return data;
|
||||
@@ -31,22 +31,21 @@ export const useAddExternalKms = (orgId: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateExternalKms = (orgId: string) => {
|
||||
export const useUpdateExternalKms = (orgId: string, provider: ExternalKmsProvider) => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
kmsId,
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
configuration
|
||||
}: {
|
||||
kmsId: string;
|
||||
} & UpdateExternalKmsType) => {
|
||||
const providerPath = provider.type === ExternalKmsProvider.Aws ? "aws" : "gcp";
|
||||
const { data } = await apiRequest.patch(`/api/v1/external-kms/${providerPath}/${kmsId}`, {
|
||||
const { data } = await apiRequest.patch(`/api/v1/external-kms/${provider}/${kmsId}`, {
|
||||
name,
|
||||
description,
|
||||
configuration: provider.inputs
|
||||
configuration: configuration?.inputs
|
||||
});
|
||||
|
||||
return data;
|
||||
|
||||
@@ -34,10 +34,8 @@ export const useGetExternalKmsById = ({
|
||||
queryKey: kmsKeys.getExternalKmsById(kmsId),
|
||||
enabled: Boolean(kmsId),
|
||||
queryFn: async () => {
|
||||
const {
|
||||
data: { externalKms }
|
||||
} = await apiRequest.get<{ externalKms: Kms }>(`/api/v1/external-kms/${provider}/${kmsId}`);
|
||||
return externalKms;
|
||||
const { data } = await apiRequest.get<Kms>(`/api/v1/external-kms/${provider}/${kmsId}`);
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -8,12 +8,13 @@ export type Kms = {
|
||||
description: string;
|
||||
orgId: string;
|
||||
name: string;
|
||||
external: {
|
||||
externalKms: {
|
||||
id: string;
|
||||
status: string;
|
||||
statusDetails: string;
|
||||
provider: string;
|
||||
providerInput: Record<string, any>;
|
||||
configuration: Record<string, any>;
|
||||
credentialsHash?: string;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -123,7 +124,7 @@ export const ExternalKmsInputSchema = z.discriminatedUnion("type", [
|
||||
export const AddExternalKmsSchema = z.object({
|
||||
name: slugSchema({ min: 1, field: "Alias" }),
|
||||
description: z.string().trim().optional(),
|
||||
provider: ExternalKmsInputSchema
|
||||
configuration: ExternalKmsInputSchema
|
||||
});
|
||||
|
||||
export type AddExternalKmsType = z.infer<typeof AddExternalKmsSchema>;
|
||||
@@ -144,9 +145,10 @@ export const UpdateExternalKmsSchema = z.object({
|
||||
.min(1)
|
||||
.refine((v) => slugify(v) === v, {
|
||||
message: "Alias must be a valid slug"
|
||||
}),
|
||||
})
|
||||
.optional(),
|
||||
description: z.string().trim().optional(),
|
||||
provider: ExternalKmsUpdateInputSchema
|
||||
configuration: ExternalKmsUpdateInputSchema.optional()
|
||||
});
|
||||
|
||||
export type UpdateExternalKmsType = z.infer<typeof UpdateExternalKmsSchema>;
|
||||
|
||||
@@ -50,9 +50,10 @@ type Props = {
|
||||
onCompleted: () => void;
|
||||
onCancel: () => void;
|
||||
kms?: Kms;
|
||||
mode?: "full" | "credentials";
|
||||
};
|
||||
|
||||
export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props) => {
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
@@ -64,20 +65,20 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
defaultValues: {
|
||||
name: kms?.name,
|
||||
description: kms?.description ?? "",
|
||||
provider: {
|
||||
configuration: {
|
||||
type: ExternalKmsProvider.Aws,
|
||||
inputs: {
|
||||
credential: {
|
||||
type: kms?.external?.providerInput?.credential?.type,
|
||||
type: kms?.externalKms?.configuration?.credential?.type,
|
||||
data: {
|
||||
accessKey: kms?.external?.providerInput?.credential?.data?.accessKey,
|
||||
secretKey: kms?.external?.providerInput?.credential?.data?.secretKey,
|
||||
assumeRoleArn: kms?.external?.providerInput?.credential?.data?.assumeRoleArn,
|
||||
externalId: kms?.external?.providerInput?.credential?.data?.externalId
|
||||
accessKey: kms?.externalKms?.configuration?.credential?.data?.accessKey,
|
||||
secretKey: kms?.externalKms?.configuration?.credential?.data?.secretKey,
|
||||
assumeRoleArn: kms?.externalKms?.configuration?.credential?.data?.assumeRoleArn,
|
||||
externalId: kms?.externalKms?.configuration?.credential?.data?.externalId
|
||||
}
|
||||
},
|
||||
awsRegion: kms?.external?.providerInput?.awsRegion,
|
||||
kmsKeyId: kms?.external?.providerInput?.kmsKeyId
|
||||
awsRegion: kms?.externalKms?.configuration?.awsRegion,
|
||||
kmsKeyId: kms?.externalKms?.configuration?.kmsKeyId
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,30 +86,42 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
|
||||
const { currentOrg } = useOrganization();
|
||||
const { mutateAsync: addAwsExternalKms } = useAddExternalKms(currentOrg.id);
|
||||
const { mutateAsync: updateAwsExternalKms } = useUpdateExternalKms(currentOrg.id);
|
||||
const { mutateAsync: updateAwsExternalKms } = useUpdateExternalKms(
|
||||
currentOrg.id,
|
||||
ExternalKmsProvider.Aws
|
||||
);
|
||||
|
||||
const selectedAwsAuthType = watch("provider.inputs.credential.type");
|
||||
const selectedAwsAuthType = watch("configuration.inputs.credential.type");
|
||||
|
||||
const handleAwsKmsFormSubmit = async (data: AddExternalKmsType) => {
|
||||
const { name, description, provider } = data;
|
||||
const { name, description, configuration } = data;
|
||||
try {
|
||||
if (kms) {
|
||||
await updateAwsExternalKms({
|
||||
kmsId: kms.id,
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
});
|
||||
if (mode === "credentials") {
|
||||
await updateAwsExternalKms({
|
||||
kmsId: kms.id,
|
||||
configuration
|
||||
});
|
||||
} else {
|
||||
await updateAwsExternalKms({
|
||||
kmsId: kms.id,
|
||||
name,
|
||||
description
|
||||
});
|
||||
}
|
||||
|
||||
createNotification({
|
||||
text: "Successfully updated AWS External KMS",
|
||||
text:
|
||||
mode === "credentials"
|
||||
? "Successfully updated AWS External KMS credentials"
|
||||
: "Successfully updated AWS External KMS",
|
||||
type: "success"
|
||||
});
|
||||
} else {
|
||||
await addAwsExternalKms({
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
configuration
|
||||
});
|
||||
|
||||
createNotification({
|
||||
@@ -125,27 +138,31 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(handleAwsKmsFormSubmit)} autoComplete="off">
|
||||
{mode === "full" && (
|
||||
<>
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Alias" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="description"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Description" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Alias" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="description"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Description" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="provider.inputs.credential.type"
|
||||
name="configuration.inputs.credential.type"
|
||||
defaultValue={KmsAwsCredentialType.AssumeRole}
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
@@ -157,10 +174,10 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
defaultValue={field.value}
|
||||
{...field}
|
||||
onValueChange={(e) => {
|
||||
setValue("provider.inputs.credential.data.accessKey", "");
|
||||
setValue("provider.inputs.credential.data.secretKey", "");
|
||||
setValue("provider.inputs.credential.data.assumeRoleArn", "");
|
||||
setValue("provider.inputs.credential.data.externalId", "");
|
||||
setValue("configuration.inputs.credential.data.accessKey", "");
|
||||
setValue("configuration.inputs.credential.data.secretKey", "");
|
||||
setValue("configuration.inputs.credential.data.assumeRoleArn", "");
|
||||
setValue("configuration.inputs.credential.data.externalId", "");
|
||||
|
||||
onChange(e);
|
||||
}}
|
||||
@@ -177,7 +194,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
<>
|
||||
<Controller
|
||||
control={control}
|
||||
name="provider.inputs.credential.data.accessKey"
|
||||
name="configuration.inputs.credential.data.accessKey"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Access Key ID"
|
||||
@@ -190,7 +207,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="provider.inputs.credential.data.secretKey"
|
||||
name="configuration.inputs.credential.data.secretKey"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Secret Access Key"
|
||||
@@ -206,7 +223,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
<>
|
||||
<Controller
|
||||
control={control}
|
||||
name="provider.inputs.credential.data.assumeRoleArn"
|
||||
name="configuration.inputs.credential.data.assumeRoleArn"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="IAM Role ARN For Role Assumption"
|
||||
@@ -219,7 +236,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="provider.inputs.credential.data.externalId"
|
||||
name="configuration.inputs.credential.data.externalId"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Assume Role External ID"
|
||||
@@ -234,7 +251,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
name="provider.inputs.awsRegion"
|
||||
name="configuration.inputs.awsRegion"
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl label="AWS Region" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Select
|
||||
@@ -254,7 +271,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="provider.inputs.kmsKeyId"
|
||||
name="configuration.inputs.kmsKeyId"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="AWS KMS Key ID" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
@@ -263,7 +280,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
/>
|
||||
<div className="mt-6 flex items-center space-x-4">
|
||||
<Button type="submit" isLoading={isSubmitting}>
|
||||
Save
|
||||
{mode === "credentials" ? "Update Credentials" : "Save"}
|
||||
</Button>
|
||||
<Button variant="outline_bg" onClick={onCancel}>
|
||||
Cancel
|
||||
|
||||
@@ -12,22 +12,33 @@ type Props = {
|
||||
onOpenChange: (state: boolean) => void;
|
||||
};
|
||||
|
||||
export const UpdateExternalKmsForm = ({ isOpen, kmsId, provider, onOpenChange }: Props) => {
|
||||
export const EditExternalKmsCredentialsModal = ({
|
||||
isOpen,
|
||||
kmsId,
|
||||
provider,
|
||||
onOpenChange
|
||||
}: Props) => {
|
||||
const { data: externalKms, isPending } = useGetExternalKmsById({ kmsId, provider });
|
||||
return (
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||
<ModalContent title="Edit configuration" bodyClassName="overflow-visible">
|
||||
<ModalContent
|
||||
title="Edit Credentials"
|
||||
subTitle="Update the credentials for this KMS."
|
||||
bodyClassName="overflow-visible"
|
||||
>
|
||||
{isPending && <ContentLoader />}
|
||||
{externalKms?.external?.provider === ExternalKmsProvider.Aws && (
|
||||
{externalKms?.externalKms?.provider === ExternalKmsProvider.Aws && (
|
||||
<AwsKmsForm
|
||||
kms={externalKms}
|
||||
mode="credentials"
|
||||
onCancel={() => onOpenChange(false)}
|
||||
onCompleted={() => onOpenChange(false)}
|
||||
/>
|
||||
)}
|
||||
{externalKms?.external?.provider === ExternalKmsProvider.Gcp && (
|
||||
{externalKms?.externalKms?.provider === ExternalKmsProvider.Gcp && (
|
||||
<GcpKmsForm
|
||||
kms={externalKms}
|
||||
mode="credentials"
|
||||
onCancel={() => onOpenChange(false)}
|
||||
onCompleted={() => onOpenChange(false)}
|
||||
/>
|
||||
@@ -0,0 +1,108 @@
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
Button,
|
||||
ContentLoader,
|
||||
FormControl,
|
||||
Input,
|
||||
Modal,
|
||||
ModalClose,
|
||||
ModalContent
|
||||
} from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import { useGetExternalKmsById, useUpdateExternalKms } from "@app/hooks/api";
|
||||
import { ExternalKmsProvider, Kms } from "@app/hooks/api/kms/types";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
onOpenChange: (isOpen: boolean) => void;
|
||||
kmsId: string;
|
||||
provider: ExternalKmsProvider;
|
||||
};
|
||||
|
||||
const formSchema = z.object({
|
||||
name: z.string().min(1).trim(),
|
||||
description: z.string().trim().optional()
|
||||
});
|
||||
|
||||
type FormData = z.infer<typeof formSchema>;
|
||||
|
||||
type ContentProps = { kms: Kms; provider: ExternalKmsProvider; onComplete: () => void };
|
||||
|
||||
const Content = ({ kms, onComplete, provider }: ContentProps) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { mutateAsync: updateExternalKms, isPending } = useUpdateExternalKms(
|
||||
currentOrg.id,
|
||||
provider
|
||||
);
|
||||
|
||||
const form = useForm<FormData>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
name: kms.name,
|
||||
description: kms.description ?? ""
|
||||
}
|
||||
});
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
formState: { isDirty }
|
||||
} = form;
|
||||
|
||||
const onSubmit = async (formData: FormData) => {
|
||||
if (!kms) return;
|
||||
|
||||
await updateExternalKms({
|
||||
kmsId: kms.id,
|
||||
name: formData.name,
|
||||
description: formData.description
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully updated KMS details",
|
||||
type: "success"
|
||||
});
|
||||
onComplete();
|
||||
};
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<FormControl label="Alias">
|
||||
<Input {...form.register("name")} />
|
||||
</FormControl>
|
||||
<FormControl label="Description">
|
||||
<Input {...form.register("description")} />
|
||||
</FormControl>
|
||||
<div className="mt-6 flex items-center space-x-4">
|
||||
<Button type="submit" isLoading={isPending} isDisabled={!isDirty}>
|
||||
Update Details
|
||||
</Button>
|
||||
<ModalClose asChild>
|
||||
<Button variant="outline_bg">Cancel</Button>
|
||||
</ModalClose>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export const EditExternalKmsDetailsModal = ({ isOpen, onOpenChange, kmsId, provider }: Props) => {
|
||||
const { data: kms, isPending } = useGetExternalKmsById({ kmsId, provider });
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||
<ModalContent
|
||||
className="max-w-2xl"
|
||||
title="Edit KMS Details"
|
||||
subTitle="Update the name and description for this KMS."
|
||||
>
|
||||
{isPending && <ContentLoader />}
|
||||
{kms && <Content kms={kms} provider={provider} onComplete={() => onOpenChange(false)} />}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
@@ -22,7 +22,9 @@ import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
type Props = {
|
||||
kms: KmsListEntry;
|
||||
handlePopUpOpen: (
|
||||
popUpName: keyof UsePopUpState<["editExternalKms", "removeExternalKms", "upgradePlan"]>,
|
||||
popUpName: keyof UsePopUpState<
|
||||
["editExternalKmsDetails", "editExternalKmsCredentials", "removeExternalKms", "upgradePlan"]
|
||||
>,
|
||||
data?: {
|
||||
kmsId?: string;
|
||||
name?: string;
|
||||
@@ -104,28 +106,52 @@ export const ExternalKmsItem = ({ kms, handlePopUpOpen, subscription }: Props) =
|
||||
<DropdownMenuContent align="start" className="p-1">
|
||||
<OrgPermissionCan I={OrgPermissionActions.Edit} an={OrgPermissionSubjects.Kms}>
|
||||
{(isAllowed) => (
|
||||
<DropdownMenuItem
|
||||
disabled={!isAllowed}
|
||||
className={twMerge(
|
||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (subscription && !subscription?.externalKms) {
|
||||
handlePopUpOpen("upgradePlan", {
|
||||
isEnterpriseFeature: true
|
||||
});
|
||||
return;
|
||||
}
|
||||
<>
|
||||
<DropdownMenuItem
|
||||
disabled={!isAllowed}
|
||||
className={twMerge(
|
||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (subscription && !subscription?.externalKms) {
|
||||
handlePopUpOpen("upgradePlan", {
|
||||
isEnterpriseFeature: true
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
handlePopUpOpen("editExternalKms", {
|
||||
kmsId: kms.id,
|
||||
provider: kms.externalKms.provider
|
||||
});
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
handlePopUpOpen("editExternalKmsDetails", {
|
||||
kmsId: kms.id,
|
||||
provider: kms.externalKms.provider
|
||||
});
|
||||
}}
|
||||
>
|
||||
Edit Details
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
disabled={!isAllowed}
|
||||
className={twMerge(
|
||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (subscription && !subscription?.externalKms) {
|
||||
handlePopUpOpen("upgradePlan", {
|
||||
isEnterpriseFeature: true
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
handlePopUpOpen("editExternalKmsCredentials", {
|
||||
kmsId: kms.id,
|
||||
provider: kms.externalKms.provider
|
||||
});
|
||||
}}
|
||||
>
|
||||
Edit Credentials
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Delete} an={OrgPermissionSubjects.Kms}>
|
||||
|
||||
@@ -24,6 +24,7 @@ type Props = {
|
||||
onCompleted: () => void;
|
||||
onCancel: () => void;
|
||||
kms?: Kms;
|
||||
mode?: "full" | "credentials";
|
||||
};
|
||||
|
||||
const GCP_REGIONS = [
|
||||
@@ -76,7 +77,7 @@ const formatOptionLabel = ({ value, label }: { value: string; label: string }) =
|
||||
</div>
|
||||
);
|
||||
|
||||
export const GcpKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props) => {
|
||||
const [isCredentialValid, setIsCredentialValid] = useState<boolean>(false);
|
||||
const [keys, setKeys] = useState<{ value: string; label: string }[]>([]);
|
||||
|
||||
@@ -98,9 +99,9 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
gcpRegion: kms
|
||||
? {
|
||||
label:
|
||||
GCP_REGIONS.find((r) => r.value === kms.external.providerInput.gcpRegion)?.label ??
|
||||
GCP_REGIONS.find((r) => r.value === kms.externalKms.configuration.gcpRegion)?.label ??
|
||||
"",
|
||||
value: kms.external.providerInput.gcpRegion
|
||||
value: kms.externalKms.configuration.gcpRegion
|
||||
}
|
||||
: undefined,
|
||||
keyObject: undefined
|
||||
@@ -109,7 +110,10 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
|
||||
const { currentOrg } = useOrganization();
|
||||
const { mutateAsync: addGcpExternalKms } = useAddExternalKms(currentOrg.id);
|
||||
const { mutateAsync: updateGcpExternalKms } = useUpdateExternalKms(currentOrg.id);
|
||||
const { mutateAsync: updateGcpExternalKms } = useUpdateExternalKms(
|
||||
currentOrg.id,
|
||||
ExternalKmsProvider.Gcp
|
||||
);
|
||||
const { mutateAsync: fetchGcpKeys, isPending: isFetchGcpKeysLoading } =
|
||||
useExternalKmsFetchGcpKeys(currentOrg?.id);
|
||||
|
||||
@@ -152,21 +156,39 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
|
||||
try {
|
||||
if (kms) {
|
||||
await updateGcpExternalKms({
|
||||
kmsId: kms.id,
|
||||
name,
|
||||
description,
|
||||
provider: {
|
||||
type: ExternalKmsProvider.Gcp,
|
||||
inputs: {
|
||||
gcpRegion,
|
||||
keyName: keyObject?.value
|
||||
if (mode === "credentials") {
|
||||
await updateGcpExternalKms({
|
||||
kmsId: kms.id,
|
||||
name: kms.name,
|
||||
description: kms.description,
|
||||
configuration: {
|
||||
type: ExternalKmsProvider.Gcp,
|
||||
inputs: {
|
||||
gcpRegion,
|
||||
keyName: keyObject?.value
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
await updateGcpExternalKms({
|
||||
kmsId: kms.id,
|
||||
name,
|
||||
description,
|
||||
configuration: {
|
||||
type: ExternalKmsProvider.Gcp,
|
||||
inputs: {
|
||||
gcpRegion,
|
||||
keyName: keyObject?.value
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
createNotification({
|
||||
text: "Successfully updated GCP External KMS",
|
||||
text:
|
||||
mode === "credentials"
|
||||
? "Successfully updated GCP External KMS configuration"
|
||||
: "Successfully updated GCP External KMS",
|
||||
type: "success"
|
||||
});
|
||||
} else {
|
||||
@@ -177,7 +199,7 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
await addGcpExternalKms({
|
||||
name,
|
||||
description,
|
||||
provider: {
|
||||
configuration: {
|
||||
type: ExternalKmsProvider.Gcp,
|
||||
inputs: {
|
||||
gcpRegion,
|
||||
@@ -231,7 +253,9 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
|
||||
setKeys(returnedKeys);
|
||||
if (kms) {
|
||||
const existingKey = returnedKeys.find((k) => k.value === kms.external.providerInput.keyName);
|
||||
const existingKey = returnedKeys.find(
|
||||
(k) => k.value === kms.externalKms.configuration.keyName
|
||||
);
|
||||
if (existingKey) {
|
||||
setValue("keyObject", existingKey);
|
||||
}
|
||||
@@ -260,24 +284,28 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(handleGcpKmsFormSubmit)} autoComplete="off">
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Alias" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="description"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Description" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
{mode === "full" && (
|
||||
<>
|
||||
<Controller
|
||||
control={control}
|
||||
name="name"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Alias" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="description"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl label="Description" errorText={error?.message} isError={Boolean(error)}>
|
||||
<Input placeholder="" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
name="gcpRegion"
|
||||
@@ -350,7 +378,7 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||
)}
|
||||
<div className="mt-6 flex items-center space-x-4">
|
||||
<Button type="submit" isLoading={isSubmitting}>
|
||||
Save
|
||||
{mode === "credentials" ? "Update Configuration" : "Save"}
|
||||
</Button>
|
||||
<Button variant="outline_bg" onClick={onCancel}>
|
||||
Cancel
|
||||
|
||||
@@ -28,8 +28,9 @@ import { useGetExternalKmsList, useRemoveExternalKms } from "@app/hooks/api";
|
||||
import { ExternalKmsProvider } from "@app/hooks/api/kms/types";
|
||||
|
||||
import { AddExternalKmsForm } from "./AddExternalKmsForm";
|
||||
import { EditExternalKmsCredentialsModal } from "./EditExternalKmsCredentialsModal";
|
||||
import { EditExternalKmsDetailsModal } from "./EditExternalKmsDetailsModal";
|
||||
import { ExternalKmsItem } from "./ExternalKmsItem";
|
||||
import { UpdateExternalKmsForm } from "./UpdateExternalKmsForm";
|
||||
|
||||
export const OrgEncryptionTab = withPermission(
|
||||
() => {
|
||||
@@ -39,7 +40,8 @@ export const OrgEncryptionTab = withPermission(
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
||||
"upgradePlan",
|
||||
"addExternalKms",
|
||||
"editExternalKms",
|
||||
"editExternalKmsDetails",
|
||||
"editExternalKmsCredentials",
|
||||
"removeExternalKms"
|
||||
] as const);
|
||||
const { data: externalKmsList, isPending: isExternalKmsListLoading } =
|
||||
@@ -130,11 +132,21 @@ export const OrgEncryptionTab = withPermission(
|
||||
isOpen={popUp.addExternalKms.isOpen}
|
||||
onToggle={(state) => handlePopUpToggle("addExternalKms", state)}
|
||||
/>
|
||||
<UpdateExternalKmsForm
|
||||
isOpen={popUp.editExternalKms.isOpen}
|
||||
kmsId={(popUp.editExternalKms.data as { kmsId: string })?.kmsId}
|
||||
provider={(popUp.editExternalKms.data as { provider: ExternalKmsProvider })?.provider}
|
||||
onOpenChange={(state) => handlePopUpToggle("editExternalKms", state)}
|
||||
<EditExternalKmsDetailsModal
|
||||
isOpen={popUp.editExternalKmsDetails.isOpen}
|
||||
kmsId={(popUp.editExternalKmsDetails.data as { kmsId: string })?.kmsId}
|
||||
provider={
|
||||
(popUp.editExternalKmsDetails.data as { provider: ExternalKmsProvider })?.provider
|
||||
}
|
||||
onOpenChange={(state) => handlePopUpToggle("editExternalKmsDetails", state)}
|
||||
/>
|
||||
<EditExternalKmsCredentialsModal
|
||||
isOpen={popUp.editExternalKmsCredentials.isOpen}
|
||||
kmsId={(popUp.editExternalKmsCredentials.data as { kmsId: string })?.kmsId}
|
||||
provider={
|
||||
(popUp.editExternalKmsCredentials.data as { provider: ExternalKmsProvider })?.provider
|
||||
}
|
||||
onOpenChange={(state) => handlePopUpToggle("editExternalKmsCredentials", state)}
|
||||
/>
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.removeExternalKms.isOpen}
|
||||
|
||||
Reference in New Issue
Block a user