mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-18 21:29:36 +00:00
merge main and deconflict
This commit is contained in:
@@ -7,6 +7,7 @@ import { ActionProjectType, ProjectType } from "@app/db/schemas";
|
||||
import { getServerSentEventsHeaders } from "@app/ee/services/event/event-sse-stream";
|
||||
import { EventRegisterSchema } from "@app/ee/services/event/types";
|
||||
import { ProjectPermissionSecretActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||
import { ApiDocsTags, EventSubscriptions } from "@app/lib/api-docs";
|
||||
import { BadRequestError, ForbiddenRequestError, RateLimitError } from "@app/lib/errors";
|
||||
import { readLimit } from "@app/server/config/rateLimiter";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@@ -20,10 +21,14 @@ export const registerEventRouter = async (server: FastifyZodProvider) => {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.Events],
|
||||
description: "Subscribe to project events",
|
||||
body: z.object({
|
||||
projectId: z.string().trim(),
|
||||
register: z.array(EventRegisterSchema).max(10)
|
||||
})
|
||||
projectId: z.string().trim().describe(EventSubscriptions.SUBSCRIBE_PROJECT_EVENTS.projectId),
|
||||
register: z.array(EventRegisterSchema).min(1).max(10)
|
||||
}),
|
||||
produces: ["text/event-stream"]
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req, reply) => {
|
||||
@@ -75,13 +80,15 @@ export const registerEventRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
|
||||
req.body.register.forEach((r) => {
|
||||
const fields = {
|
||||
environment: r.conditions?.environmentSlug ?? "",
|
||||
secretPath: r.conditions?.secretPath ?? "/",
|
||||
eventType: r.event
|
||||
};
|
||||
|
||||
const allowed = info.permission.can(
|
||||
ProjectPermissionSecretActions.Subscribe,
|
||||
subject(ProjectPermissionSub.Secrets, {
|
||||
environment: r.conditions?.environmentSlug ?? "",
|
||||
secretPath: r.conditions?.secretPath ?? "/",
|
||||
eventType: r.event
|
||||
})
|
||||
subject(ProjectPermissionSub.Secrets, fields)
|
||||
);
|
||||
|
||||
if (!allowed) {
|
||||
@@ -89,9 +96,9 @@ export const registerEventRouter = async (server: FastifyZodProvider) => {
|
||||
name: "PermissionDenied",
|
||||
message: `You are not allowed to subscribe on secrets`,
|
||||
details: {
|
||||
event: r.event,
|
||||
environmentSlug: r.conditions?.environmentSlug,
|
||||
secretPath: r.conditions?.secretPath ?? "/"
|
||||
event: fields.eventType,
|
||||
environmentSlug: fields.environment,
|
||||
secretPath: fields.secretPath
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -200,49 +200,104 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
|
||||
params: z.object({
|
||||
identityId: z.string().trim().describe(LDAP_AUTH.ATTACH.identityId)
|
||||
}),
|
||||
body: z
|
||||
.object({
|
||||
url: z.string().trim().min(1).describe(LDAP_AUTH.ATTACH.url),
|
||||
bindDN: z.string().trim().min(1).describe(LDAP_AUTH.ATTACH.bindDN),
|
||||
bindPass: z.string().trim().min(1).describe(LDAP_AUTH.ATTACH.bindPass),
|
||||
searchBase: z.string().trim().min(1).describe(LDAP_AUTH.ATTACH.searchBase),
|
||||
searchFilter: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
.default("(uid={{username}})")
|
||||
.refine(isValidLdapFilter, "Invalid LDAP search filter")
|
||||
.describe(LDAP_AUTH.ATTACH.searchFilter),
|
||||
allowedFields: AllowedFieldsSchema.array().optional().describe(LDAP_AUTH.ATTACH.allowedFields),
|
||||
ldapCaCertificate: z.string().trim().optional().describe(LDAP_AUTH.ATTACH.ldapCaCertificate),
|
||||
accessTokenTrustedIps: z
|
||||
.object({
|
||||
ipAddress: z.string().trim()
|
||||
})
|
||||
.array()
|
||||
.min(1)
|
||||
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }])
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenTrustedIps),
|
||||
accessTokenTTL: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.max(315360000)
|
||||
.default(2592000)
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenTTL),
|
||||
accessTokenMaxTTL: z
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(315360000)
|
||||
.default(2592000)
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenMaxTTL),
|
||||
accessTokenNumUsesLimit: z.number().int().min(0).default(0).describe(LDAP_AUTH.ATTACH.accessTokenNumUsesLimit)
|
||||
})
|
||||
.refine(
|
||||
(val) => val.accessTokenTTL <= val.accessTokenMaxTTL,
|
||||
"Access Token TTL cannot be greater than Access Token Max TTL."
|
||||
),
|
||||
body: z.union([
|
||||
// Template-based configuration
|
||||
z
|
||||
.object({
|
||||
templateId: z.string().trim().describe(LDAP_AUTH.ATTACH.templateId),
|
||||
searchFilter: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
.default("(uid={{username}})")
|
||||
.refine(isValidLdapFilter, "Invalid LDAP search filter")
|
||||
.describe(LDAP_AUTH.ATTACH.searchFilter),
|
||||
allowedFields: AllowedFieldsSchema.array().optional().describe(LDAP_AUTH.ATTACH.allowedFields),
|
||||
ldapCaCertificate: z.string().trim().optional().describe(LDAP_AUTH.ATTACH.ldapCaCertificate),
|
||||
accessTokenTrustedIps: z
|
||||
.object({
|
||||
ipAddress: z.string().trim()
|
||||
})
|
||||
.array()
|
||||
.min(1)
|
||||
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }])
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenTrustedIps),
|
||||
accessTokenTTL: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.max(315360000)
|
||||
.default(2592000)
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenTTL),
|
||||
accessTokenMaxTTL: z
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(315360000)
|
||||
.default(2592000)
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenMaxTTL),
|
||||
accessTokenNumUsesLimit: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.default(0)
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenNumUsesLimit)
|
||||
})
|
||||
.refine(
|
||||
(val) => val.accessTokenTTL <= val.accessTokenMaxTTL,
|
||||
"Access Token TTL cannot be greater than Access Token Max TTL."
|
||||
),
|
||||
|
||||
// Manual configuration
|
||||
z
|
||||
.object({
|
||||
url: z.string().trim().describe(LDAP_AUTH.ATTACH.url),
|
||||
bindDN: z.string().trim().describe(LDAP_AUTH.ATTACH.bindDN),
|
||||
bindPass: z.string().trim().describe(LDAP_AUTH.ATTACH.bindPass),
|
||||
searchBase: z.string().trim().describe(LDAP_AUTH.ATTACH.searchBase),
|
||||
searchFilter: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
.default("(uid={{username}})")
|
||||
.refine(isValidLdapFilter, "Invalid LDAP search filter")
|
||||
.describe(LDAP_AUTH.ATTACH.searchFilter),
|
||||
allowedFields: AllowedFieldsSchema.array().optional().describe(LDAP_AUTH.ATTACH.allowedFields),
|
||||
ldapCaCertificate: z.string().trim().optional().describe(LDAP_AUTH.ATTACH.ldapCaCertificate),
|
||||
accessTokenTrustedIps: z
|
||||
.object({
|
||||
ipAddress: z.string().trim()
|
||||
})
|
||||
.array()
|
||||
.min(1)
|
||||
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }])
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenTrustedIps),
|
||||
accessTokenTTL: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.max(315360000)
|
||||
.default(2592000)
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenTTL),
|
||||
accessTokenMaxTTL: z
|
||||
.number()
|
||||
.int()
|
||||
.min(1)
|
||||
.max(315360000)
|
||||
.default(2592000)
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenMaxTTL),
|
||||
accessTokenNumUsesLimit: z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.default(0)
|
||||
.describe(LDAP_AUTH.ATTACH.accessTokenNumUsesLimit)
|
||||
})
|
||||
.refine(
|
||||
(val) => val.accessTokenTTL <= val.accessTokenMaxTTL,
|
||||
"Access Token TTL cannot be greater than Access Token Max TTL."
|
||||
)
|
||||
]),
|
||||
response: {
|
||||
200: z.object({
|
||||
identityLdapAuth: IdentityLdapAuthsSchema.omit({
|
||||
@@ -275,7 +330,8 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
|
||||
accessTokenMaxTTL: identityLdapAuth.accessTokenMaxTTL,
|
||||
accessTokenTTL: identityLdapAuth.accessTokenTTL,
|
||||
accessTokenNumUsesLimit: identityLdapAuth.accessTokenNumUsesLimit,
|
||||
allowedFields: req.body.allowedFields
|
||||
allowedFields: req.body.allowedFields,
|
||||
templateId: identityLdapAuth.templateId
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -309,6 +365,7 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
|
||||
bindDN: z.string().trim().min(1).optional().describe(LDAP_AUTH.UPDATE.bindDN),
|
||||
bindPass: z.string().trim().min(1).optional().describe(LDAP_AUTH.UPDATE.bindPass),
|
||||
searchBase: z.string().trim().min(1).optional().describe(LDAP_AUTH.UPDATE.searchBase),
|
||||
templateId: z.string().trim().optional().describe(LDAP_AUTH.UPDATE.templateId),
|
||||
searchFilter: z
|
||||
.string()
|
||||
.trim()
|
||||
@@ -376,7 +433,8 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
|
||||
accessTokenTTL: identityLdapAuth.accessTokenTTL,
|
||||
accessTokenNumUsesLimit: identityLdapAuth.accessTokenNumUsesLimit,
|
||||
accessTokenTrustedIps: identityLdapAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
|
||||
allowedFields: req.body.allowedFields
|
||||
allowedFields: req.body.allowedFields,
|
||||
templateId: identityLdapAuth.templateId
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -413,7 +471,8 @@ export const registerIdentityLdapAuthRouter = async (server: FastifyZodProvider)
|
||||
}).extend({
|
||||
bindDN: z.string(),
|
||||
bindPass: z.string(),
|
||||
ldapCaCertificate: z.string().optional()
|
||||
ldapCaCertificate: z.string().optional(),
|
||||
templateId: z.string().optional().nullable()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
||||
lastName: true,
|
||||
id: true,
|
||||
superAdmin: true
|
||||
}).merge(z.object({ publicKey: z.string().nullable() }))
|
||||
}).merge(z.object({ publicKey: z.string().nullable().optional() }))
|
||||
})
|
||||
)
|
||||
.omit({ createdAt: true, updatedAt: true })
|
||||
|
||||
@@ -9,73 +9,6 @@ import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||
import { UserEncryption } from "@app/services/user/user-types";
|
||||
|
||||
export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/srp1",
|
||||
config: {
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
clientPublicKey: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
serverPublicKey: z.string(),
|
||||
salt: z.string()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { salt, serverPublicKey } = await server.services.password.generateServerPubKey(
|
||||
req.permission.id,
|
||||
req.body.clientPublicKey
|
||||
);
|
||||
return { salt, serverPublicKey };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/change-password",
|
||||
config: {
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
clientProof: z.string().trim(),
|
||||
protectedKey: z.string().trim(),
|
||||
protectedKeyIV: z.string().trim(),
|
||||
protectedKeyTag: z.string().trim(),
|
||||
encryptedPrivateKey: z.string().trim(),
|
||||
encryptedPrivateKeyIV: z.string().trim(),
|
||||
encryptedPrivateKeyTag: z.string().trim(),
|
||||
salt: z.string().trim(),
|
||||
verifier: z.string().trim(),
|
||||
password: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req, res) => {
|
||||
const appCfg = getConfig();
|
||||
await server.services.password.changePassword({ ...req.body, userId: req.permission.id });
|
||||
|
||||
void res.cookie("jid", "", {
|
||||
httpOnly: true,
|
||||
path: "/",
|
||||
sameSite: "strict",
|
||||
secure: appCfg.HTTPS_ENABLED
|
||||
});
|
||||
return { message: "Successfully changed password" };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/email/password-reset",
|
||||
@@ -131,41 +64,6 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "POST",
|
||||
url: "/backup-private-key",
|
||||
config: {
|
||||
rateLimit: authRateLimit
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
schema: {
|
||||
body: z.object({
|
||||
clientProof: z.string().trim(),
|
||||
encryptedPrivateKey: z.string().trim(),
|
||||
iv: z.string().trim(),
|
||||
tag: z.string().trim(),
|
||||
salt: z.string().trim(),
|
||||
verifier: z.string().trim()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
message: z.string(),
|
||||
backupPrivateKey: BackupPrivateKeySchema.omit({ verifier: true })
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
const token = validateSignUpAuthorization(req.headers.authorization as string, "", false)!;
|
||||
const backupPrivateKey = await server.services.password.createBackupPrivateKey({
|
||||
...req.body,
|
||||
userId: token.userId
|
||||
});
|
||||
if (!backupPrivateKey) throw new Error("Failed to create backup key");
|
||||
|
||||
return { message: "Successfully updated backup private key", backupPrivateKey };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/backup-private-key",
|
||||
@@ -257,14 +155,6 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
|
||||
},
|
||||
schema: {
|
||||
body: z.object({
|
||||
protectedKey: z.string().trim(),
|
||||
protectedKeyIV: z.string().trim(),
|
||||
protectedKeyTag: z.string().trim(),
|
||||
encryptedPrivateKey: z.string().trim(),
|
||||
encryptedPrivateKeyIV: z.string().trim(),
|
||||
encryptedPrivateKeyTag: z.string().trim(),
|
||||
salt: z.string().trim(),
|
||||
verifier: z.string().trim(),
|
||||
password: z.string().trim(),
|
||||
token: z.string().trim()
|
||||
}),
|
||||
|
||||
@@ -52,7 +52,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||
200: z.object({
|
||||
publicKeys: z
|
||||
.object({
|
||||
publicKey: z.string().optional(),
|
||||
publicKey: z.string().nullable().optional(),
|
||||
userId: z.string()
|
||||
})
|
||||
.array()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
|
||||
import { UsersSchema } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { authRateLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
@@ -19,23 +19,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
user: UsersSchema.merge(
|
||||
UserEncryptionKeysSchema.pick({
|
||||
clientPublicKey: true,
|
||||
serverPrivateKey: true,
|
||||
encryptionVersion: true,
|
||||
protectedKey: true,
|
||||
protectedKeyIV: true,
|
||||
protectedKeyTag: true,
|
||||
publicKey: true,
|
||||
encryptedPrivateKey: true,
|
||||
iv: true,
|
||||
tag: true,
|
||||
salt: true,
|
||||
verifier: true,
|
||||
userId: true
|
||||
})
|
||||
)
|
||||
user: UsersSchema.extend({
|
||||
encryptionVersion: z.number()
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -94,26 +80,6 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/private-key",
|
||||
config: {
|
||||
rateLimit: readLimit
|
||||
},
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
privateKey: z.string()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT], { requireOrg: false }),
|
||||
handler: async (req) => {
|
||||
const privateKey = await server.services.user.getUserPrivateKey(req.permission.id);
|
||||
return { privateKey };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/:userId/unlock",
|
||||
|
||||
Reference in New Issue
Block a user