mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge pull request #1284 from Infisical/multi-integration-auth
Enable new integration auth credential for each new integration
This commit is contained in:
@@ -2,7 +2,7 @@ import { Request, Response } from "express";
|
||||
import { Types } from "mongoose";
|
||||
import { standardRequest } from "../../config/request";
|
||||
import { getApps, getTeams, revokeAccess } from "../../integrations";
|
||||
import { Bot, IntegrationAuth, Workspace } from "../../models";
|
||||
import { Bot, IIntegrationAuth, Integration, IntegrationAuth, Workspace } from "../../models";
|
||||
import { EventType } from "../../ee/models";
|
||||
import { IntegrationService } from "../../services";
|
||||
import { EEAuditLogService } from "../../ee/services";
|
||||
@@ -130,7 +130,6 @@ export const oAuthExchange = async (req: Request, res: Response) => {
|
||||
export const saveIntegrationToken = async (req: Request, res: Response) => {
|
||||
// TODO: refactor
|
||||
// TODO: check if access token is valid for each integration
|
||||
let integrationAuth;
|
||||
const {
|
||||
body: { workspaceId, integration, url, accessId, namespace, accessToken, refreshToken }
|
||||
} = await validateRequest(reqValidator.SaveIntegrationAccessTokenV1, req);
|
||||
@@ -152,31 +151,21 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
|
||||
|
||||
if (!bot) throw new Error("Bot must be enabled to save integration access token");
|
||||
|
||||
integrationAuth = await IntegrationAuth.findOneAndUpdate(
|
||||
{
|
||||
workspace: new Types.ObjectId(workspaceId),
|
||||
integration
|
||||
},
|
||||
{
|
||||
workspace: new Types.ObjectId(workspaceId),
|
||||
integration,
|
||||
url,
|
||||
namespace,
|
||||
algorithm: ALGORITHM_AES_256_GCM,
|
||||
keyEncoding: ENCODING_SCHEME_UTF8,
|
||||
...(integration === INTEGRATION_GCP_SECRET_MANAGER
|
||||
? {
|
||||
metadata: {
|
||||
authMethod: "serviceAccount"
|
||||
}
|
||||
let integrationAuth = await new IntegrationAuth({
|
||||
workspace: new Types.ObjectId(workspaceId),
|
||||
integration,
|
||||
url,
|
||||
namespace,
|
||||
algorithm: ALGORITHM_AES_256_GCM,
|
||||
keyEncoding: ENCODING_SCHEME_UTF8,
|
||||
...(integration === INTEGRATION_GCP_SECRET_MANAGER
|
||||
? {
|
||||
metadata: {
|
||||
authMethod: "serviceAccount"
|
||||
}
|
||||
: {})
|
||||
},
|
||||
{
|
||||
new: true,
|
||||
upsert: true
|
||||
}
|
||||
);
|
||||
}
|
||||
: {})
|
||||
}).save();
|
||||
|
||||
// encrypt and save integration access details
|
||||
if (refreshToken) {
|
||||
@@ -188,12 +177,12 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
|
||||
|
||||
// encrypt and save integration access details
|
||||
if (accessId || accessToken) {
|
||||
integrationAuth = await IntegrationService.setIntegrationAuthAccess({
|
||||
integrationAuth = (await IntegrationService.setIntegrationAuthAccess({
|
||||
integrationAuthId: integrationAuth._id.toString(),
|
||||
accessId,
|
||||
accessToken,
|
||||
accessExpiresAt: undefined
|
||||
});
|
||||
})) as IIntegrationAuth;
|
||||
}
|
||||
|
||||
if (!integrationAuth) throw new Error("Failed to save integration access token");
|
||||
@@ -1208,13 +1197,64 @@ export const getIntegrationAuthTeamCityBuildConfigs = async (req: Request, res:
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete all integration authorizations and integrations for workspace with id [workspaceId]
|
||||
* with integration name [integration]
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const deleteIntegrationAuths = async (req: Request, res: Response) => {
|
||||
const {
|
||||
query: { integration, workspaceId }
|
||||
} = await validateRequest(reqValidator.DeleteIntegrationAuthsV1, req);
|
||||
|
||||
const { permission } = await getAuthDataProjectPermissions({
|
||||
authData: req.authData,
|
||||
workspaceId: new Types.ObjectId(workspaceId)
|
||||
});
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Delete,
|
||||
ProjectPermissionSub.Integrations
|
||||
);
|
||||
|
||||
const integrationAuths = await IntegrationAuth.deleteMany({
|
||||
integration,
|
||||
workspace: new Types.ObjectId(workspaceId)
|
||||
});
|
||||
|
||||
const integrations = await Integration.deleteMany({
|
||||
integration,
|
||||
workspace: new Types.ObjectId(workspaceId)
|
||||
});
|
||||
|
||||
await EEAuditLogService.createAuditLog(
|
||||
req.authData,
|
||||
{
|
||||
type: EventType.UNAUTHORIZE_INTEGRATION,
|
||||
metadata: {
|
||||
integration
|
||||
}
|
||||
},
|
||||
{
|
||||
workspaceId: new Types.ObjectId(workspaceId)
|
||||
}
|
||||
);
|
||||
|
||||
return res.status(200).send({
|
||||
integrationAuths,
|
||||
integrations
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete integration authorization with id [integrationAuthId]
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns
|
||||
*/
|
||||
export const deleteIntegrationAuth = async (req: Request, res: Response) => {
|
||||
export const deleteIntegrationAuthById = async (req: Request, res: Response) => {
|
||||
const {
|
||||
params: { integrationAuthId }
|
||||
} = await validateRequest(reqValidator.DeleteIntegrationAuthV1, req);
|
||||
|
||||
@@ -251,6 +251,21 @@ export const deleteIntegration = async (req: Request, res: Response) => {
|
||||
});
|
||||
|
||||
if (!deletedIntegration) throw new Error("Failed to find integration");
|
||||
|
||||
const numOtherIntegrationsUsingSameAuth = await Integration.countDocuments({
|
||||
integrationAuth: deletedIntegration.integrationAuth,
|
||||
_id: {
|
||||
$nin: [deletedIntegration._id]
|
||||
}
|
||||
});
|
||||
|
||||
if (numOtherIntegrationsUsingSameAuth === 0) {
|
||||
// no other integrations are using the same integration auth
|
||||
// -> delete integration auth associated with the integration being deleted
|
||||
await IntegrationAuth.deleteOne({
|
||||
_id: deletedIntegration.integrationAuth
|
||||
});
|
||||
}
|
||||
|
||||
await EEAuditLogService.createAuditLog(
|
||||
req.authData,
|
||||
|
||||
@@ -156,12 +156,20 @@ router.get(
|
||||
integrationAuthController.getIntegrationAuthTeamCityBuildConfigs
|
||||
);
|
||||
|
||||
router.delete(
|
||||
"/",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT]
|
||||
}),
|
||||
integrationAuthController.deleteIntegrationAuths
|
||||
);
|
||||
|
||||
router.delete(
|
||||
"/:integrationAuthId",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT]
|
||||
}),
|
||||
integrationAuthController.deleteIntegrationAuth
|
||||
integrationAuthController.deleteIntegrationAuthById
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -192,6 +192,13 @@ export const GetIntegrationAuthNorthflankSecretGroupsV1 = z.object({
|
||||
})
|
||||
});
|
||||
|
||||
export const DeleteIntegrationAuthsV1 = z.object({
|
||||
query: z.object({
|
||||
integration: z.string().trim(),
|
||||
workspaceId: z.string().trim()
|
||||
})
|
||||
});
|
||||
|
||||
export const DeleteIntegrationAuthV1 = z.object({
|
||||
params: z.object({
|
||||
integrationAuthId: z.string().trim()
|
||||
|
||||
Reference in New Issue
Block a user