mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-08 15:13:55 -05:00
feat: refactor PAM account access endpoint to use accountPath and projectId
This commit is contained in:
@@ -106,7 +106,8 @@ export const registerPamAccountRouter = async (server: FastifyZodProvider) => {
|
||||
schema: {
|
||||
description: "Access PAM account",
|
||||
body: z.object({
|
||||
accountId: z.string().uuid(),
|
||||
accountPath: z.string().trim(),
|
||||
projectId: z.string().uuid(),
|
||||
duration: z
|
||||
.string()
|
||||
.min(1)
|
||||
@@ -151,7 +152,9 @@ export const registerPamAccountRouter = async (server: FastifyZodProvider) => {
|
||||
actorIp: req.realIp,
|
||||
actorName: `${req.auth.user.firstName ?? ""} ${req.auth.user.lastName ?? ""}`.trim(),
|
||||
actorUserAgent: req.auditLogInfo.userAgent ?? "",
|
||||
...req.body
|
||||
accountPath: req.body.accountPath,
|
||||
projectId: req.body.projectId,
|
||||
duration: req.body.duration
|
||||
},
|
||||
req.permission
|
||||
);
|
||||
@@ -163,7 +166,8 @@ export const registerPamAccountRouter = async (server: FastifyZodProvider) => {
|
||||
event: {
|
||||
type: EventType.PAM_ACCOUNT_ACCESS,
|
||||
metadata: {
|
||||
accountId: req.body.accountId,
|
||||
accountId: response.account.id,
|
||||
accountPath: req.body.accountPath,
|
||||
accountName: response.account.name,
|
||||
duration: req.body.duration ? new Date(req.body.duration).toISOString() : undefined
|
||||
}
|
||||
|
||||
@@ -4074,6 +4074,7 @@ interface PamAccountAccessEvent {
|
||||
type: EventType.PAM_ACCOUNT_ACCESS;
|
||||
metadata: {
|
||||
accountId: string;
|
||||
accountPath: string;
|
||||
accountName: string;
|
||||
duration?: string;
|
||||
};
|
||||
|
||||
@@ -487,7 +487,7 @@ export const pamAccountServiceFactory = ({
|
||||
};
|
||||
|
||||
const access = async (
|
||||
{ accountId, actorEmail, actorIp, actorName, actorUserAgent, duration }: TAccessAccountDTO,
|
||||
{ accountPath, projectId, actorEmail, actorIp, actorName, actorUserAgent, duration }: TAccessAccountDTO,
|
||||
actor: OrgServiceActor
|
||||
) => {
|
||||
const orgLicensePlan = await licenseService.getPlan(actor.orgId);
|
||||
@@ -497,8 +497,36 @@ export const pamAccountServiceFactory = ({
|
||||
});
|
||||
}
|
||||
|
||||
const account = await pamAccountDAL.findById(accountId);
|
||||
if (!account) throw new NotFoundError({ message: `Account with ID '${accountId}' not found` });
|
||||
const pathSegments: string[] = accountPath.split("/").filter(Boolean);
|
||||
if (pathSegments.length === 0) {
|
||||
throw new BadRequestError({ message: "Invalid accountPath. Path must contain at least the account name." });
|
||||
}
|
||||
|
||||
const accountName: string = pathSegments[pathSegments.length - 1] ?? "";
|
||||
const folderPathSegments: string[] = pathSegments.slice(0, -1);
|
||||
|
||||
const folderPath: string = folderPathSegments.length > 0 ? `/${folderPathSegments.join("/")}` : "/";
|
||||
|
||||
let folderId: string | null = null;
|
||||
if (folderPath !== "/") {
|
||||
const folder = await pamFolderDAL.findByPath(projectId, folderPath);
|
||||
if (!folder) {
|
||||
throw new NotFoundError({ message: `Folder at path '${folderPath}' not found` });
|
||||
}
|
||||
folderId = folder.id;
|
||||
}
|
||||
|
||||
const account = await pamAccountDAL.findOne({
|
||||
projectId,
|
||||
folderId,
|
||||
name: accountName
|
||||
});
|
||||
|
||||
if (!account) {
|
||||
throw new NotFoundError({
|
||||
message: `Account with name '${accountName}' not found at path '${accountPath}'`
|
||||
});
|
||||
}
|
||||
|
||||
const resource = await pamResourceDAL.findById(account.resourceId);
|
||||
if (!resource) throw new NotFoundError({ message: `Resource with ID '${account.resourceId}' not found` });
|
||||
@@ -508,22 +536,16 @@ export const pamAccountServiceFactory = ({
|
||||
actorAuthMethod: actor.authMethod,
|
||||
actorId: actor.id,
|
||||
actorOrgId: actor.orgId,
|
||||
projectId: account.projectId,
|
||||
projectId,
|
||||
actionProjectType: ActionProjectType.PAM
|
||||
});
|
||||
|
||||
const accountPath = await getFullPamFolderPath({
|
||||
pamFolderDAL,
|
||||
folderId: account.folderId,
|
||||
projectId: account.projectId
|
||||
});
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionPamAccountActions.Access,
|
||||
subject(ProjectPermissionSub.PamAccounts, {
|
||||
resourceName: resource.name,
|
||||
accountName: account.name,
|
||||
accountPath
|
||||
accountPath: folderPath
|
||||
})
|
||||
);
|
||||
|
||||
@@ -533,7 +555,7 @@ export const pamAccountServiceFactory = ({
|
||||
actorIp,
|
||||
actorName,
|
||||
actorUserAgent,
|
||||
projectId: account.projectId,
|
||||
projectId,
|
||||
resourceName: resource.name,
|
||||
resourceType: resource.resourceType,
|
||||
status: PamSessionStatus.Starting,
|
||||
@@ -542,11 +564,7 @@ export const pamAccountServiceFactory = ({
|
||||
expiresAt: new Date(Date.now() + duration)
|
||||
});
|
||||
|
||||
const { connectionDetails, gatewayId, resourceType } = await decryptResource(
|
||||
resource,
|
||||
account.projectId,
|
||||
kmsService
|
||||
);
|
||||
const { connectionDetails, gatewayId, resourceType } = await decryptResource(resource, projectId, kmsService);
|
||||
|
||||
const user = await userDAL.findById(actor.id);
|
||||
if (!user) throw new NotFoundError({ message: `User with ID '${actor.id}' not found` });
|
||||
@@ -578,20 +596,20 @@ export const pamAccountServiceFactory = ({
|
||||
const connectionCredentials = (await decryptResourceConnectionDetails({
|
||||
encryptedConnectionDetails: resource.encryptedConnectionDetails,
|
||||
kmsService,
|
||||
projectId: account.projectId
|
||||
projectId
|
||||
})) as TSqlResourceConnectionDetails;
|
||||
|
||||
const credentials = await decryptAccountCredentials({
|
||||
encryptedCredentials: account.encryptedCredentials,
|
||||
kmsService,
|
||||
projectId: account.projectId
|
||||
projectId
|
||||
});
|
||||
|
||||
metadata = {
|
||||
username: credentials.username,
|
||||
database: connectionCredentials.database,
|
||||
accountName: account.name,
|
||||
accountPath
|
||||
accountPath: folderPath
|
||||
};
|
||||
}
|
||||
break;
|
||||
@@ -600,7 +618,7 @@ export const pamAccountServiceFactory = ({
|
||||
const credentials = await decryptAccountCredentials({
|
||||
encryptedCredentials: account.encryptedCredentials,
|
||||
kmsService,
|
||||
projectId: account.projectId
|
||||
projectId
|
||||
});
|
||||
|
||||
metadata = {
|
||||
@@ -622,7 +640,7 @@ export const pamAccountServiceFactory = ({
|
||||
gatewayClientPrivateKey: gatewayConnectionDetails.gateway.clientPrivateKey,
|
||||
gatewayServerCertificateChain: gatewayConnectionDetails.gateway.serverCertificateChain,
|
||||
relayHost: gatewayConnectionDetails.relayHost,
|
||||
projectId: account.projectId,
|
||||
projectId,
|
||||
account,
|
||||
metadata
|
||||
};
|
||||
|
||||
@@ -14,7 +14,8 @@ export type TUpdateAccountDTO = Partial<Omit<TCreateAccountDTO, "folderId" | "re
|
||||
};
|
||||
|
||||
export type TAccessAccountDTO = {
|
||||
accountId: string;
|
||||
accountPath: string;
|
||||
projectId: string;
|
||||
actorEmail: string;
|
||||
actorIp: string;
|
||||
actorName: string;
|
||||
|
||||
Reference in New Issue
Block a user