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