diff --git a/backend/src/controllers/v2/secretsController.ts b/backend/src/controllers/v2/secretsController.ts index 8307d373d..b93846e70 100644 --- a/backend/src/controllers/v2/secretsController.ts +++ b/backend/src/controllers/v2/secretsController.ts @@ -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" }); } } diff --git a/backend/src/helpers/secrets.ts b/backend/src/helpers/secrets.ts index cd964fe9f..1a68930bc 100644 --- a/backend/src/helpers/secrets.ts +++ b/backend/src/helpers/secrets.ts @@ -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" }); } } diff --git a/backend/src/utils/setup/backfillData.ts b/backend/src/utils/setup/backfillData.ts index 98dcad90e..801a75e6f 100644 --- a/backend/src/utils/setup/backfillData.ts +++ b/backend/src/utils/setup/backfillData.ts @@ -446,9 +446,6 @@ export const backfillServiceTokenMultiScope = async () => { $set: { scopes: [{ environment: "$environment", secretPath: "$secretPath" }] } - }, - { - $unset: ["environment", "secretPath"] } ] ); diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index 309b17631..80d51fcf5 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -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]