Restructure MIs to more generic Identity

This commit is contained in:
Tuan Dang
2023-12-09 22:18:38 +07:00
parent 89d0c0e3c3
commit 50ef23e8a0
102 changed files with 3652 additions and 2981 deletions
+22 -12
View File
@@ -3,7 +3,6 @@ import { AuditLog, Event } from "../models";
import { AuthData } from "../../interfaces/middleware";
import EELicenseService from "./EELicenseService";
import { Workspace } from "../../models";
import { OrganizationNotFoundError } from "../../utils/errors";
interface EventScope {
workspaceId?: Types.ObjectId;
@@ -14,31 +13,42 @@ type ValidEventScope =
| Required<Pick<EventScope, "workspaceId">>
| Required<Pick<EventScope, "organizationId">>
| Required<EventScope>
| Record<string, never>;
export default class EEAuditLogService {
static async createAuditLog(authData: AuthData, event: Event, eventScope: ValidEventScope, shouldSave = true) {
static async createAuditLog(authData: AuthData, event: Event, eventScope: ValidEventScope = {}, shouldSave = true) {
const MS_IN_DAY = 24 * 60 * 60 * 1000;
const organizationId = ("organizationId" in eventScope)
? eventScope.organizationId
: (await Workspace.findById(eventScope.workspaceId).select("organization").lean())?.organization;
let organizationId;
if ("organizationId" in eventScope) {
organizationId = eventScope.organizationId;
}
if (!organizationId) throw OrganizationNotFoundError({
message: "createAuditLog: Failed to create audit log due to missing organizationId"
});
const ttl = (await EELicenseService.getPlan(organizationId)).auditLogsRetentionDays * MS_IN_DAY;
let workspaceId;
if ("workspaceId" in eventScope) {
workspaceId = eventScope.workspaceId;
if (!organizationId) {
organizationId = (await Workspace.findById(workspaceId).select("organization").lean())?.organization;
}
}
let expiresAt;
if (organizationId) {
const ttl = (await EELicenseService.getPlan(organizationId)).auditLogsRetentionDays * MS_IN_DAY;
expiresAt = new Date(Date.now() + ttl);
}
const auditLog = await new AuditLog({
actor: authData.actor,
organization: organizationId,
workspace: ("workspaceId" in eventScope) ? eventScope.workspaceId : undefined,
workspace: workspaceId,
ipAddress: authData.ipAddress,
event,
userAgent: authData.userAgent,
userAgentType: authData.userAgentType,
expiresAt: new Date(Date.now() + ttl)
expiresAt
});
if (shouldSave) {
+21 -27
View File
@@ -13,13 +13,12 @@ import picomatch from "picomatch";
import { AuthData } from "../../interfaces/middleware";
import { ActorType, IRole, Role } from "../models";
import {
IMachineIdentity,
MachineMembership,
IIdentity,
IdentityMembership,
Membership,
ServiceTokenData
} from "../../models";
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables";
import { checkIPAgainstBlocklist } from "../../utils/ip";
import { BadRequestError } from "../../utils/errors";
const $glob: FieldInstruction<string> = {
@@ -62,7 +61,7 @@ export enum ProjectPermissionSub {
SecretRollback = "secret-rollback",
SecretApproval = "secret-approval",
SecretRotation = "secret-rotation",
MachineIdentity = "machine-identity"
Identity = "identity"
}
type SubjectFields = {
@@ -87,7 +86,7 @@ export type ProjectPermissionSet =
| [ProjectPermissionActions, ProjectPermissionSub.ServiceTokens]
| [ProjectPermissionActions, ProjectPermissionSub.SecretApproval]
| [ProjectPermissionActions, ProjectPermissionSub.SecretRotation]
| [ProjectPermissionActions, ProjectPermissionSub.MachineIdentity]
| [ProjectPermissionActions, ProjectPermissionSub.Identity]
| [ProjectPermissionActions.Delete, ProjectPermissionSub.Workspace]
| [ProjectPermissionActions.Edit, ProjectPermissionSub.Workspace]
| [ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback]
@@ -134,10 +133,10 @@ const buildAdminPermission = () => {
can(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks);
can(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks);
can(ProjectPermissionActions.Read, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Create, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Edit, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Delete, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Read, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Create, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens);
can(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens);
@@ -204,10 +203,10 @@ const buildMemberPermission = () => {
can(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks);
can(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks);
can(ProjectPermissionActions.Read, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Create, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Edit, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Delete, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Read, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Create, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens);
can(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens);
@@ -249,7 +248,7 @@ const buildViewerPermission = () => {
can(ProjectPermissionActions.Read, ProjectPermissionSub.Role);
can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
can(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks);
can(ProjectPermissionActions.Read, ProjectPermissionSub.MachineIdentity);
can(ProjectPermissionActions.Read, ProjectPermissionSub.Identity);
can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens);
can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings);
can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments);
@@ -310,28 +309,23 @@ export const getAuthDataProjectPermissions = async ({
role = "viewer";
break;
}
case ActorType.MACHINE: {
const machineMembership = await MachineMembership.findOne({
machineIdentity: authData.authPayload._id,
case ActorType.IDENTITY: {
const identityMembership = await IdentityMembership.findOne({
identity: authData.authPayload._id,
workspace: workspaceId
})
.populate<{
customRole: IRole & { permissions: RawRuleOf<MongoAbility<ProjectPermissionSet>>[] };
machineIdentity: IMachineIdentity
}>("customRole machineIdentity")
identity: IIdentity
}>("customRole identity")
.exec();
if (!machineMembership || (machineMembership.role === "custom" && !machineMembership.customRole)) {
if (!identityMembership || (identityMembership.role === "custom" && !identityMembership.customRole)) {
throw UnauthorizedRequestError();
}
checkIPAgainstBlocklist({
ipAddress: authData.ipAddress,
trustedIps: machineMembership.machineIdentity.accessTokenTrustedIps
});
role = machineMembership.role;
customRole = machineMembership.customRole;
role = identityMembership.role;
customRole = identityMembership.customRole;
break;
}
+20 -26
View File
@@ -1,13 +1,12 @@
import { Types } from "mongoose";
import { AbilityBuilder, MongoAbility, RawRuleOf, createMongoAbility } from "@casl/ability";
import {
IMachineIdentity,
MachineMembershipOrg,
IIdentity,
IdentityMembershipOrg,
MembershipOrg
} from "../../models";
import { ActorType, IRole, Role } from "../models";
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
import { checkIPAgainstBlocklist } from "../../utils/ip";
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS} from "../../variables";
import { conditionsMatcher } from "./ProjectRoleService";
import { AuthData } from "../../interfaces/middleware";
@@ -28,7 +27,7 @@ export enum OrgPermissionSubjects {
Sso = "sso",
Billing = "billing",
SecretScanning = "secret-scanning",
MachineIdentity = "machine-identity"
Identity = "identity"
}
export type OrgPermissionSet =
@@ -41,7 +40,7 @@ export type OrgPermissionSet =
| [OrgPermissionActions, OrgPermissionSubjects.Sso]
| [OrgPermissionActions, OrgPermissionSubjects.SecretScanning]
| [OrgPermissionActions, OrgPermissionSubjects.Billing]
| [OrgPermissionActions, OrgPermissionSubjects.MachineIdentity];
| [OrgPermissionActions, OrgPermissionSubjects.Identity];
const buildAdminPermission = () => {
const { can, build } = new AbilityBuilder<MongoAbility<OrgPermissionSet>>(createMongoAbility);
@@ -84,10 +83,10 @@ const buildAdminPermission = () => {
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Billing);
can(OrgPermissionActions.Read, OrgPermissionSubjects.MachineIdentity);
can(OrgPermissionActions.Create, OrgPermissionSubjects.MachineIdentity);
can(OrgPermissionActions.Edit, OrgPermissionSubjects.MachineIdentity);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.MachineIdentity);
can(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
can(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity);
return build({ conditionsMatcher });
};
@@ -112,10 +111,10 @@ const buildMemberPermission = () => {
can(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.SecretScanning);
can(OrgPermissionActions.Read, OrgPermissionSubjects.MachineIdentity);
can(OrgPermissionActions.Create, OrgPermissionSubjects.MachineIdentity);
can(OrgPermissionActions.Edit, OrgPermissionSubjects.MachineIdentity);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.MachineIdentity);
can(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
can(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity);
return build({ conditionsMatcher });
};
@@ -203,28 +202,23 @@ export const getUserOrgPermissions = async (userId: string, orgId: string) => {
message: "Failed to access organization-level resources with service token"
});
}
case ActorType.MACHINE: {
const machineMembershipOrg = await MachineMembershipOrg.findOne({
machineIdentity: authData.authPayload._id,
case ActorType.IDENTITY: {
const identityMembershipOrg = await IdentityMembershipOrg.findOne({
identity: authData.authPayload._id,
organization: organizationId
})
.populate<{
customRole: IRole & { permissions: RawRuleOf<MongoAbility<OrgPermissionSet>>[] };
machineIdentity: IMachineIdentity
}>("customRole machineIdentity")
identity: IIdentity
}>("customRole identity")
.exec();
if (!machineMembershipOrg || (machineMembershipOrg.role === "custom" && !machineMembershipOrg.customRole)) {
if (!identityMembershipOrg || (identityMembershipOrg.role === "custom" && !identityMembershipOrg.customRole)) {
throw UnauthorizedRequestError();
}
checkIPAgainstBlocklist({
ipAddress: authData.ipAddress,
trustedIps: machineMembershipOrg.machineIdentity.accessTokenTrustedIps
});
role = machineMembershipOrg.role;
customRole = machineMembershipOrg.customRole;
role = identityMembershipOrg.role;
customRole = identityMembershipOrg.customRole;
break;
}
default: