mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-10 14:28:35 +00:00
Show only secret keys if write only access
This commit is contained in:
@@ -17,7 +17,7 @@ import { EESecretService, EELogService } from '../../ee/services';
|
|||||||
import { postHogClient } from '../../services';
|
import { postHogClient } from '../../services';
|
||||||
import { getChannelFromUserAgent } from '../../utils/posthog';
|
import { getChannelFromUserAgent } from '../../utils/posthog';
|
||||||
import { ABILITY_READ, ABILITY_WRITE } from '../../variables/organization';
|
import { ABILITY_READ, ABILITY_WRITE } from '../../variables/organization';
|
||||||
import { userHasWorkspaceAccess } from '../../ee/helpers/checkMembershipPermissions';
|
import { userHasNoAbility, userHasWorkspaceAccess, userHasWriteOnlyAbility } from '../../ee/helpers/checkMembershipPermissions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create secret(s) for workspace with id [workspaceId] and environment [environment]
|
* Create secret(s) for workspace with id [workspaceId] and environment [environment]
|
||||||
@@ -298,27 +298,42 @@ export const getSecrets = async (req: Request, res: Response) => {
|
|||||||
userEmail = req.serviceTokenData.user.email;
|
userEmail = req.serviceTokenData.user.email;
|
||||||
}
|
}
|
||||||
|
|
||||||
// none service token case as service tokens are already scoped
|
// none service token case as service tokens are already scoped to env and project
|
||||||
|
let hasWriteOnlyAccess
|
||||||
if (!req.serviceTokenData) {
|
if (!req.serviceTokenData) {
|
||||||
const hasAccess = await userHasWorkspaceAccess(userId, workspaceId, environment, ABILITY_READ)
|
hasWriteOnlyAccess = await userHasWriteOnlyAbility(userId, workspaceId, environment)
|
||||||
if (!hasAccess) {
|
const hasNoAccess = await userHasNoAbility(userId, workspaceId, environment)
|
||||||
|
if (hasNoAccess) {
|
||||||
throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" })
|
throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let secrets: any
|
||||||
const [err, secrets] = await to(Secret.find(
|
if (hasWriteOnlyAccess) {
|
||||||
{
|
secrets = await Secret.find(
|
||||||
workspace: workspaceId,
|
{
|
||||||
environment,
|
workspace: workspaceId,
|
||||||
$or: [
|
environment,
|
||||||
{ user: userId },
|
$or: [
|
||||||
{ user: { $exists: false } }
|
{ user: userId },
|
||||||
],
|
{ user: { $exists: false } }
|
||||||
type: { $in: [SECRET_SHARED, SECRET_PERSONAL] }
|
],
|
||||||
}
|
type: { $in: [SECRET_SHARED, SECRET_PERSONAL] }
|
||||||
).populate("tags").then())
|
}
|
||||||
|
)
|
||||||
if (err) throw ValidationError({ message: 'Failed to get secrets', stack: err.stack });
|
.select("secretKeyCiphertext secretKeyIV secretKeyTag")
|
||||||
|
} else {
|
||||||
|
secrets = await Secret.find(
|
||||||
|
{
|
||||||
|
workspace: workspaceId,
|
||||||
|
environment,
|
||||||
|
$or: [
|
||||||
|
{ user: userId },
|
||||||
|
{ user: { $exists: false } }
|
||||||
|
],
|
||||||
|
type: { $in: [SECRET_SHARED, SECRET_PERSONAL] }
|
||||||
|
}
|
||||||
|
).populate("tags")
|
||||||
|
}
|
||||||
|
|
||||||
const channel = getChannelFromUserAgent(req.headers['user-agent'])
|
const channel = getChannelFromUserAgent(req.headers['user-agent'])
|
||||||
|
|
||||||
@@ -356,6 +371,59 @@ export const getSecrets = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const getOnlySecretKeys = async (req: Request, res: Response) => {
|
||||||
|
const { workspaceId, environment } = req.query;
|
||||||
|
|
||||||
|
let userId = "" // used for getting personal secrets for user
|
||||||
|
let userEmail = "" // used for posthog
|
||||||
|
if (req.user) {
|
||||||
|
userId = req.user._id;
|
||||||
|
userEmail = req.user.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.serviceTokenData) {
|
||||||
|
userId = req.serviceTokenData.user._id
|
||||||
|
userEmail = req.serviceTokenData.user.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
// none service token case as service tokens are already scoped
|
||||||
|
if (!req.serviceTokenData) {
|
||||||
|
const hasAccess = await userHasWorkspaceAccess(userId, workspaceId, environment, ABILITY_READ)
|
||||||
|
if (!hasAccess) {
|
||||||
|
throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [err, secretKeys] = await to(Secret.find(
|
||||||
|
{
|
||||||
|
workspace: workspaceId,
|
||||||
|
environment,
|
||||||
|
$or: [
|
||||||
|
{ user: userId },
|
||||||
|
{ user: { $exists: false } }
|
||||||
|
],
|
||||||
|
type: { $in: [SECRET_SHARED, SECRET_PERSONAL] }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.select("secretKeyIV secretKeyTag secretKeyCiphertext")
|
||||||
|
.then())
|
||||||
|
|
||||||
|
if (err) throw ValidationError({ message: 'Failed to get secrets', stack: err.stack });
|
||||||
|
|
||||||
|
// readAction && await EELogService.createLog({
|
||||||
|
// userId: new Types.ObjectId(userId),
|
||||||
|
// workspaceId: new Types.ObjectId(workspaceId as string),
|
||||||
|
// actions: [readAction],
|
||||||
|
// channel,
|
||||||
|
// ipAddress: req.ip
|
||||||
|
// });
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
secretKeys
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update secret(s)
|
* Update secret(s)
|
||||||
* @param req
|
* @param req
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { Membership } from "../../models";
|
import { Membership } from "../../models";
|
||||||
|
import { ABILITY_READ, ABILITY_WRITE } from "../../variables/organization";
|
||||||
|
|
||||||
export const userHasWorkspaceAccess = async (userId: any, workspaceId: any, environment: any, action: any) => {
|
export const userHasWorkspaceAccess = async (userId: any, workspaceId: any, environment: any, action: any) => {
|
||||||
const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId })
|
const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId })
|
||||||
@@ -16,3 +17,38 @@ export const userHasWorkspaceAccess = async (userId: any, workspaceId: any, envi
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const userHasWriteOnlyAbility = async (userId: any, workspaceId: any, environment: any) => {
|
||||||
|
const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId })
|
||||||
|
if (!membershipForWorkspace) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const deniedMembershipPermissions = membershipForWorkspace.deniedPermissions;
|
||||||
|
const isWriteDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: ABILITY_WRITE });
|
||||||
|
const isReadDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: ABILITY_READ });
|
||||||
|
|
||||||
|
// case: you have write only if read is blocked and write is not
|
||||||
|
if (isReadDisallowed && !isWriteDisallowed) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
export const userHasNoAbility = async (userId: any, workspaceId: any, environment: any) => {
|
||||||
|
const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId })
|
||||||
|
if (!membershipForWorkspace) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const deniedMembershipPermissions = membershipForWorkspace.deniedPermissions;
|
||||||
|
const isWriteDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: ABILITY_WRITE });
|
||||||
|
const isReadBlocked = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: ABILITY_READ });
|
||||||
|
|
||||||
|
if (isReadBlocked && isWriteDisallowed) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user