mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 16:27:46 +00:00
fix: requested changes
This commit is contained in:
@@ -10,6 +10,11 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
t.string("encryptedValue").nullable().alter();
|
t.string("encryptedValue").nullable().alter();
|
||||||
|
|
||||||
t.binary("encryptedSecret").nullable();
|
t.binary("encryptedSecret").nullable();
|
||||||
|
t.string("hashedHex").nullable().alter();
|
||||||
|
|
||||||
|
t.string("identifier", 64).nullable();
|
||||||
|
t.unique("identifier");
|
||||||
|
t.index("identifier");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,11 +22,9 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
export async function down(knex: Knex): Promise<void> {
|
export async function down(knex: Knex): Promise<void> {
|
||||||
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
||||||
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
||||||
t.string("iv").notNullable().alter();
|
|
||||||
t.string("tag").notNullable().alter();
|
|
||||||
t.string("encryptedValue").notNullable().alter();
|
|
||||||
|
|
||||||
t.dropColumn("encryptedSecret");
|
t.dropColumn("encryptedSecret");
|
||||||
|
|
||||||
|
t.dropColumn("identifier");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
import { Knex } from "knex";
|
|
||||||
|
|
||||||
import { TableName } from "../schemas";
|
|
||||||
|
|
||||||
export async function up(knex: Knex): Promise<void> {
|
|
||||||
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
|
||||||
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
|
||||||
t.string("identifier", 36).nullable();
|
|
||||||
|
|
||||||
t.unique("identifier");
|
|
||||||
t.index("identifier");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function down(knex: Knex): Promise<void> {
|
|
||||||
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
|
||||||
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
|
||||||
// If rolled back, all secrets created with this new structure will stop working.
|
|
||||||
t.dropColumn("identifier");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@ export const SecretSharingSchema = z.object({
|
|||||||
encryptedValue: z.string().nullable().optional(),
|
encryptedValue: z.string().nullable().optional(),
|
||||||
iv: z.string().nullable().optional(),
|
iv: z.string().nullable().optional(),
|
||||||
tag: z.string().nullable().optional(),
|
tag: z.string().nullable().optional(),
|
||||||
hashedHex: z.string(),
|
hashedHex: z.string().nullable().optional(),
|
||||||
expiresAt: z.date(),
|
expiresAt: z.date(),
|
||||||
userId: z.string().uuid().nullable().optional(),
|
userId: z.string().uuid().nullable().optional(),
|
||||||
orgId: z.string().uuid().nullable().optional(),
|
orgId: z.string().uuid().nullable().optional(),
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export const registerSecretSharingRouter = async (server: FastifyZodProvider) =>
|
|||||||
id: z.string()
|
id: z.string()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
hashedHex: z.string().min(1),
|
hashedHex: z.string().min(1).optional(),
|
||||||
password: z.string().optional()
|
password: z.string().optional()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
|
|||||||
@@ -72,10 +72,7 @@ export const secretSharingServiceFactory = ({
|
|||||||
|
|
||||||
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
||||||
|
|
||||||
// This will be 36 characters long, due to encoding it to base64.
|
const id = crypto.randomBytes(32).toString("hex");
|
||||||
const id = crypto.randomBytes(27).toString("base64url");
|
|
||||||
|
|
||||||
const hashedHex = crypto.createHash("sha256").update(id).digest("base64url").substring(0, 13);
|
|
||||||
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
||||||
|
|
||||||
const newSharedSecret = await secretSharingDAL.create({
|
const newSharedSecret = await secretSharingDAL.create({
|
||||||
@@ -84,7 +81,6 @@ export const secretSharingServiceFactory = ({
|
|||||||
tag: null,
|
tag: null,
|
||||||
encryptedValue: null,
|
encryptedValue: null,
|
||||||
encryptedSecret,
|
encryptedSecret,
|
||||||
hashedHex,
|
|
||||||
name,
|
name,
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
expiresAt: new Date(expiresAt),
|
expiresAt: new Date(expiresAt),
|
||||||
@@ -94,7 +90,9 @@ export const secretSharingServiceFactory = ({
|
|||||||
accessType
|
accessType
|
||||||
});
|
});
|
||||||
|
|
||||||
return { id: `${newSharedSecret.identifier}${hashedHex}` };
|
const idToReturn = `${Buffer.from(newSharedSecret.identifier!, "hex").toString("base64url")}`;
|
||||||
|
|
||||||
|
return { id: idToReturn };
|
||||||
};
|
};
|
||||||
|
|
||||||
const createPublicSharedSecret = async ({
|
const createPublicSharedSecret = async ({
|
||||||
@@ -124,8 +122,7 @@ export const secretSharingServiceFactory = ({
|
|||||||
const encryptWithRoot = kmsService.encryptWithRootKey();
|
const encryptWithRoot = kmsService.encryptWithRootKey();
|
||||||
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
const encryptedSecret = encryptWithRoot(Buffer.from(secretValue));
|
||||||
|
|
||||||
const id = crypto.randomBytes(27).toString("base64url");
|
const id = crypto.randomBytes(32).toString("hex");
|
||||||
const hashedHex = crypto.createHash("sha256").update(id).digest("base64url").substring(0, 13);
|
|
||||||
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
const hashedPassword = password ? await bcrypt.hash(password, 10) : null;
|
||||||
|
|
||||||
const newSharedSecret = await secretSharingDAL.create({
|
const newSharedSecret = await secretSharingDAL.create({
|
||||||
@@ -133,16 +130,14 @@ export const secretSharingServiceFactory = ({
|
|||||||
encryptedValue: null,
|
encryptedValue: null,
|
||||||
iv: null,
|
iv: null,
|
||||||
tag: null,
|
tag: null,
|
||||||
hashedHex,
|
|
||||||
encryptedSecret,
|
encryptedSecret,
|
||||||
|
|
||||||
password: hashedPassword,
|
password: hashedPassword,
|
||||||
expiresAt: new Date(expiresAt),
|
expiresAt: new Date(expiresAt),
|
||||||
expiresAfterViews,
|
expiresAfterViews,
|
||||||
accessType
|
accessType
|
||||||
});
|
});
|
||||||
|
|
||||||
return { id: `${newSharedSecret.identifier}${hashedHex}` };
|
return { id: `${Buffer.from(newSharedSecret.identifier!, "hex").toString("base64url")}` };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSharedSecrets = async ({
|
const getSharedSecrets = async ({
|
||||||
@@ -220,8 +215,7 @@ export const secretSharingServiceFactory = ({
|
|||||||
hashedHex
|
hashedHex
|
||||||
})
|
})
|
||||||
: await secretSharingDAL.findOne({
|
: await secretSharingDAL.findOne({
|
||||||
hashedHex,
|
identifier: Buffer.from(sharedSecretId, "base64url").toString("hex")
|
||||||
identifier: sharedSecretId
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!sharedSecret)
|
if (!sharedSecret)
|
||||||
@@ -295,12 +289,12 @@ export const secretSharingServiceFactory = ({
|
|||||||
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
||||||
if (!permission) throw new ForbiddenRequestError({ name: "User does not belong to the specified organization" });
|
if (!permission) throw new ForbiddenRequestError({ name: "User does not belong to the specified organization" });
|
||||||
|
|
||||||
const deletedSharedSecret = await secretSharingDAL.deleteById(sharedSecretId);
|
|
||||||
|
|
||||||
const sharedSecret = isUuidV4(sharedSecretId)
|
const sharedSecret = isUuidV4(sharedSecretId)
|
||||||
? await secretSharingDAL.findById(sharedSecretId)
|
? await secretSharingDAL.findById(sharedSecretId)
|
||||||
: await secretSharingDAL.findOne({ identifier: sharedSecretId });
|
: await secretSharingDAL.findOne({ identifier: sharedSecretId });
|
||||||
|
|
||||||
|
const deletedSharedSecret = await secretSharingDAL.deleteById(sharedSecretId);
|
||||||
|
|
||||||
if (sharedSecret.orgId && sharedSecret.orgId !== orgId)
|
if (sharedSecret.orgId && sharedSecret.orgId !== orgId)
|
||||||
throw new ForbiddenRequestError({ message: "User does not have permission to delete shared secret" });
|
throw new ForbiddenRequestError({ message: "User does not have permission to delete shared secret" });
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export type TCreatePublicSharedSecretDTO = {
|
|||||||
|
|
||||||
export type TGetActiveSharedSecretByIdDTO = {
|
export type TGetActiveSharedSecretByIdDTO = {
|
||||||
sharedSecretId: string;
|
sharedSecretId: string;
|
||||||
hashedHex: string;
|
hashedHex?: string;
|
||||||
orgId?: string;
|
orgId?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const secretSharingKeys = {
|
|||||||
allSharedSecrets: () => ["sharedSecrets"] as const,
|
allSharedSecrets: () => ["sharedSecrets"] as const,
|
||||||
specificSharedSecrets: ({ offset, limit }: { offset: number; limit: number }) =>
|
specificSharedSecrets: ({ offset, limit }: { offset: number; limit: number }) =>
|
||||||
[...secretSharingKeys.allSharedSecrets(), { offset, limit }] as const,
|
[...secretSharingKeys.allSharedSecrets(), { offset, limit }] as const,
|
||||||
getSecretById: (arg: { id: string; hashedHex: string; password?: string }) => [
|
getSecretById: (arg: { id: string; hashedHex: string | null; password?: string }) => [
|
||||||
"shared-secret",
|
"shared-secret",
|
||||||
arg
|
arg
|
||||||
]
|
]
|
||||||
@@ -46,7 +46,7 @@ export const useGetActiveSharedSecretById = ({
|
|||||||
password
|
password
|
||||||
}: {
|
}: {
|
||||||
sharedSecretId: string;
|
sharedSecretId: string;
|
||||||
hashedHex: string;
|
hashedHex: string | null;
|
||||||
password?: string;
|
password?: string;
|
||||||
}) => {
|
}) => {
|
||||||
return useQuery<TViewSharedSecretResponse>(
|
return useQuery<TViewSharedSecretResponse>(
|
||||||
@@ -55,7 +55,7 @@ export const useGetActiveSharedSecretById = ({
|
|||||||
const { data } = await apiRequest.post<TViewSharedSecretResponse>(
|
const { data } = await apiRequest.post<TViewSharedSecretResponse>(
|
||||||
`/api/v1/secret-sharing/public/${sharedSecretId}`,
|
`/api/v1/secret-sharing/public/${sharedSecretId}`,
|
||||||
{
|
{
|
||||||
hashedHex,
|
...(hashedHex && { hashedHex }),
|
||||||
password
|
password
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -63,7 +63,7 @@ export const useGetActiveSharedSecretById = ({
|
|||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: Boolean(sharedSecretId) && Boolean(hashedHex)
|
enabled: Boolean(sharedSecretId)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,14 +15,6 @@ const extractDetailsFromUrl = (router: NextRouter) => {
|
|||||||
|
|
||||||
const idString = id as string;
|
const idString = id as string;
|
||||||
|
|
||||||
if (!idString) {
|
|
||||||
return {
|
|
||||||
id: "",
|
|
||||||
hashedHex: "",
|
|
||||||
key: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (urlEncodedKey) {
|
if (urlEncodedKey) {
|
||||||
const [hashedHex, key] = urlEncodedKey ? urlEncodedKey.toString().split("-") : ["", ""];
|
const [hashedHex, key] = urlEncodedKey ? urlEncodedKey.toString().split("-") : ["", ""];
|
||||||
|
|
||||||
@@ -33,13 +25,9 @@ const extractDetailsFromUrl = (router: NextRouter) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the first 36 characters as id and the rest as hex
|
|
||||||
const idPart = idString.substring(0, 36);
|
|
||||||
const hexPart = idString.substring(36);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: idPart || "",
|
id: idString,
|
||||||
hashedHex: hexPart || "",
|
hashedHex: null,
|
||||||
key: null
|
key: null
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -65,6 +53,9 @@ export const ViewSecretPublicPage = () => {
|
|||||||
((error as AxiosError)?.response?.data as { message: string })?.message ===
|
((error as AxiosError)?.response?.data as { message: string })?.message ===
|
||||||
"Invalid credentials";
|
"Invalid credentials";
|
||||||
|
|
||||||
|
console.log("data", fetchSecret);
|
||||||
|
console.log("err", error);
|
||||||
|
|
||||||
const shouldShowPasswordPrompt =
|
const shouldShowPasswordPrompt =
|
||||||
isInvalidCredential || (fetchSecret?.isPasswordProtected && !fetchSecret.secret);
|
isInvalidCredential || (fetchSecret?.isPasswordProtected && !fetchSecret.secret);
|
||||||
const isValidatingPassword = Boolean(password) && isFetching;
|
const isValidatingPassword = Boolean(password) && isFetching;
|
||||||
|
|||||||
Reference in New Issue
Block a user