mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 17:27:16 +00:00
Merge pull request #1343 from Infisical/daniel/pg-endpoint-fixes
(Postgres Fix): Secret endpoints return data
This commit is contained in:
@@ -13,7 +13,7 @@ module.exports = {
|
|||||||
tsconfigRootDir: __dirname
|
tsconfigRootDir: __dirname
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
// "@typescript-eslint/no-empty-function": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
"consistent-return": "off", // my style
|
"consistent-return": "off", // my style
|
||||||
"import/order": "off", // for simple-import-order
|
"import/order": "off", // for simple-import-order
|
||||||
"import/prefer-default-export": "off", // why
|
"import/prefer-default-export": "off", // why
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { z } from "zod";
|
|||||||
import { TImmutableDBKeys } from "./models";
|
import { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
export const IdentityAccessTokensSchema = z.object({
|
export const IdentityAccessTokensSchema = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string(),
|
||||||
accessTokenTTL: z.coerce.number().default(2592000),
|
accessTokenTTL: z.coerce.number().default(2592000),
|
||||||
accessTokenMaxTTL: z.coerce.number().default(2592000),
|
accessTokenMaxTTL: z.coerce.number().default(2592000),
|
||||||
accessTokenNumUses: z.coerce.number().default(0),
|
accessTokenNumUses: z.coerce.number().default(0),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const OrganizationsSchema = z.object({
|
|||||||
customerId: z.string().nullable().optional(),
|
customerId: z.string().nullable().optional(),
|
||||||
slug: z.string(),
|
slug: z.string(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TOrganizations = z.infer<typeof OrganizationsSchema>;
|
export type TOrganizations = z.infer<typeof OrganizationsSchema>;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { TImmutableDBKeys } from "./models";
|
|||||||
export const SecretApprovalRequestsSecretsSchema = z.object({
|
export const SecretApprovalRequestsSecretsSchema = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
version: z.number().default(1).nullable().optional(),
|
version: z.number().default(1).nullable().optional(),
|
||||||
secretBlindIndex: z.string(),
|
secretBlindIndex: z.string().nullable().optional(),
|
||||||
secretKeyCiphertext: z.string(),
|
secretKeyCiphertext: z.string(),
|
||||||
secretKeyIV: z.string(),
|
secretKeyIV: z.string(),
|
||||||
secretKeyTag: z.string(),
|
secretKeyTag: z.string(),
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ export const UserEncryptionKeysSchema = z.object({
|
|||||||
clientPublicKey: z.string().nullable().optional(),
|
clientPublicKey: z.string().nullable().optional(),
|
||||||
serverPrivateKey: z.string().nullable().optional(),
|
serverPrivateKey: z.string().nullable().optional(),
|
||||||
encryptionVersion: z.number().default(2).nullable().optional(),
|
encryptionVersion: z.number().default(2).nullable().optional(),
|
||||||
protectedKey: z.string().nullable(),
|
protectedKey: z.string().nullable().optional(),
|
||||||
protectedKeyIV: z.string().nullable(),
|
protectedKeyIV: z.string().nullable().optional(),
|
||||||
protectedKeyTag: z.string().nullable(),
|
protectedKeyTag: z.string().nullable().optional(),
|
||||||
publicKey: z.string(),
|
publicKey: z.string(),
|
||||||
encryptedPrivateKey: z.string(),
|
encryptedPrivateKey: z.string(),
|
||||||
iv: z.string(),
|
iv: z.string(),
|
||||||
|
|||||||
@@ -269,7 +269,14 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
const { secsGroupedByBlindIndex: conflictGroupByBlindIndex } =
|
const { secsGroupedByBlindIndex: conflictGroupByBlindIndex } =
|
||||||
await secretService.fnSecretBlindIndexCheckV2({
|
await secretService.fnSecretBlindIndexCheckV2({
|
||||||
folderId,
|
folderId,
|
||||||
inputSecrets: secretCreationCommits.map(({ secretBlindIndex }) => ({ secretBlindIndex }))
|
inputSecrets: secretCreationCommits.map(({ secretBlindIndex }) => {
|
||||||
|
if (!secretBlindIndex) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Missing secret blind index"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { secretBlindIndex };
|
||||||
|
})
|
||||||
});
|
});
|
||||||
secretCreationCommits
|
secretCreationCommits
|
||||||
.filter(({ secretBlindIndex }) => conflictGroupByBlindIndex[secretBlindIndex || ""])
|
.filter(({ secretBlindIndex }) => conflictGroupByBlindIndex[secretBlindIndex || ""])
|
||||||
@@ -291,7 +298,14 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
({ secretBlindIndex, secret }) =>
|
({ secretBlindIndex, secret }) =>
|
||||||
secret && secret.secretBlindIndex !== secretBlindIndex
|
secret && secret.secretBlindIndex !== secretBlindIndex
|
||||||
)
|
)
|
||||||
.map(({ secretBlindIndex }) => ({ secretBlindIndex }))
|
.map(({ secretBlindIndex }) => {
|
||||||
|
if (!secretBlindIndex) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Missing secret blind index"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { secretBlindIndex };
|
||||||
|
})
|
||||||
});
|
});
|
||||||
secretUpdationCommits
|
secretUpdationCommits
|
||||||
.filter(
|
.filter(
|
||||||
@@ -381,10 +395,14 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
folderId,
|
folderId,
|
||||||
tx,
|
tx,
|
||||||
actorId: "",
|
actorId: "",
|
||||||
inputSecrets: secretDeletionCommits.map(({ secretBlindIndex }) => ({
|
inputSecrets: secretDeletionCommits.map(({ secretBlindIndex }) => {
|
||||||
secretBlindIndex,
|
if (!secretBlindIndex) {
|
||||||
type: SecretType.Shared
|
throw new BadRequestError({
|
||||||
}))
|
message: "Missing secret blind index"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { secretBlindIndex, type: SecretType.Shared };
|
||||||
|
})
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
const updatedSecretApproval = await secretApprovalRequestDAL.updateById(
|
const updatedSecretApproval = await secretApprovalRequestDAL.updateById(
|
||||||
@@ -638,7 +656,13 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
),
|
),
|
||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
const commitsGroupByBlindIndex = groupBy(approvalCommits, (i) => i.secretBlindIndex);
|
|
||||||
|
const commitsGroupByBlindIndex = groupBy(approvalCommits, (i) => {
|
||||||
|
if (!i.secretBlindIndex) {
|
||||||
|
throw new BadRequestError({ message: "Missing secret blind index" });
|
||||||
|
}
|
||||||
|
return i.secretBlindIndex;
|
||||||
|
});
|
||||||
if (tagIds.length) {
|
if (tagIds.length) {
|
||||||
await secretApprovalRequestSecretDAL.insertApprovalSecretTags(
|
await secretApprovalRequestSecretDAL.insertApprovalSecretTags(
|
||||||
Object.keys(commitTagIds).flatMap((blindIndex) =>
|
Object.keys(commitTagIds).flatMap((blindIndex) =>
|
||||||
|
|||||||
@@ -92,7 +92,10 @@ import { serviceTokenDALFactory } from "@app/services/service-token/service-toke
|
|||||||
import { serviceTokenServiceFactory } from "@app/services/service-token/service-token-service";
|
import { serviceTokenServiceFactory } from "@app/services/service-token/service-token-service";
|
||||||
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
import { TSmtpService } from "@app/services/smtp/smtp-service";
|
||||||
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||||
import { getServerCfg, superAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
|
import {
|
||||||
|
getServerCfg,
|
||||||
|
superAdminServiceFactory
|
||||||
|
} from "@app/services/super-admin/super-admin-service";
|
||||||
import { telemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
import { telemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
||||||
import { userDALFactory } from "@app/services/user/user-dal";
|
import { userDALFactory } from "@app/services/user/user-dal";
|
||||||
import { userServiceFactory } from "@app/services/user/user-service";
|
import { userServiceFactory } from "@app/services/user/user-service";
|
||||||
@@ -420,6 +423,7 @@ export const registerRoutes = async (
|
|||||||
const serviceTokenService = serviceTokenServiceFactory({
|
const serviceTokenService = serviceTokenServiceFactory({
|
||||||
projectEnvDAL,
|
projectEnvDAL,
|
||||||
serviceTokenDAL,
|
serviceTokenDAL,
|
||||||
|
userDAL,
|
||||||
permissionService
|
permissionService
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -516,14 +520,14 @@ export const registerRoutes = async (
|
|||||||
},
|
},
|
||||||
handler: () => {
|
handler: () => {
|
||||||
const cfg = getConfig();
|
const cfg = getConfig();
|
||||||
const serverCfg = getServerCfg()
|
const serverCfg = getServerCfg();
|
||||||
return {
|
return {
|
||||||
date: new Date(),
|
date: new Date(),
|
||||||
message: "Ok" as const,
|
message: "Ok" as const,
|
||||||
emailConfigured: cfg.isSmtpConfigured,
|
emailConfigured: cfg.isSmtpConfigured,
|
||||||
inviteOnlySignup: Boolean(serverCfg.allowSignUp),
|
inviteOnlySignup: Boolean(serverCfg.allowSignUp),
|
||||||
redisConfigured: cfg.isRedisConfigured,
|
redisConfigured: cfg.isRedisConfigured,
|
||||||
secretScanningConfigured: cfg.isSecretScanningConfigured,
|
secretScanningConfigured: cfg.isSecretScanningConfigured
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { IntegrationAuthsSchema, SecretApprovalPoliciesSchema } from "@app/db/schemas";
|
import { IntegrationAuthsSchema, SecretApprovalPoliciesSchema, UsersSchema } from "@app/db/schemas";
|
||||||
|
|
||||||
// sometimes the return data must be santizied to avoid leaking important values
|
// sometimes the return data must be santizied to avoid leaking important values
|
||||||
// always prefer pick over omit in zod
|
// always prefer pick over omit in zod
|
||||||
@@ -28,6 +28,18 @@ export const sapPubSchema = SecretApprovalPoliciesSchema.merge(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const sanitizedServiceTokenUserSchema = UsersSchema.pick({
|
||||||
|
authMethods: true,
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
devices: true,
|
||||||
|
email: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
mfaMethods: true
|
||||||
|
});
|
||||||
|
|
||||||
export const secretRawSchema = z.object({
|
export const secretRawSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
_id: z.string(),
|
_id: z.string(),
|
||||||
|
|||||||
@@ -86,7 +86,13 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
|
|||||||
secure: appCfg.HTTPS_ENABLED
|
secure: appCfg.HTTPS_ENABLED
|
||||||
});
|
});
|
||||||
|
|
||||||
return { token: token.access, ...user };
|
return {
|
||||||
|
...user,
|
||||||
|
token: token.access,
|
||||||
|
protectedKey: user.protectedKey || null,
|
||||||
|
protectedKeyIV: user.protectedKeyIV || null,
|
||||||
|
protectedKeyTag: user.protectedKeyTag || null
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { removeTrailingSlash } from "@app/lib/fn";
|
|||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
import { sanitizedServiceTokenUserSchema } from "../sanitizedSchemas";
|
||||||
|
|
||||||
export const sanitizedServiceTokenSchema = ServiceTokensSchema.omit({
|
export const sanitizedServiceTokenSchema = ServiceTokensSchema.omit({
|
||||||
secretHash: true,
|
secretHash: true,
|
||||||
encryptedKey: true,
|
encryptedKey: true,
|
||||||
@@ -20,15 +22,22 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
|
|||||||
onRequest: verifyAuth([AuthMode.SERVICE_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SERVICE_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
response: {
|
response: {
|
||||||
200: ServiceTokensSchema.merge(z.object({ workspace: z.string() }))
|
200: ServiceTokensSchema.merge(
|
||||||
|
z.object({
|
||||||
|
workspace: z.string(),
|
||||||
|
user: sanitizedServiceTokenUserSchema
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const serviceTokenData = await server.services.serviceToken.getServiceToken({
|
const { serviceToken, user } = await server.services.serviceToken.getServiceToken({
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actor: req.permission.type
|
actor: req.permission.type
|
||||||
});
|
});
|
||||||
return { ...serviceTokenData, workspace: serviceTokenData.projectId };
|
|
||||||
|
// We return the user here because older versions of the deprecated Python SDK depend on it to properly parse the API response.
|
||||||
|
return { ...serviceToken, workspace: serviceToken.projectId, user };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -96,9 +96,9 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
encryptedPrivateKey: data.user.encryptedPrivateKey,
|
encryptedPrivateKey: data.user.encryptedPrivateKey,
|
||||||
iv: data.user.iv,
|
iv: data.user.iv,
|
||||||
tag: data.user.tag,
|
tag: data.user.tag,
|
||||||
protectedKey: data.user.protectedKey,
|
protectedKey: data.user.protectedKey || null,
|
||||||
protectedKeyIV: data.user.protectedKeyIV,
|
protectedKeyIV: data.user.protectedKeyIV || null,
|
||||||
protectedKeyTag: data.user.protectedKeyTag
|
protectedKeyTag: data.user.protectedKeyTag || null
|
||||||
} as const;
|
} as const;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -442,6 +442,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
secrets: SecretsSchema.omit({ secretBlindIndex: true })
|
secrets: SecretsSchema.omit({ secretBlindIndex: true })
|
||||||
.merge(
|
.merge(
|
||||||
z.object({
|
z.object({
|
||||||
|
workspace: z.string(),
|
||||||
|
environment: z.string(),
|
||||||
tags: SecretTagsSchema.pick({
|
tags: SecretTagsSchema.pick({
|
||||||
id: true,
|
id: true,
|
||||||
slug: true,
|
slug: true,
|
||||||
@@ -529,7 +531,12 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
secret: SecretsSchema.omit({ secretBlindIndex: true })
|
secret: SecretsSchema.omit({ secretBlindIndex: true }).merge(
|
||||||
|
z.object({
|
||||||
|
workspace: z.string(),
|
||||||
|
environment: z.string()
|
||||||
|
})
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -610,7 +617,12 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
response: {
|
response: {
|
||||||
200: z.union([
|
200: z.union([
|
||||||
z.object({
|
z.object({
|
||||||
secret: SecretsSchema.omit({ secretBlindIndex: true })
|
secret: SecretsSchema.omit({ secretBlindIndex: true }).merge(
|
||||||
|
z.object({
|
||||||
|
workspace: z.string(),
|
||||||
|
environment: z.string()
|
||||||
|
})
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
z
|
z
|
||||||
.object({ approval: SecretApprovalRequestsSchema })
|
.object({ approval: SecretApprovalRequestsSchema })
|
||||||
@@ -780,7 +792,12 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
response: {
|
response: {
|
||||||
200: z.union([
|
200: z.union([
|
||||||
z.object({
|
z.object({
|
||||||
secret: SecretsSchema.omit({ secretBlindIndex: true })
|
secret: SecretsSchema.omit({ secretBlindIndex: true }).merge(
|
||||||
|
z.object({
|
||||||
|
workspace: z.string(),
|
||||||
|
environment: z.string()
|
||||||
|
})
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
z
|
z
|
||||||
.object({ approval: SecretApprovalRequestsSchema })
|
.object({ approval: SecretApprovalRequestsSchema })
|
||||||
@@ -944,7 +961,12 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
|
|||||||
response: {
|
response: {
|
||||||
200: z.union([
|
200: z.union([
|
||||||
z.object({
|
z.object({
|
||||||
secret: SecretsSchema.omit({ secretBlindIndex: true })
|
secret: SecretsSchema.omit({ secretBlindIndex: true }).merge(
|
||||||
|
z.object({
|
||||||
|
workspace: z.string(),
|
||||||
|
environment: z.string()
|
||||||
|
})
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
z
|
z
|
||||||
.object({ approval: SecretApprovalRequestsSchema })
|
.object({ approval: SecretApprovalRequestsSchema })
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
|||||||
|
|
||||||
import { ActorType } from "../auth/auth-type";
|
import { ActorType } from "../auth/auth-type";
|
||||||
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
|
||||||
|
import { TUserDALFactory } from "../user/user-dal";
|
||||||
import { TServiceTokenDALFactory } from "./service-token-dal";
|
import { TServiceTokenDALFactory } from "./service-token-dal";
|
||||||
import {
|
import {
|
||||||
TCreateServiceTokenDTO,
|
TCreateServiceTokenDTO,
|
||||||
@@ -23,6 +24,7 @@ import {
|
|||||||
|
|
||||||
type TServiceTokenServiceFactoryDep = {
|
type TServiceTokenServiceFactoryDep = {
|
||||||
serviceTokenDAL: TServiceTokenDALFactory;
|
serviceTokenDAL: TServiceTokenDALFactory;
|
||||||
|
userDAL: TUserDALFactory;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
projectEnvDAL: Pick<TProjectEnvDALFactory, "findBySlugs">;
|
projectEnvDAL: Pick<TProjectEnvDALFactory, "findBySlugs">;
|
||||||
};
|
};
|
||||||
@@ -31,6 +33,7 @@ export type TServiceTokenServiceFactory = ReturnType<typeof serviceTokenServiceF
|
|||||||
|
|
||||||
export const serviceTokenServiceFactory = ({
|
export const serviceTokenServiceFactory = ({
|
||||||
serviceTokenDAL,
|
serviceTokenDAL,
|
||||||
|
userDAL,
|
||||||
permissionService,
|
permissionService,
|
||||||
projectEnvDAL
|
projectEnvDAL
|
||||||
}: TServiceTokenServiceFactoryDep) => {
|
}: TServiceTokenServiceFactoryDep) => {
|
||||||
@@ -57,7 +60,7 @@ export const serviceTokenServiceFactory = ({
|
|||||||
ProjectPermissionActions.Create,
|
ProjectPermissionActions.Create,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
||||||
);
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
|
|
||||||
@@ -119,7 +122,10 @@ export const serviceTokenServiceFactory = ({
|
|||||||
const serviceToken = await serviceTokenDAL.findById(actorId);
|
const serviceToken = await serviceTokenDAL.findById(actorId);
|
||||||
if (!serviceToken) throw new BadRequestError({ message: "Token not found" });
|
if (!serviceToken) throw new BadRequestError({ message: "Token not found" });
|
||||||
|
|
||||||
return serviceToken;
|
const serviceTokenUser = await userDAL.findById(serviceToken.createdBy);
|
||||||
|
if (!serviceTokenUser) throw new BadRequestError({ message: "Service token user not found" });
|
||||||
|
|
||||||
|
return { serviceToken, user: serviceTokenUser };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getProjectServiceTokens = async ({
|
const getProjectServiceTokens = async ({
|
||||||
|
|||||||
Reference in New Issue
Block a user