Update permission implementation for ST V3

This commit is contained in:
Tuan Dang
2023-09-30 12:52:35 +01:00
parent d723d26d2e
commit 3779209ed5
12 changed files with 96 additions and 40 deletions

View File

@@ -110,14 +110,14 @@ export const getSecretsRaw = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ, Permission.READ_WRITE]
requiredPermissions: [Permission.READ]
});
permissionCheckFn = (env: string, secPath: string) =>
isValidScopeV3({
authPayload: req.authData.authPayload as IServiceTokenDataV3,
environment: env,
secretPath: secPath,
acceptedPermissions: [Permission.READ, Permission.READ_WRITE]
requiredPermissions: [Permission.READ]
});
break;
}
@@ -213,7 +213,7 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ, Permission.READ_WRITE]
requiredPermissions: [Permission.READ]
});
break;
}
@@ -285,7 +285,7 @@ export const createSecretRaw = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}
@@ -384,7 +384,7 @@ export const updateSecretByNameRaw = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}
@@ -464,7 +464,7 @@ export const deleteSecretByNameRaw = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}
@@ -559,14 +559,14 @@ export const getSecrets = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ, Permission.READ_WRITE]
requiredPermissions: [Permission.READ]
});
permissionCheckFn = (env: string, secPath: string) =>
isValidScopeV3({
authPayload: req.authData.authPayload as IServiceTokenDataV3,
environment: env,
secretPath: secPath,
acceptedPermissions: [Permission.READ, Permission.READ_WRITE]
requiredPermissions: [Permission.READ]
});
break;
}
@@ -644,7 +644,7 @@ export const getSecretByName = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ, Permission.READ_WRITE]
requiredPermissions: [Permission.READ]
});
break;
}
@@ -717,7 +717,7 @@ export const createSecret = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}
@@ -816,7 +816,7 @@ export const updateSecretByName = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}
@@ -892,7 +892,7 @@ export const deleteSecretByName = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}
@@ -950,7 +950,7 @@ export const createSecretByNameBatch = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}
@@ -999,7 +999,7 @@ export const updateSecretByNameBatch = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}
@@ -1048,7 +1048,7 @@ export const deleteSecretByNameBatch = async (req: Request, res: Response) => {
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath,
acceptedPermissions: [Permission.READ_WRITE]
requiredPermissions: [Permission.WRITE]
});
break;
}

View File

@@ -94,6 +94,7 @@ export const createServiceTokenData = async (req: Request, res: Response) => {
user,
workspace: new Types.ObjectId(workspaceId),
publicKey,
usageCount: 0,
scopes,
isActive,
expiresAt

View File

@@ -64,7 +64,7 @@ class EELicenseService {
secretVersioning: true,
pitRecovery: false,
ipAllowlisting: false,
rbac: true,
rbac: false,
customRateLimits: false,
customAlerts: false,
auditLogs: false,

View File

@@ -249,7 +249,8 @@ export const getAuthSTDPayload = async ({
isActive: true
},
{
lastUsed: new Date()
lastUsed: new Date(),
$inc: { usageCount: 1 }
},
{
new: true

View File

@@ -69,12 +69,12 @@ export const isValidScopeV3 = ({
authPayload,
environment,
secretPath,
acceptedPermissions
requiredPermissions
}: {
authPayload: IServiceTokenDataV3,
environment: string,
secretPath: string,
acceptedPermissions: Permission[]
requiredPermissions: Permission[]
}) => {
const { scopes } = authPayload;
@@ -84,7 +84,7 @@ export const isValidScopeV3 = ({
scope.environment === environment
);
if (validScope && !acceptedPermissions.includes(validScope.permission)) {
if (validScope && !requiredPermissions.every(permission => validScope.permissions.includes(permission))) {
return false;
}

View File

@@ -2,13 +2,13 @@ import { Document, Schema, Types, model } from "mongoose";
export enum Permission {
READ = "read",
READ_WRITE = "readWrite"
WRITE = "write"
}
export interface Scope {
environment: string;
secretPath: string;
permission: Permission;
permissions: Permission[];
}
export interface IServiceTokenDataV3 extends Document {
@@ -19,6 +19,7 @@ export interface IServiceTokenDataV3 extends Document {
publicKey: string;
isActive: boolean;
lastUsed?: Date;
usageCount: number;
expiresAt?: Date;
scopes: Array<Scope>;
}
@@ -51,6 +52,11 @@ const serviceTokenDataV3Schema = new Schema(
type: Date,
required: false
},
usageCount: {
type: Number,
default: 0,
required: true
},
expiresAt: {
type: Date,
required: false,
@@ -68,9 +74,10 @@ const serviceTokenDataV3Schema = new Schema(
default: "/",
required: true
},
permission: {
type: String,
enum: [Permission.READ, Permission.READ_WRITE],
permissions: {
type: [String],
enum: [Permission.READ, Permission.WRITE],
default: [Permission.READ],
required: true
}
}

View File

@@ -20,13 +20,13 @@ import { isValidScopeV3 } from "../helpers";
workspaceId,
environment,
secretPath = "/",
acceptedPermissions
requiredPermissions
}: {
serviceTokenData: IServiceTokenDataV3;
workspaceId: Types.ObjectId;
environment?: string;
secretPath?: string;
acceptedPermissions: Permission[];
requiredPermissions: Permission[];
}) => {
if (!serviceTokenData.workspace.equals(workspaceId)) {
@@ -41,7 +41,7 @@ import { isValidScopeV3 } from "../helpers";
authPayload: serviceTokenData,
environment,
secretPath,
acceptedPermissions
requiredPermissions
});
if (!isValid) throw UnauthorizedRequestError({
@@ -57,7 +57,7 @@ export const CreateServiceTokenV3 = z.object({
publicKey: z.string().trim(),
scopes: z
.object({
permission: z.enum(["read", "readWrite"]),
permissions: z.enum(["read", "write"]).array(),
environment: z.string().trim(),
secretPath: z.string().trim()
})
@@ -78,7 +78,7 @@ export const UpdateServiceTokenV3 = z.object({
isActive: z.boolean().optional(),
scopes: z
.object({
permission: z.enum(["read", "readWrite"]),
permissions: z.enum(["read", "write"]).array(),
environment: z.string().trim(),
secretPath: z.string().trim()
})