mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 01:52:22 +00:00
194 lines
5.4 KiB
TypeScript
194 lines
5.4 KiB
TypeScript
import { Request, Response } from "express";
|
|
import {
|
|
GitAppInstallationSession,
|
|
GitAppOrganizationInstallation,
|
|
GitRisks
|
|
} from "../../ee/models";
|
|
import crypto from "crypto";
|
|
import { Types } from "mongoose";
|
|
import { OrganizationNotFoundError, UnauthorizedRequestError } from "../../utils/errors";
|
|
import { scanGithubFullRepoForSecretLeaks } from "../../queues/secret-scanning/githubScanFullRepository";
|
|
import { getSecretScanningGitAppId, getSecretScanningPrivateKey } from "../../config";
|
|
import {
|
|
STATUS_RESOLVED_FALSE_POSITIVE,
|
|
STATUS_RESOLVED_NOT_REVOKED,
|
|
STATUS_RESOLVED_REVOKED
|
|
} from "../../ee/models/gitRisks";
|
|
import { ProbotOctokit } from "probot";
|
|
import { Organization } from "../../models";
|
|
import { validateRequest } from "../../helpers/validation";
|
|
import * as reqValidator from "../../validation/secretScanning";
|
|
import {
|
|
OrgPermissionActions,
|
|
OrgPermissionSubjects,
|
|
getAuthDataOrgPermissions
|
|
} from "../../ee/services/RoleService";
|
|
import { ForbiddenError } from "@casl/ability";
|
|
|
|
export const createInstallationSession = async (req: Request, res: Response) => {
|
|
const sessionId = crypto.randomBytes(16).toString("hex");
|
|
const {
|
|
params: { organizationId }
|
|
} = await validateRequest(reqValidator.CreateInstalLSessionv1, req);
|
|
|
|
const organization = await Organization.findById(organizationId);
|
|
if (!organization) {
|
|
throw OrganizationNotFoundError({
|
|
message: "Failed to find organization"
|
|
});
|
|
}
|
|
|
|
const { permission } = await getAuthDataOrgPermissions({
|
|
authData: req.authData,
|
|
organizationId: new Types.ObjectId(organizationId)
|
|
});
|
|
ForbiddenError.from(permission).throwUnlessCan(
|
|
OrgPermissionActions.Create,
|
|
OrgPermissionSubjects.SecretScanning
|
|
);
|
|
|
|
await GitAppInstallationSession.findByIdAndUpdate(
|
|
organization,
|
|
{
|
|
organization: organization.id,
|
|
sessionId: sessionId,
|
|
user: new Types.ObjectId(req.user._id)
|
|
},
|
|
{ upsert: true }
|
|
).lean();
|
|
|
|
res.send({
|
|
sessionId: sessionId
|
|
});
|
|
};
|
|
|
|
export const linkInstallationToOrganization = async (req: Request, res: Response) => {
|
|
const {
|
|
body: { sessionId, installationId }
|
|
} = await validateRequest(reqValidator.LinkInstallationToOrgv1, req);
|
|
|
|
const installationSession = await GitAppInstallationSession.findOneAndDelete({
|
|
sessionId: sessionId
|
|
});
|
|
if (!installationSession) {
|
|
throw UnauthorizedRequestError();
|
|
}
|
|
|
|
const { permission } = await getAuthDataOrgPermissions({
|
|
authData: req.authData,
|
|
organizationId: installationSession.organization
|
|
});
|
|
|
|
ForbiddenError.from(permission).throwUnlessCan(
|
|
OrgPermissionActions.Edit,
|
|
OrgPermissionSubjects.SecretScanning
|
|
);
|
|
|
|
const installationLink = await GitAppOrganizationInstallation.findOneAndUpdate(
|
|
{
|
|
organizationId: installationSession.organization
|
|
},
|
|
{
|
|
installationId: installationId,
|
|
organizationId: installationSession.organization,
|
|
user: installationSession.user
|
|
},
|
|
{
|
|
upsert: true
|
|
}
|
|
).lean();
|
|
|
|
const octokit = new ProbotOctokit({
|
|
auth: {
|
|
appId: await getSecretScanningGitAppId(),
|
|
privateKey: await getSecretScanningPrivateKey(),
|
|
installationId: installationId.toString()
|
|
}
|
|
});
|
|
|
|
const {
|
|
data: { repositories }
|
|
} = await octokit.apps.listReposAccessibleToInstallation();
|
|
for (const repository of repositories) {
|
|
scanGithubFullRepoForSecretLeaks({
|
|
organizationId: installationSession.organization.toString(),
|
|
installationId,
|
|
repository: { id: repository.id, fullName: repository.full_name }
|
|
});
|
|
}
|
|
res.json(installationLink);
|
|
};
|
|
|
|
export const getCurrentOrganizationInstallationStatus = async (req: Request, res: Response) => {
|
|
const { organizationId } = req.params;
|
|
try {
|
|
const appInstallation = await GitAppOrganizationInstallation.findOne({
|
|
organizationId: organizationId
|
|
}).lean();
|
|
if (!appInstallation) {
|
|
res.json({
|
|
appInstallationComplete: false
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
appInstallationComplete: true
|
|
});
|
|
} catch {
|
|
res.json({
|
|
appInstallationComplete: false
|
|
});
|
|
}
|
|
};
|
|
|
|
export const getRisksForOrganization = async (req: Request, res: Response) => {
|
|
const {
|
|
params: { organizationId }
|
|
} = await validateRequest(reqValidator.GetOrgRisksv1, req);
|
|
|
|
const { permission } = await getAuthDataOrgPermissions({
|
|
authData: req.authData,
|
|
organizationId: new Types.ObjectId(organizationId)
|
|
});
|
|
ForbiddenError.from(permission).throwUnlessCan(
|
|
OrgPermissionActions.Read,
|
|
OrgPermissionSubjects.SecretScanning
|
|
);
|
|
|
|
const risks = await GitRisks.find({ organization: organizationId })
|
|
.sort({ createdAt: -1 })
|
|
.lean();
|
|
res.json({
|
|
risks: risks
|
|
});
|
|
};
|
|
|
|
export const updateRisksStatus = async (req: Request, res: Response) => {
|
|
const {
|
|
params: { organizationId, riskId },
|
|
body: { status }
|
|
} = await validateRequest(reqValidator.UpdateRiskStatusv1, req);
|
|
|
|
const { permission } = await getAuthDataOrgPermissions({
|
|
authData: req.authData,
|
|
organizationId: new Types.ObjectId(organizationId)
|
|
});
|
|
ForbiddenError.from(permission).throwUnlessCan(
|
|
OrgPermissionActions.Edit,
|
|
OrgPermissionSubjects.SecretScanning
|
|
);
|
|
|
|
const isRiskResolved =
|
|
status == STATUS_RESOLVED_FALSE_POSITIVE ||
|
|
status == STATUS_RESOLVED_REVOKED ||
|
|
status == STATUS_RESOLVED_NOT_REVOKED
|
|
? true
|
|
: false;
|
|
const risk = await GitRisks.findByIdAndUpdate(riskId, {
|
|
status: status,
|
|
isResolved: isRiskResolved
|
|
}).lean();
|
|
|
|
res.json(risk);
|
|
};
|