misc: migrated to dedicated org permissions for kms management

This commit is contained in:
Sheen Capadngan
2024-07-17 12:43:55 +08:00
committed by =
parent 31af4a4602
commit 7bb0ec0111
4 changed files with 85 additions and 45 deletions

View File

@@ -54,7 +54,8 @@ export const externalKmsServiceFactory = ({
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Kms);
const kmsSlug = slug ? slugify(slug) : slugify(alphaNumericNanoId(8).toLowerCase()); const kmsSlug = slug ? slugify(slug) : slugify(alphaNumericNanoId(8).toLowerCase());
let sanitizedProviderInput = ""; let sanitizedProviderInput = "";
@@ -125,7 +126,7 @@ export const externalKmsServiceFactory = ({
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Kms);
const kmsSlug = slug ? slugify(slug) : undefined; const kmsSlug = slug ? slugify(slug) : undefined;
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id }); const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
@@ -205,7 +206,7 @@ export const externalKmsServiceFactory = ({
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Kms);
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id }); const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" }); if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });
@@ -226,7 +227,7 @@ export const externalKmsServiceFactory = ({
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Kms);
const externalKmsDocs = await externalKmsDAL.find({ orgId: actorOrgId }); const externalKmsDocs = await externalKmsDAL.find({ orgId: actorOrgId });
@@ -242,7 +243,8 @@ export const externalKmsServiceFactory = ({
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Kms);
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id }); const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" }); if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });
@@ -282,7 +284,7 @@ export const externalKmsServiceFactory = ({
actorAuthMethod, actorAuthMethod,
actorOrgId actorOrgId
); );
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Kms);
const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id }); const externalKmsDoc = await externalKmsDAL.findOne({ kmsKeyId: kmsDoc.id });
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" }); if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });

View File

@@ -21,7 +21,8 @@ export enum OrgPermissionSubjects {
Groups = "groups", Groups = "groups",
Billing = "billing", Billing = "billing",
SecretScanning = "secret-scanning", SecretScanning = "secret-scanning",
Identity = "identity" Identity = "identity",
Kms = "kms"
} }
export type OrgPermissionSet = export type OrgPermissionSet =
@@ -37,7 +38,8 @@ export type OrgPermissionSet =
| [OrgPermissionActions, OrgPermissionSubjects.Groups] | [OrgPermissionActions, OrgPermissionSubjects.Groups]
| [OrgPermissionActions, OrgPermissionSubjects.SecretScanning] | [OrgPermissionActions, OrgPermissionSubjects.SecretScanning]
| [OrgPermissionActions, OrgPermissionSubjects.Billing] | [OrgPermissionActions, OrgPermissionSubjects.Billing]
| [OrgPermissionActions, OrgPermissionSubjects.Identity]; | [OrgPermissionActions, OrgPermissionSubjects.Identity]
| [OrgPermissionActions, OrgPermissionSubjects.Kms];
const buildAdminPermission = () => { const buildAdminPermission = () => {
const { can, build } = new AbilityBuilder<MongoAbility<OrgPermissionSet>>(createMongoAbility); const { can, build } = new AbilityBuilder<MongoAbility<OrgPermissionSet>>(createMongoAbility);
@@ -100,6 +102,11 @@ const buildAdminPermission = () => {
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); can(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity); can(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity);
can(OrgPermissionActions.Read, OrgPermissionSubjects.Kms);
can(OrgPermissionActions.Create, OrgPermissionSubjects.Kms);
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Kms);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Kms);
return build({ conditionsMatcher }); return build({ conditionsMatcher });
}; };

View File

@@ -19,7 +19,8 @@ export enum OrgPermissionSubjects {
Groups = "groups", Groups = "groups",
Billing = "billing", Billing = "billing",
SecretScanning = "secret-scanning", SecretScanning = "secret-scanning",
Identity = "identity" Identity = "identity",
Kms = "kms"
} }
export type OrgPermissionSet = export type OrgPermissionSet =
@@ -35,6 +36,7 @@ export type OrgPermissionSet =
| [OrgPermissionActions, OrgPermissionSubjects.Groups] | [OrgPermissionActions, OrgPermissionSubjects.Groups]
| [OrgPermissionActions, OrgPermissionSubjects.SecretScanning] | [OrgPermissionActions, OrgPermissionSubjects.SecretScanning]
| [OrgPermissionActions, OrgPermissionSubjects.Billing] | [OrgPermissionActions, OrgPermissionSubjects.Billing]
| [OrgPermissionActions, OrgPermissionSubjects.Identity]; | [OrgPermissionActions, OrgPermissionSubjects.Identity]
| [OrgPermissionActions, OrgPermissionSubjects.Kms];
export type TOrgPermission = MongoAbility<OrgPermissionSet>; export type TOrgPermission = MongoAbility<OrgPermissionSet>;

View File

@@ -1,8 +1,10 @@
import { faAws } from "@fortawesome/free-brands-svg-icons"; import { faAws } from "@fortawesome/free-brands-svg-icons";
import { faEllipsis, faLock, faPlus } from "@fortawesome/free-solid-svg-icons"; import { faEllipsis, faLock, faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import { import {
Button, Button,
DeleteActionModal, DeleteActionModal,
@@ -67,22 +69,27 @@ export const OrgEncryptionTab = withPermission(
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"> <div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
<div className="flex justify-between"> <div className="flex justify-between">
<p className="text-xl font-semibold text-mineshaft-100">Key Management System (KMS)</p> <p className="text-xl font-semibold text-mineshaft-100">Key Management System (KMS)</p>
<Button <OrgPermissionCan I={OrgPermissionActions.Create} an={OrgPermissionSubjects.Kms}>
onClick={() => { {(isAllowed) => (
handlePopUpOpen("addExternalKms"); <Button
// if (subscription && !subscription?.auditLogStreams) { onClick={() => {
// handlePopUpOpen("upgradePlan"); handlePopUpOpen("addExternalKms");
// return; // if (subscription && !subscription?.auditLogStreams) {
// } // handlePopUpOpen("upgradePlan");
// handlePopUpOpen("auditLogStreamForm"); // return;
}} // }
leftIcon={<FontAwesomeIcon icon={faPlus} />} // handlePopUpOpen("auditLogStreamForm");
> }}
Add isDisabled={!isAllowed}
</Button> leftIcon={<FontAwesomeIcon icon={faPlus} />}
>
Add
</Button>
)}
</OrgPermissionCan>
</div> </div>
<p className="mb-4 text-gray-400"> <p className="mb-4 text-gray-400">
Integrate with external KMS systems for encrypting your organization&apos;s data Integrate with external KMS for encrypting your organization&apos;s data
</p> </p>
<TableContainer> <TableContainer>
<Table> <Table>
@@ -119,28 +126,50 @@ export const OrgEncryptionTab = withPermission(
</div> </div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="start" className="p-1"> <DropdownMenuContent align="start" className="p-1">
<DropdownMenuItem <OrgPermissionCan
onClick={(e) => { I={OrgPermissionActions.Edit}
e.stopPropagation(); an={OrgPermissionSubjects.Kms}
handlePopUpOpen("editExternalKms", {
kmsId: kms.id
});
}}
> >
Edit {(isAllowed) => (
</DropdownMenuItem> <DropdownMenuItem
<DropdownMenuItem disabled={!isAllowed}
onClick={(e) => { className={twMerge(
e.stopPropagation(); !isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
handlePopUpOpen("removeExternalKms", { )}
slug: kms.slug, onClick={(e) => {
kmsId: kms.id, e.stopPropagation();
provider: kms.externalKms.provider handlePopUpOpen("editExternalKms", {
}); kmsId: kms.id
}} });
}}
>
Edit
</DropdownMenuItem>
)}
</OrgPermissionCan>
<OrgPermissionCan
I={OrgPermissionActions.Delete}
an={OrgPermissionSubjects.Kms}
> >
Delete {(isAllowed) => (
</DropdownMenuItem> <DropdownMenuItem
disabled={!isAllowed}
className={twMerge(
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
)}
onClick={(e) => {
e.stopPropagation();
handlePopUpOpen("removeExternalKms", {
slug: kms.slug,
kmsId: kms.id,
provider: kms.externalKms.provider
});
}}
>
Delete
</DropdownMenuItem>
)}
</OrgPermissionCan>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
</Td> </Td>
@@ -175,5 +204,5 @@ export const OrgEncryptionTab = withPermission(
</div> </div>
); );
}, },
{ action: OrgPermissionActions.Edit, subject: OrgPermissionSubjects.Settings } { action: OrgPermissionActions.Read, subject: OrgPermissionSubjects.Kms }
); );