Merge branch 'main' into feat/zabbixSyncIntegration

This commit is contained in:
Carlos Monastyrski
2025-07-02 09:25:19 -03:00
651 changed files with 12487 additions and 13813 deletions
+25 -1
View File
@@ -8,6 +8,9 @@ import { Lock } from "@app/lib/red-lock";
export const mockKeyStore = (): TKeyStoreFactory => { export const mockKeyStore = (): TKeyStoreFactory => {
const store: Record<string, string | number | Buffer> = {}; const store: Record<string, string | number | Buffer> = {};
const getRegex = (pattern: string) =>
new RE2(`^${pattern.replace(/[-[\]/{}()+?.\\^$|]/g, "\\$&").replace(/\*/g, ".*")}$`);
return { return {
setItem: async (key, value) => { setItem: async (key, value) => {
store[key] = value; store[key] = value;
@@ -23,7 +26,7 @@ export const mockKeyStore = (): TKeyStoreFactory => {
return 1; return 1;
}, },
deleteItems: async ({ pattern, batchSize = 500, delay = 1500, jitter = 200 }) => { deleteItems: async ({ pattern, batchSize = 500, delay = 1500, jitter = 200 }) => {
const regex = new RE2(`^${pattern.replace(/[-[\]/{}()+?.\\^$|]/g, "\\$&").replace(/\*/g, ".*")}$`); const regex = getRegex(pattern);
let totalDeleted = 0; let totalDeleted = 0;
const keys = Object.keys(store); const keys = Object.keys(store);
@@ -53,6 +56,27 @@ export const mockKeyStore = (): TKeyStoreFactory => {
incrementBy: async () => { incrementBy: async () => {
return 1; return 1;
}, },
getItems: async (keys) => {
const values = keys.map((key) => {
const value = store[key];
if (typeof value === "string") {
return value;
}
return null;
});
return values;
},
getKeysByPattern: async (pattern) => {
const regex = getRegex(pattern);
const keys = Object.keys(store);
return keys.filter((key) => regex.test(key));
},
deleteItemsByKeyIn: async (keys) => {
for (const key of keys) {
delete store[key];
}
return keys.length;
},
acquireLock: () => { acquireLock: () => {
return Promise.resolve({ return Promise.resolve({
release: () => {} release: () => {}
+2
View File
@@ -74,6 +74,7 @@ import { TAllowedFields } from "@app/services/identity-ldap-auth/identity-ldap-a
import { TIdentityOciAuthServiceFactory } from "@app/services/identity-oci-auth/identity-oci-auth-service"; import { TIdentityOciAuthServiceFactory } from "@app/services/identity-oci-auth/identity-oci-auth-service";
import { TIdentityOidcAuthServiceFactory } from "@app/services/identity-oidc-auth/identity-oidc-auth-service"; import { TIdentityOidcAuthServiceFactory } from "@app/services/identity-oidc-auth/identity-oidc-auth-service";
import { TIdentityProjectServiceFactory } from "@app/services/identity-project/identity-project-service"; import { TIdentityProjectServiceFactory } from "@app/services/identity-project/identity-project-service";
import { TIdentityTlsCertAuthServiceFactory } from "@app/services/identity-tls-cert-auth/identity-tls-cert-auth-types";
import { TIdentityTokenAuthServiceFactory } from "@app/services/identity-token-auth/identity-token-auth-service"; import { TIdentityTokenAuthServiceFactory } from "@app/services/identity-token-auth/identity-token-auth-service";
import { TIdentityUaServiceFactory } from "@app/services/identity-ua/identity-ua-service"; import { TIdentityUaServiceFactory } from "@app/services/identity-ua/identity-ua-service";
import { TIntegrationServiceFactory } from "@app/services/integration/integration-service"; import { TIntegrationServiceFactory } from "@app/services/integration/integration-service";
@@ -218,6 +219,7 @@ declare module "fastify" {
identityKubernetesAuth: TIdentityKubernetesAuthServiceFactory; identityKubernetesAuth: TIdentityKubernetesAuthServiceFactory;
identityGcpAuth: TIdentityGcpAuthServiceFactory; identityGcpAuth: TIdentityGcpAuthServiceFactory;
identityAliCloudAuth: TIdentityAliCloudAuthServiceFactory; identityAliCloudAuth: TIdentityAliCloudAuthServiceFactory;
identityTlsCertAuth: TIdentityTlsCertAuthServiceFactory;
identityAwsAuth: TIdentityAwsAuthServiceFactory; identityAwsAuth: TIdentityAwsAuthServiceFactory;
identityAzureAuth: TIdentityAzureAuthServiceFactory; identityAzureAuth: TIdentityAzureAuthServiceFactory;
identityOciAuth: TIdentityOciAuthServiceFactory; identityOciAuth: TIdentityOciAuthServiceFactory;
+8
View File
@@ -164,6 +164,9 @@ import {
TIdentityProjectMemberships, TIdentityProjectMemberships,
TIdentityProjectMembershipsInsert, TIdentityProjectMembershipsInsert,
TIdentityProjectMembershipsUpdate, TIdentityProjectMembershipsUpdate,
TIdentityTlsCertAuths,
TIdentityTlsCertAuthsInsert,
TIdentityTlsCertAuthsUpdate,
TIdentityTokenAuths, TIdentityTokenAuths,
TIdentityTokenAuthsInsert, TIdentityTokenAuthsInsert,
TIdentityTokenAuthsUpdate, TIdentityTokenAuthsUpdate,
@@ -794,6 +797,11 @@ declare module "knex/types/tables" {
TIdentityAlicloudAuthsInsert, TIdentityAlicloudAuthsInsert,
TIdentityAlicloudAuthsUpdate TIdentityAlicloudAuthsUpdate
>; >;
[TableName.IdentityTlsCertAuth]: KnexOriginal.CompositeTableType<
TIdentityTlsCertAuths,
TIdentityTlsCertAuthsInsert,
TIdentityTlsCertAuthsUpdate
>;
[TableName.IdentityAwsAuth]: KnexOriginal.CompositeTableType< [TableName.IdentityAwsAuth]: KnexOriginal.CompositeTableType<
TIdentityAwsAuths, TIdentityAwsAuths,
TIdentityAwsAuthsInsert, TIdentityAwsAuthsInsert,
@@ -0,0 +1,28 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
export async function up(knex: Knex): Promise<void> {
if (!(await knex.schema.hasTable(TableName.IdentityTlsCertAuth))) {
await knex.schema.createTable(TableName.IdentityTlsCertAuth, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.bigInteger("accessTokenTTL").defaultTo(7200).notNullable();
t.bigInteger("accessTokenMaxTTL").defaultTo(7200).notNullable();
t.bigInteger("accessTokenNumUsesLimit").defaultTo(0).notNullable();
t.jsonb("accessTokenTrustedIps").notNullable();
t.timestamps(true, true, true);
t.uuid("identityId").notNullable().unique();
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
t.string("allowedCommonNames").nullable();
t.binary("encryptedCaCertificate").notNullable();
});
}
await createOnUpdateTrigger(knex, TableName.IdentityTlsCertAuth);
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTableIfExists(TableName.IdentityTlsCertAuth);
await dropOnUpdateTrigger(knex, TableName.IdentityTlsCertAuth);
}
@@ -0,0 +1,41 @@
import { Knex } from "knex";
import { ProjectType, TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
const hasTypeColumn = await knex.schema.hasColumn(TableName.Project, "type");
const hasDefaultTypeColumn = await knex.schema.hasColumn(TableName.Project, "defaultProduct");
if (hasTypeColumn && !hasDefaultTypeColumn) {
await knex.schema.alterTable(TableName.Project, (t) => {
t.string("type").nullable().alter();
t.string("defaultProduct").notNullable().defaultTo(ProjectType.SecretManager);
});
await knex(TableName.Project).update({
// eslint-disable-next-line
// @ts-ignore this is because this field is created later
defaultProduct: knex.raw(`
CASE
WHEN "type" IS NULL OR "type" = '' THEN 'secret-manager'
ELSE "type"
END
`)
});
}
const hasTemplateTypeColumn = await knex.schema.hasColumn(TableName.ProjectTemplates, "type");
if (hasTemplateTypeColumn) {
await knex.schema.alterTable(TableName.ProjectTemplates, (t) => {
t.string("type").nullable().alter();
});
}
}
export async function down(knex: Knex): Promise<void> {
const hasDefaultTypeColumn = await knex.schema.hasColumn(TableName.Project, "defaultProduct");
if (hasDefaultTypeColumn) {
await knex.schema.alterTable(TableName.Project, (t) => {
t.dropColumn("defaultProduct");
});
}
}
@@ -0,0 +1,27 @@
// Code generated by automation script, DO NOT EDIT.
// Automated by pulling database and generating zod schema
// To update. Just run npm run generate:schema
// Written by akhilmhdh.
import { z } from "zod";
import { zodBuffer } from "@app/lib/zod";
import { TImmutableDBKeys } from "./models";
export const IdentityTlsCertAuthsSchema = z.object({
id: z.string().uuid(),
accessTokenTTL: z.coerce.number().default(7200),
accessTokenMaxTTL: z.coerce.number().default(7200),
accessTokenNumUsesLimit: z.coerce.number().default(0),
accessTokenTrustedIps: z.unknown(),
createdAt: z.date(),
updatedAt: z.date(),
identityId: z.string().uuid(),
allowedCommonNames: z.string().nullable().optional(),
encryptedCaCertificate: zodBuffer
});
export type TIdentityTlsCertAuths = z.infer<typeof IdentityTlsCertAuthsSchema>;
export type TIdentityTlsCertAuthsInsert = Omit<z.input<typeof IdentityTlsCertAuthsSchema>, TImmutableDBKeys>;
export type TIdentityTlsCertAuthsUpdate = Partial<Omit<z.input<typeof IdentityTlsCertAuthsSchema>, TImmutableDBKeys>>;
+1
View File
@@ -52,6 +52,7 @@ export * from "./identity-org-memberships";
export * from "./identity-project-additional-privilege"; export * from "./identity-project-additional-privilege";
export * from "./identity-project-membership-role"; export * from "./identity-project-membership-role";
export * from "./identity-project-memberships"; export * from "./identity-project-memberships";
export * from "./identity-tls-cert-auths";
export * from "./identity-token-auths"; export * from "./identity-token-auths";
export * from "./identity-ua-client-secrets"; export * from "./identity-ua-client-secrets";
export * from "./identity-universal-auths"; export * from "./identity-universal-auths";
+2 -10
View File
@@ -86,6 +86,7 @@ export enum TableName {
IdentityOidcAuth = "identity_oidc_auths", IdentityOidcAuth = "identity_oidc_auths",
IdentityJwtAuth = "identity_jwt_auths", IdentityJwtAuth = "identity_jwt_auths",
IdentityLdapAuth = "identity_ldap_auths", IdentityLdapAuth = "identity_ldap_auths",
IdentityTlsCertAuth = "identity_tls_cert_auths",
IdentityOrgMembership = "identity_org_memberships", IdentityOrgMembership = "identity_org_memberships",
IdentityProjectMembership = "identity_project_memberships", IdentityProjectMembership = "identity_project_memberships",
IdentityProjectMembershipRole = "identity_project_membership_role", IdentityProjectMembershipRole = "identity_project_membership_role",
@@ -251,6 +252,7 @@ export enum IdentityAuthMethod {
ALICLOUD_AUTH = "alicloud-auth", ALICLOUD_AUTH = "alicloud-auth",
AWS_AUTH = "aws-auth", AWS_AUTH = "aws-auth",
AZURE_AUTH = "azure-auth", AZURE_AUTH = "azure-auth",
TLS_CERT_AUTH = "tls-cert-auth",
OCI_AUTH = "oci-auth", OCI_AUTH = "oci-auth",
OIDC_AUTH = "oidc-auth", OIDC_AUTH = "oidc-auth",
JWT_AUTH = "jwt-auth", JWT_AUTH = "jwt-auth",
@@ -265,16 +267,6 @@ export enum ProjectType {
SecretScanning = "secret-scanning" SecretScanning = "secret-scanning"
} }
export enum ActionProjectType {
SecretManager = ProjectType.SecretManager,
CertificateManager = ProjectType.CertificateManager,
KMS = ProjectType.KMS,
SSH = ProjectType.SSH,
SecretScanning = ProjectType.SecretScanning,
// project operations that happen on all types
Any = "any"
}
export enum SortDirection { export enum SortDirection {
ASC = "asc", ASC = "asc",
DESC = "desc" DESC = "desc"
+1 -1
View File
@@ -16,7 +16,7 @@ export const ProjectTemplatesSchema = z.object({
orgId: z.string().uuid(), orgId: z.string().uuid(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
type: z.string().default("secret-manager") type: z.string().nullable().optional()
}); });
export type TProjectTemplates = z.infer<typeof ProjectTemplatesSchema>; export type TProjectTemplates = z.infer<typeof ProjectTemplatesSchema>;
+3 -2
View File
@@ -25,11 +25,12 @@ export const ProjectsSchema = z.object({
kmsSecretManagerKeyId: z.string().uuid().nullable().optional(), kmsSecretManagerKeyId: z.string().uuid().nullable().optional(),
kmsSecretManagerEncryptedDataKey: zodBuffer.nullable().optional(), kmsSecretManagerEncryptedDataKey: zodBuffer.nullable().optional(),
description: z.string().nullable().optional(), description: z.string().nullable().optional(),
type: z.string(), type: z.string().nullable().optional(),
enforceCapitalization: z.boolean().default(false), enforceCapitalization: z.boolean().default(false),
hasDeleteProtection: z.boolean().default(false).nullable().optional(), hasDeleteProtection: z.boolean().default(false).nullable().optional(),
secretSharing: z.boolean().default(true), secretSharing: z.boolean().default(true),
showSnapshotsLegacy: z.boolean().default(false) showSnapshotsLegacy: z.boolean().default(false),
defaultProduct: z.string().default("secret-manager")
}); });
export type TProjects = z.infer<typeof ProjectsSchema>; export type TProjects = z.infer<typeof ProjectsSchema>;
@@ -60,7 +60,8 @@ export const registerAccessApprovalRequestRouter = async (server: FastifyZodProv
method: "GET", method: "GET",
schema: { schema: {
querystring: z.object({ querystring: z.object({
projectSlug: z.string().trim() projectSlug: z.string().trim(),
policyId: z.string().trim().optional()
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -73,6 +74,7 @@ export const registerAccessApprovalRequestRouter = async (server: FastifyZodProv
handler: async (req) => { handler: async (req) => {
const { count } = await server.services.accessApprovalRequest.getCount({ const { count } = await server.services.accessApprovalRequest.getCount({
projectSlug: req.query.projectSlug, projectSlug: req.query.projectSlug,
policyId: req.query.policyId,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
@@ -1,6 +1,6 @@
import { z } from "zod"; import { z } from "zod";
import { ProjectMembershipRole, ProjectTemplatesSchema, ProjectType } from "@app/db/schemas"; import { ProjectMembershipRole, ProjectTemplatesSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns"; import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
@@ -104,9 +104,6 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
hide: false, hide: false,
tags: [ApiDocsTags.ProjectTemplates], tags: [ApiDocsTags.ProjectTemplates],
description: "List project templates for the current organization.", description: "List project templates for the current organization.",
querystring: z.object({
type: z.nativeEnum(ProjectType).optional().describe(ProjectTemplates.LIST.type)
}),
response: { response: {
200: z.object({ 200: z.object({
projectTemplates: SanitizedProjectTemplateSchema.array() projectTemplates: SanitizedProjectTemplateSchema.array()
@@ -115,8 +112,7 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const { type } = req.query; const projectTemplates = await server.services.projectTemplate.listProjectTemplatesByOrg(req.permission);
const projectTemplates = await server.services.projectTemplate.listProjectTemplatesByOrg(req.permission, type);
const auditTemplates = projectTemplates.filter((template) => !isInfisicalProjectTemplate(template.name)); const auditTemplates = projectTemplates.filter((template) => !isInfisicalProjectTemplate(template.name));
@@ -188,7 +184,6 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
tags: [ApiDocsTags.ProjectTemplates], tags: [ApiDocsTags.ProjectTemplates],
description: "Create a project template.", description: "Create a project template.",
body: z.object({ body: z.object({
type: z.nativeEnum(ProjectType).describe(ProjectTemplates.CREATE.type),
name: slugSchema({ field: "name" }) name: slugSchema({ field: "name" })
.refine((val) => !isInfisicalProjectTemplate(val), { .refine((val) => !isInfisicalProjectTemplate(val), {
message: `The requested project template name is reserved.` message: `The requested project template name is reserved.`
@@ -284,7 +279,6 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
tags: [ApiDocsTags.ProjectTemplates], tags: [ApiDocsTags.ProjectTemplates],
description: "Delete a project template.", description: "Delete a project template.",
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.DELETE.templateId) }), params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.DELETE.templateId) }),
response: { response: {
200: z.object({ 200: z.object({
projectTemplate: SanitizedProjectTemplateSchema projectTemplate: SanitizedProjectTemplateSchema
@@ -94,7 +94,8 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
}, },
schema: { schema: {
querystring: z.object({ querystring: z.object({
workspaceId: z.string().trim() workspaceId: z.string().trim(),
policyId: z.string().trim().optional()
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -112,7 +113,8 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId projectId: req.query.workspaceId,
policyId: req.query.policyId
}); });
return { approvals }; return { approvals };
} }
@@ -80,6 +80,7 @@ export const registerSshCertRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SignSshKey, event: PostHogEventTypes.SignSshKey,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
certificateTemplateId: req.body.certificateTemplateId, certificateTemplateId: req.body.certificateTemplateId,
principals: req.body.principals, principals: req.body.principals,
@@ -171,6 +172,7 @@ export const registerSshCertRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IssueSshCreds, event: PostHogEventTypes.IssueSshCreds,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
certificateTemplateId: req.body.certificateTemplateId, certificateTemplateId: req.body.certificateTemplateId,
principals: req.body.principals, principals: req.body.principals,
@@ -358,6 +358,7 @@ export const registerSshHostRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IssueSshHostUserCert, event: PostHogEventTypes.IssueSshHostUserCert,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
sshHostId: req.params.sshHostId, sshHostId: req.params.sshHostId,
hostname: host.hostname, hostname: host.hostname,
@@ -427,6 +428,7 @@ export const registerSshHostRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IssueSshHostHostCert, event: PostHogEventTypes.IssueSshHostHostCert,
organizationId: req.permission.orgId,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
properties: { properties: {
sshHostId: req.params.sshHostId, sshHostId: req.params.sshHostId,
@@ -1,6 +1,5 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
@@ -97,8 +96,7 @@ export const accessApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: project.id, projectId: project.id,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -248,8 +246,7 @@ export const accessApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: project.id, projectId: project.id,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const accessApprovalPolicies = await accessApprovalPolicyDAL.find({ projectId: project.id, deletedAt: null }); const accessApprovalPolicies = await accessApprovalPolicyDAL.find({ projectId: project.id, deletedAt: null });
@@ -301,8 +298,7 @@ export const accessApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: accessApprovalPolicy.projectId, projectId: accessApprovalPolicy.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval);
@@ -498,8 +494,7 @@ export const accessApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: policy.projectId, projectId: policy.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
@@ -549,8 +544,7 @@ export const accessApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: project.id, projectId: project.id,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if (!membership) { if (!membership) {
throw new ForbiddenRequestError({ message: "You are not a member of this project" }); throw new ForbiddenRequestError({ message: "You are not a member of this project" });
@@ -589,8 +583,7 @@ export const accessApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: policy.projectId, projectId: policy.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
@@ -220,7 +220,7 @@ export interface TAccessApprovalRequestDALFactory extends Omit<TOrmify<TableName
bypassers: string[]; bypassers: string[];
}[] }[]
>; >;
getCount: ({ projectId }: { projectId: string }) => Promise<{ getCount: ({ projectId }: { projectId: string; policyId?: string }) => Promise<{
pendingCount: number; pendingCount: number;
finalizedCount: number; finalizedCount: number;
}>; }>;
@@ -702,7 +702,7 @@ export const accessApprovalRequestDALFactory = (db: TDbClient): TAccessApprovalR
} }
}; };
const getCount: TAccessApprovalRequestDALFactory["getCount"] = async ({ projectId }) => { const getCount: TAccessApprovalRequestDALFactory["getCount"] = async ({ projectId, policyId }) => {
try { try {
const accessRequests = await db const accessRequests = await db
.replicaNode()(TableName.AccessApprovalRequest) .replicaNode()(TableName.AccessApprovalRequest)
@@ -723,8 +723,10 @@ export const accessApprovalRequestDALFactory = (db: TDbClient): TAccessApprovalR
`${TableName.AccessApprovalRequest}.id`, `${TableName.AccessApprovalRequest}.id`,
`${TableName.AccessApprovalRequestReviewer}.requestId` `${TableName.AccessApprovalRequestReviewer}.requestId`
) )
.where(`${TableName.Environment}.projectId`, projectId) .where(`${TableName.Environment}.projectId`, projectId)
.where((qb) => {
if (policyId) void qb.where(`${TableName.AccessApprovalPolicy}.id`, policyId);
})
.select(selectAllTableCols(TableName.AccessApprovalRequest)) .select(selectAllTableCols(TableName.AccessApprovalRequest))
.select(db.ref("status").withSchema(TableName.AccessApprovalRequestReviewer).as("reviewerStatus")) .select(db.ref("status").withSchema(TableName.AccessApprovalRequestReviewer).as("reviewerStatus"))
.select(db.ref("reviewerUserId").withSchema(TableName.AccessApprovalRequestReviewer).as("reviewerUserId")) .select(db.ref("reviewerUserId").withSchema(TableName.AccessApprovalRequestReviewer).as("reviewerUserId"))
@@ -1,7 +1,7 @@
import slugify from "@sindresorhus/slugify"; import slugify from "@sindresorhus/slugify";
import msFn from "ms"; import msFn from "ms";
import { ActionProjectType, ProjectMembershipRole } from "@app/db/schemas"; import { ProjectMembershipRole } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn"; import { groupBy } from "@app/lib/fn";
@@ -107,8 +107,7 @@ export const accessApprovalRequestServiceFactory = ({
actorId, actorId,
projectId: project.id, projectId: project.id,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if (!membership) { if (!membership) {
throw new ForbiddenRequestError({ message: "You are not a member of this project" }); throw new ForbiddenRequestError({ message: "You are not a member of this project" });
@@ -217,7 +216,7 @@ export const accessApprovalRequestServiceFactory = ({
); );
const requesterFullName = `${requestedByUser.firstName} ${requestedByUser.lastName}`; const requesterFullName = `${requestedByUser.firstName} ${requestedByUser.lastName}`;
const approvalUrl = `${cfg.SITE_URL}/secret-manager/${project.id}/approval`; const approvalUrl = `${cfg.SITE_URL}/projects/${project.id}/secret-manager/approval`;
await triggerWorkflowIntegrationNotification({ await triggerWorkflowIntegrationNotification({
input: { input: {
@@ -290,8 +289,7 @@ export const accessApprovalRequestServiceFactory = ({
actorId, actorId,
projectId: project.id, projectId: project.id,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if (!membership) { if (!membership) {
throw new ForbiddenRequestError({ message: "You are not a member of this project" }); throw new ForbiddenRequestError({ message: "You are not a member of this project" });
@@ -337,8 +335,7 @@ export const accessApprovalRequestServiceFactory = ({
actorId, actorId,
projectId: accessApprovalRequest.projectId, projectId: accessApprovalRequest.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if (!membership) { if (!membership) {
@@ -350,6 +347,12 @@ export const accessApprovalRequestServiceFactory = ({
const canBypass = !policy.bypassers.length || policy.bypassers.some((bypasser) => bypasser.userId === actorId); const canBypass = !policy.bypassers.length || policy.bypassers.some((bypasser) => bypasser.userId === actorId);
const cannotBypassUnderSoftEnforcement = !(isSoftEnforcement && canBypass); const cannotBypassUnderSoftEnforcement = !(isSoftEnforcement && canBypass);
// Calculate break glass attempt before sequence checks
const isBreakGlassApprovalAttempt =
policy.enforcementLevel === EnforcementLevel.Soft &&
actorId === accessApprovalRequest.requestedByUserId &&
status === ApprovalStatus.APPROVED;
const isApprover = policy.approvers.find((approver) => approver.userId === actorId); const isApprover = policy.approvers.find((approver) => approver.userId === actorId);
// If user is (not an approver OR cant self approve) AND can't bypass policy // If user is (not an approver OR cant self approve) AND can't bypass policy
if ((!isApprover || (!policy.allowedSelfApprovals && isSelfApproval)) && cannotBypassUnderSoftEnforcement) { if ((!isApprover || (!policy.allowedSelfApprovals && isSelfApproval)) && cannotBypassUnderSoftEnforcement) {
@@ -409,15 +412,14 @@ export const accessApprovalRequestServiceFactory = ({
const isApproverOfTheSequence = policy.approvers.find( const isApproverOfTheSequence = policy.approvers.find(
(el) => el.sequence === presentSequence.step && el.userId === actorId (el) => el.sequence === presentSequence.step && el.userId === actorId
); );
if (!isApproverOfTheSequence) throw new BadRequestError({ message: "You are not reviewer in this step" });
// Only throw if actor is not the approver and not bypassing
if (!isApproverOfTheSequence && !isBreakGlassApprovalAttempt) {
throw new BadRequestError({ message: "You are not a reviewer in this step" });
}
} }
const reviewStatus = await accessApprovalRequestReviewerDAL.transaction(async (tx) => { const reviewStatus = await accessApprovalRequestReviewerDAL.transaction(async (tx) => {
const isBreakGlassApprovalAttempt =
policy.enforcementLevel === EnforcementLevel.Soft &&
actorId === accessApprovalRequest.requestedByUserId &&
status === ApprovalStatus.APPROVED;
let reviewForThisActorProcessing: { let reviewForThisActorProcessing: {
id: string; id: string;
requestId: string; requestId: string;
@@ -543,7 +545,7 @@ export const accessApprovalRequestServiceFactory = ({
bypassReason: bypassReason || "No reason provided", bypassReason: bypassReason || "No reason provided",
secretPath: policy.secretPath || "/", secretPath: policy.secretPath || "/",
environment, environment,
approvalUrl: `${cfg.SITE_URL}/secret-manager/${project.id}/approval`, approvalUrl: `${cfg.SITE_URL}/projects/${project.id}/secret-manager/approval`,
requestType: "access" requestType: "access"
}, },
template: SmtpTemplates.AccessSecretRequestBypassed template: SmtpTemplates.AccessSecretRequestBypassed
@@ -560,6 +562,7 @@ export const accessApprovalRequestServiceFactory = ({
const getCount: TAccessApprovalRequestServiceFactory["getCount"] = async ({ const getCount: TAccessApprovalRequestServiceFactory["getCount"] = async ({
projectSlug, projectSlug,
policyId,
actor, actor,
actorAuthMethod, actorAuthMethod,
actorId, actorId,
@@ -573,14 +576,13 @@ export const accessApprovalRequestServiceFactory = ({
actorId, actorId,
projectId: project.id, projectId: project.id,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if (!membership) { if (!membership) {
throw new ForbiddenRequestError({ message: "You are not a member of this project" }); throw new ForbiddenRequestError({ message: "You are not a member of this project" });
} }
const count = await accessApprovalRequestDAL.getCount({ projectId: project.id }); const count = await accessApprovalRequestDAL.getCount({ projectId: project.id, policyId });
return { count }; return { count };
}; };
@@ -12,6 +12,7 @@ export type TVerifyPermission = {
export type TGetAccessRequestCountDTO = { export type TGetAccessRequestCountDTO = {
projectSlug: string; projectSlug: string;
policyId?: string;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export type TReviewAccessRequestDTO = { export type TReviewAccessRequestDTO = {
@@ -1,7 +1,6 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
import { ActionProjectType } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { ActorType } from "@app/services/auth/auth-type"; import { ActorType } from "@app/services/auth/auth-type";
@@ -38,8 +37,7 @@ export const assumePrivilegeServiceFactory = ({
actorId: actorPermissionDetails.id, actorId: actorPermissionDetails.id,
projectId, projectId,
actorAuthMethod: actorPermissionDetails.authMethod, actorAuthMethod: actorPermissionDetails.authMethod,
actorOrgId: actorPermissionDetails.orgId, actorOrgId: actorPermissionDetails.orgId
actionProjectType: ActionProjectType.Any
}); });
if (targetActorType === ActorType.USER) { if (targetActorType === ActorType.USER) {
@@ -60,8 +58,7 @@ export const assumePrivilegeServiceFactory = ({
actorId: targetActorId, actorId: targetActorId,
projectId, projectId,
actorAuthMethod: actorPermissionDetails.authMethod, actorAuthMethod: actorPermissionDetails.authMethod,
actorOrgId: actorPermissionDetails.orgId, actorOrgId: actorPermissionDetails.orgId
actionProjectType: ActionProjectType.Any
}); });
const appCfg = getConfig(); const appCfg = getConfig();
@@ -131,7 +131,6 @@ export const auditLogQueueServiceFactory = async ({
}); });
try { try {
logger.info(`Streaming audit log [url=${url}] for org [orgId=${orgId}]`);
const response = await request.post( const response = await request.post(
url, url,
{ ...providerSpecificPayload(url), ...auditLog }, { ...providerSpecificPayload(url), ...auditLog },
@@ -143,9 +142,6 @@ export const auditLogQueueServiceFactory = async ({
signal: AbortSignal.timeout(AUDIT_LOG_STREAM_TIMEOUT) signal: AbortSignal.timeout(AUDIT_LOG_STREAM_TIMEOUT)
} }
); );
logger.info(
`Successfully streamed audit log [url=${url}] for org [orgId=${orgId}] [response=${JSON.stringify(response.data)}]`
);
return response; return response;
} catch (error) { } catch (error) {
logger.error( logger.error(
@@ -237,7 +233,6 @@ export const auditLogQueueServiceFactory = async ({
}); });
try { try {
logger.info(`Streaming audit log [url=${url}] for org [orgId=${orgId}]`);
const response = await request.post( const response = await request.post(
url, url,
{ ...providerSpecificPayload(url), ...auditLog }, { ...providerSpecificPayload(url), ...auditLog },
@@ -249,9 +244,6 @@ export const auditLogQueueServiceFactory = async ({
signal: AbortSignal.timeout(AUDIT_LOG_STREAM_TIMEOUT) signal: AbortSignal.timeout(AUDIT_LOG_STREAM_TIMEOUT)
} }
); );
logger.info(
`Successfully streamed audit log [url=${url}] for org [orgId=${orgId}] [response=${JSON.stringify(response.data)}]`
);
return response; return response;
} catch (error) { } catch (error) {
logger.error( logger.error(
@@ -1,7 +1,6 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { requestContext } from "@fastify/request-context"; import { requestContext } from "@fastify/request-context";
import { ActionProjectType } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { ActorType } from "@app/services/auth/auth-type"; import { ActorType } from "@app/services/auth/auth-type";
@@ -38,8 +37,7 @@ export const auditLogServiceFactory = ({
actorId, actorId,
projectId: filter.projectId, projectId: filter.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs);
} else { } else {
@@ -202,6 +202,12 @@ export enum EventType {
REVOKE_IDENTITY_ALICLOUD_AUTH = "revoke-identity-alicloud-auth", REVOKE_IDENTITY_ALICLOUD_AUTH = "revoke-identity-alicloud-auth",
GET_IDENTITY_ALICLOUD_AUTH = "get-identity-alicloud-auth", GET_IDENTITY_ALICLOUD_AUTH = "get-identity-alicloud-auth",
LOGIN_IDENTITY_TLS_CERT_AUTH = "login-identity-tls-cert-auth",
ADD_IDENTITY_TLS_CERT_AUTH = "add-identity-tls-cert-auth",
UPDATE_IDENTITY_TLS_CERT_AUTH = "update-identity-tls-cert-auth",
REVOKE_IDENTITY_TLS_CERT_AUTH = "revoke-identity-tls-cert-auth",
GET_IDENTITY_TLS_CERT_AUTH = "get-identity-tls-cert-auth",
LOGIN_IDENTITY_AWS_AUTH = "login-identity-aws-auth", LOGIN_IDENTITY_AWS_AUTH = "login-identity-aws-auth",
ADD_IDENTITY_AWS_AUTH = "add-identity-aws-auth", ADD_IDENTITY_AWS_AUTH = "add-identity-aws-auth",
UPDATE_IDENTITY_AWS_AUTH = "update-identity-aws-auth", UPDATE_IDENTITY_AWS_AUTH = "update-identity-aws-auth",
@@ -1141,6 +1147,53 @@ interface GetIdentityAliCloudAuthEvent {
}; };
} }
interface LoginIdentityTlsCertAuthEvent {
type: EventType.LOGIN_IDENTITY_TLS_CERT_AUTH;
metadata: {
identityId: string;
identityTlsCertAuthId: string;
identityAccessTokenId: string;
};
}
interface AddIdentityTlsCertAuthEvent {
type: EventType.ADD_IDENTITY_TLS_CERT_AUTH;
metadata: {
identityId: string;
allowedCommonNames: string | null | undefined;
accessTokenTTL: number;
accessTokenMaxTTL: number;
accessTokenNumUsesLimit: number;
accessTokenTrustedIps: Array<TIdentityTrustedIp>;
};
}
interface DeleteIdentityTlsCertAuthEvent {
type: EventType.REVOKE_IDENTITY_TLS_CERT_AUTH;
metadata: {
identityId: string;
};
}
interface UpdateIdentityTlsCertAuthEvent {
type: EventType.UPDATE_IDENTITY_TLS_CERT_AUTH;
metadata: {
identityId: string;
allowedCommonNames: string | null | undefined;
accessTokenTTL?: number;
accessTokenMaxTTL?: number;
accessTokenNumUsesLimit?: number;
accessTokenTrustedIps?: Array<TIdentityTrustedIp>;
};
}
interface GetIdentityTlsCertAuthEvent {
type: EventType.GET_IDENTITY_TLS_CERT_AUTH;
metadata: {
identityId: string;
};
}
interface LoginIdentityOciAuthEvent { interface LoginIdentityOciAuthEvent {
type: EventType.LOGIN_IDENTITY_OCI_AUTH; type: EventType.LOGIN_IDENTITY_OCI_AUTH;
metadata: { metadata: {
@@ -3358,6 +3411,11 @@ export type Event =
| UpdateIdentityAliCloudAuthEvent | UpdateIdentityAliCloudAuthEvent
| GetIdentityAliCloudAuthEvent | GetIdentityAliCloudAuthEvent
| DeleteIdentityAliCloudAuthEvent | DeleteIdentityAliCloudAuthEvent
| LoginIdentityTlsCertAuthEvent
| AddIdentityTlsCertAuthEvent
| UpdateIdentityTlsCertAuthEvent
| GetIdentityTlsCertAuthEvent
| DeleteIdentityTlsCertAuthEvent
| LoginIdentityOciAuthEvent | LoginIdentityOciAuthEvent
| AddIdentityOciAuthEvent | AddIdentityOciAuthEvent
| UpdateIdentityOciAuthEvent | UpdateIdentityOciAuthEvent
@@ -1,7 +1,6 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import * as x509 from "@peculiar/x509"; import * as x509 from "@peculiar/x509";
import { ActionProjectType } from "@app/db/schemas";
import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal"; import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
@@ -78,8 +77,7 @@ export const certificateAuthorityCrlServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1,7 +1,6 @@
import { ForbiddenError, subject } from "@casl/ability"; import { ForbiddenError, subject } from "@casl/ability";
import RE2 from "re2"; import RE2 from "re2";
import { ActionProjectType } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { import {
@@ -85,8 +84,7 @@ export const dynamicSecretLeaseServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const plan = await licenseService.getPlan(actorOrgId); const plan = await licenseService.getPlan(actorOrgId);
@@ -202,8 +200,7 @@ export const dynamicSecretLeaseServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
@@ -300,8 +297,7 @@ export const dynamicSecretLeaseServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
@@ -389,8 +385,7 @@ export const dynamicSecretLeaseServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
@@ -437,8 +432,7 @@ export const dynamicSecretLeaseServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
@@ -1,6 +1,5 @@
import { ForbiddenError, subject } from "@casl/ability"; import { ForbiddenError, subject } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { import {
@@ -78,8 +77,7 @@ export const dynamicSecretServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -202,8 +200,7 @@ export const dynamicSecretServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const plan = await licenseService.getPlan(actorOrgId); const plan = await licenseService.getPlan(actorOrgId);
@@ -354,8 +351,7 @@ export const dynamicSecretServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
@@ -420,8 +416,7 @@ export const dynamicSecretServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
@@ -485,8 +480,7 @@ export const dynamicSecretServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
// verify user has access to each env in request // verify user has access to each env in request
@@ -529,8 +523,7 @@ export const dynamicSecretServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionDynamicSecretActions.ReadRootCredential, ProjectPermissionDynamicSecretActions.ReadRootCredential,
@@ -578,8 +571,7 @@ export const dynamicSecretServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path); const folder = await folderDAL.findBySecretPath(projectId, environmentSlug, path);
@@ -616,8 +608,7 @@ export const dynamicSecretServiceFactory = ({
actorId: actor.id, actorId: actor.id,
projectId, projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.SecretManager
}); });
const userAccessibleFolderMappings = folderMappings.filter(({ path, environment }) => const userAccessibleFolderMappings = folderMappings.filter(({ path, environment }) =>
@@ -661,8 +652,7 @@ export const dynamicSecretServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const folders = await folderDAL.findBySecretPathMultiEnv(projectId, environmentSlugs, path); const folders = await folderDAL.findBySecretPathMultiEnv(projectId, environmentSlugs, path);
@@ -1,5 +1,5 @@
import axios from "axios"; import axios from "axios";
import * as jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
import { BadRequestError, InternalServerError } from "@app/lib/errors"; import { BadRequestError, InternalServerError } from "@app/lib/errors";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
@@ -1,7 +1,7 @@
import { ForbiddenError, subject } from "@casl/ability"; import { ForbiddenError, subject } from "@casl/ability";
import { packRules } from "@casl/ability/extra"; import { packRules } from "@casl/ability/extra";
import { ActionProjectType, TableName } from "@app/db/schemas"; import { TableName } from "@app/db/schemas";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors"; import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars"; import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
@@ -61,8 +61,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Edit, ProjectPermissionIdentityActions.Edit,
@@ -73,8 +72,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId: identityId, actorId: identityId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
// we need to validate that the privilege given is not higher than the assigning users permission // we need to validate that the privilege given is not higher than the assigning users permission
@@ -160,8 +158,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Edit, ProjectPermissionIdentityActions.Edit,
@@ -172,8 +169,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId: identityProjectMembership.identityId, actorId: identityProjectMembership.identityId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
// we need to validate that the privilege given is not higher than the assigning users permission // we need to validate that the privilege given is not higher than the assigning users permission
@@ -260,8 +256,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Edit, ProjectPermissionIdentityActions.Edit,
@@ -272,8 +267,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId: identityProjectMembership.identityId, actorId: identityProjectMembership.identityId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem, membership.shouldUseNewPrivilegeSystem,
@@ -321,8 +315,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Read, ProjectPermissionIdentityActions.Read,
@@ -356,8 +349,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Read, ProjectPermissionIdentityActions.Read,
@@ -392,8 +384,7 @@ export const identityProjectAdditionalPrivilegeV2ServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Read, ProjectPermissionIdentityActions.Read,
@@ -1,7 +1,6 @@
import { ForbiddenError, MongoAbility, RawRuleOf, subject } from "@casl/ability"; import { ForbiddenError, MongoAbility, RawRuleOf, subject } from "@casl/ability";
import { PackRule, packRules, unpackRules } from "@casl/ability/extra"; import { PackRule, packRules, unpackRules } from "@casl/ability/extra";
import { ActionProjectType } from "@app/db/schemas";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors"; import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars"; import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
@@ -73,8 +72,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -87,8 +85,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actorId: identityId, actorId: identityId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
// we need to validate that the privilege given is not higher than the assigning users permission // we need to validate that the privilege given is not higher than the assigning users permission
@@ -175,8 +172,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -189,8 +185,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actorId: identityProjectMembership.identityId, actorId: identityProjectMembership.identityId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
// we need to validate that the privilege given is not higher than the assigning users permission // we need to validate that the privilege given is not higher than the assigning users permission
@@ -293,8 +288,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Edit, ProjectPermissionIdentityActions.Edit,
@@ -306,8 +300,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actorId: identityProjectMembership.identityId, actorId: identityProjectMembership.identityId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
const permissionBoundary = validatePrivilegeChangeOperation( const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem, membership.shouldUseNewPrivilegeSystem,
@@ -366,8 +359,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Read, ProjectPermissionIdentityActions.Read,
@@ -409,8 +401,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: identityProjectMembership.projectId, projectId: identityProjectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -24,7 +24,7 @@ type TKmipOperationServiceFactoryDep = {
kmsService: TKmsServiceFactory; kmsService: TKmsServiceFactory;
kmsDAL: TKmsKeyDALFactory; kmsDAL: TKmsKeyDALFactory;
kmipClientDAL: TKmipClientDALFactory; kmipClientDAL: TKmipClientDALFactory;
projectDAL: Pick<TProjectDALFactory, "getProjectFromSplitId" | "findById">; projectDAL: Pick<TProjectDALFactory, "findById">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
}; };
+6 -13
View File
@@ -2,7 +2,6 @@ import { ForbiddenError } from "@casl/ability";
import * as x509 from "@peculiar/x509"; import * as x509 from "@peculiar/x509";
import crypto, { KeyObject } from "crypto"; import crypto, { KeyObject } from "crypto";
import { ActionProjectType } from "@app/db/schemas";
import { BadRequestError, InternalServerError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, InternalServerError, NotFoundError } from "@app/lib/errors";
import { isValidIp } from "@app/lib/ip"; import { isValidIp } from "@app/lib/ip";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
@@ -73,8 +72,7 @@ export const kmipServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -127,8 +125,7 @@ export const kmipServiceFactory = ({
actorId, actorId,
projectId: kmipClient.projectId, projectId: kmipClient.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -159,8 +156,7 @@ export const kmipServiceFactory = ({
actorId, actorId,
projectId: kmipClient.projectId, projectId: kmipClient.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -193,8 +189,7 @@ export const kmipServiceFactory = ({
actorId, actorId,
projectId: kmipClient.projectId, projectId: kmipClient.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionKmipActions.ReadClients, ProjectPermissionSub.Kmip); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionKmipActions.ReadClients, ProjectPermissionSub.Kmip);
@@ -215,8 +210,7 @@ export const kmipServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionKmipActions.ReadClients, ProjectPermissionSub.Kmip); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionKmipActions.ReadClients, ProjectPermissionSub.Kmip);
@@ -252,8 +246,7 @@ export const kmipServiceFactory = ({
actorId, actorId,
projectId: kmipClient.projectId, projectId: kmipClient.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -91,7 +91,7 @@ export interface TPermissionDALFactory {
userId: string; userId: string;
projectId: string; projectId: string;
username: string; username: string;
projectType: string; projectType?: string | null;
id: string; id: string;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
@@ -163,7 +163,7 @@ export interface TPermissionDALFactory {
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
orgId: string; orgId: string;
projectType: string; projectType?: string | null;
shouldUseNewPrivilegeSystem: boolean; shouldUseNewPrivilegeSystem: boolean;
orgAuthEnforced: boolean; orgAuthEnforced: boolean;
metadata: { metadata: {
@@ -201,7 +201,7 @@ export interface TPermissionDALFactory {
userId: string; userId: string;
projectId: string; projectId: string;
username: string; username: string;
projectType: string; projectType?: string | null;
id: string; id: string;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
@@ -267,7 +267,7 @@ export interface TPermissionDALFactory {
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
orgId: string; orgId: string;
projectType: string; projectType?: string | null;
orgAuthEnforced: boolean; orgAuthEnforced: boolean;
metadata: { metadata: {
id: string; id: string;
@@ -1,7 +1,6 @@
import { MongoAbility, RawRuleOf } from "@casl/ability"; import { MongoAbility, RawRuleOf } from "@casl/ability";
import { MongoQuery } from "@ucast/mongo2js"; import { MongoQuery } from "@ucast/mongo2js";
import { ActionProjectType } from "@app/db/schemas";
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type"; import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
import { OrgPermissionSet } from "./org-permission"; import { OrgPermissionSet } from "./org-permission";
@@ -21,7 +20,6 @@ export type TGetUserProjectPermissionArg = {
userId: string; userId: string;
projectId: string; projectId: string;
authMethod: ActorAuthMethod; authMethod: ActorAuthMethod;
actionProjectType: ActionProjectType;
userOrgId?: string; userOrgId?: string;
}; };
@@ -29,14 +27,12 @@ export type TGetIdentityProjectPermissionArg = {
identityId: string; identityId: string;
projectId: string; projectId: string;
identityOrgId?: string; identityOrgId?: string;
actionProjectType: ActionProjectType;
}; };
export type TGetServiceTokenProjectPermissionArg = { export type TGetServiceTokenProjectPermissionArg = {
serviceTokenId: string; serviceTokenId: string;
projectId: string; projectId: string;
actorOrgId?: string; actorOrgId?: string;
actionProjectType: ActionProjectType;
}; };
export type TGetProjectPermissionArg = { export type TGetProjectPermissionArg = {
@@ -45,7 +41,6 @@ export type TGetProjectPermissionArg = {
projectId: string; projectId: string;
actorAuthMethod: ActorAuthMethod; actorAuthMethod: ActorAuthMethod;
actorOrgId?: string; actorOrgId?: string;
actionProjectType: ActionProjectType;
}; };
export type TPermissionServiceFactory = { export type TPermissionServiceFactory = {
@@ -143,13 +138,7 @@ export type TPermissionServiceFactory = {
}; };
} }
>; >;
getUserProjectPermission: ({ getUserProjectPermission: ({ userId, projectId, authMethod, userOrgId }: TGetUserProjectPermissionArg) => Promise<{
userId,
projectId,
authMethod,
userOrgId,
actionProjectType
}: TGetUserProjectPermissionArg) => Promise<{
permission: MongoAbility<ProjectPermissionSet, MongoQuery>; permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
membership: { membership: {
id: string; id: string;
@@ -5,7 +5,6 @@ import { MongoQuery } from "@ucast/mongo2js";
import handlebars from "handlebars"; import handlebars from "handlebars";
import { import {
ActionProjectType,
OrgMembershipRole, OrgMembershipRole,
ProjectMembershipRole, ProjectMembershipRole,
ServiceTokenScopes, ServiceTokenScopes,
@@ -214,8 +213,7 @@ export const permissionServiceFactory = ({
userId, userId,
projectId, projectId,
authMethod, authMethod,
userOrgId, userOrgId
actionProjectType
}: TGetUserProjectPermissionArg): Promise<TProjectPermissionRT<ActorType.USER>> => { }: TGetUserProjectPermissionArg): Promise<TProjectPermissionRT<ActorType.USER>> => {
const userProjectPermission = await permissionDAL.getProjectPermission(userId, projectId); const userProjectPermission = await permissionDAL.getProjectPermission(userId, projectId);
if (!userProjectPermission) throw new ForbiddenRequestError({ name: "User not a part of the specified project" }); if (!userProjectPermission) throw new ForbiddenRequestError({ name: "User not a part of the specified project" });
@@ -242,12 +240,6 @@ export const permissionServiceFactory = ({
userProjectPermission.orgRole userProjectPermission.orgRole
); );
if (actionProjectType !== ActionProjectType.Any && actionProjectType !== userProjectPermission.projectType) {
throw new BadRequestError({
message: `The project is of type ${userProjectPermission.projectType}. Operations of type ${actionProjectType} are not allowed.`
});
}
// join two permissions and pass to build the final permission set // join two permissions and pass to build the final permission set
const rolePermissions = userProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || []; const rolePermissions = userProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || [];
const additionalPrivileges = const additionalPrivileges =
@@ -295,8 +287,7 @@ export const permissionServiceFactory = ({
const getIdentityProjectPermission = async ({ const getIdentityProjectPermission = async ({
identityId, identityId,
projectId, projectId,
identityOrgId, identityOrgId
actionProjectType
}: TGetIdentityProjectPermissionArg): Promise<TProjectPermissionRT<ActorType.IDENTITY>> => { }: TGetIdentityProjectPermissionArg): Promise<TProjectPermissionRT<ActorType.IDENTITY>> => {
const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId); const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId);
if (!identityProjectPermission) if (!identityProjectPermission)
@@ -316,12 +307,6 @@ export const permissionServiceFactory = ({
throw new ForbiddenRequestError({ name: "Identity is not a member of the specified organization" }); throw new ForbiddenRequestError({ name: "Identity is not a member of the specified organization" });
} }
if (actionProjectType !== ActionProjectType.Any && actionProjectType !== identityProjectPermission.projectType) {
throw new BadRequestError({
message: `The project is of type ${identityProjectPermission.projectType}. Operations of type ${actionProjectType} are not allowed.`
});
}
const rolePermissions = const rolePermissions =
identityProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || []; identityProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || [];
const additionalPrivileges = const additionalPrivileges =
@@ -376,8 +361,7 @@ export const permissionServiceFactory = ({
const getServiceTokenProjectPermission = async ({ const getServiceTokenProjectPermission = async ({
serviceTokenId, serviceTokenId,
projectId, projectId,
actorOrgId, actorOrgId
actionProjectType
}: TGetServiceTokenProjectPermissionArg) => { }: TGetServiceTokenProjectPermissionArg) => {
const serviceToken = await serviceTokenDAL.findById(serviceTokenId); const serviceToken = await serviceTokenDAL.findById(serviceTokenId);
if (!serviceToken) throw new NotFoundError({ message: `Service token with ID '${serviceTokenId}' not found` }); if (!serviceToken) throw new NotFoundError({ message: `Service token with ID '${serviceTokenId}' not found` });
@@ -402,12 +386,6 @@ export const permissionServiceFactory = ({
}); });
} }
if (actionProjectType !== ActionProjectType.Any && actionProjectType !== serviceTokenProject.type) {
throw new BadRequestError({
message: `The project is of type ${serviceTokenProject.type}. Operations of type ${actionProjectType} are not allowed.`
});
}
const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []); const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []);
return { return {
permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions), permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions),
@@ -559,8 +537,7 @@ export const permissionServiceFactory = ({
actorId: inputActorId, actorId: inputActorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType
}: TGetProjectPermissionArg): Promise<TProjectPermissionRT<T>> => { }: TGetProjectPermissionArg): Promise<TProjectPermissionRT<T>> => {
let actor = inputActor; let actor = inputActor;
let actorId = inputActorId; let actorId = inputActorId;
@@ -581,22 +558,19 @@ export const permissionServiceFactory = ({
userId: actorId, userId: actorId,
projectId, projectId,
authMethod: actorAuthMethod, authMethod: actorAuthMethod,
userOrgId: actorOrgId, userOrgId: actorOrgId
actionProjectType
}) as Promise<TProjectPermissionRT<T>>; }) as Promise<TProjectPermissionRT<T>>;
case ActorType.SERVICE: case ActorType.SERVICE:
return getServiceTokenProjectPermission({ return getServiceTokenProjectPermission({
serviceTokenId: actorId, serviceTokenId: actorId,
projectId, projectId,
actorOrgId, actorOrgId
actionProjectType
}) as Promise<TProjectPermissionRT<T>>; }) as Promise<TProjectPermissionRT<T>>;
case ActorType.IDENTITY: case ActorType.IDENTITY:
return getIdentityProjectPermission({ return getIdentityProjectPermission({
identityId: actorId, identityId: actorId,
projectId, projectId,
identityOrgId: actorOrgId, identityOrgId: actorOrgId
actionProjectType
}) as Promise<TProjectPermissionRT<T>>; }) as Promise<TProjectPermissionRT<T>>;
default: default:
throw new BadRequestError({ throw new BadRequestError({
+1 -3
View File
@@ -1,7 +1,6 @@
/* eslint-disable no-await-in-loop */ /* eslint-disable no-await-in-loop */
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { ProjectPermissionCommitsActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionCommitsActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { NotFoundError } from "@app/lib/errors"; import { NotFoundError } from "@app/lib/errors";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
@@ -321,8 +320,7 @@ export const pitServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(userPermission).throwUnlessCan( ForbiddenError.from(userPermission).throwUnlessCan(
@@ -1,4 +1,3 @@
import { ProjectType } from "@app/db/schemas";
import { import {
InfisicalProjectTemplate, InfisicalProjectTemplate,
TUnpackedPermission TUnpackedPermission
@@ -7,21 +6,18 @@ import { getPredefinedRoles } from "@app/services/project-role/project-role-fns"
import { ProjectTemplateDefaultEnvironments } from "./project-template-constants"; import { ProjectTemplateDefaultEnvironments } from "./project-template-constants";
export const getDefaultProjectTemplate = (orgId: string, type: ProjectType) => ({ export const getDefaultProjectTemplate = (orgId: string) => ({
id: "b11b49a9-09a9-4443-916a-4246f9ff2c69", // random ID to appease zod id: "b11b49a9-09a9-4443-916a-4246f9ff2c69", // random ID to appease zod
type,
name: InfisicalProjectTemplate.Default, name: InfisicalProjectTemplate.Default,
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
description: `Infisical's ${type} default project template`, description: `Infisical's default project template`,
environments: type === ProjectType.SecretManager ? ProjectTemplateDefaultEnvironments : null, environments: ProjectTemplateDefaultEnvironments,
roles: [...getPredefinedRoles({ projectId: "project-template", projectType: type })].map( roles: getPredefinedRoles({ projectId: "project-template" }) as Array<{
({ name, slug, permissions }) => ({ name: string;
name, slug: string;
slug, permissions: TUnpackedPermission[];
permissions: permissions as TUnpackedPermission[] }>,
})
),
orgId orgId
}); });
@@ -1,7 +1,7 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { packRules } from "@casl/ability/extra"; import { packRules } from "@casl/ability/extra";
import { ProjectType, TProjectTemplates } from "@app/db/schemas"; import { TProjectTemplates } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
@@ -29,13 +29,11 @@ const $unpackProjectTemplate = ({ roles, environments, ...rest }: TProjectTempla
...rest, ...rest,
environments: environments as TProjectTemplateEnvironment[], environments: environments as TProjectTemplateEnvironment[],
roles: [ roles: [
...getPredefinedRoles({ projectId: "project-template", projectType: rest.type as ProjectType }).map( ...getPredefinedRoles({ projectId: "project-template" }).map(({ name, slug, permissions }) => ({
({ name, slug, permissions }) => ({ name,
name, slug,
slug, permissions: permissions as TUnpackedPermission[]
permissions: permissions as TUnpackedPermission[] })),
})
),
...(roles as TProjectTemplateRole[]).map((role) => ({ ...(roles as TProjectTemplateRole[]).map((role) => ({
...role, ...role,
permissions: unpackPermissions(role.permissions) permissions: unpackPermissions(role.permissions)
@@ -48,10 +46,7 @@ export const projectTemplateServiceFactory = ({
permissionService, permissionService,
projectTemplateDAL projectTemplateDAL
}: TProjectTemplatesServiceFactoryDep): TProjectTemplateServiceFactory => { }: TProjectTemplatesServiceFactoryDep): TProjectTemplateServiceFactory => {
const listProjectTemplatesByOrg: TProjectTemplateServiceFactory["listProjectTemplatesByOrg"] = async ( const listProjectTemplatesByOrg: TProjectTemplateServiceFactory["listProjectTemplatesByOrg"] = async (actor) => {
actor,
type
) => {
const plan = await licenseService.getPlan(actor.orgId); const plan = await licenseService.getPlan(actor.orgId);
if (!plan.projectTemplates) if (!plan.projectTemplates)
@@ -70,14 +65,11 @@ export const projectTemplateServiceFactory = ({
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.ProjectTemplates); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.ProjectTemplates);
const projectTemplates = await projectTemplateDAL.find({ const projectTemplates = await projectTemplateDAL.find({
orgId: actor.orgId, orgId: actor.orgId
...(type ? { type } : {})
}); });
return [ return [
...(type getDefaultProjectTemplate(actor.orgId),
? [getDefaultProjectTemplate(actor.orgId, type)]
: Object.values(ProjectType).map((projectType) => getDefaultProjectTemplate(actor.orgId, projectType))),
...projectTemplates.map((template) => $unpackProjectTemplate(template)) ...projectTemplates.map((template) => $unpackProjectTemplate(template))
]; ];
}; };
@@ -142,7 +134,7 @@ export const projectTemplateServiceFactory = ({
}; };
const createProjectTemplate: TProjectTemplateServiceFactory["createProjectTemplate"] = async ( const createProjectTemplate: TProjectTemplateServiceFactory["createProjectTemplate"] = async (
{ roles, environments, type, ...params }, { roles, environments, ...params },
actor actor
) => { ) => {
const plan = await licenseService.getPlan(actor.orgId); const plan = await licenseService.getPlan(actor.orgId);
@@ -162,10 +154,6 @@ export const projectTemplateServiceFactory = ({
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.ProjectTemplates); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.ProjectTemplates);
if (environments && type !== ProjectType.SecretManager) {
throw new BadRequestError({ message: "Cannot configure environments for non-SecretManager project templates" });
}
if (environments && plan.environmentLimit !== null && environments.length > plan.environmentLimit) { if (environments && plan.environmentLimit !== null && environments.length > plan.environmentLimit) {
throw new BadRequestError({ throw new BadRequestError({
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
@@ -188,10 +176,8 @@ export const projectTemplateServiceFactory = ({
const projectTemplate = await projectTemplateDAL.create({ const projectTemplate = await projectTemplateDAL.create({
...params, ...params,
roles: JSON.stringify(roles.map((role) => ({ ...role, permissions: packRules(role.permissions) }))), roles: JSON.stringify(roles.map((role) => ({ ...role, permissions: packRules(role.permissions) }))),
environments: environments: environments ? JSON.stringify(environments ?? ProjectTemplateDefaultEnvironments) : null,
type === ProjectType.SecretManager ? JSON.stringify(environments ?? ProjectTemplateDefaultEnvironments) : null, orgId: actor.orgId
orgId: actor.orgId,
type
}); });
return $unpackProjectTemplate(projectTemplate); return $unpackProjectTemplate(projectTemplate);
@@ -223,12 +209,6 @@ export const projectTemplateServiceFactory = ({
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.ProjectTemplates); ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.ProjectTemplates);
if (projectTemplate.type !== ProjectType.SecretManager && environments)
throw new BadRequestError({ message: "Cannot configure environments for non-SecretManager project templates" });
if (projectTemplate.type === ProjectType.SecretManager && environments === null)
throw new BadRequestError({ message: "Environments cannot be removed for SecretManager project templates" });
if (environments && plan.environmentLimit !== null && environments.length > plan.environmentLimit) { if (environments && plan.environmentLimit !== null && environments.length > plan.environmentLimit) {
throw new BadRequestError({ throw new BadRequestError({
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
@@ -1,6 +1,6 @@
import { z } from "zod"; import { z } from "zod";
import { ProjectMembershipRole, ProjectType, TProjectEnvironments } from "@app/db/schemas"; import { ProjectMembershipRole, TProjectEnvironments } from "@app/db/schemas";
import { TProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission"; import { TProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { OrgServiceActor } from "@app/lib/types"; import { OrgServiceActor } from "@app/lib/types";
import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission"; import { UnpackedPermissionSchema } from "@app/server/routes/sanitizedSchema/permission";
@@ -16,7 +16,6 @@ export type TProjectTemplateRole = {
export type TCreateProjectTemplateDTO = { export type TCreateProjectTemplateDTO = {
name: string; name: string;
description?: string; description?: string;
type: ProjectType;
roles: TProjectTemplateRole[]; roles: TProjectTemplateRole[];
environments?: TProjectTemplateEnvironment[] | null; environments?: TProjectTemplateEnvironment[] | null;
}; };
@@ -30,14 +29,10 @@ export enum InfisicalProjectTemplate {
} }
export type TProjectTemplateServiceFactory = { export type TProjectTemplateServiceFactory = {
listProjectTemplatesByOrg: ( listProjectTemplatesByOrg: (actor: OrgServiceActor) => Promise<
actor: OrgServiceActor,
type?: ProjectType
) => Promise<
( (
| { | {
id: string; id: string;
type: ProjectType;
name: InfisicalProjectTemplate; name: InfisicalProjectTemplate;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
@@ -74,7 +69,6 @@ export type TProjectTemplateServiceFactory = {
name: string; name: string;
}[]; }[];
name: string; name: string;
type: string;
orgId: string; orgId: string;
id: string; id: string;
createdAt: Date; createdAt: Date;
@@ -99,7 +93,6 @@ export type TProjectTemplateServiceFactory = {
name: string; name: string;
}[]; }[];
name: string; name: string;
type: string;
orgId: string; orgId: string;
id: string; id: string;
createdAt: Date; createdAt: Date;
@@ -123,7 +116,6 @@ export type TProjectTemplateServiceFactory = {
name: string; name: string;
}[]; }[];
name: string; name: string;
type: string;
orgId: string; orgId: string;
id: string; id: string;
createdAt: Date; createdAt: Date;
@@ -146,7 +138,6 @@ export type TProjectTemplateServiceFactory = {
name: string; name: string;
}[]; }[];
name: string; name: string;
type: string;
orgId: string; orgId: string;
id: string; id: string;
createdAt: Date; createdAt: Date;
@@ -170,7 +161,6 @@ export type TProjectTemplateServiceFactory = {
name: string; name: string;
}[]; }[];
name: string; name: string;
type: string;
orgId: string; orgId: string;
id: string; id: string;
createdAt: Date; createdAt: Date;
@@ -194,7 +184,6 @@ export type TProjectTemplateServiceFactory = {
name: string; name: string;
}[]; }[];
name: string; name: string;
type: string;
orgId: string; orgId: string;
id: string; id: string;
createdAt: Date; createdAt: Date;
@@ -1,7 +1,7 @@
import { ForbiddenError, MongoAbility, RawRuleOf } from "@casl/ability"; import { ForbiddenError, MongoAbility, RawRuleOf } from "@casl/ability";
import { PackRule, packRules, unpackRules } from "@casl/ability/extra"; import { PackRule, packRules, unpackRules } from "@casl/ability/extra";
import { ActionProjectType, TableName } from "@app/db/schemas"; import { TableName } from "@app/db/schemas";
import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors"; import { BadRequestError, NotFoundError, PermissionBoundaryError } from "@app/lib/errors";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars"; import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
@@ -61,8 +61,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
const { permission: targetUserPermission, membership } = await permissionService.getProjectPermission({ const { permission: targetUserPermission, membership } = await permissionService.getProjectPermission({
@@ -70,8 +69,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actorId: projectMembership.userId, actorId: projectMembership.userId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
// we need to validate that the privilege given is not higher than the assigning users permission // we need to validate that the privilege given is not higher than the assigning users permission
@@ -166,8 +164,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
const { permission: targetUserPermission } = await permissionService.getProjectPermission({ const { permission: targetUserPermission } = await permissionService.getProjectPermission({
@@ -175,8 +172,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actorId: projectMembership.userId, actorId: projectMembership.userId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
// we need to validate that the privilege given is not higher than the assigning users permission // we need to validate that the privilege given is not higher than the assigning users permission
@@ -276,8 +272,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Edit, ProjectPermissionSub.Member);
@@ -322,8 +317,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member);
@@ -349,8 +343,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actorId, actorId,
projectId: projectMembership.projectId, projectId: projectMembership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionMemberActions.Read, ProjectPermissionSub.Member);
@@ -1,7 +1,6 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import picomatch from "picomatch"; import picomatch from "picomatch";
import { ActionProjectType } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, NotFoundError } from "@app/lib/errors";
@@ -91,8 +90,7 @@ export const secretApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
@@ -267,8 +265,7 @@ export const secretApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: secretApprovalPolicy.projectId, projectId: secretApprovalPolicy.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval);
@@ -423,8 +420,7 @@ export const secretApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: sapPolicy.projectId, projectId: sapPolicy.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete, ProjectPermissionActions.Delete,
@@ -463,8 +459,7 @@ export const secretApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
@@ -508,8 +503,7 @@ export const secretApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
return getSecretApprovalPolicy(projectId, environment, secretPath); return getSecretApprovalPolicy(projectId, environment, secretPath);
@@ -535,8 +529,7 @@ export const secretApprovalPolicyServiceFactory = ({
actorId, actorId,
projectId: sapPolicy.projectId, projectId: sapPolicy.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
@@ -290,7 +290,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
} }
}; };
const findProjectRequestCount = async (projectId: string, userId: string, tx?: Knex) => { const findProjectRequestCount = async (projectId: string, userId: string, policyId?: string, tx?: Knex) => {
try { try {
const docs = await (tx || db) const docs = await (tx || db)
.with( .with(
@@ -309,6 +309,9 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
`${TableName.SecretApprovalPolicy}.id` `${TableName.SecretApprovalPolicy}.id`
) )
.where({ projectId }) .where({ projectId })
.where((qb) => {
if (policyId) void qb.where(`${TableName.SecretApprovalPolicy}.id`, policyId);
})
.andWhere( .andWhere(
(bd) => (bd) =>
void bd void bd
@@ -36,7 +36,7 @@ export const sendApprovalEmailsFn = async ({
firstName: reviewerUser.firstName, firstName: reviewerUser.firstName,
projectName: project.name, projectName: project.name,
organizationName: project.organization.name, organizationName: project.organization.name,
approvalUrl: `${cfg.SITE_URL}/secret-manager/${project.id}/approval?requestId=${secretApprovalRequest.id}` approvalUrl: `${cfg.SITE_URL}/projects/${project.id}/secret-manager/approval?requestId=${secretApprovalRequest.id}`
}, },
template: SmtpTemplates.SecretApprovalRequestNeedsReview template: SmtpTemplates.SecretApprovalRequestNeedsReview
}); });
@@ -2,7 +2,6 @@
import { ForbiddenError, subject } from "@casl/ability"; import { ForbiddenError, subject } from "@casl/ability";
import { import {
ActionProjectType,
ProjectMembershipRole, ProjectMembershipRole,
SecretEncryptionAlgo, SecretEncryptionAlgo,
SecretKeyEncoding, SecretKeyEncoding,
@@ -168,7 +167,14 @@ export const secretApprovalRequestServiceFactory = ({
microsoftTeamsService, microsoftTeamsService,
folderCommitService folderCommitService
}: TSecretApprovalRequestServiceFactoryDep) => { }: TSecretApprovalRequestServiceFactoryDep) => {
const requestCount = async ({ projectId, actor, actorId, actorOrgId, actorAuthMethod }: TApprovalRequestCountDTO) => { const requestCount = async ({
projectId,
policyId,
actor,
actorId,
actorOrgId,
actorAuthMethod
}: TApprovalRequestCountDTO) => {
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" }); if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
await permissionService.getProjectPermission({ await permissionService.getProjectPermission({
@@ -176,11 +182,10 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const count = await secretApprovalRequestDAL.findProjectRequestCount(projectId, actorId); const count = await secretApprovalRequestDAL.findProjectRequestCount(projectId, actorId, policyId);
return count; return count;
}; };
@@ -204,8 +209,7 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const { shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId); const { shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
@@ -257,8 +261,7 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if ( if (
!hasRole(ProjectMembershipRole.Admin) && !hasRole(ProjectMembershipRole.Admin) &&
@@ -407,8 +410,7 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
projectId: secretApprovalRequest.projectId, projectId: secretApprovalRequest.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if ( if (
!hasRole(ProjectMembershipRole.Admin) && !hasRole(ProjectMembershipRole.Admin) &&
@@ -477,8 +479,7 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
projectId: secretApprovalRequest.projectId, projectId: secretApprovalRequest.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if ( if (
!hasRole(ProjectMembershipRole.Admin) && !hasRole(ProjectMembershipRole.Admin) &&
@@ -534,8 +535,7 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
if ( if (
@@ -951,7 +951,7 @@ export const secretApprovalRequestServiceFactory = ({
bypassReason, bypassReason,
secretPath: policy.secretPath, secretPath: policy.secretPath,
environment: env.name, environment: env.name,
approvalUrl: `${cfg.SITE_URL}/secret-manager/${project.id}/approval` approvalUrl: `${cfg.SITE_URL}/projects/${project.id}/secret-manager/approval`
}, },
template: SmtpTemplates.AccessSecretRequestBypassed template: SmtpTemplates.AccessSecretRequestBypassed
}); });
@@ -980,8 +980,7 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.ReadValue, { throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.ReadValue, {
@@ -1271,8 +1270,7 @@ export const secretApprovalRequestServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
if (!folder) if (!folder)
@@ -84,7 +84,7 @@ export type TReviewRequestDTO = {
comment?: string; comment?: string;
} & Omit<TProjectPermission, "projectId">; } & Omit<TProjectPermission, "projectId">;
export type TApprovalRequestCountDTO = TProjectPermission; export type TApprovalRequestCountDTO = TProjectPermission & { policyId?: string };
export type TListApprovalsDTO = { export type TListApprovalsDTO = {
projectId: string; projectId: string;
@@ -166,7 +166,9 @@ export const secretRotationV2QueueServiceFactory = async ({
secretPath: folder.path, secretPath: folder.path,
environment: environment.name, environment: environment.name,
projectName: project.name, projectName: project.name,
rotationUrl: encodeURI(`${appCfg.SITE_URL}/secret-manager/${projectId}/secrets/${environment.slug}`) rotationUrl: encodeURI(
`${appCfg.SITE_URL}/projects/${projectId}/secret-manager/secrets/${environment.slug}`
)
} }
}); });
} catch (error) { } catch (error) {
@@ -2,7 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability";
import { Knex } from "knex"; import { Knex } from "knex";
import isEqual from "lodash.isequal"; import isEqual from "lodash.isequal";
import { ActionProjectType, SecretType, TableName } from "@app/db/schemas"; import { SecretType, TableName } from "@app/db/schemas";
import { EventType, TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-types"; import { EventType, TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-types";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { hasSecretReadValueOrDescribePermission } from "@app/ee/services/permission/permission-fns"; import { hasSecretReadValueOrDescribePermission } from "@app/ee/services/permission/permission-fns";
@@ -218,7 +218,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -269,7 +269,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -315,7 +315,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -380,7 +380,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -424,7 +424,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -625,7 +625,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -775,7 +775,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -1105,7 +1105,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -1152,7 +1152,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -1204,7 +1204,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId projectId
}); });
@@ -1320,8 +1320,7 @@ export const secretRotationV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
projectId, projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.SecretManager
}); });
const permissiveFolderMappings = folderMappings.filter(({ path, environment }) => const permissiveFolderMappings = folderMappings.filter(({ path, environment }) =>
@@ -1,7 +1,7 @@
import { ForbiddenError, subject } from "@casl/ability"; import { ForbiddenError, subject } from "@casl/ability";
import Ajv from "ajv"; import Ajv from "ajv";
import { ActionProjectType, ProjectVersion, TableName } from "@app/db/schemas"; import { ProjectVersion, TableName } from "@app/db/schemas";
import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto/encryption"; import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto/encryption";
import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { TProjectPermission } from "@app/lib/types"; import { TProjectPermission } from "@app/lib/types";
@@ -66,8 +66,7 @@ export const secretRotationServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretRotationActions.Read, ProjectPermissionSecretRotationActions.Read,
@@ -98,8 +97,7 @@ export const secretRotationServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretRotationActions.Read, ProjectPermissionSecretRotationActions.Read,
@@ -215,8 +213,7 @@ export const secretRotationServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretRotationActions.Read, ProjectPermissionSecretRotationActions.Read,
@@ -264,8 +261,7 @@ export const secretRotationServiceFactory = ({
actorId, actorId,
projectId: project.id, projectId: project.id,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretRotationActions.Edit, ProjectPermissionSecretRotationActions.Edit,
@@ -285,8 +281,7 @@ export const secretRotationServiceFactory = ({
actorId, actorId,
projectId: doc.projectId, projectId: doc.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretRotationActions.Delete, ProjectPermissionSecretRotationActions.Delete,
@@ -588,7 +588,7 @@ export const secretScanningV2QueueServiceFactory = async ({
numberOfSecrets: payload.numberOfSecrets, numberOfSecrets: payload.numberOfSecrets,
isDiffScan: payload.isDiffScan, isDiffScan: payload.isDiffScan,
url: encodeURI( url: encodeURI(
`${appCfg.SITE_URL}/secret-scanning/${projectId}/findings?search=scanId:${payload.scanId}` `${appCfg.SITE_URL}/projects/${projectId}/secret-scanning/findings?search=scanId:${payload.scanId}`
), ),
timestamp timestamp
} }
@@ -599,7 +599,7 @@ export const secretScanningV2QueueServiceFactory = async ({
timestamp, timestamp,
errorMessage: payload.errorMessage, errorMessage: payload.errorMessage,
url: encodeURI( url: encodeURI(
`${appCfg.SITE_URL}/secret-scanning/${projectId}/data-sources/${dataSource.type}/${dataSource.id}` `${appCfg.SITE_URL}/projects/${projectId}/secret-scanning/data-sources/${dataSource.type}/${dataSource.id}`
) )
} }
}); });
@@ -1,7 +1,6 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { join } from "path"; import { join } from "path";
import { ActionProjectType } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { import {
@@ -92,7 +91,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId projectId
}); });
@@ -154,7 +153,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: dataSource.projectId projectId: dataSource.projectId
}); });
@@ -199,7 +198,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId projectId
}); });
@@ -233,7 +232,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: payload.projectId projectId: payload.projectId
}); });
@@ -346,7 +345,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: dataSource.projectId projectId: dataSource.projectId
}); });
@@ -399,7 +398,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: dataSource.projectId projectId: dataSource.projectId
}); });
@@ -444,7 +443,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: dataSource.projectId projectId: dataSource.projectId
}); });
@@ -508,7 +507,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: dataSource.projectId projectId: dataSource.projectId
}); });
@@ -553,7 +552,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: dataSource.projectId projectId: dataSource.projectId
}); });
@@ -596,7 +595,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: dataSource.projectId projectId: dataSource.projectId
}); });
@@ -639,7 +638,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: dataSource.projectId projectId: dataSource.projectId
}); });
@@ -672,7 +671,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId projectId
}); });
@@ -706,7 +705,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId projectId
}); });
@@ -746,7 +745,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId: finding.projectId projectId: finding.projectId
}); });
@@ -777,7 +776,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId projectId
}); });
@@ -812,7 +811,7 @@ export const secretScanningV2ServiceFactory = ({
actorId: actor.id, actorId: actor.id,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretScanning,
projectId projectId
}); });
@@ -2,7 +2,7 @@
// akhilmhdh: I did this, quite strange bug with eslint. Everything do have a type stil has this error // akhilmhdh: I did this, quite strange bug with eslint. Everything do have a type stil has this error
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType, TableName, TSecretTagJunctionInsert, TSecretV2TagJunctionInsert } from "@app/db/schemas"; import { TableName, TSecretTagJunctionInsert, TSecretV2TagJunctionInsert } from "@app/db/schemas";
import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto"; import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
import { InternalServerError, NotFoundError } from "@app/lib/errors"; import { InternalServerError, NotFoundError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn"; import { groupBy } from "@app/lib/fn";
@@ -103,8 +103,7 @@ export const secretSnapshotServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
@@ -140,8 +139,7 @@ export const secretSnapshotServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
@@ -169,8 +167,7 @@ export const secretSnapshotServiceFactory = ({
actorId, actorId,
projectId: snapshot.projectId, projectId: snapshot.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
@@ -390,8 +387,7 @@ export const secretSnapshotServiceFactory = ({
actorId, actorId,
projectId: snapshot.projectId, projectId: snapshot.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create, ProjectPermissionActions.Create,
@@ -1,6 +1,5 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, NotFoundError } from "@app/lib/errors";
@@ -59,8 +58,7 @@ export const sshCertificateTemplateServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -132,8 +130,7 @@ export const sshCertificateTemplateServiceFactory = ({
actorId, actorId,
projectId: certTemplate.projectId, projectId: certTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -201,8 +198,7 @@ export const sshCertificateTemplateServiceFactory = ({
actorId, actorId,
projectId: certificateTemplate.projectId, projectId: certificateTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -228,8 +224,7 @@ export const sshCertificateTemplateServiceFactory = ({
actorId, actorId,
projectId: certTemplate.projectId, projectId: certTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1,6 +1,5 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { TSshHostDALFactory } from "@app/ee/services/ssh-host/ssh-host-dal"; import { TSshHostDALFactory } from "@app/ee/services/ssh-host/ssh-host-dal";
@@ -80,8 +79,7 @@ export const sshHostGroupServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.SshHostGroups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.SshHostGroups);
@@ -173,8 +171,7 @@ export const sshHostGroupServiceFactory = ({
actorId, actorId,
projectId: sshHostGroup.projectId, projectId: sshHostGroup.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SshHostGroups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SshHostGroups);
@@ -270,8 +267,7 @@ export const sshHostGroupServiceFactory = ({
actorId, actorId,
projectId: sshHostGroup.projectId, projectId: sshHostGroup.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SshHostGroups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SshHostGroups);
@@ -294,8 +290,7 @@ export const sshHostGroupServiceFactory = ({
actorId, actorId,
projectId: sshHostGroup.projectId, projectId: sshHostGroup.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.SshHostGroups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.SshHostGroups);
@@ -321,8 +316,7 @@ export const sshHostGroupServiceFactory = ({
actorId, actorId,
projectId: sshHostGroup.projectId, projectId: sshHostGroup.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SshHostGroups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SshHostGroups);
@@ -360,8 +354,7 @@ export const sshHostGroupServiceFactory = ({
actorId, actorId,
projectId: sshHostGroup.projectId, projectId: sshHostGroup.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SshHostGroups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SshHostGroups);
@@ -400,8 +393,7 @@ export const sshHostGroupServiceFactory = ({
actorId, actorId,
projectId: sshHostGroup.projectId, projectId: sshHostGroup.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SshHostGroups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SshHostGroups);
@@ -1,6 +1,5 @@
import { Knex } from "knex"; import { Knex } from "knex";
import { ActionProjectType } from "@app/db/schemas";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { ProjectPermissionSshHostActions, ProjectPermissionSub } from "../permission/project-permission"; import { ProjectPermissionSshHostActions, ProjectPermissionSub } from "../permission/project-permission";
@@ -63,8 +62,7 @@ export const createSshLoginMappings = async ({
userId: user.id, userId: user.id,
projectId, projectId,
authMethod: actorAuthMethod, authMethod: actorAuthMethod,
userOrgId: actorOrgId, userOrgId: actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
} }
@@ -1,6 +1,5 @@
import { ForbiddenError, subject } from "@casl/ability"; import { ForbiddenError, subject } from "@casl/ability";
import { ActionProjectType, ProjectType } from "@app/db/schemas";
import { TGroupDALFactory } from "@app/ee/services/group/group-dal"; import { TGroupDALFactory } from "@app/ee/services/group/group-dal";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionSshHostActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionSshHostActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
@@ -12,11 +11,13 @@ import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certif
import { TSshHostDALFactory } from "@app/ee/services/ssh-host/ssh-host-dal"; import { TSshHostDALFactory } from "@app/ee/services/ssh-host/ssh-host-dal";
import { TSshHostLoginUserMappingDALFactory } from "@app/ee/services/ssh-host/ssh-host-login-user-mapping-dal"; import { TSshHostLoginUserMappingDALFactory } from "@app/ee/services/ssh-host/ssh-host-login-user-mapping-dal";
import { TSshHostLoginUserDALFactory } from "@app/ee/services/ssh-host/ssh-login-user-dal"; import { TSshHostLoginUserDALFactory } from "@app/ee/services/ssh-host/ssh-login-user-dal";
import { PgSqlLock } from "@app/keystore/keystore";
import { BadRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors";
import { ActorType } from "@app/services/auth/auth-type"; import { ActorType } from "@app/services/auth/auth-type";
import { TKmsServiceFactory } from "@app/services/kms/kms-service"; import { TKmsServiceFactory } from "@app/services/kms/kms-service";
import { KmsDataKey } from "@app/services/kms/kms-types"; import { KmsDataKey } from "@app/services/kms/kms-types";
import { TProjectDALFactory } from "@app/services/project/project-dal"; import { TProjectDALFactory } from "@app/services/project/project-dal";
import { bootstrapSshProject } from "@app/services/project/project-fns";
import { TProjectSshConfigDALFactory } from "@app/services/project/project-ssh-config-dal"; import { TProjectSshConfigDALFactory } from "@app/services/project/project-ssh-config-dal";
import { TUserDALFactory } from "@app/services/user/user-dal"; import { TUserDALFactory } from "@app/services/user/user-dal";
@@ -43,9 +44,9 @@ type TSshHostServiceFactoryDep = {
userDAL: Pick<TUserDALFactory, "findById" | "find">; userDAL: Pick<TUserDALFactory, "findById" | "find">;
groupDAL: Pick<TGroupDALFactory, "findGroupsByProjectId">; groupDAL: Pick<TGroupDALFactory, "findGroupsByProjectId">;
projectDAL: Pick<TProjectDALFactory, "find">; projectDAL: Pick<TProjectDALFactory, "find">;
projectSshConfigDAL: Pick<TProjectSshConfigDALFactory, "findOne">; projectSshConfigDAL: Pick<TProjectSshConfigDALFactory, "findOne" | "transaction" | "create">;
sshCertificateAuthorityDAL: Pick<TSshCertificateAuthorityDALFactory, "findOne">; sshCertificateAuthorityDAL: Pick<TSshCertificateAuthorityDALFactory, "findOne" | "transaction" | "create">;
sshCertificateAuthoritySecretDAL: Pick<TSshCertificateAuthoritySecretDALFactory, "findOne">; sshCertificateAuthoritySecretDAL: Pick<TSshCertificateAuthoritySecretDALFactory, "findOne" | "create">;
sshCertificateDAL: Pick<TSshCertificateDALFactory, "create" | "transaction">; sshCertificateDAL: Pick<TSshCertificateDALFactory, "create" | "transaction">;
sshCertificateBodyDAL: Pick<TSshCertificateBodyDALFactory, "create">; sshCertificateBodyDAL: Pick<TSshCertificateBodyDALFactory, "create">;
userGroupMembershipDAL: Pick<TUserGroupMembershipDALFactory, "findGroupMembershipsByUserIdInOrg">; userGroupMembershipDAL: Pick<TUserGroupMembershipDALFactory, "findGroupMembershipsByUserIdInOrg">;
@@ -98,8 +99,7 @@ export const sshHostServiceFactory = ({
} }
const sshProjects = await projectDAL.find({ const sshProjects = await projectDAL.find({
orgId: actorOrgId, orgId: actorOrgId
type: ProjectType.SSH
}); });
const allowedHosts = []; const allowedHosts = [];
@@ -111,8 +111,7 @@ export const sshHostServiceFactory = ({
actorId, actorId,
projectId: project.id, projectId: project.id,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
const projectHosts = await sshHostDAL.findUserAccessibleSshHosts([project.id], actorId); const projectHosts = await sshHostDAL.findUserAccessibleSshHosts([project.id], actorId);
@@ -145,8 +144,7 @@ export const sshHostServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -184,7 +182,25 @@ export const sshHostServiceFactory = ({
return ca.id; return ca.id;
}; };
const projectSshConfig = await projectSshConfigDAL.findOne({ projectId }); let projectSshConfig = await projectSshConfigDAL.findOne({ projectId });
if (!projectSshConfig) {
projectSshConfig = await projectSshConfigDAL.transaction(async (tx) => {
await tx.raw("SELECT pg_advisory_xact_lock(?)", [PgSqlLock.SshInit(projectId)]);
let sshConfig = await projectSshConfigDAL.findOne({ projectId }, tx);
if (sshConfig) return sshConfig;
sshConfig = await bootstrapSshProject({
projectId,
sshCertificateAuthorityDAL,
sshCertificateAuthoritySecretDAL,
kmsService,
projectSshConfigDAL,
tx
});
return sshConfig;
});
}
const userSshCaId = await resolveSshCaId({ const userSshCaId = await resolveSshCaId({
requestedId: requestedUserSshCaId, requestedId: requestedUserSshCaId,
@@ -257,8 +273,7 @@ export const sshHostServiceFactory = ({
actorId, actorId,
projectId: host.projectId, projectId: host.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -319,8 +334,7 @@ export const sshHostServiceFactory = ({
actorId, actorId,
projectId: host.projectId, projectId: host.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -348,8 +362,7 @@ export const sshHostServiceFactory = ({
actorId, actorId,
projectId: host.projectId, projectId: host.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -388,8 +401,7 @@ export const sshHostServiceFactory = ({
actorId, actorId,
projectId: host.projectId, projectId: host.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
const internalPrincipals = await convertActorToPrincipals({ const internalPrincipals = await convertActorToPrincipals({
@@ -508,8 +520,7 @@ export const sshHostServiceFactory = ({
actorId, actorId,
projectId: host.projectId, projectId: host.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1,6 +1,5 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { TSshCertificateAuthorityDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-dal"; import { TSshCertificateAuthorityDALFactory } from "@app/ee/services/ssh/ssh-certificate-authority-dal";
@@ -73,8 +72,7 @@ export const sshCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -109,8 +107,7 @@ export const sshCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -178,8 +175,7 @@ export const sshCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -217,8 +213,7 @@ export const sshCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -259,8 +254,7 @@ export const sshCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: sshCertificateTemplate.projectId, projectId: sshCertificateTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -381,8 +375,7 @@ export const sshCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: sshCertificateTemplate.projectId, projectId: sshCertificateTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -479,8 +472,7 @@ export const sshCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SSH
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1,6 +1,5 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { TProjectDALFactory } from "@app/services/project/project-dal"; import { TProjectDALFactory } from "@app/services/project/project-dal";
@@ -36,8 +35,7 @@ export const trustedIpServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList);
const trustedIps = await trustedIpDAL.find({ const trustedIps = await trustedIpDAL.find({
@@ -61,8 +59,7 @@ export const trustedIpServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
@@ -107,8 +104,7 @@ export const trustedIpServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
@@ -153,8 +149,7 @@ export const trustedIpServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
+35 -2
View File
@@ -12,7 +12,8 @@ export const PgSqlLock = {
OrgGatewayCertExchange: (orgId: string) => pgAdvisoryLockHashText(`org-gateway-cert-exchange:${orgId}`), OrgGatewayCertExchange: (orgId: string) => pgAdvisoryLockHashText(`org-gateway-cert-exchange:${orgId}`),
SecretRotationV2Creation: (folderId: string) => pgAdvisoryLockHashText(`secret-rotation-v2-creation:${folderId}`), SecretRotationV2Creation: (folderId: string) => pgAdvisoryLockHashText(`secret-rotation-v2-creation:${folderId}`),
CreateProject: (orgId: string) => pgAdvisoryLockHashText(`create-project:${orgId}`), CreateProject: (orgId: string) => pgAdvisoryLockHashText(`create-project:${orgId}`),
CreateFolder: (envId: string, projectId: string) => pgAdvisoryLockHashText(`create-folder:${envId}-${projectId}`) CreateFolder: (envId: string, projectId: string) => pgAdvisoryLockHashText(`create-folder:${envId}-${projectId}`),
SshInit: (projectId: string) => pgAdvisoryLockHashText(`ssh-bootstrap:${projectId}`)
} as const; } as const;
// all the key prefixes used must be set here to avoid conflict // all the key prefixes used must be set here to avoid conflict
@@ -73,6 +74,7 @@ type TWaitTillReady = {
export type TKeyStoreFactory = { export type TKeyStoreFactory = {
setItem: (key: string, value: string | number | Buffer, prefix?: string) => Promise<"OK">; setItem: (key: string, value: string | number | Buffer, prefix?: string) => Promise<"OK">;
getItem: (key: string, prefix?: string) => Promise<string | null>; getItem: (key: string, prefix?: string) => Promise<string | null>;
getItems: (keys: string[], prefix?: string) => Promise<(string | null)[]>;
setExpiry: (key: string, expiryInSeconds: number) => Promise<number>; setExpiry: (key: string, expiryInSeconds: number) => Promise<number>;
setItemWithExpiry: ( setItemWithExpiry: (
key: string, key: string,
@@ -81,6 +83,7 @@ export type TKeyStoreFactory = {
prefix?: string prefix?: string
) => Promise<"OK">; ) => Promise<"OK">;
deleteItem: (key: string) => Promise<number>; deleteItem: (key: string) => Promise<number>;
deleteItemsByKeyIn: (keys: string[]) => Promise<number>;
deleteItems: (arg: TDeleteItems) => Promise<number>; deleteItems: (arg: TDeleteItems) => Promise<number>;
incrementBy: (key: string, value: number) => Promise<number>; incrementBy: (key: string, value: number) => Promise<number>;
acquireLock( acquireLock(
@@ -89,6 +92,7 @@ export type TKeyStoreFactory = {
settings?: Partial<Settings> settings?: Partial<Settings>
): Promise<{ release: () => Promise<ExecutionResult> }>; ): Promise<{ release: () => Promise<ExecutionResult> }>;
waitTillReady: ({ key, waitingCb, keyCheckCb, waitIteration, delay, jitter }: TWaitTillReady) => Promise<void>; waitTillReady: ({ key, waitingCb, keyCheckCb, waitIteration, delay, jitter }: TWaitTillReady) => Promise<void>;
getKeysByPattern: (pattern: string, limit?: number) => Promise<string[]>;
}; };
export const keyStoreFactory = (redisConfigKeys: TRedisConfigKeys): TKeyStoreFactory => { export const keyStoreFactory = (redisConfigKeys: TRedisConfigKeys): TKeyStoreFactory => {
@@ -100,6 +104,9 @@ export const keyStoreFactory = (redisConfigKeys: TRedisConfigKeys): TKeyStoreFac
const getItem = async (key: string, prefix?: string) => redis.get(prefix ? `${prefix}:${key}` : key); const getItem = async (key: string, prefix?: string) => redis.get(prefix ? `${prefix}:${key}` : key);
const getItems = async (keys: string[], prefix?: string) =>
redis.mget(keys.map((key) => (prefix ? `${prefix}:${key}` : key)));
const setItemWithExpiry = async ( const setItemWithExpiry = async (
key: string, key: string,
expiryInSeconds: number | string, expiryInSeconds: number | string,
@@ -109,6 +116,11 @@ export const keyStoreFactory = (redisConfigKeys: TRedisConfigKeys): TKeyStoreFac
const deleteItem = async (key: string) => redis.del(key); const deleteItem = async (key: string) => redis.del(key);
const deleteItemsByKeyIn = async (keys: string[]) => {
if (keys.length === 0) return 0;
return redis.del(keys);
};
const deleteItems = async ({ pattern, batchSize = 500, delay = 1500, jitter = 200 }: TDeleteItems) => { const deleteItems = async ({ pattern, batchSize = 500, delay = 1500, jitter = 200 }: TDeleteItems) => {
let cursor = "0"; let cursor = "0";
let totalDeleted = 0; let totalDeleted = 0;
@@ -164,6 +176,24 @@ export const keyStoreFactory = (redisConfigKeys: TRedisConfigKeys): TKeyStoreFac
} }
}; };
const getKeysByPattern = async (pattern: string, limit?: number) => {
let cursor = "0";
const allKeys: string[] = [];
do {
// eslint-disable-next-line no-await-in-loop
const [nextCursor, keys] = await redis.scan(cursor, "MATCH", pattern, "COUNT", 1000);
cursor = nextCursor;
allKeys.push(...keys);
if (limit && allKeys.length >= limit) {
return allKeys.slice(0, limit);
}
} while (cursor !== "0");
return allKeys;
};
return { return {
setItem, setItem,
getItem, getItem,
@@ -175,6 +205,9 @@ export const keyStoreFactory = (redisConfigKeys: TRedisConfigKeys): TKeyStoreFac
acquireLock(resources: string[], duration: number, settings?: Partial<Settings>) { acquireLock(resources: string[], duration: number, settings?: Partial<Settings>) {
return redisLock.acquire(resources, duration, settings); return redisLock.acquire(resources, duration, settings);
}, },
waitTillReady waitTillReady,
getKeysByPattern,
deleteItemsByKeyIn,
getItems
}; };
}; };
+25 -2
View File
@@ -8,6 +8,8 @@ import { TKeyStoreFactory } from "./keystore";
export const inMemoryKeyStore = (): TKeyStoreFactory => { export const inMemoryKeyStore = (): TKeyStoreFactory => {
const store: Record<string, string | number | Buffer> = {}; const store: Record<string, string | number | Buffer> = {};
const getRegex = (pattern: string) =>
new RE2(`^${pattern.replace(/[-[\]/{}()+?.\\^$|]/g, "\\$&").replace(/\*/g, ".*")}$`);
return { return {
setItem: async (key, value) => { setItem: async (key, value) => {
@@ -24,7 +26,7 @@ export const inMemoryKeyStore = (): TKeyStoreFactory => {
return 1; return 1;
}, },
deleteItems: async ({ pattern, batchSize = 500, delay = 1500, jitter = 200 }) => { deleteItems: async ({ pattern, batchSize = 500, delay = 1500, jitter = 200 }) => {
const regex = new RE2(`^${pattern.replace(/[-[\]/{}()+?.\\^$|]/g, "\\$&").replace(/\*/g, ".*")}$`); const regex = getRegex(pattern);
let totalDeleted = 0; let totalDeleted = 0;
const keys = Object.keys(store); const keys = Object.keys(store);
@@ -59,6 +61,27 @@ export const inMemoryKeyStore = (): TKeyStoreFactory => {
release: () => {} release: () => {}
}) as Promise<Lock>; }) as Promise<Lock>;
}, },
waitTillReady: async () => {} waitTillReady: async () => {},
getKeysByPattern: async (pattern) => {
const regex = getRegex(pattern);
const keys = Object.keys(store);
return keys.filter((key) => regex.test(key));
},
deleteItemsByKeyIn: async (keys) => {
for (const key of keys) {
delete store[key];
}
return keys.length;
},
getItems: async (keys) => {
const values = keys.map((key) => {
const value = store[key];
if (typeof value === "string") {
return value;
}
return null;
});
return values;
}
}; };
}; };
+37 -2
View File
@@ -22,6 +22,7 @@ export enum ApiDocsTags {
UniversalAuth = "Universal Auth", UniversalAuth = "Universal Auth",
GcpAuth = "GCP Auth", GcpAuth = "GCP Auth",
AliCloudAuth = "Alibaba Cloud Auth", AliCloudAuth = "Alibaba Cloud Auth",
TlsCertAuth = "TLS Certificate Auth",
AwsAuth = "AWS Auth", AwsAuth = "AWS Auth",
OciAuth = "OCI Auth", OciAuth = "OCI Auth",
AzureAuth = "Azure Auth", AzureAuth = "Azure Auth",
@@ -283,6 +284,38 @@ export const ALICLOUD_AUTH = {
} }
} as const; } as const;
export const TLS_CERT_AUTH = {
LOGIN: {
identityId: "The ID of the identity to login."
},
ATTACH: {
identityId: "The ID of the identity to attach the configuration onto.",
allowedCommonNames:
"The comma-separated list of trusted common names that are allowed to authenticate with Infisical.",
caCertificate: "The PEM-encoded CA certificate to validate client certificates.",
accessTokenTTL: "The lifetime for an access token in seconds.",
accessTokenMaxTTL: "The maximum lifetime for an access token in seconds.",
accessTokenNumUsesLimit: "The maximum number of times that an access token can be used.",
accessTokenTrustedIps: "The IPs or CIDR ranges that access tokens can be used from."
},
UPDATE: {
identityId: "The ID of the identity to update the auth method for.",
allowedCommonNames:
"The comma-separated list of trusted common names that are allowed to authenticate with Infisical.",
caCertificate: "The PEM-encoded CA certificate to validate client certificates.",
accessTokenTTL: "The new lifetime for an access token in seconds.",
accessTokenMaxTTL: "The new maximum lifetime for an access token in seconds.",
accessTokenNumUsesLimit: "The new maximum number of times that an access token can be used.",
accessTokenTrustedIps: "The new IPs or CIDR ranges that access tokens can be used from."
},
RETRIEVE: {
identityId: "The ID of the identity to retrieve the auth method for."
},
REVOKE: {
identityId: "The ID of the identity to revoke the auth method for."
}
} as const;
export const AWS_AUTH = { export const AWS_AUTH = {
LOGIN: { LOGIN: {
identityId: "The ID of the identity to login.", identityId: "The ID of the identity to login.",
@@ -667,7 +700,8 @@ export const PROJECTS = {
slug: "An optional slug for the project. (must be unique within the organization)", slug: "An optional slug for the project. (must be unique within the organization)",
hasDeleteProtection: "Enable or disable delete protection for the project.", hasDeleteProtection: "Enable or disable delete protection for the project.",
secretSharing: "Enable or disable secret sharing for the project.", secretSharing: "Enable or disable secret sharing for the project.",
showSnapshotsLegacy: "Enable or disable legacy snapshots for the project." showSnapshotsLegacy: "Enable or disable legacy snapshots for the project.",
defaultProduct: "The default product in which the project will open"
}, },
GET_KEY: { GET_KEY: {
workspaceId: "The ID of the project to get the key from." workspaceId: "The ID of the project to get the key from."
@@ -2398,7 +2432,8 @@ export const SecretSyncs = {
keyOcid: "The OCID (Oracle Cloud Identifier) of the encryption key to use when creating secrets in the vault." keyOcid: "The OCID (Oracle Cloud Identifier) of the encryption key to use when creating secrets in the vault."
}, },
ONEPASS: { ONEPASS: {
vaultId: "The ID of the 1Password vault to sync secrets to." vaultId: "The ID of the 1Password vault to sync secrets to.",
valueLabel: "The label of the entry that holds the secret value."
}, },
HEROKU: { HEROKU: {
app: "The ID of the Heroku app to sync secrets to.", app: "The ID of the Heroku app to sync secrets to.",
+3
View File
@@ -193,6 +193,9 @@ const envSchema = z
PYLON_API_KEY: zpStr(z.string().optional()), PYLON_API_KEY: zpStr(z.string().optional()),
DISABLE_AUDIT_LOG_GENERATION: zodStrBool.default("false"), DISABLE_AUDIT_LOG_GENERATION: zodStrBool.default("false"),
SSL_CLIENT_CERTIFICATE_HEADER_KEY: zpStr(z.string().optional()).default("x-ssl-client-cert"), SSL_CLIENT_CERTIFICATE_HEADER_KEY: zpStr(z.string().optional()).default("x-ssl-client-cert"),
IDENTITY_TLS_CERT_AUTH_CLIENT_CERTIFICATE_HEADER_KEY: zpStr(z.string().optional()).default(
"x-identity-tls-cert-auth-client-cert"
),
WORKFLOW_SLACK_CLIENT_ID: zpStr(z.string().optional()), WORKFLOW_SLACK_CLIENT_ID: zpStr(z.string().optional()),
WORKFLOW_SLACK_CLIENT_SECRET: zpStr(z.string().optional()), WORKFLOW_SLACK_CLIENT_SECRET: zpStr(z.string().optional()),
ENABLE_MSSQL_SECRET_ROTATION_ENCRYPT: zodStrBool.default("true"), ENABLE_MSSQL_SECRET_ROTATION_ENCRYPT: zodStrBool.default("true"),
+8 -2
View File
@@ -62,7 +62,8 @@ export enum QueueName {
SecretRotationV2 = "secret-rotation-v2", SecretRotationV2 = "secret-rotation-v2",
FolderTreeCheckpoint = "folder-tree-checkpoint", FolderTreeCheckpoint = "folder-tree-checkpoint",
InvalidateCache = "invalidate-cache", InvalidateCache = "invalidate-cache",
SecretScanningV2 = "secret-scanning-v2" SecretScanningV2 = "secret-scanning-v2",
TelemetryAggregatedEvents = "telemetry-aggregated-events"
} }
export enum QueueJobs { export enum QueueJobs {
@@ -101,7 +102,8 @@ export enum QueueJobs {
SecretScanningV2DiffScan = "secret-scanning-v2-diff-scan", SecretScanningV2DiffScan = "secret-scanning-v2-diff-scan",
SecretScanningV2SendNotification = "secret-scanning-v2-notification", SecretScanningV2SendNotification = "secret-scanning-v2-notification",
CaOrderCertificateForSubscriber = "ca-order-certificate-for-subscriber", CaOrderCertificateForSubscriber = "ca-order-certificate-for-subscriber",
PkiSubscriberDailyAutoRenewal = "pki-subscriber-daily-auto-renewal" PkiSubscriberDailyAutoRenewal = "pki-subscriber-daily-auto-renewal",
TelemetryAggregatedEvents = "telemetry-aggregated-events"
} }
export type TQueueJobTypes = { export type TQueueJobTypes = {
@@ -292,6 +294,10 @@ export type TQueueJobTypes = {
name: QueueJobs.PkiSubscriberDailyAutoRenewal; name: QueueJobs.PkiSubscriberDailyAutoRenewal;
payload: undefined; payload: undefined;
}; };
[QueueName.TelemetryAggregatedEvents]: {
name: QueueJobs.TelemetryAggregatedEvents;
payload: undefined;
};
}; };
const SECRET_SCANNING_JOBS = [ const SECRET_SCANNING_JOBS = [
+25 -11
View File
@@ -193,6 +193,8 @@ import { identityOidcAuthServiceFactory } from "@app/services/identity-oidc-auth
import { identityProjectDALFactory } from "@app/services/identity-project/identity-project-dal"; import { identityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
import { identityProjectMembershipRoleDALFactory } from "@app/services/identity-project/identity-project-membership-role-dal"; import { identityProjectMembershipRoleDALFactory } from "@app/services/identity-project/identity-project-membership-role-dal";
import { identityProjectServiceFactory } from "@app/services/identity-project/identity-project-service"; import { identityProjectServiceFactory } from "@app/services/identity-project/identity-project-service";
import { identityTlsCertAuthDALFactory } from "@app/services/identity-tls-cert-auth/identity-tls-cert-auth-dal";
import { identityTlsCertAuthServiceFactory } from "@app/services/identity-tls-cert-auth/identity-tls-cert-auth-service";
import { identityTokenAuthDALFactory } from "@app/services/identity-token-auth/identity-token-auth-dal"; import { identityTokenAuthDALFactory } from "@app/services/identity-token-auth/identity-token-auth-dal";
import { identityTokenAuthServiceFactory } from "@app/services/identity-token-auth/identity-token-auth-service"; import { identityTokenAuthServiceFactory } from "@app/services/identity-token-auth/identity-token-auth-service";
import { identityUaClientSecretDALFactory } from "@app/services/identity-ua/identity-ua-client-secret-dal"; import { identityUaClientSecretDALFactory } from "@app/services/identity-ua/identity-ua-client-secret-dal";
@@ -384,6 +386,7 @@ export const registerRoutes = async (
const identityKubernetesAuthDAL = identityKubernetesAuthDALFactory(db); const identityKubernetesAuthDAL = identityKubernetesAuthDALFactory(db);
const identityUaClientSecretDAL = identityUaClientSecretDALFactory(db); const identityUaClientSecretDAL = identityUaClientSecretDALFactory(db);
const identityAliCloudAuthDAL = identityAliCloudAuthDALFactory(db); const identityAliCloudAuthDAL = identityAliCloudAuthDALFactory(db);
const identityTlsCertAuthDAL = identityTlsCertAuthDALFactory(db);
const identityAwsAuthDAL = identityAwsAuthDALFactory(db); const identityAwsAuthDAL = identityAwsAuthDALFactory(db);
const identityGcpAuthDAL = identityGcpAuthDALFactory(db); const identityGcpAuthDAL = identityGcpAuthDALFactory(db);
const identityOciAuthDAL = identityOciAuthDALFactory(db); const identityOciAuthDAL = identityOciAuthDALFactory(db);
@@ -684,7 +687,8 @@ export const registerRoutes = async (
const telemetryQueue = telemetryQueueServiceFactory({ const telemetryQueue = telemetryQueueServiceFactory({
keyStore, keyStore,
telemetryDAL, telemetryDAL,
queueService queueService,
telemetryService
}); });
const invalidateCacheQueue = invalidateCacheQueueFactory({ const invalidateCacheQueue = invalidateCacheQueueFactory({
@@ -991,8 +995,7 @@ export const registerRoutes = async (
pkiAlertDAL, pkiAlertDAL,
pkiCollectionDAL, pkiCollectionDAL,
permissionService, permissionService,
smtpService, smtpService
projectDAL
}); });
const pkiCollectionService = pkiCollectionServiceFactory({ const pkiCollectionService = pkiCollectionServiceFactory({
@@ -1000,8 +1003,7 @@ export const registerRoutes = async (
pkiCollectionItemDAL, pkiCollectionItemDAL,
certificateAuthorityDAL, certificateAuthorityDAL,
certificateDAL, certificateDAL,
permissionService, permissionService
projectDAL
}); });
const projectTemplateService = projectTemplateServiceFactory({ const projectTemplateService = projectTemplateServiceFactory({
@@ -1185,7 +1187,9 @@ export const registerRoutes = async (
projectEnvDAL, projectEnvDAL,
snapshotService, snapshotService,
projectDAL, projectDAL,
folderCommitService folderCommitService,
secretApprovalPolicyService,
secretV2BridgeDAL
}); });
const secretImportService = secretImportServiceFactory({ const secretImportService = secretImportServiceFactory({
@@ -1415,7 +1419,8 @@ export const registerRoutes = async (
const identityAccessTokenService = identityAccessTokenServiceFactory({ const identityAccessTokenService = identityAccessTokenServiceFactory({
identityAccessTokenDAL, identityAccessTokenDAL,
identityOrgMembershipDAL, identityOrgMembershipDAL,
accessTokenQueue accessTokenQueue,
identityDAL
}); });
const identityProjectService = identityProjectServiceFactory({ const identityProjectService = identityProjectServiceFactory({
@@ -1491,6 +1496,15 @@ export const registerRoutes = async (
permissionService permissionService
}); });
const identityTlsCertAuthService = identityTlsCertAuthServiceFactory({
identityAccessTokenDAL,
identityTlsCertAuthDAL,
identityOrgMembershipDAL,
licenseService,
permissionService,
kmsService
});
const identityAwsAuthService = identityAwsAuthServiceFactory({ const identityAwsAuthService = identityAwsAuthServiceFactory({
identityAccessTokenDAL, identityAccessTokenDAL,
identityAwsAuthDAL, identityAwsAuthDAL,
@@ -1649,8 +1663,7 @@ export const registerRoutes = async (
const cmekService = cmekServiceFactory({ const cmekService = cmekServiceFactory({
kmsDAL, kmsDAL,
kmsService, kmsService,
permissionService, permissionService
projectDAL
}); });
const externalMigrationQueue = externalMigrationQueueFactory({ const externalMigrationQueue = externalMigrationQueueFactory({
@@ -1792,7 +1805,6 @@ export const registerRoutes = async (
const certificateAuthorityService = certificateAuthorityServiceFactory({ const certificateAuthorityService = certificateAuthorityServiceFactory({
certificateAuthorityDAL, certificateAuthorityDAL,
projectDAL,
permissionService, permissionService,
appConnectionDAL, appConnectionDAL,
appConnectionService, appConnectionService,
@@ -1802,7 +1814,8 @@ export const registerRoutes = async (
certificateBodyDAL, certificateBodyDAL,
certificateSecretDAL, certificateSecretDAL,
kmsService, kmsService,
pkiSubscriberDAL pkiSubscriberDAL,
projectDAL
}); });
const internalCaFns = InternalCertificateAuthorityFns({ const internalCaFns = InternalCertificateAuthorityFns({
@@ -1945,6 +1958,7 @@ export const registerRoutes = async (
identityAwsAuth: identityAwsAuthService, identityAwsAuth: identityAwsAuthService,
identityAzureAuth: identityAzureAuthService, identityAzureAuth: identityAzureAuthService,
identityOciAuth: identityOciAuthService, identityOciAuth: identityOciAuthService,
identityTlsCertAuth: identityTlsCertAuthService,
identityOidcAuth: identityOidcAuthService, identityOidcAuth: identityOidcAuthService,
identityJwtAuth: identityJwtAuthService, identityJwtAuth: identityJwtAuthService,
identityLdapAuth: identityLdapAuthService, identityLdapAuth: identityLdapAuthService,
@@ -251,6 +251,7 @@ export const SanitizedProjectSchema = ProjectsSchema.pick({
name: true, name: true,
description: true, description: true,
type: true, type: true,
defaultProduct: true,
slug: true, slug: true,
autoCapitalization: true, autoCapitalization: true,
orgId: true, orgId: true,
@@ -722,6 +722,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.InvalidateCache, event: PostHogEventTypes.InvalidateCache,
organizationId: req.permission.orgId,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
properties: { properties: {
...req.auditLogInfo ...req.auditLogInfo
@@ -692,6 +692,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IssueCert, event: PostHogEventTypes.IssueCert,
organizationId: req.permission.orgId,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
properties: { properties: {
caId: ca.id, caId: ca.id,
@@ -786,6 +787,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SignCert, event: PostHogEventTypes.SignCert,
organizationId: req.permission.orgId,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
properties: { properties: {
caId: ca.id, caId: ca.id,
@@ -266,6 +266,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IssueCert, event: PostHogEventTypes.IssueCert,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
caId: req.body.caId, caId: req.body.caId,
certificateTemplateId: req.body.certificateTemplateId, certificateTemplateId: req.body.certificateTemplateId,
@@ -442,6 +443,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SignCert, event: PostHogEventTypes.SignCert,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
caId: req.body.caId, caId: req.body.caId,
certificateTemplateId: req.body.certificateTemplateId, certificateTemplateId: req.body.certificateTemplateId,
@@ -475,6 +475,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled, event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secretCountFromEnv, numberOfSecrets: secretCountFromEnv,
workspaceId: projectId, workspaceId: projectId,
@@ -979,6 +980,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled, event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secretCount, numberOfSecrets: secretCount,
workspaceId: projectId, workspaceId: projectId,
@@ -1144,6 +1146,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled, event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secretCountForEnv, numberOfSecrets: secretCountForEnv,
workspaceId: projectId, workspaceId: projectId,
@@ -1336,6 +1339,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled, event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId: projectId, workspaceId: projectId,
@@ -85,6 +85,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.MachineIdentityCreated, event: PostHogEventTypes.MachineIdentityCreated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
orgId: req.body.organizationId, orgId: req.body.organizationId,
name: identity.name, name: identity.name,
@@ -0,0 +1,396 @@
import crypto from "node:crypto";
import { z } from "zod";
import { IdentityTlsCertAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApiDocsTags, TLS_CERT_AUTH } from "@app/lib/api-docs";
import { getConfig } from "@app/lib/config/env";
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";
import { TIdentityTrustedIp } from "@app/services/identity/identity-types";
import { isSuperAdmin } from "@app/services/super-admin/super-admin-fns";
const validateCommonNames = z
.string()
.min(1)
.trim()
.transform((el) =>
el
.split(",")
.map((i) => i.trim())
.join(",")
);
const validateCaCertificate = (caCert: string) => {
if (!caCert) return true;
try {
// eslint-disable-next-line no-new
new crypto.X509Certificate(caCert);
return true;
} catch (err) {
return false;
}
};
export const registerIdentityTlsCertAuthRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/login",
config: {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.TlsCertAuth],
description: "Login with TLS Certificate Auth",
body: z.object({
identityId: z.string().trim().describe(TLS_CERT_AUTH.LOGIN.identityId)
}),
response: {
200: z.object({
accessToken: z.string(),
expiresIn: z.coerce.number(),
accessTokenMaxTTL: z.coerce.number(),
tokenType: z.literal("Bearer")
})
}
},
handler: async (req) => {
const appCfg = getConfig();
const clientCertificate = req.headers[appCfg.IDENTITY_TLS_CERT_AUTH_CLIENT_CERTIFICATE_HEADER_KEY];
if (!clientCertificate) {
throw new BadRequestError({ message: "Missing TLS certificate in header" });
}
const { identityTlsCertAuth, accessToken, identityAccessToken, identityMembershipOrg } =
await server.services.identityTlsCertAuth.login({
identityId: req.body.identityId,
clientCertificate: clientCertificate as string
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
event: {
type: EventType.LOGIN_IDENTITY_TLS_CERT_AUTH,
metadata: {
identityId: identityTlsCertAuth.identityId,
identityAccessTokenId: identityAccessToken.id,
identityTlsCertAuthId: identityTlsCertAuth.id
}
}
});
return {
accessToken,
tokenType: "Bearer" as const,
expiresIn: identityTlsCertAuth.accessTokenTTL,
accessTokenMaxTTL: identityTlsCertAuth.accessTokenMaxTTL
};
}
});
server.route({
method: "POST",
url: "/identities/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TlsCertAuth],
description: "Attach TLS Certificate Auth configuration onto identity",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().trim().describe(TLS_CERT_AUTH.ATTACH.identityId)
}),
body: z
.object({
allowedCommonNames: validateCommonNames
.optional()
.nullable()
.describe(TLS_CERT_AUTH.ATTACH.allowedCommonNames),
caCertificate: z
.string()
.min(1)
.max(10240)
.refine(validateCaCertificate, "Invalid CA Certificate.")
.describe(TLS_CERT_AUTH.ATTACH.caCertificate),
accessTokenTrustedIps: z
.object({
ipAddress: z.string().trim()
})
.array()
.min(1)
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }])
.describe(TLS_CERT_AUTH.ATTACH.accessTokenTrustedIps),
accessTokenTTL: z
.number()
.int()
.min(0)
.max(315360000)
.default(2592000)
.describe(TLS_CERT_AUTH.ATTACH.accessTokenTTL),
accessTokenMaxTTL: z
.number()
.int()
.min(1)
.max(315360000)
.default(2592000)
.describe(TLS_CERT_AUTH.ATTACH.accessTokenMaxTTL),
accessTokenNumUsesLimit: z
.number()
.int()
.min(0)
.default(0)
.describe(TLS_CERT_AUTH.ATTACH.accessTokenNumUsesLimit)
})
.refine(
(val) => val.accessTokenTTL <= val.accessTokenMaxTTL,
"Access Token TTL cannot be greater than Access Token Max TTL."
),
response: {
200: z.object({
identityTlsCertAuth: IdentityTlsCertAuthsSchema
})
}
},
handler: async (req) => {
const identityTlsCertAuth = await server.services.identityTlsCertAuth.attachTlsCertAuth({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
...req.body,
identityId: req.params.identityId,
isActorSuperAdmin: isSuperAdmin(req.auth)
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: req.permission.orgId,
event: {
type: EventType.ADD_IDENTITY_TLS_CERT_AUTH,
metadata: {
identityId: identityTlsCertAuth.identityId,
allowedCommonNames: identityTlsCertAuth.allowedCommonNames,
accessTokenTTL: identityTlsCertAuth.accessTokenTTL,
accessTokenMaxTTL: identityTlsCertAuth.accessTokenMaxTTL,
accessTokenTrustedIps: identityTlsCertAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
accessTokenNumUsesLimit: identityTlsCertAuth.accessTokenNumUsesLimit
}
}
});
return { identityTlsCertAuth };
}
});
server.route({
method: "PATCH",
url: "/identities/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TlsCertAuth],
description: "Update TLS Certificate Auth configuration on identity",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().describe(TLS_CERT_AUTH.UPDATE.identityId)
}),
body: z
.object({
caCertificate: z
.string()
.min(1)
.max(10240)
.refine(validateCaCertificate, "Invalid CA Certificate.")
.optional()
.describe(TLS_CERT_AUTH.UPDATE.caCertificate),
allowedCommonNames: validateCommonNames
.optional()
.nullable()
.describe(TLS_CERT_AUTH.UPDATE.allowedCommonNames),
accessTokenTrustedIps: z
.object({
ipAddress: z.string().trim()
})
.array()
.min(1)
.optional()
.describe(TLS_CERT_AUTH.UPDATE.accessTokenTrustedIps),
accessTokenTTL: z
.number()
.int()
.min(0)
.max(315360000)
.optional()
.describe(TLS_CERT_AUTH.UPDATE.accessTokenTTL),
accessTokenNumUsesLimit: z
.number()
.int()
.min(0)
.optional()
.describe(TLS_CERT_AUTH.UPDATE.accessTokenNumUsesLimit),
accessTokenMaxTTL: z
.number()
.int()
.max(315360000)
.min(0)
.optional()
.describe(TLS_CERT_AUTH.UPDATE.accessTokenMaxTTL)
})
.refine(
(val) => (val.accessTokenMaxTTL && val.accessTokenTTL ? val.accessTokenTTL <= val.accessTokenMaxTTL : true),
"Access Token TTL cannot be greater than Access Token Max TTL."
),
response: {
200: z.object({
identityTlsCertAuth: IdentityTlsCertAuthsSchema
})
}
},
handler: async (req) => {
const identityTlsCertAuth = await server.services.identityTlsCertAuth.updateTlsCertAuth({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
...req.body,
identityId: req.params.identityId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: req.permission.orgId,
event: {
type: EventType.UPDATE_IDENTITY_TLS_CERT_AUTH,
metadata: {
identityId: identityTlsCertAuth.identityId,
allowedCommonNames: identityTlsCertAuth.allowedCommonNames,
accessTokenTTL: identityTlsCertAuth.accessTokenTTL,
accessTokenMaxTTL: identityTlsCertAuth.accessTokenMaxTTL,
accessTokenTrustedIps: identityTlsCertAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
accessTokenNumUsesLimit: identityTlsCertAuth.accessTokenNumUsesLimit
}
}
});
return { identityTlsCertAuth };
}
});
server.route({
method: "GET",
url: "/identities/:identityId",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TlsCertAuth],
description: "Retrieve TLS Certificate Auth configuration on identity",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().describe(TLS_CERT_AUTH.RETRIEVE.identityId)
}),
response: {
200: z.object({
identityTlsCertAuth: IdentityTlsCertAuthsSchema.extend({
caCertificate: z.string()
})
})
}
},
handler: async (req) => {
const identityTlsCertAuth = await server.services.identityTlsCertAuth.getTlsCertAuth({
identityId: req.params.identityId,
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: req.permission.orgId,
event: {
type: EventType.GET_IDENTITY_TLS_CERT_AUTH,
metadata: {
identityId: identityTlsCertAuth.identityId
}
}
});
return { identityTlsCertAuth };
}
});
server.route({
method: "DELETE",
url: "/identities/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TlsCertAuth],
description: "Delete TLS Certificate Auth configuration on identity",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().describe(TLS_CERT_AUTH.REVOKE.identityId)
}),
response: {
200: z.object({
identityTlsCertAuth: IdentityTlsCertAuthsSchema
})
}
},
handler: async (req) => {
const identityTlsCertAuth = await server.services.identityTlsCertAuth.revokeTlsCertAuth({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: req.permission.orgId,
event: {
type: EventType.REVOKE_IDENTITY_TLS_CERT_AUTH,
metadata: {
identityId: identityTlsCertAuth.identityId
}
}
});
return { identityTlsCertAuth };
}
});
};
+2
View File
@@ -25,6 +25,7 @@ import { registerIdentityLdapAuthRouter } from "./identity-ldap-auth-router";
import { registerIdentityOciAuthRouter } from "./identity-oci-auth-router"; import { registerIdentityOciAuthRouter } from "./identity-oci-auth-router";
import { registerIdentityOidcAuthRouter } from "./identity-oidc-auth-router"; import { registerIdentityOidcAuthRouter } from "./identity-oidc-auth-router";
import { registerIdentityRouter } from "./identity-router"; import { registerIdentityRouter } from "./identity-router";
import { registerIdentityTlsCertAuthRouter } from "./identity-tls-cert-auth-router";
import { registerIdentityTokenAuthRouter } from "./identity-token-auth-router"; import { registerIdentityTokenAuthRouter } from "./identity-token-auth-router";
import { registerIdentityUaRouter } from "./identity-universal-auth-router"; import { registerIdentityUaRouter } from "./identity-universal-auth-router";
import { registerIntegrationAuthRouter } from "./integration-auth-router"; import { registerIntegrationAuthRouter } from "./integration-auth-router";
@@ -66,6 +67,7 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
await authRouter.register(registerIdentityAccessTokenRouter); await authRouter.register(registerIdentityAccessTokenRouter);
await authRouter.register(registerIdentityAliCloudAuthRouter); await authRouter.register(registerIdentityAliCloudAuthRouter);
await authRouter.register(registerIdentityAwsAuthRouter); await authRouter.register(registerIdentityAwsAuthRouter);
await authRouter.register(registerIdentityTlsCertAuthRouter, { prefix: "/tls-cert-auth" });
await authRouter.register(registerIdentityAzureAuthRouter); await authRouter.register(registerIdentityAzureAuthRouter);
await authRouter.register(registerIdentityOciAuthRouter); await authRouter.register(registerIdentityOciAuthRouter);
await authRouter.register(registerIdentityOidcAuthRouter); await authRouter.register(registerIdentityOidcAuthRouter);
@@ -103,6 +103,7 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IntegrationCreated, event: PostHogEventTypes.IntegrationCreated,
organizationId: req.permission.orgId,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
properties: { properties: {
...createIntegrationEventProperty, ...createIntegrationEventProperty,
@@ -64,6 +64,7 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.UserOrgInvitation, event: PostHogEventTypes.UserOrgInvitation,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
inviteeEmails: req.body.inviteeEmails, inviteeEmails: req.body.inviteeEmails,
organizationRoleSlug: req.body.organizationRoleSlug, organizationRoleSlug: req.body.organizationRoleSlug,
@@ -331,6 +331,7 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IssueCert, event: PostHogEventTypes.IssueCert,
organizationId: req.permission.orgId,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
properties: { properties: {
subscriberId: subscriber.id, subscriberId: subscriber.id,
@@ -399,6 +400,7 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IssueCert, event: PostHogEventTypes.IssueCert,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
subscriberId: subscriber.id, subscriberId: subscriber.id,
commonName: subscriber.commonName, commonName: subscriber.commonName,
@@ -471,6 +473,7 @@ export const registerPkiSubscriberRouter = async (server: FastifyZodProvider) =>
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SignCert, event: PostHogEventTypes.SignCert,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
subscriberId: subscriber.id, subscriberId: subscriber.id,
commonName: subscriber.commonName, commonName: subscriber.commonName,
+5 -15
View File
@@ -158,17 +158,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
includeRoles: z includeRoles: z
.enum(["true", "false"]) .enum(["true", "false"])
.default("false") .default("false")
.transform((value) => value === "true"), .transform((value) => value === "true")
type: z
.enum([
ProjectType.SecretManager,
ProjectType.KMS,
ProjectType.CertificateManager,
ProjectType.SSH,
ProjectType.SecretScanning,
"all"
])
.optional()
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -187,8 +177,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
actor: req.permission.type, actor: req.permission.type,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId
type: req.query.type
}); });
return { workspaces }; return { workspaces };
} }
@@ -377,7 +366,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
.optional() .optional()
.describe(PROJECTS.UPDATE.slug), .describe(PROJECTS.UPDATE.slug),
secretSharing: z.boolean().optional().describe(PROJECTS.UPDATE.secretSharing), secretSharing: z.boolean().optional().describe(PROJECTS.UPDATE.secretSharing),
showSnapshotsLegacy: z.boolean().optional().describe(PROJECTS.UPDATE.showSnapshotsLegacy) showSnapshotsLegacy: z.boolean().optional().describe(PROJECTS.UPDATE.showSnapshotsLegacy),
defaultProduct: z.nativeEnum(ProjectType).optional().describe(PROJECTS.UPDATE.defaultProduct)
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -396,6 +386,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
name: req.body.name, name: req.body.name,
description: req.body.description, description: req.body.description,
autoCapitalization: req.body.autoCapitalization, autoCapitalization: req.body.autoCapitalization,
defaultProduct: req.body.defaultProduct,
hasDeleteProtection: req.body.hasDeleteProtection, hasDeleteProtection: req.body.hasDeleteProtection,
slug: req.body.slug, slug: req.body.slug,
secretSharing: req.body.secretSharing, secretSharing: req.body.secretSharing,
@@ -1059,7 +1050,6 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
body: z.object({ body: z.object({
limit: z.number().default(100), limit: z.number().default(100),
offset: z.number().default(0), offset: z.number().default(0),
type: z.nativeEnum(ProjectType).optional(),
orderBy: z.nativeEnum(SearchProjectSortBy).optional().default(SearchProjectSortBy.NAME), orderBy: z.nativeEnum(SearchProjectSortBy).optional().default(SearchProjectSortBy.NAME),
orderDirection: z.nativeEnum(SortDirection).optional().default(SortDirection.ASC), orderDirection: z.nativeEnum(SortDirection).optional().default(SortDirection.ASC),
name: z name: z
@@ -165,6 +165,7 @@ export const registerSecretRequestsRouter = async (server: FastifyZodProvider) =
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretRequestDeleted, event: PostHogEventTypes.SecretRequestDeleted,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
secretRequestId: req.params.id, secretRequestId: req.params.id,
organizationId: req.permission.orgId, organizationId: req.permission.orgId,
@@ -256,6 +257,7 @@ export const registerSecretRequestsRouter = async (server: FastifyZodProvider) =
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretRequestCreated, event: PostHogEventTypes.SecretRequestCreated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
secretRequestId: shareRequest.id, secretRequestId: shareRequest.id,
organizationId: req.permission.orgId, organizationId: req.permission.orgId,
@@ -4,7 +4,6 @@ import {
OrgMembershipsSchema, OrgMembershipsSchema,
ProjectMembershipsSchema, ProjectMembershipsSchema,
ProjectsSchema, ProjectsSchema,
ProjectType,
UserEncryptionKeysSchema, UserEncryptionKeysSchema,
UsersSchema UsersSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
@@ -85,9 +84,6 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
params: z.object({ params: z.object({
organizationId: z.string().trim().describe(ORGANIZATIONS.GET_PROJECTS.organizationId) organizationId: z.string().trim().describe(ORGANIZATIONS.GET_PROJECTS.organizationId)
}), }),
querystring: z.object({
type: z.nativeEnum(ProjectType).optional().describe(ORGANIZATIONS.GET_PROJECTS.type)
}),
response: { response: {
200: z.object({ 200: z.object({
workspaces: z workspaces: z
@@ -114,8 +110,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
actorId: req.permission.id, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
orgId: req.params.organizationId, orgId: req.params.organizationId
type: req.query.type
}); });
return { workspaces }; return { workspaces };
@@ -198,6 +198,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.ProjectCreated, event: PostHogEventTypes.ProjectCreated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
orgId: project.orgId, orgId: project.orgId,
name: project.name, name: project.name,
@@ -456,6 +457,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
params: z.object({ params: z.object({
projectId: z.string().trim() projectId: z.string().trim()
}), }),
@@ -486,6 +489,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
params: z.object({ params: z.object({
projectId: z.string().trim() projectId: z.string().trim()
}), }),
@@ -548,6 +553,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: z.object({ params: z.object({
projectId: z.string().trim() projectId: z.string().trim()
}), }),
@@ -333,6 +333,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled, event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId, workspaceId,
@@ -489,6 +490,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
if (getUserAgentType(req.headers["user-agent"]) !== UserAgentType.K8_OPERATOR) { if (getUserAgentType(req.headers["user-agent"]) !== UserAgentType.K8_OPERATOR) {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled, event: PostHogEventTypes.SecretPulled,
organizationId: req.permission.orgId,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
properties: { properties: {
numberOfSecrets: 1, numberOfSecrets: 1,
@@ -615,6 +617,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretCreated, event: PostHogEventTypes.SecretCreated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: 1, numberOfSecrets: 1,
workspaceId: projectId, workspaceId: projectId,
@@ -750,6 +753,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretUpdated, event: PostHogEventTypes.SecretUpdated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: 1, numberOfSecrets: 1,
workspaceId: projectId, workspaceId: projectId,
@@ -850,6 +854,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretDeleted, event: PostHogEventTypes.SecretDeleted,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: 1, numberOfSecrets: 1,
workspaceId: projectId, workspaceId: projectId,
@@ -957,6 +962,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled, event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId: req.query.workspaceId, workspaceId: req.query.workspaceId,
@@ -1036,6 +1042,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled, event: PostHogEventTypes.SecretPulled,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: 1, numberOfSecrets: 1,
workspaceId: req.query.workspaceId, workspaceId: req.query.workspaceId,
@@ -1207,6 +1214,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretCreated, event: PostHogEventTypes.SecretCreated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: 1, numberOfSecrets: 1,
workspaceId: req.body.workspaceId, workspaceId: req.body.workspaceId,
@@ -1396,6 +1404,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretUpdated, event: PostHogEventTypes.SecretUpdated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: 1, numberOfSecrets: 1,
workspaceId: req.body.workspaceId, workspaceId: req.body.workspaceId,
@@ -1519,6 +1528,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretDeleted, event: PostHogEventTypes.SecretDeleted,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: 1, numberOfSecrets: 1,
workspaceId: req.body.workspaceId, workspaceId: req.body.workspaceId,
@@ -1702,6 +1712,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretCreated, event: PostHogEventTypes.SecretCreated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId: req.body.workspaceId, workspaceId: req.body.workspaceId,
@@ -1828,6 +1839,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretUpdated, event: PostHogEventTypes.SecretUpdated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId: req.body.workspaceId, workspaceId: req.body.workspaceId,
@@ -1946,6 +1958,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretDeleted, event: PostHogEventTypes.SecretDeleted,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId: req.body.workspaceId, workspaceId: req.body.workspaceId,
@@ -2054,6 +2067,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretCreated, event: PostHogEventTypes.SecretCreated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId: secrets[0].workspace, workspaceId: secrets[0].workspace,
@@ -2209,6 +2223,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretUpdated, event: PostHogEventTypes.SecretUpdated,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId: secrets[0].workspace, workspaceId: secrets[0].workspace,
@@ -2307,6 +2322,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
await server.services.telemetry.sendPostHogEvents({ await server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretDeleted, event: PostHogEventTypes.SecretDeleted,
distinctId: getTelemetryDistinctId(req), distinctId: getTelemetryDistinctId(req),
organizationId: req.permission.orgId,
properties: { properties: {
numberOfSecrets: secrets.length, numberOfSecrets: secrets.length,
workspaceId: secrets[0].workspace, workspaceId: secrets[0].workspace,
@@ -1,3 +1,4 @@
import { logger } from "@app/lib/logger";
import { OrgServiceActor } from "@app/lib/types"; import { OrgServiceActor } from "@app/lib/types";
import { AppConnection } from "../app-connection-enums"; import { AppConnection } from "../app-connection-enums";
@@ -19,6 +20,7 @@ export const gcpConnectionService = (getAppConnection: TGetAppConnectionFunc) =>
return projects; return projects;
} catch (error) { } catch (error) {
logger.error(error, "Error listing GCP secret manager projects");
return []; return [];
} }
}; };
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType, ProjectType, TableName } from "@app/db/schemas"; import { TableName } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, NotFoundError } from "@app/lib/errors";
@@ -50,10 +50,7 @@ type TCertificateAuthorityServiceFactoryDep = {
>; >;
externalCertificateAuthorityDAL: Pick<TExternalCertificateAuthorityDALFactory, "create" | "update">; externalCertificateAuthorityDAL: Pick<TExternalCertificateAuthorityDALFactory, "create" | "update">;
internalCertificateAuthorityService: TInternalCertificateAuthorityServiceFactory; internalCertificateAuthorityService: TInternalCertificateAuthorityServiceFactory;
projectDAL: Pick< projectDAL: Pick<TProjectDALFactory, "findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction">;
TProjectDALFactory,
"findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction" | "getProjectFromSplitId"
>;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
certificateDAL: Pick<TCertificateDALFactory, "create" | "transaction">; certificateDAL: Pick<TCertificateDALFactory, "create" | "transaction">;
certificateBodyDAL: Pick<TCertificateBodyDALFactory, "create">; certificateBodyDAL: Pick<TCertificateBodyDALFactory, "create">;
@@ -98,23 +95,12 @@ export const certificateAuthorityServiceFactory = ({
{ type, projectId, name, enableDirectIssuance, configuration, status }: TCreateCertificateAuthorityDTO, { type, projectId, name, enableDirectIssuance, configuration, status }: TCreateCertificateAuthorityDTO,
actor: OrgServiceActor actor: OrgServiceActor
) => { ) => {
let finalProjectId: string = projectId;
const certManagerProjectFromSplit = await projectDAL.getProjectFromSplitId(
projectId,
ProjectType.CertificateManager
);
if (certManagerProjectFromSplit) {
finalProjectId = certManagerProjectFromSplit.id;
}
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor: actor.type, actor: actor.type,
actorId: actor.id, actorId: actor.id,
projectId: finalProjectId, projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -126,7 +112,7 @@ export const certificateAuthorityServiceFactory = ({
const ca = await internalCertificateAuthorityService.createCa({ const ca = await internalCertificateAuthorityService.createCa({
...(configuration as TCreateInternalCertificateAuthorityDTO["configuration"]), ...(configuration as TCreateInternalCertificateAuthorityDTO["configuration"]),
isInternal: true, isInternal: true,
projectId: finalProjectId, projectId,
enableDirectIssuance, enableDirectIssuance,
name name
}); });
@@ -142,7 +128,7 @@ export const certificateAuthorityServiceFactory = ({
type, type,
enableDirectIssuance: ca.enableDirectIssuance, enableDirectIssuance: ca.enableDirectIssuance,
name: ca.name, name: ca.name,
projectId: finalProjectId, projectId,
status, status,
configuration: ca.internalCa configuration: ca.internalCa
} as TCertificateAuthority; } as TCertificateAuthority;
@@ -151,7 +137,7 @@ export const certificateAuthorityServiceFactory = ({
if (type === CaType.ACME) { if (type === CaType.ACME) {
return acmeFns.createCertificateAuthority({ return acmeFns.createCertificateAuthority({
name, name,
projectId: finalProjectId, projectId,
configuration: configuration as TCreateAcmeCertificateAuthorityDTO["configuration"], configuration: configuration as TCreateAcmeCertificateAuthorityDTO["configuration"],
enableDirectIssuance, enableDirectIssuance,
status, status,
@@ -181,8 +167,7 @@ export const certificateAuthorityServiceFactory = ({
actorId: actor.id, actorId: actor.id,
projectId: certificateAuthority.projectId, projectId: certificateAuthority.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -225,23 +210,12 @@ export const certificateAuthorityServiceFactory = ({
{ projectId, type }: { projectId: string; type: CaType }, { projectId, type }: { projectId: string; type: CaType },
actor: OrgServiceActor actor: OrgServiceActor
) => { ) => {
let finalProjectId: string = projectId;
const certManagerProjectFromSplit = await projectDAL.getProjectFromSplitId(
projectId,
ProjectType.CertificateManager
);
if (certManagerProjectFromSplit) {
finalProjectId = certManagerProjectFromSplit.id;
}
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor: actor.type, actor: actor.type,
actorId: actor.id, actorId: actor.id,
projectId: finalProjectId, projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -251,7 +225,7 @@ export const certificateAuthorityServiceFactory = ({
if (type === CaType.INTERNAL) { if (type === CaType.INTERNAL) {
const cas = await certificateAuthorityDAL.findWithAssociatedCa({ const cas = await certificateAuthorityDAL.findWithAssociatedCa({
[`${TableName.CertificateAuthority}.projectId` as "projectId"]: finalProjectId, [`${TableName.CertificateAuthority}.projectId` as "projectId"]: projectId,
$notNull: [`${TableName.InternalCertificateAuthority}.id` as "id"] $notNull: [`${TableName.InternalCertificateAuthority}.id` as "id"]
}); });
@@ -269,7 +243,7 @@ export const certificateAuthorityServiceFactory = ({
} }
if (type === CaType.ACME) { if (type === CaType.ACME) {
return acmeFns.listCertificateAuthorities({ projectId: finalProjectId }); return acmeFns.listCertificateAuthorities({ projectId });
} }
throw new BadRequestError({ message: "Invalid certificate authority type" }); throw new BadRequestError({ message: "Invalid certificate authority type" });
@@ -294,8 +268,7 @@ export const certificateAuthorityServiceFactory = ({
actorId: actor.id, actorId: actor.id,
projectId: certificateAuthority.projectId, projectId: certificateAuthority.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -368,8 +341,7 @@ export const certificateAuthorityServiceFactory = ({
actorId: actor.id, actorId: actor.id,
projectId: certificateAuthority.projectId, projectId: certificateAuthority.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -5,13 +5,7 @@ import slugify from "@sindresorhus/slugify";
import crypto, { KeyObject } from "crypto"; import crypto, { KeyObject } from "crypto";
import { z } from "zod"; import { z } from "zod";
import { import { TableName, TCertificateAuthorities, TCertificateTemplates } from "@app/db/schemas";
ActionProjectType,
ProjectType,
TableName,
TCertificateAuthorities,
TCertificateTemplates
} from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { import {
ProjectPermissionActions, ProjectPermissionActions,
@@ -105,10 +99,7 @@ type TInternalCertificateAuthorityServiceFactoryDep = {
certificateBodyDAL: Pick<TCertificateBodyDALFactory, "create">; certificateBodyDAL: Pick<TCertificateBodyDALFactory, "create">;
pkiCollectionDAL: Pick<TPkiCollectionDALFactory, "findById">; pkiCollectionDAL: Pick<TPkiCollectionDALFactory, "findById">;
pkiCollectionItemDAL: Pick<TPkiCollectionItemDALFactory, "create">; pkiCollectionItemDAL: Pick<TPkiCollectionItemDALFactory, "create">;
projectDAL: Pick< projectDAL: Pick<TProjectDALFactory, "findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction">;
TProjectDALFactory,
"findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction" | "getProjectFromSplitId"
>;
kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encryptWithKmsKey" | "decryptWithKmsKey">; kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encryptWithKmsKey" | "decryptWithKmsKey">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
}; };
@@ -154,21 +145,12 @@ export const internalCertificateAuthorityServiceFactory = ({
if (!project) throw new NotFoundError({ message: `Project with slug '${dto.projectSlug}' not found` }); if (!project) throw new NotFoundError({ message: `Project with slug '${dto.projectSlug}' not found` });
projectId = project.id; projectId = project.id;
const certManagerProjectFromSplit = await projectDAL.getProjectFromSplitId(
projectId,
ProjectType.CertificateManager
);
if (certManagerProjectFromSplit) {
projectId = certManagerProjectFromSplit.id;
}
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor: dto.actor, actor: dto.actor,
actorId: dto.actorId, actorId: dto.actorId,
projectId, projectId,
actorAuthMethod: dto.actorAuthMethod, actorAuthMethod: dto.actorAuthMethod,
actorOrgId: dto.actorOrgId, actorOrgId: dto.actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -351,8 +333,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read, ProjectPermissionActions.Read,
@@ -376,8 +357,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId: dto.actorId, actorId: dto.actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod: dto.actorAuthMethod, actorAuthMethod: dto.actorAuthMethod,
actorOrgId: dto.actorOrgId, actorOrgId: dto.actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -409,8 +389,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -435,8 +414,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -499,8 +477,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -786,8 +763,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -823,8 +799,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -904,8 +879,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1052,8 +1026,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1224,8 +1197,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1581,8 +1553,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId: dto.actorId, actorId: dto.actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod: dto.actorAuthMethod, actorAuthMethod: dto.actorAuthMethod,
actorOrgId: dto.actorOrgId, actorOrgId: dto.actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1949,8 +1920,7 @@ export const internalCertificateAuthorityServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
const certificateTemplates = await certificateTemplateDAL.find({ caId }); const certificateTemplates = await certificateTemplateDAL.find({ caId });
@@ -2,7 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability";
import * as x509 from "@peculiar/x509"; import * as x509 from "@peculiar/x509";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
import { ActionProjectType, TCertificateTemplateEstConfigsUpdate } from "@app/db/schemas"; import { TCertificateTemplateEstConfigsUpdate } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { import {
@@ -76,8 +76,7 @@ export const certificateTemplateServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -138,8 +137,7 @@ export const certificateTemplateServiceFactory = ({
actorId, actorId,
projectId: certTemplate.projectId, projectId: certTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -203,8 +201,7 @@ export const certificateTemplateServiceFactory = ({
actorId, actorId,
projectId: certTemplate.projectId, projectId: certTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -230,8 +227,7 @@ export const certificateTemplateServiceFactory = ({
actorId, actorId,
projectId: certTemplate.projectId, projectId: certTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -272,8 +268,7 @@ export const certificateTemplateServiceFactory = ({
actorId, actorId,
projectId: certTemplate.projectId, projectId: certTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -355,8 +350,7 @@ export const certificateTemplateServiceFactory = ({
actorId, actorId,
projectId: certTemplate.projectId, projectId: certTemplate.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -435,8 +429,7 @@ export const certificateTemplateServiceFactory = ({
actorId: dto.actorId, actorId: dto.actorId,
projectId: certTemplate.projectId, projectId: certTemplate.projectId,
actorAuthMethod: dto.actorAuthMethod, actorAuthMethod: dto.actorAuthMethod,
actorOrgId: dto.actorOrgId, actorOrgId: dto.actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -2,7 +2,6 @@ import { ForbiddenError } from "@casl/ability";
import * as x509 from "@peculiar/x509"; import * as x509 from "@peculiar/x509";
import { createPrivateKey, createPublicKey, sign, verify } from "crypto"; import { createPrivateKey, createPublicKey, sign, verify } from "crypto";
import { ActionProjectType, ProjectType } from "@app/db/schemas";
import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal"; import { TCertificateAuthorityCrlDALFactory } from "@app/ee/services/certificate-authority-crl/certificate-authority-crl-dal";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { import {
@@ -48,10 +47,7 @@ type TCertificateServiceFactoryDep = {
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">; certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
pkiCollectionDAL: Pick<TPkiCollectionDALFactory, "findById">; pkiCollectionDAL: Pick<TPkiCollectionDALFactory, "findById">;
pkiCollectionItemDAL: Pick<TPkiCollectionItemDALFactory, "create">; pkiCollectionItemDAL: Pick<TPkiCollectionItemDALFactory, "create">;
projectDAL: Pick< projectDAL: Pick<TProjectDALFactory, "findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction">;
TProjectDALFactory,
"findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction" | "getProjectFromSplitId"
>;
kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encryptWithKmsKey" | "decryptWithKmsKey">; kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encryptWithKmsKey" | "decryptWithKmsKey">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
}; };
@@ -83,8 +79,7 @@ export const certificateServiceFactory = ({
actorId, actorId,
projectId: cert.projectId, projectId: cert.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -114,8 +109,7 @@ export const certificateServiceFactory = ({
actorId, actorId,
projectId: cert.projectId, projectId: cert.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -148,8 +142,7 @@ export const certificateServiceFactory = ({
actorId, actorId,
projectId: cert.projectId, projectId: cert.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -198,8 +191,7 @@ export const certificateServiceFactory = ({
actorId, actorId,
projectId: ca.projectId, projectId: ca.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -247,8 +239,7 @@ export const certificateServiceFactory = ({
actorId, actorId,
projectId: cert.projectId, projectId: cert.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -321,23 +312,14 @@ export const certificateServiceFactory = ({
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId); const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` }); if (!project) throw new NotFoundError({ message: `Project with slug '${projectSlug}' not found` });
let projectId = project.id; const projectId = project.id;
const certManagerProjectFromSplit = await projectDAL.getProjectFromSplitId(
projectId,
ProjectType.CertificateManager
);
if (certManagerProjectFromSplit) {
projectId = certManagerProjectFromSplit.id;
}
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -541,8 +523,7 @@ export const certificateServiceFactory = ({
actorId, actorId,
projectId: cert.projectId, projectId: cert.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.CertificateManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
+15 -45
View File
@@ -1,6 +1,5 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType, ProjectType } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionCmekActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionCmekActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { SigningAlgorithm } from "@app/lib/crypto/sign"; import { SigningAlgorithm } from "@app/lib/crypto/sign";
@@ -23,32 +22,23 @@ import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal";
import { TKmsServiceFactory } from "@app/services/kms/kms-service"; import { TKmsServiceFactory } from "@app/services/kms/kms-service";
import { KmsKeyUsage } from "../kms/kms-types"; import { KmsKeyUsage } from "../kms/kms-types";
import { TProjectDALFactory } from "../project/project-dal";
type TCmekServiceFactoryDep = { type TCmekServiceFactoryDep = {
kmsService: TKmsServiceFactory; kmsService: TKmsServiceFactory;
kmsDAL: TKmsKeyDALFactory; kmsDAL: TKmsKeyDALFactory;
permissionService: TPermissionServiceFactory; permissionService: TPermissionServiceFactory;
projectDAL: Pick<TProjectDALFactory, "getProjectFromSplitId">;
}; };
export type TCmekServiceFactory = ReturnType<typeof cmekServiceFactory>; export type TCmekServiceFactory = ReturnType<typeof cmekServiceFactory>;
export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, projectDAL }: TCmekServiceFactoryDep) => { export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService }: TCmekServiceFactoryDep) => {
const createCmek = async ({ projectId: preSplitProjectId, ...dto }: TCreateCmekDTO, actor: OrgServiceActor) => { const createCmek = async ({ projectId, ...dto }: TCreateCmekDTO, actor: OrgServiceActor) => {
let projectId = preSplitProjectId;
const cmekProjectFromSplit = await projectDAL.getProjectFromSplitId(projectId, ProjectType.KMS);
if (cmekProjectFromSplit) {
projectId = cmekProjectFromSplit.id;
}
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor: actor.type, actor: actor.type,
actorId: actor.id, actorId: actor.id,
projectId, projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Create, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Create, ProjectPermissionSub.Cmek);
@@ -87,8 +77,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Edit, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Edit, ProjectPermissionSub.Cmek);
@@ -124,8 +113,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Delete, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Delete, ProjectPermissionSub.Cmek);
@@ -135,23 +123,13 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
return key; return key;
}; };
const listCmeksByProjectId = async ( const listCmeksByProjectId = async ({ projectId, ...filters }: TListCmeksByProjectIdDTO, actor: OrgServiceActor) => {
{ projectId: preSplitProjectId, ...filters }: TListCmeksByProjectIdDTO,
actor: OrgServiceActor
) => {
let projectId = preSplitProjectId;
const cmekProjectFromSplit = await projectDAL.getProjectFromSplitId(preSplitProjectId, ProjectType.KMS);
if (cmekProjectFromSplit) {
projectId = cmekProjectFromSplit.id;
}
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor: actor.type, actor: actor.type,
actorId: actor.id, actorId: actor.id,
projectId, projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek);
@@ -173,8 +151,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek);
@@ -195,8 +172,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek);
@@ -218,8 +194,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Encrypt, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Encrypt, ProjectPermissionSub.Cmek);
@@ -246,8 +221,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek);
@@ -294,8 +268,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek);
@@ -318,8 +291,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Sign, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Sign, ProjectPermissionSub.Cmek);
@@ -353,8 +325,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Verify, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Verify, ProjectPermissionSub.Cmek);
@@ -389,8 +360,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
actorId: actor.id, actorId: actor.id,
projectId: key.projectId, projectId: key.projectId,
actorAuthMethod: actor.authMethod, actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId, actorOrgId: actor.orgId
actionProjectType: ActionProjectType.KMS
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Decrypt, ProjectPermissionSub.Cmek); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Decrypt, ProjectPermissionSub.Cmek);
@@ -4,7 +4,7 @@
import { Knex } from "knex"; import { Knex } from "knex";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { ProjectType, TSecretFolderVersions, TSecretVersionsV2 } from "@app/db/schemas"; import { TSecretFolderVersions, TSecretVersionsV2 } from "@app/db/schemas";
import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { ActorType } from "../auth/auth-type"; import { ActorType } from "../auth/auth-type";
@@ -433,8 +433,7 @@ describe("folderCommitServiceFactory", () => {
mockFolderCommitDAL.findCommitsToRecreate.mockResolvedValue([]); mockFolderCommitDAL.findCommitsToRecreate.mockResolvedValue([]);
mockProjectDAL.findProjectByEnvId.mockResolvedValue({ mockProjectDAL.findProjectByEnvId.mockResolvedValue({
id: "project-id", id: "project-id",
name: "test-project", name: "test-project"
type: ProjectType.SecretManager
}); });
// Act // Act
@@ -2,13 +2,7 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { Knex } from "knex"; import { Knex } from "knex";
import { import { TSecretFolders, TSecretFolderVersions, TSecretV2TagJunctionInsert, TSecretVersionsV2 } from "@app/db/schemas";
ActionProjectType,
TSecretFolders,
TSecretFolderVersions,
TSecretV2TagJunctionInsert,
TSecretVersionsV2
} from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionCommitsActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionCommitsActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
@@ -223,8 +217,7 @@ export const folderCommitServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCommitsActions.Read, ProjectPermissionSub.Commits); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCommitsActions.Read, ProjectPermissionSub.Commits);
@@ -2067,8 +2060,7 @@ export const folderCommitServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -1,6 +1,6 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType, ProjectMembershipRole, SecretKeyEncoding, TGroups } from "@app/db/schemas"; import { ProjectMembershipRole, SecretKeyEncoding, TGroups } from "@app/db/schemas";
import { TListProjectGroupUsersDTO } from "@app/ee/services/group/group-types"; import { TListProjectGroupUsersDTO } from "@app/ee/services/group/group-types";
import { import {
constructPermissionErrorMessage, constructPermissionErrorMessage,
@@ -79,8 +79,7 @@ export const groupProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Create, ProjectPermissionSub.Groups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Create, ProjectPermissionSub.Groups);
@@ -267,8 +266,7 @@ export const groupProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Edit, ProjectPermissionSub.Groups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Edit, ProjectPermissionSub.Groups);
@@ -381,8 +379,7 @@ export const groupProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Delete, ProjectPermissionSub.Groups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Delete, ProjectPermissionSub.Groups);
@@ -426,8 +423,7 @@ export const groupProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups);
@@ -454,8 +450,7 @@ export const groupProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups);
@@ -496,8 +491,7 @@ export const groupProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionGroupActions.Read, ProjectPermissionSub.Groups);
@@ -17,70 +17,11 @@ export const identityAccessTokenDALFactory = (db: TDbClient) => {
const doc = await (tx || db.replicaNode())(TableName.IdentityAccessToken) const doc = await (tx || db.replicaNode())(TableName.IdentityAccessToken)
.where(filter) .where(filter)
.join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityAccessToken}.identityId`) .join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityAccessToken}.identityId`)
.leftJoin(
TableName.IdentityUaClientSecret,
`${TableName.IdentityAccessToken}.identityUAClientSecretId`,
`${TableName.IdentityUaClientSecret}.id`
)
.leftJoin(
TableName.IdentityUniversalAuth,
`${TableName.IdentityUaClientSecret}.identityUAId`,
`${TableName.IdentityUniversalAuth}.id`
)
.leftJoin(TableName.IdentityGcpAuth, `${TableName.Identity}.id`, `${TableName.IdentityGcpAuth}.identityId`)
.leftJoin(
TableName.IdentityAliCloudAuth,
`${TableName.Identity}.id`,
`${TableName.IdentityAliCloudAuth}.identityId`
)
.leftJoin(TableName.IdentityAwsAuth, `${TableName.Identity}.id`, `${TableName.IdentityAwsAuth}.identityId`)
.leftJoin(TableName.IdentityAzureAuth, `${TableName.Identity}.id`, `${TableName.IdentityAzureAuth}.identityId`)
.leftJoin(TableName.IdentityLdapAuth, `${TableName.Identity}.id`, `${TableName.IdentityLdapAuth}.identityId`)
.leftJoin(
TableName.IdentityKubernetesAuth,
`${TableName.Identity}.id`,
`${TableName.IdentityKubernetesAuth}.identityId`
)
.leftJoin(TableName.IdentityOciAuth, `${TableName.Identity}.id`, `${TableName.IdentityOciAuth}.identityId`)
.leftJoin(TableName.IdentityOidcAuth, `${TableName.Identity}.id`, `${TableName.IdentityOidcAuth}.identityId`)
.leftJoin(TableName.IdentityTokenAuth, `${TableName.Identity}.id`, `${TableName.IdentityTokenAuth}.identityId`)
.leftJoin(TableName.IdentityJwtAuth, `${TableName.Identity}.id`, `${TableName.IdentityJwtAuth}.identityId`)
.select(selectAllTableCols(TableName.IdentityAccessToken)) .select(selectAllTableCols(TableName.IdentityAccessToken))
.select( .select(db.ref("name").withSchema(TableName.Identity))
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityUniversalAuth).as("accessTokenTrustedIpsUa"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityGcpAuth).as("accessTokenTrustedIpsGcp"),
db
.ref("accessTokenTrustedIps")
.withSchema(TableName.IdentityAliCloudAuth)
.as("accessTokenTrustedIpsAliCloud"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityAwsAuth).as("accessTokenTrustedIpsAws"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityAzureAuth).as("accessTokenTrustedIpsAzure"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityKubernetesAuth).as("accessTokenTrustedIpsK8s"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityOciAuth).as("accessTokenTrustedIpsOci"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityOidcAuth).as("accessTokenTrustedIpsOidc"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityTokenAuth).as("accessTokenTrustedIpsToken"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityJwtAuth).as("accessTokenTrustedIpsJwt"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityLdapAuth).as("accessTokenTrustedIpsLdap"),
db.ref("name").withSchema(TableName.Identity)
)
.first(); .first();
if (!doc) return; return doc;
return {
...doc,
trustedIpsUniversalAuth: doc.accessTokenTrustedIpsUa,
trustedIpsGcpAuth: doc.accessTokenTrustedIpsGcp,
trustedIpsAliCloudAuth: doc.accessTokenTrustedIpsAliCloud,
trustedIpsAwsAuth: doc.accessTokenTrustedIpsAws,
trustedIpsAzureAuth: doc.accessTokenTrustedIpsAzure,
trustedIpsKubernetesAuth: doc.accessTokenTrustedIpsK8s,
trustedIpsOciAuth: doc.accessTokenTrustedIpsOci,
trustedIpsOidcAuth: doc.accessTokenTrustedIpsOidc,
trustedIpsAccessTokenAuth: doc.accessTokenTrustedIpsToken,
trustedIpsAccessJwtAuth: doc.accessTokenTrustedIpsJwt,
trustedIpsAccessLdapAuth: doc.accessTokenTrustedIpsLdap
};
} catch (error) { } catch (error) {
throw new DatabaseError({ error, name: "IdAccessTokenFindOne" }); throw new DatabaseError({ error, name: "IdAccessTokenFindOne" });
} }
@@ -7,12 +7,14 @@ import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip";
import { TAccessTokenQueueServiceFactory } from "../access-token-queue/access-token-queue"; import { TAccessTokenQueueServiceFactory } from "../access-token-queue/access-token-queue";
import { AuthTokenType } from "../auth/auth-type"; import { AuthTokenType } from "../auth/auth-type";
import { TIdentityDALFactory } from "../identity/identity-dal";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal"; import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityAccessTokenDALFactory } from "./identity-access-token-dal"; import { TIdentityAccessTokenDALFactory } from "./identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload, TRenewAccessTokenDTO } from "./identity-access-token-types"; import { TIdentityAccessTokenJwtPayload, TRenewAccessTokenDTO } from "./identity-access-token-types";
type TIdentityAccessTokenServiceFactoryDep = { type TIdentityAccessTokenServiceFactoryDep = {
identityAccessTokenDAL: TIdentityAccessTokenDALFactory; identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
identityDAL: Pick<TIdentityDALFactory, "getTrustedIpsByAuthMethod">;
identityOrgMembershipDAL: TIdentityOrgDALFactory; identityOrgMembershipDAL: TIdentityOrgDALFactory;
accessTokenQueue: Pick< accessTokenQueue: Pick<
TAccessTokenQueueServiceFactory, TAccessTokenQueueServiceFactory,
@@ -25,7 +27,8 @@ export type TIdentityAccessTokenServiceFactory = ReturnType<typeof identityAcces
export const identityAccessTokenServiceFactory = ({ export const identityAccessTokenServiceFactory = ({
identityAccessTokenDAL, identityAccessTokenDAL,
identityOrgMembershipDAL, identityOrgMembershipDAL,
accessTokenQueue accessTokenQueue,
identityDAL
}: TIdentityAccessTokenServiceFactoryDep) => { }: TIdentityAccessTokenServiceFactoryDep) => {
const validateAccessTokenExp = async (identityAccessToken: TIdentityAccessTokens) => { const validateAccessTokenExp = async (identityAccessToken: TIdentityAccessTokens) => {
const { const {
@@ -190,23 +193,11 @@ export const identityAccessTokenServiceFactory = ({
message: "Failed to authorize revoked access token, access token is revoked" message: "Failed to authorize revoked access token, access token is revoked"
}); });
const trustedIpsMap: Record<IdentityAuthMethod, unknown> = { const trustedIps = await identityDAL.getTrustedIpsByAuthMethod(
[IdentityAuthMethod.UNIVERSAL_AUTH]: identityAccessToken.trustedIpsUniversalAuth, identityAccessToken.identityId,
[IdentityAuthMethod.GCP_AUTH]: identityAccessToken.trustedIpsGcpAuth, identityAccessToken.authMethod as IdentityAuthMethod
[IdentityAuthMethod.ALICLOUD_AUTH]: identityAccessToken.trustedIpsAliCloudAuth, );
[IdentityAuthMethod.AWS_AUTH]: identityAccessToken.trustedIpsAwsAuth, if (ipAddress && trustedIps) {
[IdentityAuthMethod.OCI_AUTH]: identityAccessToken.trustedIpsOciAuth,
[IdentityAuthMethod.AZURE_AUTH]: identityAccessToken.trustedIpsAzureAuth,
[IdentityAuthMethod.KUBERNETES_AUTH]: identityAccessToken.trustedIpsKubernetesAuth,
[IdentityAuthMethod.OIDC_AUTH]: identityAccessToken.trustedIpsOidcAuth,
[IdentityAuthMethod.TOKEN_AUTH]: identityAccessToken.trustedIpsAccessTokenAuth,
[IdentityAuthMethod.JWT_AUTH]: identityAccessToken.trustedIpsAccessJwtAuth,
[IdentityAuthMethod.LDAP_AUTH]: identityAccessToken.trustedIpsAccessLdapAuth
};
const trustedIps = trustedIpsMap[identityAccessToken.authMethod as IdentityAuthMethod];
if (ipAddress) {
checkIPAgainstBlocklist({ checkIPAgainstBlocklist({
ipAddress, ipAddress,
trustedIps: trustedIps as TIp[] trustedIps: trustedIps as TIp[]
@@ -1,6 +1,6 @@
import { ForbiddenError, subject } from "@casl/ability"; import { ForbiddenError, subject } from "@casl/ability";
import { ActionProjectType, ProjectMembershipRole } from "@app/db/schemas"; import { ProjectMembershipRole } from "@app/db/schemas";
import { import {
constructPermissionErrorMessage, constructPermissionErrorMessage,
validatePrivilegeChangeOperation validatePrivilegeChangeOperation
@@ -62,8 +62,7 @@ export const identityProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Create, ProjectPermissionIdentityActions.Create,
@@ -180,8 +179,7 @@ export const identityProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Edit, ProjectPermissionIdentityActions.Edit,
@@ -291,8 +289,7 @@ export const identityProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Delete, ProjectPermissionIdentityActions.Delete,
@@ -320,8 +317,7 @@ export const identityProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionIdentityActions.Read, ProjectPermissionIdentityActions.Read,
@@ -354,8 +350,7 @@ export const identityProjectServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -391,8 +386,7 @@ export const identityProjectServiceFactory = ({
actorId, actorId,
projectId: membership.projectId, projectId: membership.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.Any
}); });
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
@@ -0,0 +1,10 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify, TOrmify } from "@app/lib/knex";
export type TIdentityTlsCertAuthDALFactory = TOrmify<TableName.IdentityTlsCertAuth>;
export const identityTlsCertAuthDALFactory = (db: TDbClient) => {
const orm = ormify(db, TableName.IdentityTlsCertAuth);
return orm;
};
@@ -0,0 +1,423 @@
import crypto from "node:crypto";
import { ForbiddenError } from "@casl/ability";
import jwt from "jsonwebtoken";
import { IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import {
constructPermissionErrorMessage,
validatePrivilegeChangeOperation
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { extractX509CertFromChain } from "@app/lib/certificates/extract-certificate";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
import { TKmsServiceFactory } from "../kms/kms-service";
import { KmsDataKey } from "../kms/kms-types";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
import { TIdentityTlsCertAuthDALFactory } from "./identity-tls-cert-auth-dal";
import { TIdentityTlsCertAuthServiceFactory } from "./identity-tls-cert-auth-types";
type TIdentityTlsCertAuthServiceFactoryDep = {
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
identityTlsCertAuthDAL: Pick<
TIdentityTlsCertAuthDALFactory,
"findOne" | "transaction" | "create" | "updateById" | "delete"
>;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
};
const parseSubjectDetails = (data: string) => {
const values: Record<string, string> = {};
data.split("\n").forEach((el) => {
const [key, value] = el.split("=");
values[key.trim()] = value.trim();
});
return values;
};
export const identityTlsCertAuthServiceFactory = ({
identityAccessTokenDAL,
identityTlsCertAuthDAL,
identityOrgMembershipDAL,
licenseService,
permissionService,
kmsService
}: TIdentityTlsCertAuthServiceFactoryDep): TIdentityTlsCertAuthServiceFactory => {
const login: TIdentityTlsCertAuthServiceFactory["login"] = async ({ identityId, clientCertificate }) => {
const identityTlsCertAuth = await identityTlsCertAuthDAL.findOne({ identityId });
if (!identityTlsCertAuth) {
throw new NotFoundError({
message: "TLS Certificate auth method not found for identity, did you configure TLS Certificate auth?"
});
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
identityId: identityTlsCertAuth.identityId
});
if (!identityMembershipOrg) {
throw new NotFoundError({
message: `Identity organization membership for identity with ID '${identityTlsCertAuth.identityId}' not found`
});
}
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
});
const caCertificate = decryptor({
cipherTextBlob: identityTlsCertAuth.encryptedCaCertificate
}).toString();
const leafCertificate = extractX509CertFromChain(decodeURIComponent(clientCertificate))?.[0];
if (!leafCertificate) {
throw new BadRequestError({ message: "Missing client certificate" });
}
const clientCertificateX509 = new crypto.X509Certificate(leafCertificate);
const caCertificateX509 = new crypto.X509Certificate(caCertificate);
const isValidCertificate = clientCertificateX509.verify(caCertificateX509.publicKey);
if (!isValidCertificate)
throw new UnauthorizedError({
message: "Access denied: Certificate not issued by the provided CA."
});
if (new Date(clientCertificateX509.validTo) < new Date()) {
throw new UnauthorizedError({
message: "Access denied: Certificate has expired."
});
}
if (new Date(clientCertificateX509.validFrom) > new Date()) {
throw new UnauthorizedError({
message: "Access denied: Certificate not yet valid."
});
}
const subjectDetails = parseSubjectDetails(clientCertificateX509.subject);
if (identityTlsCertAuth.allowedCommonNames) {
const isValidCommonName = identityTlsCertAuth.allowedCommonNames.split(",").includes(subjectDetails.CN);
if (!isValidCommonName) {
throw new UnauthorizedError({
message: "Access denied: TLS Certificate Auth common name not allowed."
});
}
}
// Generate the token
const identityAccessToken = await identityTlsCertAuthDAL.transaction(async (tx) => {
const newToken = await identityAccessTokenDAL.create(
{
identityId: identityTlsCertAuth.identityId,
isAccessTokenRevoked: false,
accessTokenTTL: identityTlsCertAuth.accessTokenTTL,
accessTokenMaxTTL: identityTlsCertAuth.accessTokenMaxTTL,
accessTokenNumUses: 0,
accessTokenNumUsesLimit: identityTlsCertAuth.accessTokenNumUsesLimit,
authMethod: IdentityAuthMethod.TLS_CERT_AUTH
},
tx
);
return newToken;
});
const appCfg = getConfig();
const accessToken = jwt.sign(
{
identityId: identityTlsCertAuth.identityId,
identityAccessTokenId: identityAccessToken.id,
authTokenType: AuthTokenType.IDENTITY_ACCESS_TOKEN
} as TIdentityAccessTokenJwtPayload,
appCfg.AUTH_SECRET,
Number(identityAccessToken.accessTokenTTL) === 0
? undefined
: {
expiresIn: Number(identityAccessToken.accessTokenTTL)
}
);
return {
identityTlsCertAuth,
accessToken,
identityAccessToken,
identityMembershipOrg
};
};
const attachTlsCertAuth: TIdentityTlsCertAuthServiceFactory["attachTlsCertAuth"] = async ({
identityId,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps,
actorId,
actorAuthMethod,
actor,
actorOrgId,
isActorSuperAdmin,
caCertificate,
allowedCommonNames
}) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new BadRequestError({
message: "Failed to add TLS Certificate Auth to already configured identity"
});
}
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
}
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" &&
accessTokenTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({
message:
"Failed to add IP access range to access token due to plan restriction. Upgrade plan to add IP access range."
});
if (!isValidIpOrCidr(accessTokenTrustedIp.ipAddress))
throw new BadRequestError({
message: "The IP is not a valid IPv4, IPv6, or CIDR block"
});
return extractIPDetails(accessTokenTrustedIp.ipAddress);
});
const { encryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
});
const identityTlsCertAuth = await identityTlsCertAuthDAL.transaction(async (tx) => {
const doc = await identityTlsCertAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
accessTokenMaxTTL,
allowedCommonNames,
accessTokenTTL,
encryptedCaCertificate: encryptor({ plainText: Buffer.from(caCertificate) }).cipherTextBlob,
accessTokenNumUsesLimit,
accessTokenTrustedIps: JSON.stringify(reformattedAccessTokenTrustedIps)
},
tx
);
return doc;
});
return { ...identityTlsCertAuth, orgId: identityMembershipOrg.orgId };
};
const updateTlsCertAuth: TIdentityTlsCertAuthServiceFactory["updateTlsCertAuth"] = async ({
identityId,
caCertificate,
allowedCommonNames,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps,
actorId,
actorAuthMethod,
actor,
actorOrgId
}) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new NotFoundError({
message: "The identity does not have TLS Certificate Auth attached"
});
}
const identityTlsCertAuth = await identityTlsCertAuthDAL.findOne({ identityId });
if (
(accessTokenMaxTTL || identityTlsCertAuth.accessTokenMaxTTL) > 0 &&
(accessTokenTTL || identityTlsCertAuth.accessTokenTTL) >
(accessTokenMaxTTL || identityTlsCertAuth.accessTokenMaxTTL)
) {
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
}
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" &&
accessTokenTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({
message:
"Failed to add IP access range to access token due to plan restriction. Upgrade plan to add IP access range."
});
if (!isValidIpOrCidr(accessTokenTrustedIp.ipAddress))
throw new BadRequestError({
message: "The IP is not a valid IPv4, IPv6, or CIDR block"
});
return extractIPDetails(accessTokenTrustedIp.ipAddress);
});
const { encryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
});
const updatedTlsCertAuth = await identityTlsCertAuthDAL.updateById(identityTlsCertAuth.id, {
allowedCommonNames,
encryptedCaCertificate: caCertificate
? encryptor({ plainText: Buffer.from(caCertificate) }).cipherTextBlob
: undefined,
accessTokenMaxTTL,
accessTokenTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps: reformattedAccessTokenTrustedIps
? JSON.stringify(reformattedAccessTokenTrustedIps)
: undefined
});
return { ...updatedTlsCertAuth, orgId: identityMembershipOrg.orgId };
};
const getTlsCertAuth: TIdentityTlsCertAuthServiceFactory["getTlsCertAuth"] = async ({
identityId,
actorId,
actor,
actorAuthMethod,
actorOrgId
}) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new BadRequestError({
message: "The identity does not have TLS Certificate Auth attached"
});
}
const identityAuth = await identityTlsCertAuthDAL.findOne({ identityId });
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
const { decryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.Organization,
orgId: identityMembershipOrg.orgId
});
let caCertificate = "";
if (identityAuth.encryptedCaCertificate) {
caCertificate = decryptor({ cipherTextBlob: identityAuth.encryptedCaCertificate }).toString();
}
return { ...identityAuth, caCertificate, orgId: identityMembershipOrg.orgId };
};
const revokeTlsCertAuth: TIdentityTlsCertAuthServiceFactory["revokeTlsCertAuth"] = async ({
identityId,
actorId,
actor,
actorAuthMethod,
actorOrgId
}) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TLS_CERT_AUTH)) {
throw new BadRequestError({
message: "The identity does not have TLS Certificate auth"
});
}
const { permission, membership } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke TLS Certificate auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const revokedIdentityTlsCertAuth = await identityTlsCertAuthDAL.transaction(async (tx) => {
const deletedTlsCertAuth = await identityTlsCertAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.TLS_CERT_AUTH }, tx);
return { ...deletedTlsCertAuth?.[0], orgId: identityMembershipOrg.orgId };
});
return revokedIdentityTlsCertAuth;
};
return {
login,
attachTlsCertAuth,
updateTlsCertAuth,
getTlsCertAuth,
revokeTlsCertAuth
};
};
@@ -0,0 +1,49 @@
import { TIdentityAccessTokens, TIdentityOrgMemberships, TIdentityTlsCertAuths } from "@app/db/schemas";
import { TProjectPermission } from "@app/lib/types";
export type TLoginTlsCertAuthDTO = {
identityId: string;
clientCertificate: string;
};
export type TAttachTlsCertAuthDTO = {
identityId: string;
caCertificate: string;
allowedCommonNames?: string | null;
accessTokenTTL: number;
accessTokenMaxTTL: number;
accessTokenNumUsesLimit: number;
accessTokenTrustedIps: { ipAddress: string }[];
isActorSuperAdmin?: boolean;
} & Omit<TProjectPermission, "projectId">;
export type TUpdateTlsCertAuthDTO = {
identityId: string;
caCertificate?: string;
allowedCommonNames?: string | null;
accessTokenTTL?: number;
accessTokenMaxTTL?: number;
accessTokenNumUsesLimit?: number;
accessTokenTrustedIps?: { ipAddress: string }[];
} & Omit<TProjectPermission, "projectId">;
export type TGetTlsCertAuthDTO = {
identityId: string;
} & Omit<TProjectPermission, "projectId">;
export type TRevokeTlsCertAuthDTO = {
identityId: string;
} & Omit<TProjectPermission, "projectId">;
export type TIdentityTlsCertAuthServiceFactory = {
login: (dto: TLoginTlsCertAuthDTO) => Promise<{
identityTlsCertAuth: TIdentityTlsCertAuths;
accessToken: string;
identityAccessToken: TIdentityAccessTokens;
identityMembershipOrg: TIdentityOrgMemberships;
}>;
attachTlsCertAuth: (dto: TAttachTlsCertAuthDTO) => Promise<TIdentityTlsCertAuths>;
updateTlsCertAuth: (dto: TUpdateTlsCertAuthDTO) => Promise<TIdentityTlsCertAuths>;
revokeTlsCertAuth: (dto: TRevokeTlsCertAuthDTO) => Promise<TIdentityTlsCertAuths>;
getTlsCertAuth: (dto: TGetTlsCertAuthDTO) => Promise<TIdentityTlsCertAuths & { caCertificate: string }>;
};
+24 -2
View File
@@ -1,5 +1,5 @@
import { TDbClient } from "@app/db"; import { TDbClient } from "@app/db";
import { TableName, TIdentities } from "@app/db/schemas"; import { IdentityAuthMethod, TableName, TIdentities } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors"; import { DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols } from "@app/lib/knex"; import { ormify, selectAllTableCols } from "@app/lib/knex";
@@ -8,6 +8,28 @@ export type TIdentityDALFactory = ReturnType<typeof identityDALFactory>;
export const identityDALFactory = (db: TDbClient) => { export const identityDALFactory = (db: TDbClient) => {
const identityOrm = ormify(db, TableName.Identity); const identityOrm = ormify(db, TableName.Identity);
const getTrustedIpsByAuthMethod = async (identityId: string, authMethod: IdentityAuthMethod) => {
const authMethodToTableName = {
[IdentityAuthMethod.TOKEN_AUTH]: TableName.IdentityTokenAuth,
[IdentityAuthMethod.UNIVERSAL_AUTH]: TableName.IdentityUniversalAuth,
[IdentityAuthMethod.KUBERNETES_AUTH]: TableName.IdentityKubernetesAuth,
[IdentityAuthMethod.GCP_AUTH]: TableName.IdentityGcpAuth,
[IdentityAuthMethod.ALICLOUD_AUTH]: TableName.IdentityAliCloudAuth,
[IdentityAuthMethod.AWS_AUTH]: TableName.IdentityAwsAuth,
[IdentityAuthMethod.AZURE_AUTH]: TableName.IdentityAzureAuth,
[IdentityAuthMethod.TLS_CERT_AUTH]: TableName.IdentityTlsCertAuth,
[IdentityAuthMethod.OCI_AUTH]: TableName.IdentityOciAuth,
[IdentityAuthMethod.OIDC_AUTH]: TableName.IdentityOidcAuth,
[IdentityAuthMethod.JWT_AUTH]: TableName.IdentityJwtAuth,
[IdentityAuthMethod.LDAP_AUTH]: TableName.IdentityLdapAuth
} as const;
const tableName = authMethodToTableName[authMethod];
if (!tableName) return;
const data = await db(tableName).where({ identityId }).first();
if (!data) return;
return data.accessTokenTrustedIps;
};
const getIdentitiesByFilter = async ({ const getIdentitiesByFilter = async ({
limit, limit,
offset, offset,
@@ -38,5 +60,5 @@ export const identityDALFactory = (db: TDbClient) => {
} }
}; };
return { ...identityOrm, getIdentitiesByFilter }; return { ...identityOrm, getTrustedIpsByAuthMethod, getIdentitiesByFilter };
}; };
@@ -11,7 +11,8 @@ export const buildAuthMethods = ({
azureId, azureId,
tokenId, tokenId,
jwtId, jwtId,
ldapId ldapId,
tlsCertId
}: { }: {
uaId?: string; uaId?: string;
gcpId?: string; gcpId?: string;
@@ -24,6 +25,7 @@ export const buildAuthMethods = ({
tokenId?: string; tokenId?: string;
jwtId?: string; jwtId?: string;
ldapId?: string; ldapId?: string;
tlsCertId?: string;
}) => { }) => {
return [ return [
...[uaId ? IdentityAuthMethod.UNIVERSAL_AUTH : null], ...[uaId ? IdentityAuthMethod.UNIVERSAL_AUTH : null],
@@ -36,6 +38,7 @@ export const buildAuthMethods = ({
...[azureId ? IdentityAuthMethod.AZURE_AUTH : null], ...[azureId ? IdentityAuthMethod.AZURE_AUTH : null],
...[tokenId ? IdentityAuthMethod.TOKEN_AUTH : null], ...[tokenId ? IdentityAuthMethod.TOKEN_AUTH : null],
...[jwtId ? IdentityAuthMethod.JWT_AUTH : null], ...[jwtId ? IdentityAuthMethod.JWT_AUTH : null],
...[ldapId ? IdentityAuthMethod.LDAP_AUTH : null] ...[ldapId ? IdentityAuthMethod.LDAP_AUTH : null],
...[tlsCertId ? IdentityAuthMethod.TLS_CERT_AUTH : null]
].filter((authMethod) => authMethod) as IdentityAuthMethod[]; ].filter((authMethod) => authMethod) as IdentityAuthMethod[];
}; };
@@ -12,6 +12,7 @@ import {
TIdentityOciAuths, TIdentityOciAuths,
TIdentityOidcAuths, TIdentityOidcAuths,
TIdentityOrgMemberships, TIdentityOrgMemberships,
TIdentityTlsCertAuths,
TIdentityTokenAuths, TIdentityTokenAuths,
TIdentityUniversalAuths, TIdentityUniversalAuths,
TOrgRoles TOrgRoles
@@ -99,7 +100,11 @@ export const identityOrgDALFactory = (db: TDbClient) => {
`${TableName.IdentityOrgMembership}.identityId`, `${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityLdapAuth}.identityId` `${TableName.IdentityLdapAuth}.identityId`
) )
.leftJoin<TIdentityTlsCertAuths>(
TableName.IdentityTlsCertAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityTlsCertAuth}.identityId`
)
.select( .select(
selectAllTableCols(TableName.IdentityOrgMembership), selectAllTableCols(TableName.IdentityOrgMembership),
@@ -114,6 +119,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth), db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth),
db.ref("id").as("jwtId").withSchema(TableName.IdentityJwtAuth), db.ref("id").as("jwtId").withSchema(TableName.IdentityJwtAuth),
db.ref("id").as("ldapId").withSchema(TableName.IdentityLdapAuth), db.ref("id").as("ldapId").withSchema(TableName.IdentityLdapAuth),
db.ref("id").as("tlsCertId").withSchema(TableName.IdentityTlsCertAuth),
db.ref("name").withSchema(TableName.Identity), db.ref("name").withSchema(TableName.Identity),
db.ref("hasDeleteProtection").withSchema(TableName.Identity) db.ref("hasDeleteProtection").withSchema(TableName.Identity)
); );
@@ -238,7 +244,11 @@ export const identityOrgDALFactory = (db: TDbClient) => {
"paginatedIdentity.identityId", "paginatedIdentity.identityId",
`${TableName.IdentityLdapAuth}.identityId` `${TableName.IdentityLdapAuth}.identityId`
) )
.leftJoin<TIdentityTlsCertAuths>(
TableName.IdentityTlsCertAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityTlsCertAuth}.identityId`
)
.select( .select(
db.ref("id").withSchema("paginatedIdentity"), db.ref("id").withSchema("paginatedIdentity"),
db.ref("role").withSchema("paginatedIdentity"), db.ref("role").withSchema("paginatedIdentity"),
@@ -260,7 +270,8 @@ export const identityOrgDALFactory = (db: TDbClient) => {
db.ref("id").as("azureId").withSchema(TableName.IdentityAzureAuth), db.ref("id").as("azureId").withSchema(TableName.IdentityAzureAuth),
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth), db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth),
db.ref("id").as("jwtId").withSchema(TableName.IdentityJwtAuth), db.ref("id").as("jwtId").withSchema(TableName.IdentityJwtAuth),
db.ref("id").as("ldapId").withSchema(TableName.IdentityLdapAuth) db.ref("id").as("ldapId").withSchema(TableName.IdentityLdapAuth),
db.ref("id").as("tlsCertId").withSchema(TableName.IdentityTlsCertAuth)
) )
// cr stands for custom role // cr stands for custom role
.select(db.ref("id").as("crId").withSchema(TableName.OrgRoles)) .select(db.ref("id").as("crId").withSchema(TableName.OrgRoles))
@@ -306,6 +317,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
azureId, azureId,
tokenId, tokenId,
ldapId, ldapId,
tlsCertId,
createdAt, createdAt,
updatedAt updatedAt
}) => ({ }) => ({
@@ -313,7 +325,6 @@ export const identityOrgDALFactory = (db: TDbClient) => {
roleId, roleId,
identityId, identityId,
id, id,
orgId, orgId,
createdAt, createdAt,
updatedAt, updatedAt,
@@ -341,7 +352,8 @@ export const identityOrgDALFactory = (db: TDbClient) => {
azureId, azureId,
tokenId, tokenId,
jwtId, jwtId,
ldapId ldapId,
tlsCertId
}) })
} }
}), }),
@@ -380,7 +392,12 @@ export const identityOrgDALFactory = (db: TDbClient) => {
.join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityOrgMembership}.identityId`) .join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityOrgMembership}.identityId`)
.where(`${TableName.IdentityOrgMembership}.orgId`, orgId) .where(`${TableName.IdentityOrgMembership}.orgId`, orgId)
.leftJoin(TableName.OrgRoles, `${TableName.IdentityOrgMembership}.roleId`, `${TableName.OrgRoles}.id`) .leftJoin(TableName.OrgRoles, `${TableName.IdentityOrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
.orderBy(`${TableName.Identity}.${orderBy}`, orderDirection) .orderBy(
orderBy === OrgIdentityOrderBy.Role
? `${TableName.IdentityOrgMembership}.${orderBy}`
: `${TableName.Identity}.${orderBy}`,
orderDirection
)
.select(`${TableName.IdentityOrgMembership}.id`) .select(`${TableName.IdentityOrgMembership}.id`)
.select<{ id: string; total_count: string }>( .select<{ id: string; total_count: string }>(
db.raw( db.raw(
@@ -511,6 +528,23 @@ export const identityOrgDALFactory = (db: TDbClient) => {
if (orderBy === OrgIdentityOrderBy.Name) { if (orderBy === OrgIdentityOrderBy.Name) {
void query.orderBy("identityName", orderDirection); void query.orderBy("identityName", orderDirection);
} else if (orderBy === OrgIdentityOrderBy.Role) {
void query.orderByRaw(
`
CASE
WHEN ??.role = ?
THEN ??.slug
ELSE ??.role
END ?
`,
[
TableName.IdentityOrgMembership,
"custom",
TableName.OrgRoles,
TableName.IdentityOrgMembership,
db.raw(orderDirection)
]
);
} }
const docs = await query; const docs = await query;
@@ -46,8 +46,8 @@ export type TListOrgIdentitiesByOrgIdDTO = {
} & TOrgPermission; } & TOrgPermission;
export enum OrgIdentityOrderBy { export enum OrgIdentityOrderBy {
Name = "name" Name = "name",
// Role = "role" Role = "role"
} }
export type TSearchOrgIdentitiesByOrgIdDAL = { export type TSearchOrgIdentitiesByOrgIdDAL = {
@@ -4,13 +4,7 @@ import { Octokit } from "@octokit/rest";
import { Client as OctopusClient, SpaceRepository as OctopusSpaceRepository } from "@octopusdeploy/api-client"; import { Client as OctopusClient, SpaceRepository as OctopusSpaceRepository } from "@octopusdeploy/api-client";
import AWS from "aws-sdk"; import AWS from "aws-sdk";
import { import { SecretEncryptionAlgo, SecretKeyEncoding, TIntegrationAuths, TIntegrationAuthsInsert } from "@app/db/schemas";
ActionProjectType,
SecretEncryptionAlgo,
SecretKeyEncoding,
TIntegrationAuths,
TIntegrationAuthsInsert
} from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
@@ -103,8 +97,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const authorizations = await integrationAuthDAL.find({ projectId }); const authorizations = await integrationAuthDAL.find({ projectId });
@@ -122,8 +115,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: auth.projectId, projectId: auth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
return permission.can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations) ? auth : null; return permission.can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations) ? auth : null;
@@ -146,8 +138,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
return integrationAuth; return integrationAuth;
@@ -172,8 +163,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations);
@@ -282,8 +272,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations);
@@ -417,8 +406,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations);
@@ -679,8 +667,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -714,8 +701,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -745,8 +731,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -787,8 +772,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -816,8 +800,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -891,8 +874,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -939,8 +921,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -974,8 +955,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1033,8 +1013,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1070,8 +1049,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1112,8 +1090,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1153,8 +1130,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1194,8 +1170,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1234,8 +1209,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1275,8 +1249,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1344,8 +1317,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1419,8 +1391,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1470,8 +1441,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1519,8 +1489,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1588,8 +1557,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1630,8 +1598,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1743,8 +1710,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations);
@@ -1767,8 +1733,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations);
@@ -1801,8 +1766,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(sourcePermission).throwUnlessCan( ForbiddenError.from(sourcePermission).throwUnlessCan(
@@ -1815,8 +1779,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(targetPermission).throwUnlessCan( ForbiddenError.from(targetPermission).throwUnlessCan(
@@ -1849,8 +1812,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -1884,8 +1846,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1925,8 +1886,7 @@ export const integrationAuthServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId); const { shouldUseSecretV2Bridge, botKey } = await projectBotService.getBotKey(integrationAuth.projectId);
@@ -1,6 +1,5 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { ActionProjectType } from "@app/db/schemas";
import { throwIfMissingSecretReadValueOrDescribePermission } from "@app/ee/services/permission/permission-fns"; import { throwIfMissingSecretReadValueOrDescribePermission } from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
import { import {
@@ -91,8 +90,7 @@ export const integrationServiceFactory = ({
actorId, actorId,
projectId: integrationAuth.projectId, projectId: integrationAuth.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations);
@@ -167,8 +165,7 @@ export const integrationServiceFactory = ({
actorId, actorId,
projectId: integration.projectId, projectId: integration.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations);
@@ -231,8 +228,7 @@ export const integrationServiceFactory = ({
actorId, actorId,
projectId: integration.projectId, projectId: integration.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -259,8 +255,7 @@ export const integrationServiceFactory = ({
actorId, actorId,
projectId: integration.projectId, projectId: integration.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -302,8 +297,7 @@ export const integrationServiceFactory = ({
actorId, actorId,
projectId: integration.projectId, projectId: integration.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations);
@@ -339,8 +333,7 @@ export const integrationServiceFactory = ({
actorId, actorId,
projectId, projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -359,8 +352,7 @@ export const integrationServiceFactory = ({
actorId, actorId,
projectId: integration.projectId, projectId: integration.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId
actionProjectType: ActionProjectType.SecretManager
}); });
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
@@ -400,7 +400,7 @@ export const buildTeamsPayload = (notification: TNotification) => {
{ {
type: "Action.OpenUrl", type: "Action.OpenUrl",
title: "View request in Infisical", title: "View request in Infisical",
url: `${appCfg.SITE_URL}/secret-manager/${payload.projectId}/approval?requestId=${payload.requestId}` url: `${appCfg.SITE_URL}/projects/${payload.projectId}/secret-manager/approval?requestId=${payload.requestId}`
} }
] ]
}; };

Some files were not shown because too many files have changed in this diff Show More