mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
fix: resolved secret version empty
This commit is contained in:
@@ -54,23 +54,20 @@ export const getSecretVersions = async (req: Request, res: Response) => {
|
||||
}
|
||||
}
|
||||
*/
|
||||
const { secretId, workspaceId, environment, folderId } = req.params;
|
||||
const { secretId } = req.params;
|
||||
|
||||
const offset: number = parseInt(req.query.offset as string);
|
||||
const limit: number = parseInt(req.query.limit as string);
|
||||
|
||||
const secretVersions = await SecretVersion.find({
|
||||
secret: secretId,
|
||||
workspace: workspaceId,
|
||||
environment,
|
||||
folder: folderId,
|
||||
secret: secretId
|
||||
})
|
||||
.sort({ createdAt: -1 })
|
||||
.skip(offset)
|
||||
.limit(limit);
|
||||
|
||||
return res.status(200).send({
|
||||
secretVersions,
|
||||
secretVersions
|
||||
});
|
||||
};
|
||||
|
||||
@@ -135,7 +132,7 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
|
||||
// validate secret version
|
||||
const oldSecretVersion = await SecretVersion.findOne({
|
||||
secret: secretId,
|
||||
version,
|
||||
version
|
||||
}).select("+secretBlindIndex");
|
||||
|
||||
if (!oldSecretVersion) throw new Error("Failed to find secret version");
|
||||
@@ -154,7 +151,7 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
|
||||
secretValueTag,
|
||||
algorithm,
|
||||
folder,
|
||||
keyEncoding,
|
||||
keyEncoding
|
||||
} = oldSecretVersion;
|
||||
|
||||
// update secret
|
||||
@@ -162,7 +159,7 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
|
||||
secretId,
|
||||
{
|
||||
$inc: {
|
||||
version: 1,
|
||||
version: 1
|
||||
},
|
||||
workspace,
|
||||
type,
|
||||
@@ -177,10 +174,10 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
|
||||
secretValueTag,
|
||||
folderId: folder,
|
||||
algorithm,
|
||||
keyEncoding,
|
||||
keyEncoding
|
||||
},
|
||||
{
|
||||
new: true,
|
||||
new: true
|
||||
}
|
||||
);
|
||||
|
||||
@@ -204,17 +201,17 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
|
||||
secretValueTag,
|
||||
folder,
|
||||
algorithm,
|
||||
keyEncoding,
|
||||
keyEncoding
|
||||
}).save();
|
||||
|
||||
// take secret snapshot
|
||||
await EESecretService.takeSecretSnapshot({
|
||||
workspaceId: secret.workspace,
|
||||
environment,
|
||||
folderId: folder,
|
||||
folderId: folder
|
||||
});
|
||||
|
||||
return res.status(200).send({
|
||||
secret,
|
||||
secret
|
||||
});
|
||||
};
|
||||
|
||||
@@ -81,76 +81,79 @@ export const useGetProjectSecrets = ({
|
||||
enabled: Boolean(decryptFileKey && workspaceId && env) && !isPaused,
|
||||
queryKey: secretKeys.getProjectSecret(workspaceId, env, folderId),
|
||||
queryFn: () => fetchProjectEncryptedSecrets(workspaceId, env, folderId),
|
||||
select: useCallback((data: EncryptedSecret[]) => {
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
const latestKey = decryptFileKey;
|
||||
const key = decryptAssymmetric({
|
||||
ciphertext: latestKey.encryptedKey,
|
||||
nonce: latestKey.nonce,
|
||||
publicKey: latestKey.sender.publicKey,
|
||||
privateKey: PRIVATE_KEY
|
||||
});
|
||||
|
||||
const sharedSecrets: DecryptedSecret[] = [];
|
||||
const personalSecrets: Record<string, { id: string; value: string }> = {};
|
||||
// this used for add-only mode in dashboard
|
||||
// type won't be there thus only one key is shown
|
||||
const duplicateSecretKey: Record<string, boolean> = {};
|
||||
data.forEach((encSecret: EncryptedSecret) => {
|
||||
const secretKey = decryptSymmetric({
|
||||
ciphertext: encSecret.secretKeyCiphertext,
|
||||
iv: encSecret.secretKeyIV,
|
||||
tag: encSecret.secretKeyTag,
|
||||
key
|
||||
select: useCallback(
|
||||
(data: EncryptedSecret[]) => {
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
const latestKey = decryptFileKey;
|
||||
const key = decryptAssymmetric({
|
||||
ciphertext: latestKey.encryptedKey,
|
||||
nonce: latestKey.nonce,
|
||||
publicKey: latestKey.sender.publicKey,
|
||||
privateKey: PRIVATE_KEY
|
||||
});
|
||||
|
||||
const secretValue = decryptSymmetric({
|
||||
ciphertext: encSecret.secretValueCiphertext,
|
||||
iv: encSecret.secretValueIV,
|
||||
tag: encSecret.secretValueTag,
|
||||
key
|
||||
});
|
||||
const sharedSecrets: DecryptedSecret[] = [];
|
||||
const personalSecrets: Record<string, { id: string; value: string }> = {};
|
||||
// this used for add-only mode in dashboard
|
||||
// type won't be there thus only one key is shown
|
||||
const duplicateSecretKey: Record<string, boolean> = {};
|
||||
data.forEach((encSecret: EncryptedSecret) => {
|
||||
const secretKey = decryptSymmetric({
|
||||
ciphertext: encSecret.secretKeyCiphertext,
|
||||
iv: encSecret.secretKeyIV,
|
||||
tag: encSecret.secretKeyTag,
|
||||
key
|
||||
});
|
||||
|
||||
const secretComment = decryptSymmetric({
|
||||
ciphertext: encSecret.secretCommentCiphertext,
|
||||
iv: encSecret.secretCommentIV,
|
||||
tag: encSecret.secretCommentTag,
|
||||
key
|
||||
});
|
||||
const secretValue = decryptSymmetric({
|
||||
ciphertext: encSecret.secretValueCiphertext,
|
||||
iv: encSecret.secretValueIV,
|
||||
tag: encSecret.secretValueTag,
|
||||
key
|
||||
});
|
||||
|
||||
const decryptedSecret = {
|
||||
_id: encSecret._id,
|
||||
env: encSecret.environment,
|
||||
key: secretKey,
|
||||
value: secretValue,
|
||||
tags: encSecret.tags,
|
||||
comment: secretComment,
|
||||
createdAt: encSecret.createdAt,
|
||||
updatedAt: encSecret.updatedAt
|
||||
};
|
||||
const secretComment = decryptSymmetric({
|
||||
ciphertext: encSecret.secretCommentCiphertext,
|
||||
iv: encSecret.secretCommentIV,
|
||||
tag: encSecret.secretCommentTag,
|
||||
key
|
||||
});
|
||||
|
||||
if (encSecret.type === "personal") {
|
||||
personalSecrets[`${decryptedSecret.key}-${decryptedSecret.env}`] = {
|
||||
id: encSecret._id,
|
||||
value: secretValue
|
||||
const decryptedSecret = {
|
||||
_id: encSecret._id,
|
||||
env: encSecret.environment,
|
||||
key: secretKey,
|
||||
value: secretValue,
|
||||
tags: encSecret.tags,
|
||||
comment: secretComment,
|
||||
createdAt: encSecret.createdAt,
|
||||
updatedAt: encSecret.updatedAt
|
||||
};
|
||||
} else {
|
||||
if (!duplicateSecretKey?.[`${decryptedSecret.key}-${decryptedSecret.env}`]) {
|
||||
sharedSecrets.push(decryptedSecret);
|
||||
|
||||
if (encSecret.type === "personal") {
|
||||
personalSecrets[`${decryptedSecret.key}-${decryptedSecret.env}`] = {
|
||||
id: encSecret._id,
|
||||
value: secretValue
|
||||
};
|
||||
} else {
|
||||
if (!duplicateSecretKey?.[`${decryptedSecret.key}-${decryptedSecret.env}`]) {
|
||||
sharedSecrets.push(decryptedSecret);
|
||||
}
|
||||
duplicateSecretKey[`${decryptedSecret.key}-${decryptedSecret.env}`] = true;
|
||||
}
|
||||
duplicateSecretKey[`${decryptedSecret.key}-${decryptedSecret.env}`] = true;
|
||||
}
|
||||
});
|
||||
sharedSecrets.forEach((val) => {
|
||||
const dupKey = `${val.key}-${val.env}`;
|
||||
if (personalSecrets?.[dupKey]) {
|
||||
val.idOverride = personalSecrets[dupKey].id;
|
||||
val.valueOverride = personalSecrets[dupKey].value;
|
||||
val.overrideAction = "modified";
|
||||
}
|
||||
});
|
||||
return { secrets: sharedSecrets };
|
||||
}, [decryptFileKey])
|
||||
});
|
||||
sharedSecrets.forEach((val) => {
|
||||
const dupKey = `${val.key}-${val.env}`;
|
||||
if (personalSecrets?.[dupKey]) {
|
||||
val.idOverride = personalSecrets[dupKey].id;
|
||||
val.valueOverride = personalSecrets[dupKey].value;
|
||||
val.overrideAction = "modified";
|
||||
}
|
||||
});
|
||||
return { secrets: sharedSecrets };
|
||||
},
|
||||
[decryptFileKey]
|
||||
)
|
||||
});
|
||||
|
||||
export const useGetProjectSecretsByKey = ({
|
||||
@@ -167,82 +170,85 @@ export const useGetProjectSecretsByKey = ({
|
||||
// right now secretpath is passed as folderid as only this is used in overview
|
||||
queryKey: secretKeys.getProjectSecret(workspaceId, env, secretPath),
|
||||
queryFn: () => fetchProjectEncryptedSecrets(workspaceId, env, folderId, secretPath),
|
||||
select: useCallback((data: EncryptedSecret[]) => {
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
const latestKey = decryptFileKey;
|
||||
const key = decryptAssymmetric({
|
||||
ciphertext: latestKey.encryptedKey,
|
||||
nonce: latestKey.nonce,
|
||||
publicKey: latestKey.sender.publicKey,
|
||||
privateKey: PRIVATE_KEY
|
||||
});
|
||||
|
||||
const sharedSecrets: Record<string, DecryptedSecret[]> = {};
|
||||
const personalSecrets: Record<string, { id: string; value: string }> = {};
|
||||
// this used for add-only mode in dashboard
|
||||
// type won't be there thus only one key is shown
|
||||
const duplicateSecretKey: Record<string, boolean> = {};
|
||||
const uniqSecKeys: Record<string, boolean> = {};
|
||||
data.forEach((encSecret: EncryptedSecret) => {
|
||||
const secretKey = decryptSymmetric({
|
||||
ciphertext: encSecret.secretKeyCiphertext,
|
||||
iv: encSecret.secretKeyIV,
|
||||
tag: encSecret.secretKeyTag,
|
||||
key
|
||||
});
|
||||
if (!uniqSecKeys?.[secretKey]) uniqSecKeys[secretKey] = true;
|
||||
|
||||
const secretValue = decryptSymmetric({
|
||||
ciphertext: encSecret.secretValueCiphertext,
|
||||
iv: encSecret.secretValueIV,
|
||||
tag: encSecret.secretValueTag,
|
||||
key
|
||||
select: useCallback(
|
||||
(data: EncryptedSecret[]) => {
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
const latestKey = decryptFileKey;
|
||||
const key = decryptAssymmetric({
|
||||
ciphertext: latestKey.encryptedKey,
|
||||
nonce: latestKey.nonce,
|
||||
publicKey: latestKey.sender.publicKey,
|
||||
privateKey: PRIVATE_KEY
|
||||
});
|
||||
|
||||
const secretComment = decryptSymmetric({
|
||||
ciphertext: encSecret.secretCommentCiphertext,
|
||||
iv: encSecret.secretCommentIV,
|
||||
tag: encSecret.secretCommentTag,
|
||||
key
|
||||
});
|
||||
const sharedSecrets: Record<string, DecryptedSecret[]> = {};
|
||||
const personalSecrets: Record<string, { id: string; value: string }> = {};
|
||||
// this used for add-only mode in dashboard
|
||||
// type won't be there thus only one key is shown
|
||||
const duplicateSecretKey: Record<string, boolean> = {};
|
||||
const uniqSecKeys: Record<string, boolean> = {};
|
||||
data.forEach((encSecret: EncryptedSecret) => {
|
||||
const secretKey = decryptSymmetric({
|
||||
ciphertext: encSecret.secretKeyCiphertext,
|
||||
iv: encSecret.secretKeyIV,
|
||||
tag: encSecret.secretKeyTag,
|
||||
key
|
||||
});
|
||||
if (!uniqSecKeys?.[secretKey]) uniqSecKeys[secretKey] = true;
|
||||
|
||||
const decryptedSecret = {
|
||||
_id: encSecret._id,
|
||||
env: encSecret.environment,
|
||||
key: secretKey,
|
||||
value: secretValue,
|
||||
tags: encSecret.tags,
|
||||
comment: secretComment,
|
||||
createdAt: encSecret.createdAt,
|
||||
updatedAt: encSecret.updatedAt
|
||||
};
|
||||
const secretValue = decryptSymmetric({
|
||||
ciphertext: encSecret.secretValueCiphertext,
|
||||
iv: encSecret.secretValueIV,
|
||||
tag: encSecret.secretValueTag,
|
||||
key
|
||||
});
|
||||
|
||||
if (encSecret.type === "personal") {
|
||||
personalSecrets[`${decryptedSecret.key}-${decryptedSecret.env}`] = {
|
||||
id: encSecret._id,
|
||||
value: secretValue
|
||||
const secretComment = decryptSymmetric({
|
||||
ciphertext: encSecret.secretCommentCiphertext,
|
||||
iv: encSecret.secretCommentIV,
|
||||
tag: encSecret.secretCommentTag,
|
||||
key
|
||||
});
|
||||
|
||||
const decryptedSecret = {
|
||||
_id: encSecret._id,
|
||||
env: encSecret.environment,
|
||||
key: secretKey,
|
||||
value: secretValue,
|
||||
tags: encSecret.tags,
|
||||
comment: secretComment,
|
||||
createdAt: encSecret.createdAt,
|
||||
updatedAt: encSecret.updatedAt
|
||||
};
|
||||
} else {
|
||||
if (!duplicateSecretKey?.[`${decryptedSecret.key}-${decryptedSecret.env}`]) {
|
||||
if (!sharedSecrets?.[secretKey]) sharedSecrets[secretKey] = [];
|
||||
sharedSecrets[secretKey].push(decryptedSecret);
|
||||
}
|
||||
duplicateSecretKey[`${decryptedSecret.key}-${decryptedSecret.env}`] = true;
|
||||
}
|
||||
});
|
||||
Object.keys(sharedSecrets).forEach((secName) => {
|
||||
sharedSecrets[secName].forEach((val) => {
|
||||
const dupKey = `${val.key}-${val.env}`;
|
||||
if (personalSecrets?.[dupKey]) {
|
||||
val.idOverride = personalSecrets[dupKey].id;
|
||||
val.valueOverride = personalSecrets[dupKey].value;
|
||||
val.overrideAction = "modified";
|
||||
|
||||
if (encSecret.type === "personal") {
|
||||
personalSecrets[`${decryptedSecret.key}-${decryptedSecret.env}`] = {
|
||||
id: encSecret._id,
|
||||
value: secretValue
|
||||
};
|
||||
} else {
|
||||
if (!duplicateSecretKey?.[`${decryptedSecret.key}-${decryptedSecret.env}`]) {
|
||||
if (!sharedSecrets?.[secretKey]) sharedSecrets[secretKey] = [];
|
||||
sharedSecrets[secretKey].push(decryptedSecret);
|
||||
}
|
||||
duplicateSecretKey[`${decryptedSecret.key}-${decryptedSecret.env}`] = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
Object.keys(sharedSecrets).forEach((secName) => {
|
||||
sharedSecrets[secName].forEach((val) => {
|
||||
const dupKey = `${val.key}-${val.env}`;
|
||||
if (personalSecrets?.[dupKey]) {
|
||||
val.idOverride = personalSecrets[dupKey].id;
|
||||
val.valueOverride = personalSecrets[dupKey].value;
|
||||
val.overrideAction = "modified";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return { secrets: sharedSecrets, uniqueSecCount: Object.keys(uniqSecKeys).length };
|
||||
}, [decryptFileKey])
|
||||
return { secrets: sharedSecrets, uniqueSecCount: Object.keys(uniqSecKeys).length };
|
||||
},
|
||||
[decryptFileKey]
|
||||
)
|
||||
});
|
||||
|
||||
const fetchEncryptedSecretVersion = async (secretId: string, offset: number, limit: number) => {
|
||||
@@ -263,29 +269,32 @@ export const useGetSecretVersion = (dto: GetSecretVersionsDTO) =>
|
||||
enabled: Boolean(dto.secretId && dto.decryptFileKey),
|
||||
queryKey: secretKeys.getSecretVersion(dto.secretId),
|
||||
queryFn: () => fetchEncryptedSecretVersion(dto.secretId, dto.offset, dto.limit),
|
||||
select: useCallback((data: EncryptedSecretVersion[]) => {
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
const latestKey = dto.decryptFileKey;
|
||||
const key = decryptAssymmetric({
|
||||
ciphertext: latestKey.encryptedKey,
|
||||
nonce: latestKey.nonce,
|
||||
publicKey: latestKey.sender.publicKey,
|
||||
privateKey: PRIVATE_KEY
|
||||
});
|
||||
select: useCallback(
|
||||
(data: EncryptedSecretVersion[]) => {
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
const latestKey = dto.decryptFileKey;
|
||||
const key = decryptAssymmetric({
|
||||
ciphertext: latestKey.encryptedKey,
|
||||
nonce: latestKey.nonce,
|
||||
publicKey: latestKey.sender.publicKey,
|
||||
privateKey: PRIVATE_KEY
|
||||
});
|
||||
|
||||
return data
|
||||
.map((el) => ({
|
||||
createdAt: el.createdAt,
|
||||
id: el._id,
|
||||
value: decryptSymmetric({
|
||||
ciphertext: el.secretValueCiphertext,
|
||||
iv: el.secretValueIV,
|
||||
tag: el.secretValueTag,
|
||||
key
|
||||
})
|
||||
}))
|
||||
.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
||||
}, [])
|
||||
return data
|
||||
.map((el) => ({
|
||||
createdAt: el.createdAt,
|
||||
id: el._id,
|
||||
value: decryptSymmetric({
|
||||
ciphertext: el.secretValueCiphertext,
|
||||
iv: el.secretValueIV,
|
||||
tag: el.secretValueTag,
|
||||
key
|
||||
})
|
||||
}))
|
||||
.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
||||
},
|
||||
[dto.decryptFileKey]
|
||||
)
|
||||
});
|
||||
|
||||
export const useBatchSecretsOp = () => {
|
||||
|
||||
@@ -193,8 +193,8 @@ export const SecretDetailDrawer = ({
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-1.5 flex items-center space-x-2 border-l border-bunker-300 pl-4">
|
||||
<div className="rounded-sm bg-primary-500/30 px-1">Value:</div>
|
||||
<div className="font-mono">{value}</div>
|
||||
<div className="self-start rounded-sm bg-primary-500/30 px-1">Value:</div>
|
||||
<div className="break-all font-mono">{value}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user