mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-10 01:28:33 +00:00
Fix: Make API keys compatible with old endpoints
This commit is contained in:
@@ -13,6 +13,7 @@ import { conditionsMatcher } from "@app/lib/casl";
|
|||||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||||
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
|
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
|
||||||
import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal";
|
import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal";
|
||||||
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { TProjectRoleDALFactory } from "@app/services/project-role/project-role-dal";
|
import { TProjectRoleDALFactory } from "@app/services/project-role/project-role-dal";
|
||||||
import { TServiceTokenDALFactory } from "@app/services/service-token/service-token-dal";
|
import { TServiceTokenDALFactory } from "@app/services/service-token/service-token-dal";
|
||||||
|
|
||||||
@@ -33,6 +34,7 @@ type TPermissionServiceFactoryDep = {
|
|||||||
orgRoleDAL: Pick<TOrgRoleDALFactory, "findOne">;
|
orgRoleDAL: Pick<TOrgRoleDALFactory, "findOne">;
|
||||||
projectRoleDAL: Pick<TProjectRoleDALFactory, "findOne">;
|
projectRoleDAL: Pick<TProjectRoleDALFactory, "findOne">;
|
||||||
serviceTokenDAL: Pick<TServiceTokenDALFactory, "findById">;
|
serviceTokenDAL: Pick<TServiceTokenDALFactory, "findById">;
|
||||||
|
projectDAL: Pick<TProjectDALFactory, "findById">;
|
||||||
permissionDAL: TPermissionDALFactory;
|
permissionDAL: TPermissionDALFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,7 +44,8 @@ export const permissionServiceFactory = ({
|
|||||||
permissionDAL,
|
permissionDAL,
|
||||||
orgRoleDAL,
|
orgRoleDAL,
|
||||||
projectRoleDAL,
|
projectRoleDAL,
|
||||||
serviceTokenDAL
|
serviceTokenDAL,
|
||||||
|
projectDAL
|
||||||
}: TPermissionServiceFactoryDep) => {
|
}: TPermissionServiceFactoryDep) => {
|
||||||
const buildOrgPermission = (role: string, permission?: unknown) => {
|
const buildOrgPermission = (role: string, permission?: unknown) => {
|
||||||
switch (role) {
|
switch (role) {
|
||||||
@@ -99,7 +102,7 @@ export const permissionServiceFactory = ({
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Get user permission in an organization
|
* Get user permission in an organization
|
||||||
* */
|
*/
|
||||||
const getUserOrgPermission = async (
|
const getUserOrgPermission = async (
|
||||||
userId: string,
|
userId: string,
|
||||||
orgId: string,
|
orgId: string,
|
||||||
@@ -112,8 +115,13 @@ export const permissionServiceFactory = ({
|
|||||||
throw new BadRequestError({ name: "Custom permission not found" });
|
throw new BadRequestError({ name: "Custom permission not found" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (membership.orgId !== userOrgId) {
|
// If the org ID is API_KEY, the request is being made with an API Key.
|
||||||
throw new UnauthorizedError({ name: "You are not a member of this organization" });
|
// Since we can't scope API keys to an organization, we'll need to do an arbitrary check to see if the user is a member of the organization.
|
||||||
|
|
||||||
|
// Extra: This means that when users are using API keys to make requests, they can't use slug-based routes.
|
||||||
|
// Slug-based routes depend on the organization ID being present on the request, since project slugs aren't globally unique, and we need a way to filter by organization.
|
||||||
|
if (userOrgId !== "API_KEY" && membership.orgId !== userOrgId) {
|
||||||
|
throw new UnauthorizedError({ name: "You are not logged into this organization" });
|
||||||
}
|
}
|
||||||
|
|
||||||
validateOrgSAML(authMethod, membership.orgAuthEnforced);
|
validateOrgSAML(authMethod, membership.orgAuthEnforced);
|
||||||
@@ -179,8 +187,13 @@ export const permissionServiceFactory = ({
|
|||||||
throw new BadRequestError({ name: "Custom permission not found" });
|
throw new BadRequestError({ name: "Custom permission not found" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (membership.orgId !== userOrgId) {
|
// If the org ID is API_KEY, the request is being made with an API Key.
|
||||||
throw new UnauthorizedError({ name: "You are not a member of this organization" });
|
// Since we can't scope API keys to an organization, we'll need to do an arbitrary check to see if the user is a member of the organization.
|
||||||
|
|
||||||
|
// Extra: This means that when users are using API keys to make requests, they can't use slug-based routes.
|
||||||
|
// Slug-based routes depend on the organization ID being present on the request, since project slugs aren't globally unique, and we need a way to filter by organization.
|
||||||
|
if (userOrgId !== "API_KEY" && membership.orgId !== userOrgId) {
|
||||||
|
throw new UnauthorizedError({ name: "You are not logged into this organization" });
|
||||||
}
|
}
|
||||||
|
|
||||||
validateOrgSAML(authMethod, membership.orgAuthEnforced);
|
validateOrgSAML(authMethod, membership.orgAuthEnforced);
|
||||||
@@ -195,7 +208,8 @@ export const permissionServiceFactory = ({
|
|||||||
|
|
||||||
const getIdentityProjectPermission = async (
|
const getIdentityProjectPermission = async (
|
||||||
identityId: string,
|
identityId: string,
|
||||||
projectId: string
|
projectId: string,
|
||||||
|
identityOrgId: string | undefined
|
||||||
): Promise<TProjectPermissionRT<ActorType.IDENTITY>> => {
|
): Promise<TProjectPermissionRT<ActorType.IDENTITY>> => {
|
||||||
const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId);
|
const identityProjectPermission = await permissionDAL.getProjectIdentityPermission(identityId, projectId);
|
||||||
if (!identityProjectPermission) throw new UnauthorizedError({ name: "Identity not in project" });
|
if (!identityProjectPermission) throw new UnauthorizedError({ name: "Identity not in project" });
|
||||||
@@ -208,6 +222,10 @@ export const permissionServiceFactory = ({
|
|||||||
throw new BadRequestError({ name: "Custom permission not found" });
|
throw new BadRequestError({ name: "Custom permission not found" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (identityProjectPermission.orgId !== identityOrgId) {
|
||||||
|
throw new UnauthorizedError({ name: "You are not a member of this organization" });
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
permission: buildProjectPermission(identityProjectPermission.roles),
|
permission: buildProjectPermission(identityProjectPermission.roles),
|
||||||
membership: identityProjectPermission,
|
membership: identityProjectPermission,
|
||||||
@@ -218,14 +236,32 @@ export const permissionServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getServiceTokenProjectPermission = async (serviceTokenId: string, projectId: string) => {
|
const getServiceTokenProjectPermission = async (
|
||||||
|
serviceTokenId: string,
|
||||||
|
projectId: string,
|
||||||
|
actorOrgId: string | undefined
|
||||||
|
) => {
|
||||||
const serviceToken = await serviceTokenDAL.findById(serviceTokenId);
|
const serviceToken = await serviceTokenDAL.findById(serviceTokenId);
|
||||||
if (!serviceToken) throw new BadRequestError({ message: "Service token not found" });
|
if (!serviceToken) throw new BadRequestError({ message: "Service token not found" });
|
||||||
|
|
||||||
|
const serviceTokenProject = await projectDAL.findById(serviceToken.projectId);
|
||||||
|
|
||||||
|
if (!serviceTokenProject) throw new BadRequestError({ message: "Service token not linked to a project" });
|
||||||
|
|
||||||
|
if (serviceTokenProject.orgId !== actorOrgId) {
|
||||||
|
throw new UnauthorizedError({ message: "Service token not a part of this organization" });
|
||||||
|
}
|
||||||
|
|
||||||
if (serviceToken.projectId !== projectId)
|
if (serviceToken.projectId !== projectId)
|
||||||
throw new UnauthorizedError({
|
throw new UnauthorizedError({
|
||||||
message: "Failed to find service authorization for given project"
|
message: "Failed to find service authorization for given project"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (serviceTokenProject.orgId !== actorOrgId)
|
||||||
|
throw new UnauthorizedError({
|
||||||
|
message: "Failed to find service authorization for given project"
|
||||||
|
});
|
||||||
|
|
||||||
const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []);
|
const scopes = ServiceTokenScopes.parse(serviceToken.scopes || []);
|
||||||
return {
|
return {
|
||||||
permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions),
|
permission: buildServiceTokenProjectPermission(scopes, serviceToken.permissions),
|
||||||
@@ -260,9 +296,9 @@ export const permissionServiceFactory = ({
|
|||||||
case ActorType.USER:
|
case ActorType.USER:
|
||||||
return getUserProjectPermission(id, projectId, actorAuthMethod, actorOrgId) as Promise<TProjectPermissionRT<T>>;
|
return getUserProjectPermission(id, projectId, actorAuthMethod, actorOrgId) as Promise<TProjectPermissionRT<T>>;
|
||||||
case ActorType.SERVICE:
|
case ActorType.SERVICE:
|
||||||
return getServiceTokenProjectPermission(id, projectId) as Promise<TProjectPermissionRT<T>>;
|
return getServiceTokenProjectPermission(id, projectId, actorOrgId) as Promise<TProjectPermissionRT<T>>;
|
||||||
case ActorType.IDENTITY:
|
case ActorType.IDENTITY:
|
||||||
return getIdentityProjectPermission(id, projectId) as Promise<TProjectPermissionRT<T>>;
|
return getIdentityProjectPermission(id, projectId, actorOrgId) as Promise<TProjectPermissionRT<T>>;
|
||||||
default:
|
default:
|
||||||
throw new UnauthorizedError({
|
throw new UnauthorizedError({
|
||||||
message: "Permission not defined",
|
message: "Permission not defined",
|
||||||
|
|||||||
Reference in New Issue
Block a user