feat(secret-ref): removed migration field unset op, refactored service token scope check to a utility fn

This commit is contained in:
akhilmhdh
2023-07-06 20:01:46 +05:30
parent 5599132efe
commit 5aba0c60b8
4 changed files with 45 additions and 66 deletions

View File

@@ -1,6 +1,5 @@
import { Types } from "mongoose";
import { Request, Response } from "express";
import picomatch from "picomatch";
import { ISecret, Secret, ServiceTokenData } from "../../models";
import { IAction, SecretVersion } from "../../ee/models";
import {
@@ -33,6 +32,7 @@ import {
getFolderIdFromServiceToken,
searchByFolderId
} from "../../services/FolderService";
import { isValidScope } from "../../helpers/secrets";
/**
* Peform a batch of any specified CUD secret operations
@@ -74,16 +74,11 @@ export const batchSecrets = async (req: Request, res: Response) => {
}
if (req.authData.authPayload instanceof ServiceTokenData) {
const { scopes: tkScopes } = req.authData.authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
scope.environment === environment
);
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, secretPath);
// in service token when not giving secretpath folderid must be root
// this is to avoid giving folderid when service tokens are used
if ((!secretPath && folderId !== "root") || (secretPath && !validScope)) {
if ((!secretPath && folderId !== "root") || (secretPath && !isValidScopeAccess)) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
}
@@ -447,16 +442,15 @@ export const createSecrets = async (req: Request, res: Response) => {
}
if (req.authData.authPayload instanceof ServiceTokenData) {
const { scopes: tkScopes } = req.authData.authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch(secretPath || "/", scope.secretPath, { strictSlashes: false }) &&
scope.environment === environment
const isValidScopeAccess = isValidScope(
req.authData.authPayload,
environment,
secretPath || "/"
);
// in service token when not giving secretpath folderid must be root
// this is to avoid giving folderid when service tokens are used
if ((!secretPath && folderId !== "root") || (secretPath && !validScope)) {
if ((!secretPath && folderId !== "root") || (secretPath && !isValidScopeAccess)) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
}
@@ -704,17 +698,15 @@ export const getSecrets = async (req: Request, res: Response) => {
}
if (req.authData.authPayload instanceof ServiceTokenData) {
const { scopes: tkScopes } = req.authData.authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch((secretPath as string) || "/", scope.secretPath, {
strictSlashes: false
}) && scope.environment === environment
const isValidScopeAccess = isValidScope(
req.authData.authPayload,
environment,
(secretPath as string) || "/"
);
// in service token when not giving secretpath folderid must be root
// this is to avoid giving folderid when service tokens are used
if ((!secretPath && folderId !== "root") || (secretPath && !validScope)) {
if ((!secretPath && folderId !== "root") || (secretPath && !isValidScopeAccess)) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
}

View File

@@ -6,7 +6,13 @@ import {
GetSecretsParams,
UpdateSecretParams
} from "../interfaces/services/SecretService";
import { ISecret, Secret, SecretBlindIndexData, ServiceTokenData } from "../models";
import {
ISecret,
IServiceTokenData,
Secret,
SecretBlindIndexData,
ServiceTokenData
} from "../models";
import { SecretVersion } from "../ee/models";
import {
BadRequestError,
@@ -39,6 +45,21 @@ import { getAuthDataPayloadIdObj, getAuthDataPayloadUserObj } from "../utils/aut
import { getFolderIdFromServiceToken } from "../services/FolderService";
import picomatch from "picomatch";
export const isValidScope = (
authPayload: IServiceTokenData,
environment: string,
secretPath: string
) => {
const { scopes: tkScopes } = authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
scope.environment === environment
);
return Boolean(validScope);
};
/**
* Returns an object containing secret [secret] but with its value, key, comment decrypted.
*
@@ -306,14 +327,7 @@ export const createSecretHelper = async ({
// if using service token filter towards the folderId by secretpath
if (authData.authPayload instanceof ServiceTokenData) {
const { scopes: tkScopes } = authData.authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
scope.environment === environment
);
if (!validScope) {
if (!isValidScope(authData.authPayload, environment, secretPath)) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
}
@@ -459,14 +473,7 @@ export const getSecretsHelper = async ({
let secrets: ISecret[] = [];
// if using service token filter towards the folderId by secretpath
if (authData.authPayload instanceof ServiceTokenData) {
const { scopes: tkScopes } = authData.authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
scope.environment === environment
);
if (!validScope) {
if (!isValidScope(authData.authPayload, environment, secretPath)) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
}
@@ -562,14 +569,7 @@ export const getSecretHelper = async ({
let secret: ISecret | null = null;
// if using service token filter towards the folderId by secretpath
if (authData.authPayload instanceof ServiceTokenData) {
const { scopes: tkScopes } = authData.authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
scope.environment === environment
);
if (!validScope) {
if (!isValidScope(authData.authPayload, environment, secretPath)) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
}
@@ -671,14 +671,7 @@ export const updateSecretHelper = async ({
let secret: ISecret | null = null;
// if using service token filter towards the folderId by secretpath
if (authData.authPayload instanceof ServiceTokenData) {
const { scopes: tkScopes } = authData.authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
scope.environment === environment
);
if (!validScope) {
if (!isValidScope(authData.authPayload, environment, secretPath)) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
}
@@ -826,14 +819,7 @@ export const deleteSecretHelper = async ({
// if using service token filter towards the folderId by secretpath
if (authData.authPayload instanceof ServiceTokenData) {
const { scopes: tkScopes } = authData.authPayload;
const validScope = tkScopes.find(
(scope) =>
picomatch.isMatch(secretPath, scope.secretPath, { strictSlashes: false }) &&
scope.environment === environment
);
if (!validScope) {
if (!isValidScope(authData.authPayload, environment, secretPath)) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
}

View File

@@ -446,9 +446,6 @@ export const backfillServiceTokenMultiScope = async () => {
$set: {
scopes: [{ environment: "$environment", secretPath: "$secretPath" }]
}
},
{
$unset: ["environment", "secretPath"]
}
]
);

View File

@@ -292,7 +292,11 @@ func recursivelyExpandSecret(expandedSecs map[string]string, interpolatedSecs ma
return v
}
interpolatedVal := interpolatedSecs[key]
interpolatedVal, ok := interpolatedSecs[key]
if !ok {
HandleError(fmt.Errorf("Could not find refered secret - %s", key), "Kindly check whether its provided")
}
refs := secRefRegex.FindAllStringSubmatch(interpolatedVal, -1)
for _, val := range refs {
// key: "${something}" val: [${something},something]