Merge remote-tracking branch 'origin' into improve-service-accounts

This commit is contained in:
Tuan Dang
2023-04-12 22:41:41 +03:00
16 changed files with 824 additions and 95 deletions
+52 -50
View File
@@ -550,7 +550,10 @@ export const getSecrets = async (req: Request, res: Response) => {
const workspaceId = req.query.workspaceId as string;
const environment = req.query.environment as string;
// tags logic
// secrets to return
let secrets: ISecret[] = [];
// query tags table to get all tags ids for the tag names for the given workspace
let tagIds = [];
const tagNamesList = typeof tagSlugs === 'string' && tagSlugs !== '' ? tagSlugs.split(',') : [];
if (tagNamesList != undefined && tagNamesList.length != 0) {
@@ -561,71 +564,70 @@ export const getSecrets = async (req: Request, res: Response) => {
});
}
let secrets: ISecret[] = [];
if (req.user) {
// case: client authorization is via JWT
let hasWriteOnlyAccess
if (!req.serviceTokenData) {
hasWriteOnlyAccess = await userHasWriteOnlyAbility(req.user._id, new Types.ObjectId(workspaceId), environment)
const hasNoAccess = await userHasNoAbility(req.user._id, new Types.ObjectId(workspaceId), environment)
if (hasNoAccess) {
throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" })
}
const hasWriteOnlyAccess = await userHasWriteOnlyAbility(req.user._id, new Types.ObjectId(workspaceId), environment)
const hasNoAccess = await userHasNoAbility(req.user._id, new Types.ObjectId(workspaceId), environment)
if (hasNoAccess) {
throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" })
}
let secretQuery: any;
if (tagNamesList != undefined && tagNamesList.length != 0) {
const workspaceFromDB = await Tag.find({ workspace: workspaceId })
const secretQuery: any = {
workspace: workspaceId,
environment,
$or: [
{ user: req.user._id }, // personal secrets for this user
{ user: { $exists: false } } // shared secrets from workspace
]
}
const tagIds = _.map(tagNamesList, (tagName) => {
const tag = _.find(workspaceFromDB, { slug: tagName });
return tag ? tag.id : null;
});
secretQuery = {
workspace: workspaceId,
environment,
$or: [
{ user: req.user._id },
{ user: { $exists: false } }
],
tags: { $in: tagIds },
type: { $in: [SECRET_SHARED, SECRET_PERSONAL] }
}
} else {
secretQuery = {
workspace: workspaceId,
environment,
$or: [
{ user: req.user._id },
{ user: { $exists: false } }
],
type: { $in: [SECRET_SHARED, SECRET_PERSONAL] }
}
if (tagIds.length > 0) {
secretQuery.tags = { $in: tagIds };
}
if (hasWriteOnlyAccess) {
// (i.e. you don't get values to decrypt since you can only write)
// only return the secret keys and not the values since user does not have right to see values
secrets = await Secret.find(secretQuery).select("secretKeyCiphertext secretKeyIV secretKeyTag").populate("tags")
} else {
secrets = await Secret.find(secretQuery).populate("tags")
}
}
if (req.serviceAccount || req.serviceTokenData) {
// case: client authorization is either via service account or service token
// case: client authorization is via service token
if (req.serviceTokenData) {
const userId = req.serviceTokenData.user._id
secrets = await Secret.find({
workspace: new Types.ObjectId(workspaceId),
const secretQuery: any = {
workspace: workspaceId,
environment,
user: {
$exists: false
},
...(tagIds.length > 0 ? { tags: { $in: tagIds } } : {}),
type: SECRET_SHARED
}).populate("tags");
$or: [
{ user: userId }, // personal secrets for this user
{ user: { $exists: false } } // shared secrets from workspace
]
}
if (tagIds.length > 0) {
secretQuery.tags = { $in: tagIds };
}
// TODO check if service token has write only permission
secrets = await Secret.find(secretQuery).populate("tags");
}
// case: client authorization is via service account
if (req.serviceAccount) {
const secretQuery: any = {
workspace: workspaceId,
environment,
user: { $exists: false } // shared secrets only from workspace
}
if (tagIds.length > 0) {
secretQuery.tags = { $in: tagIds };
}
secrets = await Secret.find(secretQuery).populate("tags");
}
const channel = getChannelFromUserAgent(req.headers['user-agent'])
+12 -4
View File
@@ -15,7 +15,7 @@ const apiLimiter = rateLimit({
});
// 10 requests per minute
const authLimiter = rateLimit({
const authLimit = rateLimit({
windowMs: 60 * 1000,
max: 10,
standardHeaders: true,
@@ -36,8 +36,16 @@ const passwordLimiter = rateLimit({
}
});
export {
apiLimiter,
const authLimiter = (req: any, res: any, next: any) => {
if (process.env.NODE_ENV === 'production') {
authLimit(req, res, next);
} else {
next();
}
};
export {
apiLimiter,
authLimiter,
passwordLimiter
passwordLimiter
};
+13 -13
View File
@@ -48,18 +48,18 @@ import {
integrationAuth as v1IntegrationAuthRouter
} from './routes/v1';
import {
signup as v2SignupRouter,
auth as v2AuthRouter,
users as v2UsersRouter,
organizations as v2OrganizationsRouter,
workspace as v2WorkspaceRouter,
secret as v2SecretRouter, // begin to phase out
secrets as v2SecretsRouter,
serviceTokenData as v2ServiceTokenDataRouter,
serviceAccounts as v2ServiceAccountsRouter,
apiKeyData as v2APIKeyDataRouter,
environment as v2EnvironmentRouter,
tags as v2TagsRouter,
signup as v2SignupRouter,
auth as v2AuthRouter,
users as v2UsersRouter,
organizations as v2OrganizationsRouter,
workspace as v2WorkspaceRouter,
secret as v2SecretRouter, // begin to phase out
secrets as v2SecretsRouter,
serviceTokenData as v2ServiceTokenDataRouter,
serviceAccounts as v2ServiceAccountsRouter,
apiKeyData as v2APIKeyDataRouter,
environment as v2EnvironmentRouter,
tags as v2TagsRouter,
} from './routes/v2';
import { healthCheck } from './routes/status';
import { getLogger } from './utils/logger';
@@ -172,7 +172,7 @@ const main = async () => {
getLogger("backend-main").info(`Server started listening at port ${getPort()}`)
});
createTestUserForDevelopment();
await createTestUserForDevelopment();
setUpHealthEndpoint(server);
server.on('close', async () => {
+11 -10
View File
@@ -8,17 +8,18 @@ import { Key, Membership, MembershipOrg, Organization, User, Workspace } from ".
import { Types } from 'mongoose';
import { getNodeEnv } from '../config';
export const createTestUserForDevelopment = async () => {
if (getNodeEnv() === "development") {
const testUserEmail = "[email protected]"
const testUserPassword = "testInfisical1"
const testUserId = "63cefa6ec8d3175601cfa980"
const testWorkspaceId = "63cefb15c8d3175601cfa989"
const testOrgId = "63cefb15c8d3175601cfa985"
const testMembershipId = "63cefb159185d9aa3ef0cf35"
const testMembershipOrgId = "63cefb159185d9aa3ef0cf31"
const testWorkspaceKeyId = "63cf48f0225e6955acec5eff"
export const testUserEmail = "[email protected]"
export const testUserPassword = "testInfisical1"
export const testUserId = "63cefa6ec8d3175601cfa980"
export const testWorkspaceId = "63cefb15c8d3175601cfa989"
export const testOrgId = "63cefb15c8d3175601cfa985"
export const testMembershipId = "63cefb159185d9aa3ef0cf35"
export const testMembershipOrgId = "63cefb159185d9aa3ef0cf31"
export const testWorkspaceKeyId = "63cf48f0225e6955acec5eff"
export const plainTextWorkspaceKey = "543fef8224813a46230b0a50a46c5fb2"
export const createTestUserForDevelopment = async () => {
if (getNodeEnv() === "development" || getNodeEnv() === "test") {
const testUser = {
_id: testUserId,
email: testUserEmail,