Add logging to MI secret endpoints

This commit is contained in:
Tuan Dang
2023-12-04 17:48:32 +07:00
parent 282830e7a2
commit c917cf8a18
5 changed files with 126 additions and 5 deletions
@@ -3,6 +3,7 @@ import crypto from "crypto";
import { Request, Response } from "express"; import { Request, Response } from "express";
import { Types } from "mongoose"; import { Types } from "mongoose";
import { import {
IMachineIdentity,
IMachineIdentityClientSecretData, IMachineIdentityClientSecretData,
IMachineIdentityTrustedIp, IMachineIdentityTrustedIp,
MachineIdentity, MachineIdentity,
@@ -12,6 +13,7 @@ import {
Organization, Organization,
} from "../../../models"; } from "../../../models";
import { import {
ActorType,
EventType, EventType,
Role Role
} from "../../models"; } from "../../models";
@@ -34,6 +36,7 @@ import {
} from "../../services/RoleService"; } from "../../services/RoleService";
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { checkIPAgainstBlocklist } from "../../../utils/ip"; import { checkIPAgainstBlocklist } from "../../../utils/ip";
import { getUserAgentType } from "../../../utils/posthog";
const packageClientSecretData = (clientSecretData: IMachineIdentityClientSecretData) => ({ const packageClientSecretData = (clientSecretData: IMachineIdentityClientSecretData) => ({
_id: clientSecretData._id, _id: clientSecretData._id,
@@ -60,7 +63,7 @@ export const getMIClientSecrets = async (req: Request, res: Response) => {
const machineMembershipOrg = await MachineMembershipOrg.findOne({ const machineMembershipOrg = await MachineMembershipOrg.findOne({
machineIdentity: new Types.ObjectId(machineId) machineIdentity: new Types.ObjectId(machineId)
}); }).populate<{ machineIdentity: IMachineIdentity }>("machineIdentity");
if (!machineMembershipOrg) throw ResourceNotFoundError(); if (!machineMembershipOrg) throw ResourceNotFoundError();
@@ -85,6 +88,20 @@ export const getMIClientSecrets = async (req: Request, res: Response) => {
}) })
.sort({ createdAt: -1 }) .sort({ createdAt: -1 })
.limit(5); .limit(5);
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.GET_MACHINE_IDENTITY_CLIENT_SECRETS,
metadata: {
machineId: machineMembershipOrg.machineIdentity._id.toString(),
clientId: machineMembershipOrg.machineIdentity.clientId,
}
},
{
organizationId: machineMembershipOrg.organization
}
);
return res.status(200).send({ return res.status(200).send({
clientSecretData: clientSecretData.map((clientSecretDatum) => packageClientSecretData(clientSecretDatum)) clientSecretData: clientSecretData.map((clientSecretDatum) => packageClientSecretData(clientSecretDatum))
@@ -110,7 +127,7 @@ export const createMIClientSecret = async (req: Request, res: Response) => {
const machineMembershipOrg = await MachineMembershipOrg.findOne({ const machineMembershipOrg = await MachineMembershipOrg.findOne({
machineIdentity: new Types.ObjectId(machineId) machineIdentity: new Types.ObjectId(machineId)
}); }).populate<{ machineIdentity: IMachineIdentity }>("machineIdentity");
if (!machineMembershipOrg) throw ResourceNotFoundError(); if (!machineMembershipOrg) throw ResourceNotFoundError();
@@ -147,6 +164,21 @@ export const createMIClientSecret = async (req: Request, res: Response) => {
accessTokenVersion: 1, accessTokenVersion: 1,
expiresAt expiresAt
}).save(); }).save();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_MACHINE_IDENTITY_CLIENT_SECRET,
metadata: {
machineId: machineMembershipOrg.machineIdentity._id.toString(),
clientId: machineMembershipOrg.machineIdentity.clientId,
clientSecretId: machineIdentityClientSecretData._id.toString()
}
},
{
organizationId: machineMembershipOrg.organization
}
);
return res.status(200).send({ return res.status(200).send({
clientSecret, clientSecret,
@@ -169,7 +201,7 @@ export const deleteMIClientSecret = async (req: Request, res: Response) => {
const machineMembershipOrg = await MachineMembershipOrg.findOne({ const machineMembershipOrg = await MachineMembershipOrg.findOne({
machineIdentity: new Types.ObjectId(machineId) machineIdentity: new Types.ObjectId(machineId)
}); }).populate<{ machineIdentity: IMachineIdentity }>("machineIdentity");
if (!machineMembershipOrg) throw ResourceNotFoundError(); if (!machineMembershipOrg) throw ResourceNotFoundError();
@@ -194,6 +226,21 @@ export const deleteMIClientSecret = async (req: Request, res: Response) => {
if (!clientSecretData) throw ResourceNotFoundError(); if (!clientSecretData) throw ResourceNotFoundError();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.DELETE_MACHINE_IDENTITY_CLIENT_SECRET,
metadata: {
machineId: machineMembershipOrg.machineIdentity._id.toString(),
clientId: machineMembershipOrg.machineIdentity.clientId,
clientSecretId: clientSecretId
}
},
{
organizationId: machineMembershipOrg.organization
}
);
return res.status(200).send({ return res.status(200).send({
clientSecretData: packageClientSecretData(clientSecretData) clientSecretData: packageClientSecretData(clientSecretData)
}) })
@@ -306,6 +353,35 @@ export const loginMI = async (req: Request, res: Response) => {
secret: await getAuthSecret() secret: await getAuthSecret()
}); });
const userAgent = req.headers["user-agent"] ?? "";
await EEAuditLogService.createAuditLog(
{
actor: {
type: ActorType.MACHINE,
metadata: {
machineId: machineIdentity._id.toString(),
name: machineIdentity.name
}
},
authPayload: machineIdentity,
ipAddress: req.realIP,
userAgent,
userAgentType: getUserAgentType(userAgent)
},
{
type: EventType.LOGIN_MACHINE_IDENTITY,
metadata: {
machineId: machineIdentity._id.toString(),
clientId,
clientSecretId: validatedClientSecretDatum._id.toString()
}
},
{
organizationId: machineIdentity.organization
}
);
return res.status(200).send({ return res.status(200).send({
accessToken, accessToken,
expiresIn: machineIdentity.accessTokenTTL, expiresIn: machineIdentity.accessTokenTTL,
+4
View File
@@ -34,6 +34,10 @@ export enum EventType {
CREATE_MACHINE_IDENTITY = "create-machine-identity", CREATE_MACHINE_IDENTITY = "create-machine-identity",
UPDATE_MACHINE_IDENTITY = "update-machine-identity", UPDATE_MACHINE_IDENTITY = "update-machine-identity",
DELETE_MACHINE_IDENTITY = "delete-machine-identity", DELETE_MACHINE_IDENTITY = "delete-machine-identity",
LOGIN_MACHINE_IDENTITY = "login-machine-identity",
CREATE_MACHINE_IDENTITY_CLIENT_SECRET = "create-machine-identity-secret",
DELETE_MACHINE_IDENTITY_CLIENT_SECRET = "delete-machine-identity-secret",
GET_MACHINE_IDENTITY_CLIENT_SECRETS = "get-machine-identity-secrets",
CREATE_ENVIRONMENT = "create-environment", CREATE_ENVIRONMENT = "create-environment",
UPDATE_ENVIRONMENT = "update-environment", UPDATE_ENVIRONMENT = "update-environment",
DELETE_ENVIRONMENT = "delete-environment", DELETE_ENVIRONMENT = "delete-environment",
+41
View File
@@ -225,6 +225,8 @@ interface DeleteServiceTokenEvent {
}; };
} }
// TODO: review all logging for MIs including params etc.
interface CreateMachineIdentityEvent { interface CreateMachineIdentityEvent {
type: EventType.CREATE_MACHINE_IDENTITY; type: EventType.CREATE_MACHINE_IDENTITY;
metadata: { metadata: {
@@ -257,6 +259,41 @@ interface DeleteMachineIdentityEvent {
}; };
} }
interface LoginMachineIdentityEvent {
type: EventType.LOGIN_MACHINE_IDENTITY ;
metadata: {
machineId: string;
clientId: string;
clientSecretId: string;
};
}
interface CreateMachineIdentitySecretEvent {
type: EventType.CREATE_MACHINE_IDENTITY_CLIENT_SECRET ;
metadata: {
machineId: string;
clientId: string;
clientSecretId: string;
};
}
interface DeleteMachineIdentitySecretEvent {
type: EventType.DELETE_MACHINE_IDENTITY_CLIENT_SECRET ;
metadata: {
machineId: string;
clientId: string;
clientSecretId: string;
};
}
interface GetMachineIdentitySecretsEvent {
type: EventType.GET_MACHINE_IDENTITY_CLIENT_SECRETS ;
metadata: {
machineId: string;
clientId: string;
};
}
interface CreateEnvironmentEvent { interface CreateEnvironmentEvent {
type: EventType.CREATE_ENVIRONMENT; type: EventType.CREATE_ENVIRONMENT;
metadata: { metadata: {
@@ -502,6 +539,10 @@ export type Event =
| CreateMachineIdentityEvent | CreateMachineIdentityEvent
| UpdateMachineIdentityEvent | UpdateMachineIdentityEvent
| DeleteMachineIdentityEvent | DeleteMachineIdentityEvent
| CreateMachineIdentitySecretEvent
| DeleteMachineIdentitySecretEvent
| LoginMachineIdentityEvent
| GetMachineIdentitySecretsEvent
| CreateEnvironmentEvent | CreateEnvironmentEvent
| UpdateEnvironmentEvent | UpdateEnvironmentEvent
| DeleteEnvironmentEvent | DeleteEnvironmentEvent
@@ -29,7 +29,7 @@ export const MembersPage = withPermission(
<div className="flex items-center"> <div className="flex items-center">
<p>App Clients</p> <p>App Clients</p>
<div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default"> <div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
Beta New
</div> </div>
</div> </div>
</Tab> </Tab>
@@ -34,7 +34,7 @@ export const MembersPage = withProjectPermission(
<div className="flex items-center"> <div className="flex items-center">
<p>App Clients</p> <p>App Clients</p>
<div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default"> <div className="ml-2 rounded-md text-yellow text-sm inline-block bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] opacity-80 hover:opacity-100 cursor-default">
Beta New
</div> </div>
</div> </div>
</Tab> </Tab>