Merge branch 'main' into feat/azureClientSecretsRotation

This commit is contained in:
carlosmonastyrski
2025-04-25 12:42:48 -03:00
148 changed files with 1735 additions and 561 deletions
@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { DynamicSecretLeasesSchema } from "@app/db/schemas"; import { DynamicSecretLeasesSchema } from "@app/db/schemas";
import { DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs"; import { ApiDocsTags, DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates"; import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn"; import { removeTrailingSlash } from "@app/lib/fn";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
@@ -18,6 +18,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
body: z.object({ body: z.object({
dynamicSecretName: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.dynamicSecretName).toLowerCase(), dynamicSecretName: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.dynamicSecretName).toLowerCase(),
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.projectSlug), projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.projectSlug),
@@ -65,6 +67,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({ params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.leaseId) leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.leaseId)
}), }),
@@ -107,6 +111,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({ params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.leaseId) leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.leaseId)
}), }),
@@ -160,6 +166,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({ params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.leaseId) leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.leaseId)
}), }),
@@ -2,7 +2,7 @@ import { z } from "zod";
import { DynamicSecretLeasesSchema } from "@app/db/schemas"; import { DynamicSecretLeasesSchema } from "@app/db/schemas";
import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/providers/models"; import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/providers/models";
import { DYNAMIC_SECRETS } from "@app/lib/api-docs"; import { ApiDocsTags, DYNAMIC_SECRETS } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates"; import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn"; import { removeTrailingSlash } from "@app/lib/fn";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
@@ -21,6 +21,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
body: z.object({ body: z.object({
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.CREATE.projectSlug), projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.CREATE.projectSlug),
provider: DynamicSecretProviderSchema.describe(DYNAMIC_SECRETS.CREATE.provider), provider: DynamicSecretProviderSchema.describe(DYNAMIC_SECRETS.CREATE.provider),
@@ -111,6 +113,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({ params: z.object({
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.UPDATE.name) name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.UPDATE.name)
}), }),
@@ -179,6 +183,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({ params: z.object({
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.DELETE.name) name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.DELETE.name)
}), }),
@@ -215,6 +221,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({ params: z.object({
name: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.name) name: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.name)
}), }),
@@ -253,6 +261,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
querystring: z.object({ querystring: z.object({
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST.projectSlug), projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST.projectSlug),
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.LIST.path), path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.LIST.path),
@@ -284,18 +294,20 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({ params: z.object({
name: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.name) name: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.name)
}), }),
querystring: z.object({ querystring: z.object({
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.projectSlug), projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.projectSlug),
path: z path: z
.string() .string()
.trim() .trim()
.default("/") .default("/")
.transform(removeTrailingSlash) .transform(removeTrailingSlash)
.describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.path), .describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.path),
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.environmentSlug) environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.environmentSlug)
}), }),
response: { response: {
200: z.object({ 200: z.object({
+17 -1
View File
@@ -2,7 +2,7 @@ import { z } from "zod";
import { GroupsSchema, OrgMembershipRole, UsersSchema } from "@app/db/schemas"; import { GroupsSchema, OrgMembershipRole, UsersSchema } from "@app/db/schemas";
import { EFilterReturnedUsers } from "@app/ee/services/group/group-types"; import { EFilterReturnedUsers } from "@app/ee/services/group/group-types";
import { GROUPS } from "@app/lib/api-docs"; import { ApiDocsTags, GROUPS } from "@app/lib/api-docs";
import { slugSchema } from "@app/server/lib/schemas"; import { slugSchema } from "@app/server/lib/schemas";
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";
@@ -13,6 +13,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "POST", method: "POST",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Groups],
body: z.object({ body: z.object({
name: z.string().trim().min(1).max(50).describe(GROUPS.CREATE.name), name: z.string().trim().min(1).max(50).describe(GROUPS.CREATE.name),
slug: slugSchema({ min: 5, max: 36 }).optional().describe(GROUPS.CREATE.slug), slug: slugSchema({ min: 5, max: 36 }).optional().describe(GROUPS.CREATE.slug),
@@ -40,6 +42,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "GET", method: "GET",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({ params: z.object({
id: z.string().trim().describe(GROUPS.GET_BY_ID.id) id: z.string().trim().describe(GROUPS.GET_BY_ID.id)
}), }),
@@ -65,6 +69,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "GET", method: "GET",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Groups],
response: { response: {
200: GroupsSchema.array() 200: GroupsSchema.array()
} }
@@ -87,6 +93,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "PATCH", method: "PATCH",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({ params: z.object({
id: z.string().trim().describe(GROUPS.UPDATE.id) id: z.string().trim().describe(GROUPS.UPDATE.id)
}), }),
@@ -120,6 +128,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "DELETE", method: "DELETE",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({ params: z.object({
id: z.string().trim().describe(GROUPS.DELETE.id) id: z.string().trim().describe(GROUPS.DELETE.id)
}), }),
@@ -145,6 +155,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
url: "/:id/users", url: "/:id/users",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({ params: z.object({
id: z.string().trim().describe(GROUPS.LIST_USERS.id) id: z.string().trim().describe(GROUPS.LIST_USERS.id)
}), }),
@@ -194,6 +206,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
url: "/:id/users/:username", url: "/:id/users/:username",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({ params: z.object({
id: z.string().trim().describe(GROUPS.ADD_USER.id), id: z.string().trim().describe(GROUPS.ADD_USER.id),
username: z.string().trim().describe(GROUPS.ADD_USER.username) username: z.string().trim().describe(GROUPS.ADD_USER.username)
@@ -227,6 +241,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
url: "/:id/users/:username", url: "/:id/users/:username",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({ params: z.object({
id: z.string().trim().describe(GROUPS.DELETE_USER.id), id: z.string().trim().describe(GROUPS.DELETE_USER.id),
username: z.string().trim().describe(GROUPS.DELETE_USER.username) username: z.string().trim().describe(GROUPS.DELETE_USER.username)
@@ -3,7 +3,7 @@ import { z } from "zod";
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-types"; import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-types";
import { backfillPermissionV1SchemaToV2Schema } from "@app/ee/services/permission/project-permission"; import { backfillPermissionV1SchemaToV2Schema } from "@app/ee/services/permission/project-permission";
import { IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs"; import { ApiDocsTags, IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
import { UnauthorizedError } from "@app/lib/errors"; import { UnauthorizedError } from "@app/lib/errors";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
@@ -25,6 +25,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Create a permanent or a non expiry specific privilege for identity.", description: "Create a permanent or a non expiry specific privilege for identity.",
security: [ security: [
{ {
@@ -85,6 +87,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Create a temporary or a expiring specific privilege for identity.", description: "Create a temporary or a expiring specific privilege for identity.",
security: [ security: [
{ {
@@ -157,6 +161,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Update a specific privilege of an identity.", description: "Update a specific privilege of an identity.",
security: [ security: [
{ {
@@ -240,6 +246,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Delete a specific privilege of an identity.", description: "Delete a specific privilege of an identity.",
security: [ security: [
{ {
@@ -279,6 +287,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Retrieve details of a specific privilege by privilege slug.", description: "Retrieve details of a specific privilege by privilege slug.",
security: [ security: [
{ {
@@ -319,6 +329,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "List of a specific privilege of an identity in a project.", description: "List of a specific privilege of an identity in a project.",
security: [ security: [
{ {
+3 -1
View File
@@ -2,7 +2,7 @@ import { z } from "zod";
import { AuditLogsSchema, SecretSnapshotsSchema } from "@app/db/schemas"; import { AuditLogsSchema, SecretSnapshotsSchema } from "@app/db/schemas";
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
import { AUDIT_LOGS, PROJECTS } from "@app/lib/api-docs"; import { ApiDocsTags, AUDIT_LOGS, PROJECTS } from "@app/lib/api-docs";
import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn"; import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -17,6 +17,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Return project secret snapshots ids", description: "Return project secret snapshots ids",
security: [ security: [
{ {
@@ -5,7 +5,7 @@ import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { ProjectTemplateDefaultEnvironments } from "@app/ee/services/project-template/project-template-constants"; import { ProjectTemplateDefaultEnvironments } from "@app/ee/services/project-template/project-template-constants";
import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns"; import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
import { ProjectTemplates } from "@app/lib/api-docs"; import { ApiDocsTags, ProjectTemplates } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas"; import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -101,6 +101,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "List project templates for the current organization.", description: "List project templates for the current organization.",
response: { response: {
200: z.object({ 200: z.object({
@@ -137,6 +139,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "Get a project template by ID.", description: "Get a project template by ID.",
params: z.object({ params: z.object({
templateId: z.string().uuid() templateId: z.string().uuid()
@@ -176,6 +180,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "Create a project template.", description: "Create a project template.",
body: z.object({ body: z.object({
name: slugSchema({ field: "name" }) name: slugSchema({ field: "name" })
@@ -219,6 +225,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "Update a project template.", description: "Update a project template.",
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.UPDATE.templateId) }), params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.UPDATE.templateId) }),
body: z.object({ body: z.object({
@@ -269,6 +277,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "Delete a project template.", description: "Delete a project template.",
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.DELETE.templateId) }), params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.DELETE.templateId) }),
+3 -1
View File
@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { SecretSnapshotsSchema } from "@app/db/schemas"; import { SecretSnapshotsSchema } from "@app/db/schemas";
import { PROJECTS } from "@app/lib/api-docs"; import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { SanitizedTagSchema, secretRawSchema } from "@app/server/routes/sanitizedSchemas"; import { SanitizedTagSchema, secretRawSchema } from "@app/server/routes/sanitizedSchemas";
@@ -65,6 +65,8 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Roll back project secrets to those captured in a secret snapshot version.", description: "Roll back project secrets to those captured in a secret snapshot version.",
security: [ security: [
{ {
@@ -6,7 +6,7 @@ import { sanitizedSshCa } from "@app/ee/services/ssh/ssh-certificate-authority-s
import { SshCaKeySource, SshCaStatus } from "@app/ee/services/ssh/ssh-certificate-authority-types"; import { SshCaKeySource, SshCaStatus } from "@app/ee/services/ssh/ssh-certificate-authority-types";
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types"; import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema"; import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema";
import { SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs"; import { ApiDocsTags, SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -20,6 +20,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Create SSH CA", description: "Create SSH CA",
body: z body: z
.object({ .object({
@@ -92,6 +94,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Get SSH CA", description: "Get SSH CA",
params: z.object({ params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET.sshCaId) sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET.sshCaId)
@@ -138,6 +142,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Get public key of SSH CA", description: "Get public key of SSH CA",
params: z.object({ params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_PUBLIC_KEY.sshCaId) sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_PUBLIC_KEY.sshCaId)
@@ -163,6 +169,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Update SSH CA", description: "Update SSH CA",
params: z.object({ params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.UPDATE.sshCaId) sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.UPDATE.sshCaId)
@@ -216,6 +224,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Delete SSH CA", description: "Delete SSH CA",
params: z.object({ params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.DELETE.sshCaId) sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.DELETE.sshCaId)
@@ -261,6 +271,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Get list of certificate templates for the SSH CA", description: "Get list of certificate templates for the SSH CA",
params: z.object({ params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_CERTIFICATE_TEMPLATES.sshCaId) sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_CERTIFICATE_TEMPLATES.sshCaId)
@@ -3,7 +3,7 @@ import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { SshCertType } from "@app/ee/services/ssh/ssh-certificate-authority-types"; import { SshCertType } from "@app/ee/services/ssh/ssh-certificate-authority-types";
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types"; import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
import { SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs"; import { ApiDocsTags, SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { writeLimit } from "@app/server/config/rateLimiter"; import { writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@@ -20,6 +20,8 @@ export const registerSshCertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificates],
description: "Sign SSH public key", description: "Sign SSH public key",
body: z.object({ body: z.object({
certificateTemplateId: z certificateTemplateId: z
@@ -100,6 +102,8 @@ export const registerSshCertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificates],
description: "Issue SSH credentials (certificate + key)", description: "Issue SSH credentials (certificate + key)",
body: z.object({ body: z.object({
certificateTemplateId: z certificateTemplateId: z
@@ -8,7 +8,7 @@ import {
isValidHostPattern, isValidHostPattern,
isValidUserPattern isValidUserPattern
} from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-validators"; } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-validators";
import { SSH_CERTIFICATE_TEMPLATES } from "@app/lib/api-docs"; import { ApiDocsTags, SSH_CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -22,6 +22,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
params: z.object({ params: z.object({
certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.GET.certificateTemplateId) certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
}), }),
@@ -61,6 +63,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
body: z body: z
.object({ .object({
sshCaId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.CREATE.sshCaId), sshCaId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.CREATE.sshCaId),
@@ -141,6 +145,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
body: z.object({ body: z.object({
status: z.nativeEnum(SshCertTemplateStatus).optional(), status: z.nativeEnum(SshCertTemplateStatus).optional(),
name: z name: z
@@ -224,6 +230,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
params: z.object({ params: z.object({
certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId) certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
}), }),
@@ -4,7 +4,7 @@ import { z } from "zod";
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-types"; import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-types";
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns"; import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs"; import { ApiDocsTags, IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
@@ -21,6 +21,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Add an additional privilege for identity.", description: "Add an additional privilege for identity.",
security: [ security: [
{ {
@@ -84,6 +86,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Update a specific identity privilege.", description: "Update a specific identity privilege.",
security: [ security: [
{ {
@@ -148,6 +152,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Delete the specified identity privilege.", description: "Delete the specified identity privilege.",
security: [ security: [
{ {
@@ -183,6 +189,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Retrieve details of a specific privilege by id.", description: "Retrieve details of a specific privilege by id.",
security: [ security: [
{ {
@@ -218,6 +226,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Retrieve details of a specific privilege by slug.", description: "Retrieve details of a specific privilege by slug.",
security: [ security: [
{ {
@@ -258,6 +268,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "List privileges for the specified identity by project.", description: "List privileges for the specified identity by project.",
security: [ security: [
{ {
@@ -4,7 +4,7 @@ import { z } from "zod";
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas"; import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns"; import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission"; import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { PROJECT_ROLE } from "@app/lib/api-docs"; import { ApiDocsTags, PROJECT_ROLE } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas"; import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -20,6 +20,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
description: "Create a project role", description: "Create a project role",
security: [ security: [
{ {
@@ -75,6 +77,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
description: "Update a project role", description: "Update a project role",
security: [ security: [
{ {
@@ -130,6 +134,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
description: "Delete a project role", description: "Delete a project role",
security: [ security: [
{ {
@@ -166,6 +172,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
description: "List project role", description: "List project role",
security: [ security: [
{ {
@@ -204,6 +212,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.projectId), projectId: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.projectId),
roleSlug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.roleSlug) roleSlug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.roleSlug)
@@ -9,7 +9,7 @@ import {
TSecretRotationV2GeneratedCredentials, TSecretRotationV2GeneratedCredentials,
TSecretRotationV2Input TSecretRotationV2Input
} from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-types"; } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-types";
import { SecretRotations } from "@app/lib/api-docs"; import { ApiDocsTags, SecretRotations } from "@app/lib/api-docs";
import { startsWithVowel } from "@app/lib/fn"; import { startsWithVowel } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -66,6 +66,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `List the ${rotationType} Rotations for the specified project.`, description: `List the ${rotationType} Rotations for the specified project.`,
querystring: z.object({ querystring: z.object({
projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST(type).projectId) projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST(type).projectId)
@@ -109,6 +111,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Get the specified ${rotationType} Rotation by ID.`, description: `Get the specified ${rotationType} Rotation by ID.`,
params: z.object({ params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.GET_BY_ID(type).rotationId) rotationId: z.string().uuid().describe(SecretRotations.GET_BY_ID(type).rotationId)
@@ -151,6 +155,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Get the specified ${rotationType} Rotation by name, secret path, environment and project ID.`, description: `Get the specified ${rotationType} Rotation by name, secret path, environment and project ID.`,
params: z.object({ params: z.object({
rotationName: z rotationName: z
@@ -215,6 +221,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Create ${ description: `Create ${
startsWithVowel(rotationType) ? "an" : "a" startsWithVowel(rotationType) ? "an" : "a"
} ${rotationType} Rotation for the specified project.`, } ${rotationType} Rotation for the specified project.`,
@@ -254,6 +262,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Update the specified ${rotationType} Rotation.`, description: `Update the specified ${rotationType} Rotation.`,
params: z.object({ params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.UPDATE(type).rotationId) rotationId: z.string().uuid().describe(SecretRotations.UPDATE(type).rotationId)
@@ -296,6 +306,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Delete the specified ${rotationType} Rotation.`, description: `Delete the specified ${rotationType} Rotation.`,
params: z.object({ params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.DELETE(type).rotationId) rotationId: z.string().uuid().describe(SecretRotations.DELETE(type).rotationId)
@@ -349,6 +361,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Get the generated credentials for the specified ${rotationType} Rotation.`, description: `Get the generated credentials for the specified ${rotationType} Rotation.`,
params: z.object({ params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.GET_GENERATED_CREDENTIALS_BY_ID(type).rotationId) rotationId: z.string().uuid().describe(SecretRotations.GET_GENERATED_CREDENTIALS_BY_ID(type).rotationId)
@@ -402,6 +416,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Rotate the generated credentials for the specified ${rotationType} Rotation.`, description: `Rotate the generated credentials for the specified ${rotationType} Rotation.`,
params: z.object({ params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.ROTATE(type).rotationId) rotationId: z.string().uuid().describe(SecretRotations.ROTATE(type).rotationId)
@@ -6,7 +6,7 @@ import { AzureClientSecretRotationListItemSchema } from "@app/ee/services/secret
import { MsSqlCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/mssql-credentials"; import { MsSqlCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/mssql-credentials";
import { PostgresCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/postgres-credentials"; import { PostgresCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/postgres-credentials";
import { SecretRotationV2Schema } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-union-schema"; import { SecretRotationV2Schema } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-union-schema";
import { SecretRotations } from "@app/lib/api-docs"; import { ApiDocsTags, SecretRotations } from "@app/lib/api-docs";
import { readLimit } from "@app/server/config/rateLimiter"; import { readLimit } from "@app/server/config/rateLimiter";
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";
@@ -26,6 +26,8 @@ export const registerSecretRotationV2Router = async (server: FastifyZodProvider)
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: "List the available Secret Rotation Options.", description: "List the available Secret Rotation Options.",
response: { response: {
200: z.object({ 200: z.object({
@@ -47,6 +49,8 @@ export const registerSecretRotationV2Router = async (server: FastifyZodProvider)
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: "List all the Secret Rotations for the specified project.", description: "List all the Secret Rotations for the specified project.",
querystring: z.object({ querystring: z.object({
projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST().projectId) projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST().projectId)
@@ -234,6 +234,7 @@ export enum EventType {
GET_PROJECT_KMS_BACKUP = "get-project-kms-backup", GET_PROJECT_KMS_BACKUP = "get-project-kms-backup",
LOAD_PROJECT_KMS_BACKUP = "load-project-kms-backup", LOAD_PROJECT_KMS_BACKUP = "load-project-kms-backup",
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project", ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso",
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template", CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template", UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template", DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
@@ -1907,6 +1908,11 @@ interface OrgAdminAccessProjectEvent {
}; // no metadata yet }; // no metadata yet
} }
interface OrgAdminBypassSSOEvent {
type: EventType.ORG_ADMIN_BYPASS_SSO;
metadata: Record<string, string>; // no metadata yet
}
interface CreateCertificateTemplateEstConfig { interface CreateCertificateTemplateEstConfig {
type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG; type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG;
metadata: { metadata: {
@@ -2656,6 +2662,7 @@ export type Event =
| GetProjectKmsBackupEvent | GetProjectKmsBackupEvent
| LoadProjectKmsBackupEvent | LoadProjectKmsBackupEvent
| OrgAdminAccessProjectEvent | OrgAdminAccessProjectEvent
| OrgAdminBypassSSOEvent
| CreateCertificateTemplate | CreateCertificateTemplate
| UpdateCertificateTemplate | UpdateCertificateTemplate
| GetCertificateTemplate | GetCertificateTemplate
@@ -130,7 +130,17 @@ export const dynamicSecretLeaseServiceFactory = ({
if (expireAt > maxExpiryDate) throw new BadRequestError({ message: "TTL cannot be larger than max TTL" }); if (expireAt > maxExpiryDate) throw new BadRequestError({ message: "TTL cannot be larger than max TTL" });
} }
const { entityId, data } = await selectedProvider.create(decryptedStoredInput, expireAt.getTime()); let result;
try {
result = await selectedProvider.create(decryptedStoredInput, expireAt.getTime());
} catch (error: unknown) {
if (error && typeof error === "object" && error !== null && "sqlMessage" in error) {
throw new BadRequestError({ message: error.sqlMessage as string });
}
throw error;
}
const { entityId, data } = result;
const dynamicSecretLease = await dynamicSecretLeaseDAL.create({ const dynamicSecretLease = await dynamicSecretLeaseDAL.create({
expireAt, expireAt,
version: 1, version: 1,
@@ -267,7 +267,6 @@ export const secretReplicationServiceFactory = ({
const sourceLocalSecrets = await secretV2BridgeDAL.find({ folderId: folder.id, type: SecretType.Shared }); const sourceLocalSecrets = await secretV2BridgeDAL.find({ folderId: folder.id, type: SecretType.Shared });
const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id }); const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id });
const sourceImportedSecrets = await fnSecretsV2FromImports({ const sourceImportedSecrets = await fnSecretsV2FromImports({
projectId,
secretImports: sourceSecretImports, secretImports: sourceSecretImports,
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
folderDAL, folderDAL,
+46 -1
View File
@@ -8,6 +8,51 @@ import { APP_CONNECTION_NAME_MAP } from "@app/services/app-connection/app-connec
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps"; import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
export enum ApiDocsTags {
Identities = "Identities",
TokenAuth = "Token Auth",
UniversalAuth = "Universal Auth",
GcpAuth = "GCP Auth",
AwsAuth = "AWS Auth",
AzureAuth = "Azure Auth",
KubernetesAuth = "Kubernetes Auth",
JwtAuth = "JWT Auth",
OidcAuth = "OIDC Auth",
Groups = "Groups",
Organizations = "Organizations",
Projects = "Projects",
ProjectUsers = "Project Users",
ProjectGroups = "Project Groups",
ProjectIdentities = "Project Identities",
ProjectRoles = "Project Roles",
ProjectTemplates = "Project Templates",
Environments = "Environments",
Folders = "Folders",
SecretTags = "Secret Tags",
Secrets = "Secrets",
DynamicSecrets = "Dynamic Secrets",
SecretImports = "Secret Imports",
SecretRotations = "Secret Rotations",
IdentitySpecificPrivilegesV1 = "Identity Specific Privileges",
IdentitySpecificPrivilegesV2 = "Identity Specific Privileges V2",
AppConnections = "App Connections",
SecretSyncs = "Secret Syncs",
Integrations = "Integrations",
ServiceTokens = "Service Tokens",
AuditLogs = "Audit Logs",
PkiCertificateAuthorities = "PKI Certificate Authorities",
PkiCertificates = "PKI Certificates",
PkiCertificateTemplates = "PKI Certificate Templates",
PkiCertificateCollections = "PKI Certificate Collections",
PkiAlerting = "PKI Alerting",
SshCertificates = "SSH Certificates",
SshCertificateAuthorities = "SSH Certificate Authorities",
SshCertificateTemplates = "SSH Certificate Templates",
KmsKeys = "KMS Keys",
KmsEncryption = "KMS Encryption",
KmsSigning = "KMS Signing"
}
export const GROUPS = { export const GROUPS = {
CREATE: { CREATE: {
name: "The name of the group to create.", name: "The name of the group to create.",
@@ -888,7 +933,7 @@ export const DYNAMIC_SECRETS = {
environmentSlug: "The slug of the environment to list folders from.", environmentSlug: "The slug of the environment to list folders from.",
path: "The path to list folders from." path: "The path to list folders from."
}, },
LIST_LEAES_BY_NAME: { LIST_LEASES_BY_NAME: {
projectSlug: "The slug of the project to create dynamic secret in.", projectSlug: "The slug of the project to create dynamic secret in.",
environmentSlug: "The slug of the environment to list folders from.", environmentSlug: "The slug of the environment to list folders from.",
path: "The path to list folders from.", path: "The path to list folders from.",
+10 -6
View File
@@ -73,6 +73,7 @@ const run = async () => {
// eslint-disable-next-line // eslint-disable-next-line
process.on("SIGINT", async () => { process.on("SIGINT", async () => {
await server.close(); await server.close();
await queue.shutdown();
await db.destroy(); await db.destroy();
await removeTemporaryBaseDirectory(); await removeTemporaryBaseDirectory();
hsmModule.finalize(); hsmModule.finalize();
@@ -82,19 +83,22 @@ const run = async () => {
// eslint-disable-next-line // eslint-disable-next-line
process.on("SIGTERM", async () => { process.on("SIGTERM", async () => {
await server.close(); await server.close();
await queue.shutdown();
await db.destroy(); await db.destroy();
await removeTemporaryBaseDirectory(); await removeTemporaryBaseDirectory();
hsmModule.finalize(); hsmModule.finalize();
process.exit(0); process.exit(0);
}); });
process.on("uncaughtException", (error) => { if (!envConfig.isDevelopmentMode) {
logger.error(error, "CRITICAL ERROR: Uncaught Exception"); process.on("uncaughtException", (error) => {
}); logger.error(error, "CRITICAL ERROR: Uncaught Exception");
});
process.on("unhandledRejection", (error) => { process.on("unhandledRejection", (error) => {
logger.error(error, "CRITICAL ERROR: Unhandled Promise Rejection"); logger.error(error, "CRITICAL ERROR: Unhandled Promise Rejection");
}); });
}
await server.listen({ await server.listen({
port: envConfig.PORT, port: envConfig.PORT,
+5 -2
View File
@@ -49,14 +49,17 @@ function resolveSchema(maybeSchema: ZodAny | { properties: ZodAny }): Pick<ZodAn
} }
export const createJsonSchemaTransform = ({ skipList }: { skipList: readonly string[] }) => { export const createJsonSchemaTransform = ({ skipList }: { skipList: readonly string[] }) => {
return ({ schema, url }: { schema: Schema; url: string }) => { return ({ schema = {}, url }: { schema: Schema; url: string }) => {
if (!schema) { if (!schema) {
return { return {
schema, schema: { hide: true },
url url
}; };
} }
if (typeof schema.hide === "undefined") {
schema.hide = true;
}
const { response, headers, querystring, body, params, hide, ...rest } = schema; const { response, headers, querystring, body, params, hide, ...rest } = schema;
const transformed: FreeformRecord = {}; const transformed: FreeformRecord = {};
+10 -2
View File
@@ -596,7 +596,14 @@ export const registerRoutes = async (
kmsService kmsService
}); });
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService, orgDAL, totpService }); const loginService = authLoginServiceFactory({
userDAL,
smtpService,
tokenService,
orgDAL,
totpService,
auditLogService
});
const passwordService = authPaswordServiceFactory({ const passwordService = authPaswordServiceFactory({
tokenService, tokenService,
smtpService, smtpService,
@@ -1089,7 +1096,8 @@ export const registerRoutes = async (
secretApprovalRequestSecretDAL, secretApprovalRequestSecretDAL,
kmsService, kmsService,
snapshotService, snapshotService,
resourceMetadataDAL resourceMetadataDAL,
keyStore
}); });
const secretApprovalRequestService = secretApprovalRequestServiceFactory({ const secretApprovalRequestService = secretApprovalRequestServiceFactory({
@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { AppConnections } from "@app/lib/api-docs"; import { ApiDocsTags, AppConnections } from "@app/lib/api-docs";
import { startsWithVowel } from "@app/lib/fn"; import { startsWithVowel } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -43,6 +43,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `List the ${appName} Connections for the current organization.`, description: `List the ${appName} Connections for the current organization.`,
response: { response: {
200: z.object({ appConnections: sanitizedResponseSchema.array() }) 200: z.object({ appConnections: sanitizedResponseSchema.array() })
@@ -76,6 +78,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `List the ${appName} Connections the current user has permission to establish connections with.`, description: `List the ${appName} Connections the current user has permission to establish connections with.`,
response: { response: {
200: z.object({ 200: z.object({
@@ -120,6 +124,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Get the specified ${appName} Connection by ID.`, description: `Get the specified ${appName} Connection by ID.`,
params: z.object({ params: z.object({
connectionId: z.string().uuid().describe(AppConnections.GET_BY_ID(app).connectionId) connectionId: z.string().uuid().describe(AppConnections.GET_BY_ID(app).connectionId)
@@ -160,6 +166,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Get the specified ${appName} Connection by name.`, description: `Get the specified ${appName} Connection by name.`,
params: z.object({ params: z.object({
connectionName: z connectionName: z
@@ -204,6 +212,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Create ${ description: `Create ${
startsWithVowel(appName) ? "an" : "a" startsWithVowel(appName) ? "an" : "a"
} ${appName} Connection for the current organization.`, } ${appName} Connection for the current organization.`,
@@ -247,6 +257,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Update the specified ${appName} Connection.`, description: `Update the specified ${appName} Connection.`,
params: z.object({ params: z.object({
connectionId: z.string().uuid().describe(AppConnections.UPDATE(app).connectionId) connectionId: z.string().uuid().describe(AppConnections.UPDATE(app).connectionId)
@@ -292,6 +304,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Delete the specified ${appName} Connection.`, description: `Delete the specified ${appName} Connection.`,
params: z.object({ params: z.object({
connectionId: z.string().uuid().describe(AppConnections.DELETE(app).connectionId) connectionId: z.string().uuid().describe(AppConnections.DELETE(app).connectionId)
@@ -1,6 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApiDocsTags } from "@app/lib/api-docs";
import { readLimit } from "@app/server/config/rateLimiter"; import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { Auth0ConnectionListItemSchema, SanitizedAuth0ConnectionSchema } from "@app/services/app-connection/auth0"; import { Auth0ConnectionListItemSchema, SanitizedAuth0ConnectionSchema } from "@app/services/app-connection/auth0";
@@ -92,6 +93,8 @@ export const registerAppConnectionRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: "List the available App Connection Options.", description: "List the available App Connection Options.",
response: { response: {
200: z.object({ 200: z.object({
@@ -113,6 +116,8 @@ export const registerAppConnectionRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: "List all the App Connections for the current organization.", description: "List all the App Connections for the current organization.",
response: { response: {
200: z.object({ appConnections: SanitizedAppConnectionSchema.array() }) 200: z.object({ appConnections: SanitizedAppConnectionSchema.array() })
@@ -3,7 +3,7 @@ import { z } from "zod";
import { CertificateAuthoritiesSchema, CertificateTemplatesSchema } from "@app/db/schemas"; import { CertificateAuthoritiesSchema, CertificateTemplatesSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs"; import { ApiDocsTags, CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@@ -26,6 +26,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Create CA", description: "Create CA",
body: z body: z
.object({ .object({
@@ -105,6 +107,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get CA", description: "Get CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET.caId)
@@ -151,6 +155,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get DER-encoded certificate of CA", description: "Get DER-encoded certificate of CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caId), caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caId),
@@ -177,6 +183,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Update CA", description: "Update CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.UPDATE.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.UPDATE.caId)
@@ -231,6 +239,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Delete CA", description: "Delete CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.DELETE.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.DELETE.caId)
@@ -276,6 +286,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get CA CSR", description: "Get CA CSR",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CSR.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CSR.caId)
@@ -321,6 +333,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Perform CA certificate renewal", description: "Perform CA certificate renewal",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.caId)
@@ -376,6 +390,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get list of past and current CA certificates for a CA", description: "Get list of past and current CA certificates for a CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.caId)
@@ -424,6 +440,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get current CA cert and cert chain of a CA", description: "Get current CA cert and cert chain of a CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT.caId)
@@ -473,6 +491,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Create intermediate CA certificate from parent CA", description: "Create intermediate CA certificate from parent CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.caId)
@@ -536,6 +556,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Import certificate and chain to CA", description: "Import certificate and chain to CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.IMPORT_CERT.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.IMPORT_CERT.caId)
@@ -588,6 +610,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Issue certificate from CA", description: "Issue certificate from CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.caId)
@@ -679,6 +703,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Sign certificate from CA", description: "Sign certificate from CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId)
@@ -770,6 +796,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get list of certificate templates for the CA", description: "Get list of certificate templates for the CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId)
@@ -815,6 +843,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get list of CRLs of the CA", description: "Get list of CRLs of the CA",
params: z.object({ params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CRLS.caId) caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CRLS.caId)
@@ -2,7 +2,7 @@ import { z } from "zod";
import { CertificatesSchema } from "@app/db/schemas"; import { CertificatesSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { CERTIFICATE_AUTHORITIES, CERTIFICATES } from "@app/lib/api-docs"; import { ApiDocsTags, CERTIFICATE_AUTHORITIES, CERTIFICATES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@@ -24,6 +24,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Get certificate", description: "Get certificate",
params: z.object({ params: z.object({
serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber) serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber)
@@ -70,6 +72,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Issue certificate", description: "Issue certificate",
body: z body: z
.object({ .object({
@@ -181,6 +185,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Sign certificate", description: "Sign certificate",
body: z body: z
.object({ .object({
@@ -292,6 +298,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Revoke", description: "Revoke",
params: z.object({ params: z.object({
serialNumber: z.string().trim().describe(CERTIFICATES.REVOKE.serialNumber) serialNumber: z.string().trim().describe(CERTIFICATES.REVOKE.serialNumber)
@@ -346,6 +354,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Delete certificate", description: "Delete certificate",
params: z.object({ params: z.object({
serialNumber: z.string().trim().describe(CERTIFICATES.DELETE.serialNumber) serialNumber: z.string().trim().describe(CERTIFICATES.DELETE.serialNumber)
@@ -392,6 +402,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Get certificate body of certificate", description: "Get certificate body of certificate",
params: z.object({ params: z.object({
serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber) serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber)
@@ -2,7 +2,7 @@ import { z } from "zod";
import { CertificateTemplateEstConfigsSchema } from "@app/db/schemas"; import { CertificateTemplateEstConfigsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { CERTIFICATE_TEMPLATES } from "@app/lib/api-docs"; import { ApiDocsTags, CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -26,6 +26,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: z.object({ params: z.object({
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.GET.certificateTemplateId) certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
}), }),
@@ -65,6 +67,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
body: z.object({ body: z.object({
caId: z.string().describe(CERTIFICATE_TEMPLATES.CREATE.caId), caId: z.string().describe(CERTIFICATE_TEMPLATES.CREATE.caId),
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.CREATE.pkiCollectionId), pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.CREATE.pkiCollectionId),
@@ -132,6 +136,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
body: z.object({ body: z.object({
caId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.caId), caId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.caId),
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.pkiCollectionId), pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.pkiCollectionId),
@@ -198,6 +204,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: z.object({ params: z.object({
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId) certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
}), }),
@@ -238,6 +246,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
description: "Create Certificate Template EST configuration", description: "Create Certificate Template EST configuration",
params: z.object({ params: z.object({
certificateTemplateId: z.string().trim() certificateTemplateId: z.string().trim()
@@ -292,6 +302,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
description: "Update Certificate Template EST configuration", description: "Update Certificate Template EST configuration",
params: z.object({ params: z.object({
certificateTemplateId: z.string().trim() certificateTemplateId: z.string().trim()
@@ -340,6 +352,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
description: "Get Certificate Template EST configuration", description: "Get Certificate Template EST configuration",
params: z.object({ params: z.object({
certificateTemplateId: z.string().trim() certificateTemplateId: z.string().trim()
+25 -1
View File
@@ -2,7 +2,7 @@ import { z } from "zod";
import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas"; import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { KMS } from "@app/lib/api-docs"; import { ApiDocsTags, KMS } from "@app/lib/api-docs";
import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64"; import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64";
import { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; import { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign"; import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign";
@@ -46,6 +46,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Create KMS key", description: "Create KMS key",
body: z body: z
.object({ .object({
@@ -138,6 +140,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Update KMS key", description: "Update KMS key",
params: z.object({ params: z.object({
keyId: z.string().uuid().describe(KMS.UPDATE_KEY.keyId) keyId: z.string().uuid().describe(KMS.UPDATE_KEY.keyId)
@@ -187,6 +191,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Delete KMS key", description: "Delete KMS key",
params: z.object({ params: z.object({
keyId: z.string().uuid().describe(KMS.DELETE_KEY.keyId) keyId: z.string().uuid().describe(KMS.DELETE_KEY.keyId)
@@ -229,6 +235,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "List KMS keys", description: "List KMS keys",
querystring: z.object({ querystring: z.object({
projectId: z.string().describe(KMS.LIST_KEYS.projectId), projectId: z.string().describe(KMS.LIST_KEYS.projectId),
@@ -280,6 +288,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Get KMS key by ID", description: "Get KMS key by ID",
params: z.object({ params: z.object({
keyId: z.string().uuid().describe(KMS.GET_KEY_BY_ID.keyId) keyId: z.string().uuid().describe(KMS.GET_KEY_BY_ID.keyId)
@@ -321,6 +331,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Get KMS key by name", description: "Get KMS key by name",
params: z.object({ params: z.object({
keyName: slugSchema({ field: "Key name" }).describe(KMS.GET_KEY_BY_NAME.keyName) keyName: slugSchema({ field: "Key name" }).describe(KMS.GET_KEY_BY_NAME.keyName)
@@ -367,6 +379,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsEncryption],
description: "Encrypt data with KMS key", description: "Encrypt data with KMS key",
params: z.object({ params: z.object({
keyId: z.string().uuid().describe(KMS.ENCRYPT.keyId) keyId: z.string().uuid().describe(KMS.ENCRYPT.keyId)
@@ -412,6 +426,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsSigning],
description: description:
"Get the public key for a KMS key that is used for signing and verifying data. This endpoint is only available for asymmetric keys.", "Get the public key for a KMS key that is used for signing and verifying data. This endpoint is only available for asymmetric keys.",
params: z.object({ params: z.object({
@@ -454,6 +470,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsSigning],
description: "List all available signing algorithms for a KMS key", description: "List all available signing algorithms for a KMS key",
params: z.object({ params: z.object({
keyId: z.string().uuid().describe(KMS.LIST_SIGNING_ALGORITHMS.keyId) keyId: z.string().uuid().describe(KMS.LIST_SIGNING_ALGORITHMS.keyId)
@@ -495,6 +513,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsSigning],
description: "Sign data with a KMS key.", description: "Sign data with a KMS key.",
params: z.object({ params: z.object({
keyId: z.string().uuid().describe(KMS.SIGN.keyId) keyId: z.string().uuid().describe(KMS.SIGN.keyId)
@@ -548,6 +568,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsSigning],
description: "Verify data signatures with a KMS key.", description: "Verify data signatures with a KMS key.",
params: z.object({ params: z.object({
keyId: z.string().uuid().describe(KMS.VERIFY.keyId) keyId: z.string().uuid().describe(KMS.VERIFY.keyId)
@@ -604,6 +626,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KmsEncryption],
description: "Decrypt data with KMS key", description: "Decrypt data with KMS key",
params: z.object({ params: z.object({
keyId: z.string().uuid().describe(KMS.DECRYPT.keyId) keyId: z.string().uuid().describe(KMS.DECRYPT.keyId)
@@ -1,6 +1,6 @@
import { z } from "zod"; import { z } from "zod";
import { UNIVERSAL_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, UNIVERSAL_AUTH } from "@app/lib/api-docs";
import { writeLimit } from "@app/server/config/rateLimiter"; import { writeLimit } from "@app/server/config/rateLimiter";
export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => { export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => {
@@ -11,6 +11,8 @@ export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvid
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Renew access token", description: "Renew access token",
body: z.object({ body: z.object({
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.RENEW_ACCESS_TOKEN.accessToken) accessToken: z.string().trim().describe(UNIVERSAL_AUTH.RENEW_ACCESS_TOKEN.accessToken)
@@ -44,6 +46,8 @@ export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvid
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Revoke access token", description: "Revoke access token",
body: z.object({ body: z.object({
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.REVOKE_ACCESS_TOKEN.accessToken) accessToken: z.string().trim().describe(UNIVERSAL_AUTH.REVOKE_ACCESS_TOKEN.accessToken)
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityAwsAuthsSchema } from "@app/db/schemas"; import { IdentityAwsAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { AWS_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, AWS_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -21,6 +21,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Login with AWS Auth", description: "Login with AWS Auth",
body: z.object({ body: z.object({
identityId: z.string().trim().describe(AWS_AUTH.LOGIN.identityId), identityId: z.string().trim().describe(AWS_AUTH.LOGIN.identityId),
@@ -71,6 +73,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Attach AWS Auth configuration onto identity", description: "Attach AWS Auth configuration onto identity",
security: [ security: [
{ {
@@ -165,6 +169,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Update AWS Auth configuration on identity", description: "Update AWS Auth configuration on identity",
security: [ security: [
{ {
@@ -247,6 +253,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Retrieve AWS Auth configuration on identity", description: "Retrieve AWS Auth configuration on identity",
security: [ security: [
{ {
@@ -293,6 +301,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Delete AWS Auth configuration on identity", description: "Delete AWS Auth configuration on identity",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityAzureAuthsSchema } from "@app/db/schemas"; import { IdentityAzureAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { AZURE_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, AZURE_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -18,6 +18,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Login with Azure Auth", description: "Login with Azure Auth",
body: z.object({ body: z.object({
identityId: z.string().trim().describe(AZURE_AUTH.LOGIN.identityId), identityId: z.string().trim().describe(AZURE_AUTH.LOGIN.identityId),
@@ -66,6 +68,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Attach Azure Auth configuration onto identity", description: "Attach Azure Auth configuration onto identity",
security: [ security: [
{ {
@@ -159,6 +163,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Update Azure Auth configuration on identity", description: "Update Azure Auth configuration on identity",
security: [ security: [
{ {
@@ -247,6 +253,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Retrieve Azure Auth configuration on identity", description: "Retrieve Azure Auth configuration on identity",
security: [ security: [
{ {
@@ -294,6 +302,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Delete Azure Auth configuration on identity", description: "Delete Azure Auth configuration on identity",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityGcpAuthsSchema } from "@app/db/schemas"; import { IdentityGcpAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { GCP_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, GCP_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -18,9 +18,11 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Login with GCP Auth", description: "Login with GCP Auth",
body: z.object({ body: z.object({
identityId: z.string().trim().describe(GCP_AUTH.LOGIN.identityId).trim(), identityId: z.string().trim().describe(GCP_AUTH.LOGIN.identityId),
jwt: z.string() jwt: z.string()
}), }),
response: { response: {
@@ -66,6 +68,8 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Attach GCP Auth configuration onto identity", description: "Attach GCP Auth configuration onto identity",
security: [ security: [
{ {
@@ -157,6 +161,8 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Update GCP Auth configuration on identity", description: "Update GCP Auth configuration on identity",
security: [ security: [
{ {
@@ -241,6 +247,8 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Retrieve GCP Auth configuration on identity", description: "Retrieve GCP Auth configuration on identity",
security: [ security: [
{ {
@@ -288,6 +296,8 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Delete GCP Auth configuration on identity", description: "Delete GCP Auth configuration on identity",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityJwtAuthsSchema } from "@app/db/schemas"; import { IdentityJwtAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { JWT_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, JWT_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -94,6 +94,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Login with JWT Auth", description: "Login with JWT Auth",
body: z.object({ body: z.object({
identityId: z.string().trim().describe(JWT_AUTH.LOGIN.identityId), identityId: z.string().trim().describe(JWT_AUTH.LOGIN.identityId),
@@ -144,6 +146,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Attach JWT Auth configuration onto identity", description: "Attach JWT Auth configuration onto identity",
security: [ security: [
{ {
@@ -211,6 +215,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Update JWT Auth configuration on identity", description: "Update JWT Auth configuration on identity",
security: [ security: [
{ {
@@ -275,6 +281,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Retrieve JWT Auth configuration on identity", description: "Retrieve JWT Auth configuration on identity",
security: [ security: [
{ {
@@ -322,6 +330,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Delete JWT Auth configuration on identity", description: "Delete JWT Auth configuration on identity",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityKubernetesAuthsSchema } from "@app/db/schemas"; import { IdentityKubernetesAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { KUBERNETES_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, KUBERNETES_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -35,6 +35,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Login with Kubernetes Auth", description: "Login with Kubernetes Auth",
body: z.object({ body: z.object({
identityId: z.string().trim().describe(KUBERNETES_AUTH.LOGIN.identityId), identityId: z.string().trim().describe(KUBERNETES_AUTH.LOGIN.identityId),
@@ -85,6 +87,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Attach Kubernetes Auth configuration onto identity", description: "Attach Kubernetes Auth configuration onto identity",
security: [ security: [
{ {
@@ -182,6 +186,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Update Kubernetes Auth configuration on identity", description: "Update Kubernetes Auth configuration on identity",
security: [ security: [
{ {
@@ -278,6 +284,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Retrieve Kubernetes Auth configuration on identity", description: "Retrieve Kubernetes Auth configuration on identity",
security: [ security: [
{ {
@@ -325,6 +333,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Delete Kubernetes Auth configuration on identity", description: "Delete Kubernetes Auth configuration on identity",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityOidcAuthsSchema } from "@app/db/schemas"; import { IdentityOidcAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { OIDC_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, OIDC_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -42,6 +42,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Login with OIDC Auth", description: "Login with OIDC Auth",
body: z.object({ body: z.object({
identityId: z.string().trim().describe(OIDC_AUTH.LOGIN.identityId), identityId: z.string().trim().describe(OIDC_AUTH.LOGIN.identityId),
@@ -96,6 +98,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Attach OIDC Auth configuration onto identity", description: "Attach OIDC Auth configuration onto identity",
security: [ security: [
{ {
@@ -195,6 +199,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Update OIDC Auth configuration on identity", description: "Update OIDC Auth configuration on identity",
security: [ security: [
{ {
@@ -292,6 +298,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Retrieve OIDC Auth configuration on identity", description: "Retrieve OIDC Auth configuration on identity",
security: [ security: [
{ {
@@ -339,6 +347,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Delete OIDC Auth configuration on identity", description: "Delete OIDC Auth configuration on identity",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgMembershipRole, OrgRolesSchema } from "@app/db/schemas"; import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgMembershipRole, OrgRolesSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { IDENTITIES } from "@app/lib/api-docs"; import { ApiDocsTags, IDENTITIES } from "@app/lib/api-docs";
import { buildSearchZodSchema, SearchResourceOperators } from "@app/lib/search-resource/search"; import { buildSearchZodSchema, SearchResourceOperators } from "@app/lib/search-resource/search";
import { OrderByDirection } from "@app/lib/types"; import { OrderByDirection } from "@app/lib/types";
import { CharacterType, zodValidateCharacters } from "@app/lib/validator/validate-string"; import { CharacterType, zodValidateCharacters } from "@app/lib/validator/validate-string";
@@ -32,6 +32,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Create identity", description: "Create identity",
security: [ security: [
{ {
@@ -100,6 +102,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Update identity", description: "Update identity",
security: [ security: [
{ {
@@ -158,6 +162,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Delete identity", description: "Delete identity",
security: [ security: [
{ {
@@ -205,6 +211,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Get an identity by id", description: "Get an identity by id",
security: [ security: [
{ {
@@ -260,6 +268,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "List identities", description: "List identities",
security: [ security: [
{ {
@@ -308,6 +318,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Search identities", description: "Search identities",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityAccessTokensSchema, IdentityTokenAuthsSchema } from "@app/db/schemas"; import { IdentityAccessTokensSchema, IdentityTokenAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { TOKEN_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, TOKEN_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -18,6 +18,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Attach Token Auth configuration onto identity", description: "Attach Token Auth configuration onto identity",
security: [ security: [
{ {
@@ -108,6 +110,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Update Token Auth configuration on identity", description: "Update Token Auth configuration on identity",
security: [ security: [
{ {
@@ -192,6 +196,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Retrieve Token Auth configuration on identity", description: "Retrieve Token Auth configuration on identity",
security: [ security: [
{ {
@@ -239,6 +245,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Delete Token Auth configuration on identity", description: "Delete Token Auth configuration on identity",
security: [ security: [
{ {
@@ -287,6 +295,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Create token for identity with Token Auth", description: "Create token for identity with Token Auth",
security: [ security: [
{ {
@@ -349,6 +359,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Get tokens for identity with Token Auth", description: "Get tokens for identity with Token Auth",
security: [ security: [
{ {
@@ -402,6 +414,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Update token for identity with Token Auth", description: "Update token for identity with Token Auth",
security: [ security: [
{ {
@@ -456,6 +470,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Revoke token for identity with Token Auth", description: "Revoke token for identity with Token Auth",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityUaClientSecretsSchema, IdentityUniversalAuthsSchema } from "@app/db/schemas"; import { IdentityUaClientSecretsSchema, IdentityUniversalAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { UNIVERSAL_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, UNIVERSAL_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -30,6 +30,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Login with Universal Auth", description: "Login with Universal Auth",
body: z.object({ body: z.object({
clientId: z.string().trim().describe(UNIVERSAL_AUTH.LOGIN.clientId), clientId: z.string().trim().describe(UNIVERSAL_AUTH.LOGIN.clientId),
@@ -78,6 +80,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Attach Universal Auth configuration onto identity", description: "Attach Universal Auth configuration onto identity",
security: [ security: [
{ {
@@ -175,6 +179,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Update Universal Auth configuration on identity", description: "Update Universal Auth configuration on identity",
security: [ security: [
{ {
@@ -271,6 +277,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Retrieve Universal Auth configuration on identity", description: "Retrieve Universal Auth configuration on identity",
security: [ security: [
{ {
@@ -318,6 +326,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Delete Universal Auth configuration on identity", description: "Delete Universal Auth configuration on identity",
security: [ security: [
{ {
@@ -365,6 +375,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Create Universal Auth Client Secret for identity", description: "Create Universal Auth Client Secret for identity",
security: [ security: [
{ {
@@ -421,6 +433,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "List Universal Auth Client Secrets for identity", description: "List Universal Auth Client Secrets for identity",
security: [ security: [
{ {
@@ -469,6 +483,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Get Universal Auth Client Secret for identity", description: "Get Universal Auth Client Secret for identity",
security: [ security: [
{ {
@@ -519,6 +535,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Revoke Universal Auth Client Secrets for identity", description: "Revoke Universal Auth Client Secrets for identity",
security: [ security: [
{ {
@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { INTEGRATION_AUTH } from "@app/lib/api-docs"; import { ApiDocsTags, INTEGRATION_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -19,6 +19,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "List of integrations available.", description: "List of integrations available.",
security: [ security: [
{ {
@@ -57,6 +59,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Get details of an integration authorization by auth object id.", description: "Get details of an integration authorization by auth object id.",
security: [ security: [
{ {
@@ -92,6 +96,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Update the integration authentication object required for syncing secrets.", description: "Update the integration authentication object required for syncing secrets.",
security: [ security: [
{ {
@@ -153,6 +159,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Remove all integration's auth object from the project.", description: "Remove all integration's auth object from the project.",
security: [ security: [
{ {
@@ -202,6 +210,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Remove an integration auth object by object id.", description: "Remove an integration auth object by object id.",
security: [ security: [
{ {
@@ -294,6 +304,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Create the integration authentication object required for syncing secrets.", description: "Create the integration authentication object required for syncing secrets.",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { IntegrationsSchema } from "@app/db/schemas"; import { IntegrationsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { INTEGRATION } from "@app/lib/api-docs"; import { ApiDocsTags, INTEGRATION } from "@app/lib/api-docs";
import { removeTrailingSlash, shake } from "@app/lib/fn"; import { removeTrailingSlash, shake } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@@ -22,6 +22,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Create an integration to sync secrets.", description: "Create an integration to sync secrets.",
security: [ security: [
{ {
@@ -119,6 +121,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Update an integration by integration id", description: "Update an integration by integration id",
security: [ security: [
{ {
@@ -178,6 +182,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Get an integration by integration id", description: "Get an integration by integration id",
security: [ security: [
{ {
@@ -247,6 +253,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Remove an integration using the integration object ID", description: "Remove an integration using the integration object ID",
security: [ security: [
{ {
@@ -315,6 +323,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Manually trigger sync of an integration by integration id", description: "Manually trigger sync of an integration by integration id",
security: [ security: [
{ {
@@ -9,7 +9,7 @@ import {
UsersSchema UsersSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
import { AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs"; import { ApiDocsTags, AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn"; import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { GenericResourceNameSchema, slugSchema } from "@app/server/lib/schemas"; import { GenericResourceNameSchema, slugSchema } from "@app/server/lib/schemas";
@@ -109,6 +109,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.AuditLogs],
description: "Get all audit logs for an organization", description: "Get all audit logs for an organization",
querystring: z.object({ querystring: z.object({
projectId: z.string().optional().describe(AUDIT_LOGS.EXPORT.projectId), projectId: z.string().optional().describe(AUDIT_LOGS.EXPORT.projectId),
@@ -2,7 +2,7 @@ import { z } from "zod";
import { PkiAlertsSchema } from "@app/db/schemas"; import { PkiAlertsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ALERTS } from "@app/lib/api-docs"; import { ALERTS, ApiDocsTags } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -16,6 +16,8 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
description: "Create PKI alert", description: "Create PKI alert",
body: z.object({ body: z.object({
projectId: z.string().trim().describe(ALERTS.CREATE.projectId), projectId: z.string().trim().describe(ALERTS.CREATE.projectId),
@@ -68,6 +70,8 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
description: "Get PKI alert", description: "Get PKI alert",
params: z.object({ params: z.object({
alertId: z.string().trim().describe(ALERTS.GET.alertId) alertId: z.string().trim().describe(ALERTS.GET.alertId)
@@ -108,6 +112,8 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
description: "Update PKI alert", description: "Update PKI alert",
params: z.object({ params: z.object({
alertId: z.string().trim().describe(ALERTS.UPDATE.alertId) alertId: z.string().trim().describe(ALERTS.UPDATE.alertId)
@@ -164,6 +170,8 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
description: "Delete PKI alert", description: "Delete PKI alert",
params: z.object({ params: z.object({
alertId: z.string().trim().describe(ALERTS.DELETE.alertId) alertId: z.string().trim().describe(ALERTS.DELETE.alertId)
@@ -2,7 +2,7 @@ import { z } from "zod";
import { PkiCollectionItemsSchema, PkiCollectionsSchema } from "@app/db/schemas"; import { PkiCollectionItemsSchema, PkiCollectionsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PKI_COLLECTIONS } from "@app/lib/api-docs"; import { ApiDocsTags, PKI_COLLECTIONS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -17,6 +17,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Create PKI collection", description: "Create PKI collection",
body: z.object({ body: z.object({
projectId: z.string().trim().describe(PKI_COLLECTIONS.CREATE.projectId), projectId: z.string().trim().describe(PKI_COLLECTIONS.CREATE.projectId),
@@ -60,6 +62,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Get PKI collection", description: "Get PKI collection",
params: z.object({ params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.GET.collectionId) collectionId: z.string().trim().describe(PKI_COLLECTIONS.GET.collectionId)
@@ -100,6 +104,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Update PKI collection", description: "Update PKI collection",
params: z.object({ params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.UPDATE.collectionId) collectionId: z.string().trim().describe(PKI_COLLECTIONS.UPDATE.collectionId)
@@ -146,6 +152,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Delete PKI collection", description: "Delete PKI collection",
params: z.object({ params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.DELETE.collectionId) collectionId: z.string().trim().describe(PKI_COLLECTIONS.DELETE.collectionId)
@@ -186,6 +194,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Get items in PKI collection", description: "Get items in PKI collection",
params: z.object({ params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.LIST_ITEMS.collectionId) collectionId: z.string().trim().describe(PKI_COLLECTIONS.LIST_ITEMS.collectionId)
@@ -247,6 +257,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Add item to PKI collection", description: "Add item to PKI collection",
params: z.object({ params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.ADD_ITEM.collectionId) collectionId: z.string().trim().describe(PKI_COLLECTIONS.ADD_ITEM.collectionId)
@@ -298,6 +310,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Remove item from PKI collection", description: "Remove item from PKI collection",
params: z.object({ params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.DELETE_ITEM.collectionId), collectionId: z.string().trim().describe(PKI_COLLECTIONS.DELETE_ITEM.collectionId),
@@ -2,7 +2,7 @@ import { z } from "zod";
import { ProjectEnvironmentsSchema } from "@app/db/schemas"; import { ProjectEnvironmentsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ENVIRONMENTS } from "@app/lib/api-docs"; import { ApiDocsTags, ENVIRONMENTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas"; import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -13,9 +13,11 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
method: "GET", method: "GET",
url: "/:workspaceId/environments/:envId", url: "/:workspaceId/environments/:envId",
config: { config: {
rateLimit: writeLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Get Environment", description: "Get Environment",
security: [ security: [
{ {
@@ -65,6 +67,8 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Get Environment by ID", description: "Get Environment by ID",
security: [ security: [
{ {
@@ -112,6 +116,8 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Create environment", description: "Create environment",
security: [ security: [
{ {
@@ -171,6 +177,8 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Update environment", description: "Update environment",
security: [ security: [
{ {
@@ -237,6 +245,8 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Delete environment", description: "Delete environment",
security: [ security: [
{ {
@@ -8,7 +8,7 @@ import {
UsersSchema UsersSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECT_USERS } from "@app/lib/api-docs"; import { ApiDocsTags, PROJECT_USERS } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -23,6 +23,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Return project user memberships", description: "Return project user memberships",
security: [ security: [
{ {
@@ -141,6 +143,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Return project user memberships", description: "Return project user memberships",
security: [ security: [
{ {
@@ -255,6 +259,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Update project user membership", description: "Update project user membership",
security: [ security: [
{ {
+11 -1
View File
@@ -13,7 +13,7 @@ import {
UsersSchema UsersSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECTS } from "@app/lib/api-docs"; import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
import { CharacterType, characterValidator } from "@app/lib/validator/validate-string"; import { CharacterType, characterValidator } from "@app/lib/validator/validate-string";
import { re2Validator } from "@app/lib/zod"; import { re2Validator } from "@app/lib/zod";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
@@ -177,6 +177,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Get project", description: "Get project",
security: [ security: [
{ {
@@ -215,6 +217,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Delete project", description: "Delete project",
security: [ security: [
{ {
@@ -290,6 +294,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Update project", description: "Update project",
security: [ security: [
{ {
@@ -513,6 +519,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "List integrations for a project.", description: "List integrations for a project.",
security: [ security: [
{ {
@@ -556,6 +564,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "List integration auth objects for a workspace.", description: "List integration auth objects for a workspace.",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { SecretFoldersSchema } from "@app/db/schemas"; import { SecretFoldersSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { FOLDERS } from "@app/lib/api-docs"; import { ApiDocsTags, FOLDERS } from "@app/lib/api-docs";
import { prefixWithSlash, removeTrailingSlash } from "@app/lib/fn"; import { prefixWithSlash, removeTrailingSlash } from "@app/lib/fn";
import { isValidFolderName } from "@app/lib/validator"; import { isValidFolderName } from "@app/lib/validator";
import { readLimit, secretsLimit } from "@app/server/config/rateLimiter"; import { readLimit, secretsLimit } from "@app/server/config/rateLimiter";
@@ -19,6 +19,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Create folders", description: "Create folders",
security: [ security: [
{ {
@@ -98,6 +100,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Update folder", description: "Update folder",
security: [ security: [
{ {
@@ -181,6 +185,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Update folders by batch", description: "Update folders by batch",
security: [ security: [
{ {
@@ -259,6 +265,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Delete a folder", description: "Delete a folder",
security: [ security: [
{ {
@@ -332,6 +340,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Get folders", description: "Get folders",
security: [ security: [
{ {
@@ -390,6 +400,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Get folder by id", description: "Get folder by id",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { SecretImportsSchema, SecretsSchema } from "@app/db/schemas"; import { SecretImportsSchema, SecretsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { SECRET_IMPORTS } from "@app/lib/api-docs"; import { ApiDocsTags, SECRET_IMPORTS } from "@app/lib/api-docs";
import { removeTrailingSlash } from "@app/lib/fn"; import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, secretsLimit } from "@app/server/config/rateLimiter"; import { readLimit, secretsLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -18,6 +18,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Create secret imports", description: "Create secret imports",
security: [ security: [
{ {
@@ -83,6 +85,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Update secret imports", description: "Update secret imports",
security: [ security: [
{ {
@@ -157,6 +161,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Delete secret imports", description: "Delete secret imports",
security: [ security: [
{ {
@@ -263,6 +269,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Get secret imports", description: "Get secret imports",
security: [ security: [
{ {
@@ -319,6 +327,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Get single secret import", description: "Get single secret import",
security: [ security: [
{ {
@@ -421,6 +431,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
querystring: z.object({ querystring: z.object({
workspaceId: z.string().trim(), workspaceId: z.string().trim(),
environment: z.string().trim(), environment: z.string().trim(),
@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { SecretSyncs } from "@app/lib/api-docs"; import { ApiDocsTags, SecretSyncs } from "@app/lib/api-docs";
import { startsWithVowel } from "@app/lib/fn"; import { startsWithVowel } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -51,6 +51,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `List the ${destinationName} Syncs for the specified project.`, description: `List the ${destinationName} Syncs for the specified project.`,
querystring: z.object({ querystring: z.object({
projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.LIST(destination).projectId) projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.LIST(destination).projectId)
@@ -94,6 +96,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Get the specified ${destinationName} Sync by ID.`, description: `Get the specified ${destinationName} Sync by ID.`,
params: z.object({ params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.GET_BY_ID(destination).syncId) syncId: z.string().uuid().describe(SecretSyncs.GET_BY_ID(destination).syncId)
@@ -134,6 +138,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Get the specified ${destinationName} Sync by name and project ID.`, description: `Get the specified ${destinationName} Sync by name and project ID.`,
params: z.object({ params: z.object({
syncName: z.string().trim().min(1, "Sync name required").describe(SecretSyncs.GET_BY_NAME(destination).syncName) syncName: z.string().trim().min(1, "Sync name required").describe(SecretSyncs.GET_BY_NAME(destination).syncName)
@@ -182,6 +188,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Create ${ description: `Create ${
startsWithVowel(destinationName) ? "an" : "a" startsWithVowel(destinationName) ? "an" : "a"
} ${destinationName} Sync for the specified project environment.`, } ${destinationName} Sync for the specified project environment.`,
@@ -221,6 +229,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Update the specified ${destinationName} Sync.`, description: `Update the specified ${destinationName} Sync.`,
params: z.object({ params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.UPDATE(destination).syncId) syncId: z.string().uuid().describe(SecretSyncs.UPDATE(destination).syncId)
@@ -263,6 +273,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Delete the specified ${destinationName} Sync.`, description: `Delete the specified ${destinationName} Sync.`,
params: z.object({ params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.DELETE(destination).syncId) syncId: z.string().uuid().describe(SecretSyncs.DELETE(destination).syncId)
@@ -312,6 +324,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Trigger a sync for the specified ${destinationName} Sync.`, description: `Trigger a sync for the specified ${destinationName} Sync.`,
params: z.object({ params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.SYNC_SECRETS(destination).syncId) syncId: z.string().uuid().describe(SecretSyncs.SYNC_SECRETS(destination).syncId)
@@ -344,6 +358,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Import secrets from the specified ${destinationName} Sync destination.`, description: `Import secrets from the specified ${destinationName} Sync destination.`,
params: z.object({ params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.IMPORT_SECRETS(destination).syncId) syncId: z.string().uuid().describe(SecretSyncs.IMPORT_SECRETS(destination).syncId)
@@ -382,6 +398,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Remove previously synced secrets from the specified ${destinationName} Sync destination.`, description: `Remove previously synced secrets from the specified ${destinationName} Sync destination.`,
params: z.object({ params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.REMOVE_SECRETS(destination).syncId) syncId: z.string().uuid().describe(SecretSyncs.REMOVE_SECRETS(destination).syncId)
@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { SecretSyncs } from "@app/lib/api-docs"; import { ApiDocsTags, SecretSyncs } from "@app/lib/api-docs";
import { readLimit } from "@app/server/config/rateLimiter"; import { readLimit } from "@app/server/config/rateLimiter";
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";
@@ -65,6 +65,8 @@ export const registerSecretSyncRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: "List the available Secret Sync Options.", description: "List the available Secret Sync Options.",
response: { response: {
200: z.object({ 200: z.object({
@@ -86,6 +88,8 @@ export const registerSecretSyncRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: "List all the Secret Syncs for the specified project.", description: "List all the Secret Syncs for the specified project.",
querystring: z.object({ querystring: z.object({
projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.LIST().projectId) projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.LIST().projectId)
@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { SecretTagsSchema } from "@app/db/schemas"; import { SecretTagsSchema } from "@app/db/schemas";
import { SECRET_TAGS } from "@app/lib/api-docs"; import { ApiDocsTags, SECRET_TAGS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas"; import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -15,6 +15,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.LIST.projectId) projectId: z.string().trim().describe(SECRET_TAGS.LIST.projectId)
}), }),
@@ -44,6 +46,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_ID.projectId), projectId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_ID.projectId),
tagId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_ID.tagId) tagId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_ID.tagId)
@@ -75,6 +79,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_SLUG.projectId), projectId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_SLUG.projectId),
tagSlug: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_SLUG.tagSlug) tagSlug: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_SLUG.tagSlug)
@@ -107,6 +113,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.CREATE.projectId) projectId: z.string().trim().describe(SECRET_TAGS.CREATE.projectId)
}), }),
@@ -141,6 +149,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.UPDATE.projectId), projectId: z.string().trim().describe(SECRET_TAGS.UPDATE.projectId),
tagId: z.string().trim().describe(SECRET_TAGS.UPDATE.tagId) tagId: z.string().trim().describe(SECRET_TAGS.UPDATE.tagId)
@@ -176,6 +186,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.DELETE.projectId), projectId: z.string().trim().describe(SECRET_TAGS.DELETE.projectId),
tagId: z.string().trim().describe(SECRET_TAGS.DELETE.tagId) tagId: z.string().trim().describe(SECRET_TAGS.DELETE.tagId)
@@ -6,7 +6,7 @@ import {
ProjectMembershipRole, ProjectMembershipRole,
ProjectUserMembershipRolesSchema ProjectUserMembershipRolesSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
import { PROJECTS } from "@app/lib/api-docs"; import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -22,6 +22,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Add group to project", description: "Add group to project",
security: [ security: [
{ {
@@ -88,6 +90,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
url: "/:projectId/groups/:groupId", url: "/:projectId/groups/:groupId",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Update group in project", description: "Update group in project",
security: [ security: [
{ {
@@ -147,6 +151,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Remove group from project", description: "Remove group from project",
security: [ security: [
{ {
@@ -185,6 +191,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Return list of groups in project", description: "Return list of groups in project",
security: [ security: [
{ {
@@ -243,6 +251,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Return project group", description: "Return project group",
security: [ security: [
{ {
@@ -1,7 +1,7 @@
import { z } from "zod"; import { z } from "zod";
import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas"; import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
import { ORGANIZATIONS } from "@app/lib/api-docs"; import { ApiDocsTags, ORGANIZATIONS } from "@app/lib/api-docs";
import { OrderByDirection } from "@app/lib/types"; import { OrderByDirection } from "@app/lib/types";
import { readLimit } from "@app/server/config/rateLimiter"; import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -17,6 +17,8 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Return organization identity memberships", description: "Return organization identity memberships",
security: [ security: [
{ {
@@ -6,7 +6,7 @@ import {
ProjectMembershipRole, ProjectMembershipRole,
ProjectUserMembershipRolesSchema ProjectUserMembershipRolesSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
import { ORGANIZATIONS, PROJECT_IDENTITIES } from "@app/lib/api-docs"; import { ApiDocsTags, ORGANIZATIONS, PROJECT_IDENTITIES } from "@app/lib/api-docs";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { OrderByDirection } from "@app/lib/types"; import { OrderByDirection } from "@app/lib/types";
@@ -27,6 +27,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Create project identity membership", description: "Create project identity membership",
security: [ security: [
{ {
@@ -101,6 +103,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Update project identity memberships", description: "Update project identity memberships",
security: [ security: [
{ {
@@ -170,6 +174,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Delete project identity memberships", description: "Delete project identity memberships",
security: [ security: [
{ {
@@ -207,6 +213,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Return project identity memberships", description: "Return project identity memberships",
security: [ security: [
{ {
@@ -300,6 +308,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Return project identity membership", description: "Return project identity membership",
security: [ security: [
{ {
@@ -360,6 +370,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
}, },
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
params: z.object({ params: z.object({
identityMembershipId: z.string().trim() identityMembershipId: z.string().trim()
}), }),
@@ -8,7 +8,7 @@ import {
UserEncryptionKeysSchema, UserEncryptionKeysSchema,
UsersSchema UsersSchema
} from "@app/db/schemas"; } from "@app/db/schemas";
import { ORGANIZATIONS } from "@app/lib/api-docs"; import { ApiDocsTags, ORGANIZATIONS } from "@app/lib/api-docs";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { GenericResourceNameSchema } from "@app/server/lib/schemas"; import { GenericResourceNameSchema } from "@app/server/lib/schemas";
@@ -24,6 +24,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Return organization user memberships", description: "Return organization user memberships",
security: [ security: [
{ {
@@ -72,6 +74,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Return projects in organization that user is apart of", description: "Return projects in organization that user is apart of",
security: [ security: [
{ {
@@ -179,6 +183,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Update organization user memberships", description: "Update organization user memberships",
security: [ security: [
{ {
@@ -229,6 +235,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Delete organization user memberships", description: "Delete organization user memberships",
security: [ security: [
{ {
@@ -2,7 +2,7 @@ import { z } from "zod";
import { OrgMembershipRole, ProjectMembershipRole, ProjectMembershipsSchema } from "@app/db/schemas"; import { OrgMembershipRole, ProjectMembershipRole, ProjectMembershipsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECT_USERS } from "@app/lib/api-docs"; import { ApiDocsTags, PROJECT_USERS } from "@app/lib/api-docs";
import { writeLimit } from "@app/server/config/rateLimiter"; import { writeLimit } from "@app/server/config/rateLimiter";
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";
@@ -15,6 +15,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Invite members to project", description: "Invite members to project",
security: [ security: [
{ {
@@ -78,6 +80,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Remove members from project", description: "Remove members from project",
security: [ security: [
{ {
+15 -2
View File
@@ -14,7 +14,7 @@ import { sanitizedSshCa } from "@app/ee/services/ssh/ssh-certificate-authority-s
import { sanitizedSshCertificate } from "@app/ee/services/ssh-certificate/ssh-certificate-schema"; import { sanitizedSshCertificate } from "@app/ee/services/ssh-certificate/ssh-certificate-schema";
import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema"; import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema";
import { loginMappingSchema, sanitizedSshHost } from "@app/ee/services/ssh-host/ssh-host-schema"; import { loginMappingSchema, sanitizedSshHost } from "@app/ee/services/ssh-host/ssh-host-schema";
import { PROJECTS } from "@app/lib/api-docs"; import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas"; import { slugSchema } from "@app/server/lib/schemas";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry"; import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@@ -29,7 +29,8 @@ import { SanitizedProjectSchema } from "../sanitizedSchemas";
const projectWithEnv = SanitizedProjectSchema.extend({ const projectWithEnv = SanitizedProjectSchema.extend({
_id: z.string(), _id: z.string(),
environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array() environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array(),
kmsSecretManagerKeyId: z.string().nullable().optional()
}); });
export const registerProjectRouter = async (server: FastifyZodProvider) => { export const registerProjectRouter = async (server: FastifyZodProvider) => {
@@ -150,6 +151,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Create a new project", description: "Create a new project",
security: [ security: [
{ {
@@ -224,6 +227,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Delete project", description: "Delete project",
security: [ security: [
{ {
@@ -342,6 +347,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
params: z.object({ params: z.object({
slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CAS.slug) slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CAS.slug)
}), }),
@@ -383,6 +390,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
params: z.object({ params: z.object({
slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CERTIFICATES.slug) slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CERTIFICATES.slug)
}), }),
@@ -551,6 +560,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CERTIFICATE_TEMPLATES.projectId) projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CERTIFICATE_TEMPLATES.projectId)
}), }),
@@ -581,6 +592,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
params: z.object({ params: z.object({
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CAS.projectId) projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CAS.projectId)
}), }),
@@ -2,6 +2,7 @@ import { z } from "zod";
import { ServiceTokensSchema } from "@app/db/schemas"; import { ServiceTokensSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApiDocsTags } from "@app/lib/api-docs";
import { removeTrailingSlash } from "@app/lib/fn"; import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -25,6 +26,8 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
}, },
onRequest: verifyAuth([AuthMode.SERVICE_TOKEN]), onRequest: verifyAuth([AuthMode.SERVICE_TOKEN]),
schema: { schema: {
hide: false,
tags: [ApiDocsTags.ServiceTokens],
description: "Return Infisical Token data", description: "Return Infisical Token data",
security: [ security: [
{ {
+27 -1
View File
@@ -3,7 +3,7 @@ import { z } from "zod";
import { SecretApprovalRequestsSchema, SecretsSchema, SecretType, ServiceTokenScopes } from "@app/db/schemas"; import { SecretApprovalRequestsSchema, SecretsSchema, SecretType, ServiceTokenScopes } from "@app/db/schemas";
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
import { RAW_SECRETS, SECRETS } from "@app/lib/api-docs"; import { ApiDocsTags, RAW_SECRETS, SECRETS } from "@app/lib/api-docs";
import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { removeTrailingSlash } from "@app/lib/fn"; import { removeTrailingSlash } from "@app/lib/fn";
import { secretsLimit, writeLimit } from "@app/server/config/rateLimiter"; import { secretsLimit, writeLimit } from "@app/server/config/rateLimiter";
@@ -48,6 +48,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Attach tags to a secret", description: "Attach tags to a secret",
security: [ security: [
{ {
@@ -103,6 +105,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit rateLimit: writeLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Detach tags from a secret", description: "Detach tags from a secret",
security: [ security: [
{ {
@@ -158,6 +162,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "List secrets", description: "List secrets",
security: [ security: [
{ {
@@ -355,6 +361,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
params: z.object({ params: z.object({
secretId: z.string() secretId: z.string()
}), }),
@@ -390,6 +398,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Get a secret by name", description: "Get a secret by name",
security: [ security: [
{ {
@@ -496,6 +506,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Create secret", description: "Create secret",
security: [ security: [
{ {
@@ -609,6 +621,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Update secret", description: "Update secret",
security: [ security: [
{ {
@@ -729,6 +743,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Delete secret", description: "Delete secret",
security: [ security: [
{ {
@@ -1486,6 +1502,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
body: z.object({ body: z.object({
projectSlug: z.string().trim(), projectSlug: z.string().trim(),
sourceEnvironment: z.string().trim(), sourceEnvironment: z.string().trim(),
@@ -1911,6 +1929,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Create many secrets", description: "Create many secrets",
security: [ security: [
{ {
@@ -2017,6 +2037,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Update many secrets", description: "Update many secrets",
security: [ security: [
{ {
@@ -2170,6 +2192,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Delete many secrets", description: "Delete many secrets",
security: [ security: [
{ {
@@ -2266,6 +2290,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit rateLimit: secretsLimit
}, },
schema: { schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Get secret reference tree", description: "Get secret reference tree",
security: [ security: [
{ {
@@ -3,6 +3,8 @@ import jwt from "jsonwebtoken";
import { Knex } from "knex"; import { Knex } from "knex";
import { OrgMembershipRole, TUsers, UserDeviceSchema } from "@app/db/schemas"; import { OrgMembershipRole, TUsers, UserDeviceSchema } from "@app/db/schemas";
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns"; import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { request } from "@app/lib/config/request"; import { request } from "@app/lib/config/request";
@@ -11,6 +13,7 @@ import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
import { getUserPrivateKey } from "@app/lib/crypto/srp"; import { getUserPrivateKey } from "@app/lib/crypto/srp";
import { BadRequestError, DatabaseError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, DatabaseError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { getUserAgentType } from "@app/server/plugins/audit-log";
import { getServerCfg } from "@app/services/super-admin/super-admin-service"; import { getServerCfg } from "@app/services/super-admin/super-admin-service";
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
@@ -28,7 +31,15 @@ import {
TOauthTokenExchangeDTO, TOauthTokenExchangeDTO,
TVerifyMfaTokenDTO TVerifyMfaTokenDTO
} from "./auth-login-type"; } from "./auth-login-type";
import { AuthMethod, AuthModeJwtTokenPayload, AuthModeMfaJwtTokenPayload, AuthTokenType, MfaMethod } from "./auth-type"; import {
ActorType,
AuthMethod,
AuthModeJwtTokenPayload,
AuthModeMfaJwtTokenPayload,
AuthTokenType,
MfaMethod
} from "./auth-type";
import { removeTrailingSlash } from "@app/lib/fn";
type TAuthLoginServiceFactoryDep = { type TAuthLoginServiceFactoryDep = {
userDAL: TUserDALFactory; userDAL: TUserDALFactory;
@@ -36,6 +47,7 @@ type TAuthLoginServiceFactoryDep = {
tokenService: TAuthTokenServiceFactory; tokenService: TAuthTokenServiceFactory;
smtpService: TSmtpService; smtpService: TSmtpService;
totpService: Pick<TTotpServiceFactory, "verifyUserTotp" | "verifyWithUserRecoveryCode">; totpService: Pick<TTotpServiceFactory, "verifyUserTotp" | "verifyWithUserRecoveryCode">;
auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
}; };
export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>; export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>;
@@ -44,7 +56,8 @@ export const authLoginServiceFactory = ({
tokenService, tokenService,
smtpService, smtpService,
orgDAL, orgDAL,
totpService totpService,
auditLogService
}: TAuthLoginServiceFactoryDep) => { }: TAuthLoginServiceFactoryDep) => {
/* /*
* Private * Private
@@ -412,6 +425,55 @@ export const authLoginServiceFactory = ({
mfaMethod: decodedToken.mfaMethod mfaMethod: decodedToken.mfaMethod
}); });
// In the event of this being a break-glass request (non-saml / non-oidc, when either is enforced)
if (
selectedOrg.authEnforced &&
selectedOrg.bypassOrgAuthEnabled &&
!isAuthMethodSaml(decodedToken.authMethod) &&
decodedToken.authMethod !== AuthMethod.OIDC
) {
await auditLogService.createAuditLog({
orgId: organizationId,
ipAddress,
userAgent,
userAgentType: getUserAgentType(userAgent),
actor: {
type: ActorType.USER,
metadata: {
email: user.email,
userId: user.id,
username: user.username
}
},
event: {
type: EventType.ORG_ADMIN_BYPASS_SSO,
metadata: {}
}
});
// Notify all admins via email (besides the actor)
const orgAdmins = await orgDAL.findOrgMembersByRole(organizationId, OrgMembershipRole.Admin);
const adminEmails = orgAdmins
.filter((admin) => admin.user.id !== user.id)
.map((admin) => admin.user.email)
.filter(Boolean) as string[];
if (adminEmails.length > 0) {
await smtpService.sendMail({
recipients: adminEmails,
subjectLine: "Security Alert: Admin SSO Bypass",
substitutions: {
email: user.email,
timestamp: new Date().toISOString(),
ip: ipAddress,
userAgent,
siteUrl: removeTrailingSlash(cfg.SITE_URL || "https://app.infisical.com")
},
template: SmtpTemplates.OrgAdminBreakglassAccess
});
}
}
return { return {
...tokens, ...tokens,
isMfaEnabled: false isMfaEnabled: false
@@ -68,18 +68,15 @@ const awsRegionFromHeader = (authorizationHeader: string): string | null => {
return null; return null;
}; };
function isValidAwsRegion(region: string | null): boolean {
const validRegionPattern = new RE2("^[a-z0-9-]+$");
function isValidAwsRegion(region: (string | null)): boolean { if (typeof region !== "string" || region.length === 0 || region.length > 20) {
const validRegionPattern = new RE2('^[a-z0-9-]+$');
if (typeof region !== 'string' || region.length === 0 || region.length > 20) {
return false; return false;
} }
return validRegionPattern.test(region); return validRegionPattern.test(region);
} }
export const identityAwsAuthServiceFactory = ({ export const identityAwsAuthServiceFactory = ({
identityAccessTokenDAL, identityAccessTokenDAL,
identityAwsAuthDAL, identityAwsAuthDAL,
@@ -100,7 +97,7 @@ export const identityAwsAuthServiceFactory = ({
const region = headers.Authorization ? awsRegionFromHeader(headers.Authorization) : null; const region = headers.Authorization ? awsRegionFromHeader(headers.Authorization) : null;
if (!isValidAwsRegion(region)) { if (!isValidAwsRegion(region)) {
throw new BadRequestError({message: "Invalid AWS region"}); throw new BadRequestError({ message: "Invalid AWS region" });
} }
const url = region ? `https://sts.${region}.amazonaws.com` : identityAwsAuth.stsEndpoint; const url = region ? `https://sts.${region}.amazonaws.com` : identityAwsAuth.stsEndpoint;
@@ -435,12 +435,16 @@ export const identityKubernetesAuthServiceFactory = ({
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` }); if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
if (!identityKubernetesAuth) {
throw new NotFoundError({ message: `Failed to find Kubernetes Auth for identity with ID ${identityId}` });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) { if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
throw new BadRequestError({ throw new BadRequestError({
message: "The identity does not have Kubernetes Auth attached" message: "The identity does not have Kubernetes Auth attached"
}); });
} }
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
const { permission } = await permissionService.getOrgPermission( const { permission } = await permissionService.getOrgPermission(
actor, actor,
@@ -50,7 +50,7 @@ const getIntegrationSecretsV2 = async (
} }
// process secrets in current folder // process secrets in current folder
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId, projectId: dto.projectId }); const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId });
secrets.forEach((secret) => { secrets.forEach((secret) => {
const secretKey = secret.key; const secretKey = secret.key;
@@ -63,7 +63,6 @@ const getIntegrationSecretsV2 = async (
// if no imports then return secrets in the current folder // if no imports then return secrets in the current folder
if (!secretImports.length) return content; if (!secretImports.length) return content;
const importedSecrets = await fnSecretsV2FromImports({ const importedSecrets = await fnSecretsV2FromImports({
projectId: dto.projectId,
decryptor: dto.decryptor, decryptor: dto.decryptor,
folderDAL, folderDAL,
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
+7 -1
View File
@@ -787,13 +787,19 @@ export const kmsServiceFactory = ({
return projectDataKey; return projectDataKey;
} }
} }
} catch (error) {
logger.error(
error,
`getProjectSecretManagerKmsDataKey: Failed to get project data key for [projectId=${projectId}]`
);
throw error;
} finally { } finally {
await lock?.release(); await lock?.release();
} }
} }
if (!project.kmsSecretManagerEncryptedDataKey) { if (!project.kmsSecretManagerEncryptedDataKey) {
throw new Error("Missing project data key"); throw new BadRequestError({ message: "Missing project data key" });
} }
const kmsDecryptor = await decryptWithKmsKey({ const kmsDecryptor = await decryptWithKmsKey({
+40 -2
View File
@@ -2,6 +2,7 @@ import { Knex } from "knex";
import { TDbClient } from "@app/db"; import { TDbClient } from "@app/db";
import { import {
OrgMembershipRole,
TableName, TableName,
TOrganizations, TOrganizations,
TOrganizationsInsert, TOrganizationsInsert,
@@ -216,9 +217,8 @@ export const orgDALFactory = (db: TDbClient) => {
const findOrgMembersByUsername = async (orgId: string, usernames: string[], tx?: Knex) => { const findOrgMembersByUsername = async (orgId: string, usernames: string[], tx?: Knex) => {
try { try {
const conn = tx || db; const conn = tx || db.replicaNode();
const members = await conn(TableName.OrgMembership) const members = await conn(TableName.OrgMembership)
// .replicaNode()(TableName.OrgMembership)
.where(`${TableName.OrgMembership}.orgId`, orgId) .where(`${TableName.OrgMembership}.orgId`, orgId)
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`) .join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
.leftJoin<TUserEncryptionKeys>( .leftJoin<TUserEncryptionKeys>(
@@ -251,6 +251,43 @@ export const orgDALFactory = (db: TDbClient) => {
} }
}; };
const findOrgMembersByRole = async (orgId: string, role: OrgMembershipRole, tx?: Knex) => {
try {
const conn = tx || db.replicaNode();
const members = await conn(TableName.OrgMembership)
.where(`${TableName.OrgMembership}.orgId`, orgId)
.where(`${TableName.OrgMembership}.role`, role)
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
.leftJoin<TUserEncryptionKeys>(
TableName.UserEncryptionKey,
`${TableName.UserEncryptionKey}.userId`,
`${TableName.Users}.id`
)
.select(
conn.ref("id").withSchema(TableName.OrgMembership),
conn.ref("inviteEmail").withSchema(TableName.OrgMembership),
conn.ref("orgId").withSchema(TableName.OrgMembership),
conn.ref("role").withSchema(TableName.OrgMembership),
conn.ref("roleId").withSchema(TableName.OrgMembership),
conn.ref("status").withSchema(TableName.OrgMembership),
conn.ref("username").withSchema(TableName.Users),
conn.ref("email").withSchema(TableName.Users),
conn.ref("firstName").withSchema(TableName.Users),
conn.ref("lastName").withSchema(TableName.Users),
conn.ref("id").withSchema(TableName.Users).as("userId"),
conn.ref("publicKey").withSchema(TableName.UserEncryptionKey)
)
.where({ isGhost: false });
return members.map(({ username, email, firstName, lastName, userId, publicKey, ...data }) => ({
...data,
user: { username, email, firstName, lastName, id: userId, publicKey }
}));
} catch (error) {
throw new DatabaseError({ error, name: "Find org members by role" });
}
};
const findOrgGhostUser = async (orgId: string) => { const findOrgGhostUser = async (orgId: string) => {
try { try {
const member = await db const member = await db
@@ -472,6 +509,7 @@ export const orgDALFactory = (db: TDbClient) => {
findAllOrgsByUserId, findAllOrgsByUserId,
ghostUserExists, ghostUserExists,
findOrgMembersByUsername, findOrgMembersByUsername,
findOrgMembersByRole,
findOrgGhostUser, findOrgGhostUser,
create, create,
updateById, updateById,
@@ -159,8 +159,7 @@ export const fnSecretsV2FromImports = async ({
decryptor, decryptor,
expandSecretReferences, expandSecretReferences,
hasSecretAccess, hasSecretAccess,
viewSecretValue, viewSecretValue
projectId
}: { }: {
secretImports: (Omit<TSecretImports, "importEnv"> & { secretImports: (Omit<TSecretImports, "importEnv"> & {
importEnv: { id: string; slug: string; name: string }; importEnv: { id: string; slug: string; name: string };
@@ -177,7 +176,6 @@ export const fnSecretsV2FromImports = async ({
environment: string; environment: string;
}) => Promise<string | undefined>; }) => Promise<string | undefined>;
hasSecretAccess: (environment: string, secretPath: string, secretName: string, secretTagSlugs: string[]) => boolean; hasSecretAccess: (environment: string, secretPath: string, secretName: string, secretTagSlugs: string[]) => boolean;
projectId: string;
}) => { }) => {
const cyclicDetector = new Set(); const cyclicDetector = new Set();
const stack: { const stack: {
@@ -209,7 +207,10 @@ export const fnSecretsV2FromImports = async ({
); );
if (!importedFolders.length) continue; if (!importedFolders.length) continue;
const importedFolderIds = importedFolders.map((el) => el?.id) as string[]; const importedFolderIds = importedFolders.filter(Boolean).map((el) => el?.id) as string[];
if (!importedFolderIds.length) continue;
const importedFolderGroupBySourceImport = groupBy(importedFolders, (i) => `${i?.envId}-${i?.path}`); const importedFolderGroupBySourceImport = groupBy(importedFolders, (i) => `${i?.envId}-${i?.path}`);
const importedSecrets = await secretDAL.find( const importedSecrets = await secretDAL.find(
@@ -218,8 +219,7 @@ export const fnSecretsV2FromImports = async ({
type: SecretType.Shared type: SecretType.Shared
}, },
{ {
sort: [["id", "asc"]], sort: [["id", "asc"]]
useCache: { projectId }
} }
); );
const importedSecretsGroupByFolderId = groupBy(importedSecrets, (i) => i.folderId); const importedSecretsGroupByFolderId = groupBy(importedSecrets, (i) => i.folderId);
@@ -698,7 +698,6 @@ export const secretImportServiceFactory = ({
projectId projectId
}); });
const importedSecrets = await fnSecretsV2FromImports({ const importedSecrets = await fnSecretsV2FromImports({
projectId,
secretImports, secretImports,
folderDAL, folderDAL,
viewSecretValue: true, viewSecretValue: true,
@@ -214,7 +214,7 @@ export const secretSyncQueueFactory = ({
canExpandValue: () => true canExpandValue: () => true
}); });
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId, projectId }); const secrets = await secretV2BridgeDAL.findByFolderId({ folderId });
await Promise.allSettled( await Promise.allSettled(
secrets.map(async (secret) => { secrets.map(async (secret) => {
@@ -244,7 +244,6 @@ export const secretSyncQueueFactory = ({
if (secretImports.length) { if (secretImports.length) {
const importedSecrets = await fnSecretsV2FromImports({ const importedSecrets = await fnSecretsV2FromImports({
projectId,
decryptor: decryptSecretValue, decryptor: decryptSecretValue,
folderDAL, folderDAL,
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
@@ -1,3 +1,4 @@
import { MongoAbility } from "@casl/ability";
import { Knex } from "knex"; import { Knex } from "knex";
import { validate as uuidValidate } from "uuid"; import { validate as uuidValidate } from "uuid";
@@ -15,46 +16,29 @@ import {
TFindFilter, TFindFilter,
TFindOpt TFindOpt
} from "@app/lib/knex"; } from "@app/lib/knex";
import { BufferKeysToString, OrderByDirection } from "@app/lib/types"; import { OrderByDirection } from "@app/lib/types";
import { SecretsOrderBy } from "@app/services/secret/secret-types"; import { SecretsOrderBy } from "@app/services/secret/secret-types";
import type { TFindSecretsByFolderIdsFilter } from "@app/services/secret-v2-bridge/secret-v2-bridge-types"; import type {
TFindSecretsByFolderIdsFilter,
TGetSecretsDTO
} from "@app/services/secret-v2-bridge/secret-v2-bridge-types";
export const SecretDalCacheKeys = { export const SecretServiceCacheKeys = {
get productKey() { get productKey() {
const { INFISICAL_PLATFORM_VERSION } = getConfig(); const { INFISICAL_PLATFORM_VERSION } = getConfig();
return `${ProjectType.SecretManager}:${INFISICAL_PLATFORM_VERSION || 0}`; return `${ProjectType.SecretManager}:${INFISICAL_PLATFORM_VERSION || 0}`;
}, },
getSecretDalVersion: (projectId: string) => { getSecretDalVersion: (projectId: string) => {
return `${SecretDalCacheKeys.productKey}:${projectId}:${TableName.SecretV2}-dal-version`; return `${SecretServiceCacheKeys.productKey}:${projectId}:${TableName.SecretV2}-dal-version`;
}, },
findByFolderIds: ( getSecretsOfServiceLayer: (
projectId: string, projectId: string,
version: number, version: number,
{ useCache, tx, ...cacheKey }: Parameters<TSecretV2BridgeDALFactory["findByFolderIds"]>[0] dto: TGetSecretsDTO & { permissionRules: MongoAbility["rules"] }
) => { ) => {
return `${SecretDalCacheKeys.productKey}:${projectId}:${ return `${SecretServiceCacheKeys.productKey}:${projectId}:${
TableName.SecretV2 TableName.SecretV2
}-dal:v${version}:find-by-folder-ids:${generateCacheKeyFromData(cacheKey)}`; }-dal:v${version}:get-secrets-service-layer:${dto.actorId}-${generateCacheKeyFromData(dto)}`;
},
findByFolderId: (
projectId: string,
version: number,
{ useCache, tx, ...cacheKey }: Parameters<TSecretV2BridgeDALFactory["findByFolderId"]>[0]
) => {
return `${SecretDalCacheKeys.productKey}:${projectId}:${
TableName.SecretV2
}-dal:v${version}:find-by-folder-id:${generateCacheKeyFromData(cacheKey)}`;
},
find: (projectId: string, version: number, ...args: Parameters<TSecretV2BridgeDALFactory["find"]>) => {
const [filter, opts] = args;
delete opts?.tx;
delete opts?.useCache;
return `${SecretDalCacheKeys.productKey}:${projectId}:${
TableName.SecretV2
}-dal:v${version}:find:${generateCacheKeyFromData({
filter,
opts
})}`;
} }
}; };
@@ -64,14 +48,14 @@ interface TSecretV2DalArg {
keyStore: TKeyStoreFactory; keyStore: TKeyStoreFactory;
} }
const SECRET_DAL_TTL = 5 * 60; export const SECRET_DAL_TTL = 5 * 60;
const SECRET_DAL_VERSION_TTL = 15 * 60; export const SECRET_DAL_VERSION_TTL = 15 * 60;
const MAX_SECRET_CACHE_BYTES = 25 * 1024 * 1024; export const MAX_SECRET_CACHE_BYTES = 25 * 1024 * 1024;
export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => { export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
const secretOrm = ormify(db, TableName.SecretV2); const secretOrm = ormify(db, TableName.SecretV2);
const invalidateSecretCacheByProjectId = async (projectId: string) => { const invalidateSecretCacheByProjectId = async (projectId: string) => {
const secretDalVersionKey = SecretDalCacheKeys.getSecretDalVersion(projectId); const secretDalVersionKey = SecretServiceCacheKeys.getSecretDalVersion(projectId);
await keyStore.incrementBy(secretDalVersionKey, 1); await keyStore.incrementBy(secretDalVersionKey, 1);
await keyStore.setExpiry(secretDalVersionKey, SECRET_DAL_VERSION_TTL); await keyStore.setExpiry(secretDalVersionKey, SECRET_DAL_VERSION_TTL);
}; };
@@ -128,35 +112,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
} }
}; };
const find = async ( const find = async (filter: TFindFilter<TSecretsV2>, opts: TFindOpt<TSecretsV2> = {}) => {
filter: TFindFilter<TSecretsV2>, const { offset, limit, sort, tx } = opts;
opts: TFindOpt<TSecretsV2> & { useCache?: { projectId: string } } = {}
) => {
const { offset, limit, sort, tx, useCache } = opts;
try { try {
let secretDalVersion = 0;
if (useCache) {
const cachedSecretDalVersion = await keyStore.getItem(
SecretDalCacheKeys.getSecretDalVersion(useCache.projectId)
);
secretDalVersion = Number(cachedSecretDalVersion || 0);
const cacheKey = SecretDalCacheKeys.find(useCache.projectId, secretDalVersion, filter, opts);
const cachedSecrets = await keyStore.getItem(cacheKey);
if (cachedSecrets) {
await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL);
const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[];
const sanitizedSecrets = unsanitizedSecrets.map((el) => {
const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null;
const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null;
const createdAt = new Date(el.createdAt);
const updatedAt = new Date(el.updatedAt);
return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt };
});
return sanitizedSecrets;
}
}
const query = (tx || db)(TableName.SecretV2) const query = (tx || db)(TableName.SecretV2)
// eslint-disable-next-line @typescript-eslint/no-misused-promises // eslint-disable-next-line @typescript-eslint/no-misused-promises
.where(buildFindFilter(filter)) .where(buildFindFilter(filter))
@@ -225,22 +183,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
] ]
}); });
if (useCache) {
const cachedSecrets = data.map((el) => {
const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null;
const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null;
return { ...el, encryptedValue, encryptedComment };
});
const cache = JSON.stringify(cachedSecrets);
if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(
SecretDalCacheKeys.find(useCache.projectId, secretDalVersion, filter, opts),
SECRET_DAL_TTL,
cache
);
}
}
return data; return data;
} catch (error) { } catch (error) {
throw new DatabaseError({ error, name: `${TableName.SecretV2}: Find` }); throw new DatabaseError({ error, name: `${TableName.SecretV2}: Find` });
@@ -345,15 +287,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
} }
}; };
const findByFolderId = async (dto: { const findByFolderId = async (dto: { folderId: string; userId?: string; tx?: Knex }) => {
folderId: string;
userId?: string;
tx?: Knex;
projectId: string;
useCache?: boolean;
}) => {
try { try {
const { folderId, tx, projectId } = dto; const { folderId, tx } = dto;
let { userId } = dto; let { userId } = dto;
// check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo // check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo
if (userId && !uuidValidate(userId)) { if (userId && !uuidValidate(userId)) {
@@ -361,27 +297,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
userId = undefined; userId = undefined;
} }
const cachedSecretDalVersion = await keyStore.getItem(SecretDalCacheKeys.getSecretDalVersion(projectId));
const secretDalVersion = Number(cachedSecretDalVersion || 0);
if (dto.useCache) {
const cacheKey = SecretDalCacheKeys.findByFolderId(projectId, secretDalVersion, dto);
const cachedSecrets = await keyStore.getItem(cacheKey);
if (cachedSecrets) {
await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL);
const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[];
const sanitizedSecrets = unsanitizedSecrets.map((el) => {
const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null;
const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null;
const createdAt = new Date(el.createdAt);
const updatedAt = new Date(el.updatedAt);
return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt };
});
return sanitizedSecrets;
}
}
const secs = await (tx || db.replicaNode())(TableName.SecretV2) const secs = await (tx || db.replicaNode())(TableName.SecretV2)
.where({ folderId }) .where({ folderId })
.where((bd) => { .where((bd) => {
@@ -437,22 +352,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
} }
] ]
}); });
if (dto.useCache) {
const newCachedSecrets = data.map((el) => {
const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null;
const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null;
return { ...el, encryptedValue, encryptedComment };
});
const cache = JSON.stringify(newCachedSecrets);
if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(
SecretDalCacheKeys.findByFolderId(projectId, secretDalVersion, dto),
SECRET_DAL_TTL,
cache
);
}
}
return data; return data;
} catch (error) { } catch (error) {
throw new DatabaseError({ error, name: "get all secret" }); throw new DatabaseError({ error, name: "get all secret" });
@@ -542,11 +441,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
folderIds: string[]; folderIds: string[];
userId?: string; userId?: string;
tx?: Knex; tx?: Knex;
projectId: string;
filters?: TFindSecretsByFolderIdsFilter; filters?: TFindSecretsByFolderIdsFilter;
useCache?: boolean;
}) => { }) => {
const { folderIds, tx, filters, useCache, projectId } = dto; const { folderIds, tx, filters } = dto;
let { userId } = dto; let { userId } = dto;
try { try {
// check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo) // check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo)
@@ -555,26 +452,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
userId = undefined; userId = undefined;
} }
const cachedSecretDalVersion = await keyStore.getItem(SecretDalCacheKeys.getSecretDalVersion(projectId));
const secretDalVersion = Number(cachedSecretDalVersion || 0);
if (useCache) {
const cacheKey = SecretDalCacheKeys.findByFolderIds(projectId, secretDalVersion, dto);
const cachedSecrets = await keyStore.getItem(cacheKey);
if (cachedSecrets) {
await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL);
const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[];
const sanitizedSecrets = unsanitizedSecrets.map((el) => {
const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null;
const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null;
const createdAt = new Date(el.createdAt);
const updatedAt = new Date(el.updatedAt);
return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt };
});
return sanitizedSecrets;
}
}
const query = (tx || db.replicaNode())(TableName.SecretV2) const query = (tx || db.replicaNode())(TableName.SecretV2)
.whereIn(`${TableName.SecretV2}.folderId`, folderIds) .whereIn(`${TableName.SecretV2}.folderId`, folderIds)
.where((bd) => { .where((bd) => {
@@ -700,22 +577,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
} }
] ]
}); });
if (useCache) {
const cachedSecrets = data.map((el) => {
const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null;
const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null;
return { ...el, encryptedValue, encryptedComment };
});
const cache = JSON.stringify(cachedSecrets);
if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(
SecretDalCacheKeys.findByFolderIds(projectId, secretDalVersion, dto),
SECRET_DAL_TTL,
cache
);
}
}
return data; return data;
} catch (error) { } catch (error) {
@@ -509,7 +509,7 @@ export const expandSecretReferencesFactory = ({
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
if (!folder) return { value: "", tags: [] }; if (!folder) return { value: "", tags: [] };
const secrets = await secretDAL.findByFolderId({ folderId: folder.id, projectId, useCache: true }); const secrets = await secretDAL.findByFolderId({ folderId: folder.id });
const decryptedSecret = secrets.reduce<Record<string, { value: string; tags: string[] }>>((prev, secret) => { const decryptedSecret = secrets.reduce<Record<string, { value: string; tags: string[] }>>((prev, secret) => {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
@@ -25,6 +25,7 @@ import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-app
import { TSecretApprovalRequestDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-dal"; import { TSecretApprovalRequestDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-dal";
import { TSecretApprovalRequestSecretDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-secret-dal"; import { TSecretApprovalRequestSecretDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-secret-dal";
import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/secret-snapshot-service"; import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/secret-snapshot-service";
import { TKeyStoreFactory } from "@app/keystore/keystore";
import { DatabaseErrorCode } from "@app/lib/error-codes"; import { DatabaseErrorCode } from "@app/lib/error-codes";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { diff, groupBy } from "@app/lib/fn"; import { diff, groupBy } from "@app/lib/fn";
@@ -43,7 +44,12 @@ import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal"; import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns"; import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns";
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal"; import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal"; import {
MAX_SECRET_CACHE_BYTES,
SECRET_DAL_TTL,
SecretServiceCacheKeys,
TSecretV2BridgeDALFactory
} from "./secret-v2-bridge-dal";
import { import {
buildHierarchy, buildHierarchy,
expandSecretReferencesFactory, expandSecretReferencesFactory,
@@ -105,6 +111,7 @@ type TSecretV2BridgeServiceFactoryDep = {
>; >;
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">; snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">; resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
keyStore: Pick<TKeyStoreFactory, "getItem" | "setExpiry" | "setItemWithExpiry" | "deleteItem">;
}; };
export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>; export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>;
@@ -127,7 +134,8 @@ export const secretV2BridgeServiceFactory = ({
secretApprovalRequestDAL, secretApprovalRequestDAL,
secretApprovalRequestSecretDAL, secretApprovalRequestSecretDAL,
kmsService, kmsService,
resourceMetadataDAL resourceMetadataDAL,
keyStore
}: TSecretV2BridgeServiceFactoryDep) => { }: TSecretV2BridgeServiceFactoryDep) => {
const $validateSecretReferences = async ( const $validateSecretReferences = async (
projectId: string, projectId: string,
@@ -800,12 +808,10 @@ export const secretV2BridgeServiceFactory = ({
const groupedFolderMappings = groupBy(folderMappings, (folderMapping) => folderMapping.folderId); const groupedFolderMappings = groupBy(folderMappings, (folderMapping) => folderMapping.folderId);
const secrets = await secretDAL.findByFolderIds({ const secrets = await secretDAL.findByFolderIds({
projectId,
folderIds: folderMappings.map((folderMapping) => folderMapping.folderId), folderIds: folderMappings.map((folderMapping) => folderMapping.folderId),
userId, userId,
tx: undefined, tx: undefined,
filters, filters
useCache: true
}); });
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
@@ -909,21 +915,22 @@ export const secretV2BridgeServiceFactory = ({
return decryptedSecrets; return decryptedSecrets;
}; };
const getSecrets = async ({ const getSecrets = async (dto: TGetSecretsDTO) => {
actorId, const {
path, actorId,
environment, path,
projectId, environment,
actor, projectId,
actorOrgId, actor,
viewSecretValue, actorOrgId,
actorAuthMethod, viewSecretValue,
includeImports, actorAuthMethod,
recursive, includeImports,
expandSecretReferences: shouldExpandSecretReferences, recursive,
throwOnMissingReadValuePermission = true, expandSecretReferences: shouldExpandSecretReferences,
...params throwOnMissingReadValuePermission = true,
}: TGetSecretsDTO) => { ...params
} = dto;
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
@@ -934,6 +941,42 @@ export const secretV2BridgeServiceFactory = ({
}); });
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret); throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret);
const cachedSecretDalVersion = await keyStore.getItem(SecretServiceCacheKeys.getSecretDalVersion(projectId));
const secretDalVersion = Number(cachedSecretDalVersion || 0);
const cacheKey = SecretServiceCacheKeys.getSecretsOfServiceLayer(projectId, secretDalVersion, {
...dto,
permissionRules: permission.rules
});
const { decryptor: secretManagerDecryptor, encryptor: secretManagerEncryptor } =
await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.SecretManager,
projectId
});
const encryptedCachedSecrets = await keyStore.getItem(cacheKey);
if (encryptedCachedSecrets) {
try {
await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL);
const cachedSecrets = secretManagerDecryptor({ cipherTextBlob: Buffer.from(encryptedCachedSecrets, "base64") });
const { secrets, imports = [] } = JSON.parse(cachedSecrets.toString("utf8")) as {
secrets: typeof decryptedSecrets;
imports: typeof importedSecrets;
};
return {
secrets: secrets.map((el) => ({
...el,
createdAt: new Date(el.createdAt),
updatedAt: new Date(el.updatedAt)
})),
imports
};
} catch (err) {
logger.error(err, "Secret service layer cache miss");
await keyStore.deleteItem(cacheKey);
}
}
let paths: { folderId: string; path: string }[] = []; let paths: { folderId: string; path: string }[] = [];
if (recursive) { if (recursive) {
@@ -958,17 +1001,10 @@ export const secretV2BridgeServiceFactory = ({
const groupedPaths = groupBy(paths, (p) => p.folderId); const groupedPaths = groupBy(paths, (p) => p.folderId);
const secrets = await secretDAL.findByFolderIds({ const secrets = await secretDAL.findByFolderIds({
projectId,
folderIds: paths.map((p) => p.folderId), folderIds: paths.map((p) => p.folderId),
userId: actorId, userId: actorId,
tx: undefined, tx: undefined,
filters: params, filters: params
useCache: true
});
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.SecretManager,
projectId
}); });
// scott: if any of this changes it also needs to be mirrored in secret rotation for getting dashboard secrets // scott: if any of this changes it also needs to be mirrored in secret rotation for getting dashboard secrets
@@ -1086,15 +1122,19 @@ export const secretV2BridgeServiceFactory = ({
} }
if (!includeImports) { if (!includeImports) {
return { const payload = { secrets: decryptedSecrets, imports: [] };
secrets: decryptedSecrets const encryptedUpdatedCachedSecrets = secretManagerEncryptor({
}; plainText: Buffer.from(JSON.stringify(payload))
}).cipherTextBlob;
if (encryptedUpdatedCachedSecrets.byteLength < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(cacheKey, SECRET_DAL_TTL, encryptedUpdatedCachedSecrets.toString("base64"));
}
return payload;
} }
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId)); const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
const allowedImports = secretImports.filter(({ isReplication }) => !isReplication); const allowedImports = secretImports.filter(({ isReplication }) => !isReplication);
const importedSecrets = await fnSecretsV2FromImports({ const importedSecrets = await fnSecretsV2FromImports({
projectId,
viewSecretValue, viewSecretValue,
secretImports: allowedImports, secretImports: allowedImports,
secretDAL, secretDAL,
@@ -1129,10 +1169,14 @@ export const secretV2BridgeServiceFactory = ({
} }
}); });
return { const payload = { secrets: decryptedSecrets, imports: importedSecrets };
secrets: decryptedSecrets, const encryptedUpdatedCachedSecrets = secretManagerEncryptor({
imports: importedSecrets plainText: Buffer.from(JSON.stringify(payload))
}; }).cipherTextBlob;
if (encryptedUpdatedCachedSecrets.byteLength < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(cacheKey, SECRET_DAL_TTL, encryptedUpdatedCachedSecrets.toString("base64"));
}
return payload;
}; };
const getSecretById = async ({ actorId, actor, actorOrgId, actorAuthMethod, secretId }: TGetASecretByIdDTO) => { const getSecretById = async ({ actorId, actor, actorOrgId, actorAuthMethod, secretId }: TGetASecretByIdDTO) => {
@@ -1312,7 +1356,6 @@ export const secretV2BridgeServiceFactory = ({
if (!secret && includeImports) { if (!secret && includeImports) {
const secretImports = await secretImportDAL.find({ folderId, isReplication: false }); const secretImports = await secretImportDAL.find({ folderId, isReplication: false });
const importedSecrets = await fnSecretsV2FromImports({ const importedSecrets = await fnSecretsV2FromImports({
projectId,
secretImports, secretImports,
viewSecretValue, viewSecretValue,
secretDAL, secretDAL,
@@ -2729,7 +2772,7 @@ export const secretV2BridgeServiceFactory = ({
generatePaths(folderMap).map(({ folderId, path }) => [folderId, path === "/" ? path : path.substring(1)]) generatePaths(folderMap).map(({ folderId, path }) => [folderId, path === "/" ? path : path.substring(1)])
); );
const secrets = await secretDAL.findByFolderIds({ folderIds: folders.map((f) => f.id), projectId, useCache: true }); const secrets = await secretDAL.findByFolderIds({ folderIds: folders.map((f) => f.id) });
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({ const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.SecretManager, type: KmsDataKey.SecretManager,
+1 -2
View File
@@ -367,7 +367,7 @@ export const secretQueueFactory = ({
canExpandValue: () => true canExpandValue: () => true
}); });
// process secrets in current folder // process secrets in current folder
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId, projectId: dto.projectId }); const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId });
await Promise.allSettled( await Promise.allSettled(
secrets.map(async (secret) => { secrets.map(async (secret) => {
@@ -397,7 +397,6 @@ export const secretQueueFactory = ({
// if no imports then return secrets in the current folder // if no imports then return secrets in the current folder
if (!secretImports.length) return content; if (!secretImports.length) return content;
const importedSecrets = await fnSecretsV2FromImports({ const importedSecrets = await fnSecretsV2FromImports({
projectId: dto.projectId,
decryptor: dto.decryptor, decryptor: dto.decryptor,
folderDAL, folderDAL,
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
@@ -44,6 +44,7 @@ export enum SmtpTemplates {
SecretRotationFailed = "secretRotationFailed.handlebars", SecretRotationFailed = "secretRotationFailed.handlebars",
ProjectAccessRequest = "projectAccess.handlebars", ProjectAccessRequest = "projectAccess.handlebars",
OrgAdminProjectDirectAccess = "orgAdminProjectGrantAccess.handlebars", OrgAdminProjectDirectAccess = "orgAdminProjectGrantAccess.handlebars",
OrgAdminBreakglassAccess = "orgAdminBreakglassAccess.handlebars",
ServiceTokenExpired = "serviceTokenExpired.handlebars" ServiceTokenExpired = "serviceTokenExpired.handlebars"
} }
@@ -0,0 +1,20 @@
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Organization admin has bypassed SSO</title>
</head>
<body>
<h2>Infisical</h2>
<p>The organization admin {{email}} has bypassed enforced SSO login.</p>
<p><strong>Timestamp</strong>: {{timestamp}}</p>
<p><strong>IP address</strong>: {{ip}}</p>
<p><strong>User agent</strong>: {{userAgent}}</p>
<p>If you'd like to disable Admin SSO Bypass, please visit <a href="{{siteUrl}}/organization/settings">Organization Settings</a> > Security.</p>
{{emailFooter}}
</body>
</html>
@@ -1,4 +1,4 @@
--- ---
title: "Create Project Membership" title: "Create Project Membership"
openapi: "POST /api/v2/workspace/{projectId}/groups/{groupId}" openapi: "POST /api/v2/workspace/{projectId}/groups/{groupIdOrName}"
--- ---
@@ -1,8 +1,10 @@
--- ---
title: "Create" title: "Create"
openapi: "POST /api/v1/workspace/{projectSlug}/roles" openapi: "POST /api/v2/workspace/{projectId}/roles"
--- ---
<Note> <Note>
You can read more about the permissions field in the [permissions documentation](/internals/permissions). You can read more about the permissions field in the [permissions
</Note> documentation](/internals/permissions).
</Note>
@@ -1,4 +1,4 @@
--- ---
title: "Delete" title: "Delete"
openapi: "DELETE /api/v1/workspace/{projectSlug}/roles/{roleId}" openapi: "DELETE /api/v2/workspace/{projectId}/roles/{roleId}"
--- ---
@@ -1,4 +1,4 @@
--- ---
title: "Get By Slug" title: "Get By Slug"
openapi: "GET /api/v1/workspace/{projectSlug}/roles/slug/{slug}" openapi: "GET /api/v2/workspace/{projectId}/roles/slug/{roleSlug}"
--- ---
@@ -1,4 +1,4 @@
--- ---
title: "List" title: "List"
openapi: "GET /api/v1/workspace/{projectSlug}/roles" openapi: "GET /api/v2/workspace/{projectId}/roles"
--- ---
@@ -1,4 +1,4 @@
--- ---
title: "Update" title: "Update"
openapi: "PATCH /api/v1/workspace/{projectSlug}/roles/{roleId}" openapi: "PATCH /api/v2/workspace/{projectId}/roles/{roleId}"
--- ---
+22 -11
View File
@@ -28,21 +28,32 @@ You can use it across various environments, whether it's local development, CI/C
``` ```
</Tab> </Tab>
<Tab title="Windows"> <Tab title="Windows">
Use [Scoop](https://scoop.sh/) package manager
```bash <Accordion title="Scoop package manager">
scoop bucket add org https://github.com/Infisical/scoop-infisical.git Use [Scoop](https://scoop.sh/) package manager
```
```bash ```bash
scoop install infisical scoop bucket add org https://github.com/Infisical/scoop-infisical.git
``` ```
### Updates ```bash
scoop install infisical
```
```bash ### Updates
scoop update infisical
``` ```bash
scoop update infisical
```
</Accordion>
<Accordion title="Winget package manager">
Use [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/) package manager
```bash
winget install infisical
```
</Accordion>
</Tab> </Tab>
<Tab title="NPM"> <Tab title="NPM">
@@ -6,40 +6,55 @@ description: "Learn how to structure your projects, secrets, and other resources
Infisical is designed to provide comprehensive, centralized, and efficient management of secrets, certificates, and encryption keys within organizations. Below is an overview of Infisical's structured components, which developers and administrators can leverage for optimal project management and security posture. Infisical is designed to provide comprehensive, centralized, and efficient management of secrets, certificates, and encryption keys within organizations. Below is an overview of Infisical's structured components, which developers and administrators can leverage for optimal project management and security posture.
### 1. Projects ### 0. Cluster/Instance
- **Best Practice**: In most cases, a single Infisical instance or cluster is sufficient. Multiple clusters are typically only necessary for large, globally distributed organizations.
- **Use Cases**:
- **Cloud-hosted** deployments typically use a single cluster. While technically possible, using multiple clusters is not a common practice and is generally unnecessary.
- **Self-hosted** deployments can be configured with multiple clusters if needed.
### 1. Organization
- **Definition**: An Infisical [organization](/documentation/platform/organization) is a set of projects that use the same billing.
- **Use Cases**:
- In **self-hosted** setups, you can create multiple organizations (e.g., one for each department or business unit).
- In **cloud-hosted deployments**, it's standard to use a single organization.
### 2. Projects
- **Definition and Role**: [Projects](/documentation/platform/project) are the highest-level construct within an [organization](/documentation/platform/organization) in Infisical. They serve as the primary container for all functionalities. - **Definition and Role**: [Projects](/documentation/platform/project) are the highest-level construct within an [organization](/documentation/platform/organization) in Infisical. They serve as the primary container for all functionalities.
- **Correspondence to Code Repositories**: Projects typically align with specific code repositories. - **Correspondence to Code Repositories**: Projects typically align with specific code repositories.
- **Functional Capabilities**: Each project encompasses features for managing secrets, certificates, and encryption keys, serving as the central hub for these resources. - **Functional Capabilities**: Each project encompasses features for managing secrets, certificates, and encryption keys, serving as the central hub for these resources.
### 2. Environments ### 3. Environments
- **Purpose**: Environments are designed for organizing and compartmentalizing secrets within projects. - **Purpose**: Environments are designed for organizing and compartmentalizing secrets within projects.
- **Customization Options**: Environments can be tailored to align with existing infrastructure setups of any project. Default options include **Development**, **Staging**, and **Production**. - **Customization Options**: Environments can be tailored to align with existing infrastructure setups of any project. Default options include **Development**, **Staging**, and **Production**.
- **Structure**: Each environment inherently has a root level for storing secrets, but additional sub-organizations can be created through [folders](/documentation/platform/folder) for better secret management. - **Structure**: Each environment inherently has a root level for storing secrets, but additional sub-organizations can be created through [folders](/documentation/platform/folder) for better secret management.
### 3. Folders ### 4. Folders
- **Use Case**: Folders are available for more advanced organizational needs, allowing logical separation of secrets. - **Use Case**: Folders are available for more advanced organizational needs, allowing logical separation of secrets.
- **Typical Structure**: Folders can correspond to specific logical units, such as microservices or different layers of an application, providing refined control over secrets. - **Typical Structure**: Folders can correspond to specific logical units, such as microservices or different layers of an application, providing refined control over secrets.
### 4. Imports ### 5. Imports
- **Purpose and Benefits**: To promote reusability and avoid redundancy, Infisical supports the use of imports. This allows secrets, folders, or entire environments to be referenced across multiple projects as needed. - **Purpose and Benefits**: To promote reusability and avoid redundancy, Infisical supports the use of imports. This allows secrets, folders, or entire environments to be referenced across multiple projects as needed.
- **Best Practice**: Utilizing [secret imports](/documentation/platform/secret-reference#secret-imports) or [references](/documentation/platform/secret-reference#secret-referencing) ensures consistency and minimizes manual overhead. - **Best Practice**: Utilizing [secret imports](/documentation/platform/secret-reference#secret-imports) or [references](/documentation/platform/secret-reference#secret-referencing) ensures consistency and minimizes manual overhead.
### 5. Approval Workflows ### 6. Approval Workflows
- **Importance**: Implementing approval workflows is recommended for organizations aiming to enhance efficiency and strengthen their security posture. - **Importance**: Implementing approval workflows is recommended for organizations aiming to enhance efficiency and strengthen their security posture.
- **Types of Workflows**: - **Types of Workflows**:
- **[Access Requests](/documentation/platform/pr-workflows)**: This workflow allows developers to request access to sensitive resources. Such access can be configured for temporary use, a practice known as "just-in-time" access. - **[Access Requests](/documentation/platform/pr-workflows)**: This workflow allows developers to request access to sensitive resources. Such access can be configured for temporary use, a practice known as "just-in-time" access.
- **[Change Requests](/documentation/platform/access-controls/access-requests)**: Facilitates reviews and approvals when changes are proposed for sensitive environments or specific folders, ensuring proper oversight. - **[Change Requests](/documentation/platform/access-controls/access-requests)**: Facilitates reviews and approvals when changes are proposed for sensitive environments or specific folders, ensuring proper oversight.
### 6. Access Controls ### 7. Access Controls
Infisical’s access control framework is unified for both human users and machine identities, ensuring consistent management across the board. Infisical’s access control framework is unified for both human users and machine identities, ensuring consistent management across the board.
### 6.1 Roles ### 7.1 Roles
- **2 Role Types**: - **2 Role Types**:
- **Organization-Level Roles**: Provide broad access across the organization (e.g., ability to manage billing, configure settings, etc.). - **Organization-Level Roles**: Provide broad access across the organization (e.g., ability to manage billing, configure settings, etc.).
@@ -49,17 +64,17 @@ Infisical’s access control framework is unified for both human users and machi
<Note>Project access is defined not via an organization-level role, but rather through specific project memberships of both human and machine identities. Admin roles bypass this by default. </Note> <Note>Project access is defined not via an organization-level role, but rather through specific project memberships of both human and machine identities. Admin roles bypass this by default. </Note>
### 6.2 Additional Privileges ### 7.2 Additional Privileges
[Additional privileges](/documentation/platform/access-controls/additional-privileges) can be assigned to users and machines on an ad-hoc basis for specific scenarios where roles alone are insufficient. If you find yourself using additional privileges too much, it is recommended to create custom roles. Additional privileges can be temporary or permanent. [Additional privileges](/documentation/platform/access-controls/additional-privileges) can be assigned to users and machines on an ad-hoc basis for specific scenarios where roles alone are insufficient. If you find yourself using additional privileges too much, it is recommended to create custom roles. Additional privileges can be temporary or permanent.
### 6.3 Attribute-Based Access Control (ABAC) ### 7.3 Attribute-Based Access Control (ABAC)
[Attribute-based Access Controls](/documentation/platform/access-controls/attribute-based-access-controls) allow restrictions based on tags or attributes linked to secrets. These can be integrated with SAML assertions and other security frameworks for dynamic access management. [Attribute-based Access Controls](/documentation/platform/access-controls/attribute-based-access-controls) allow restrictions based on tags or attributes linked to secrets. These can be integrated with SAML assertions and other security frameworks for dynamic access management.
### 6.4 User Groups ### 7.4 User Groups
- **Application**: Organizations should use users groups in situations when they have a lot of developers with the same level of access (e.g., separated by team, department, seniority, etc.). - **Application**: Organizations should use users groups in situations when they have a lot of developers with the same level of access (e.g., separated by team, department, seniority, etc.).
- **Synchronization**: [User groups](/documentation/platform/groups) can be synced with an identity provider to maintain consistency and reduce manual management. - **Synchronization**: [User groups](/documentation/platform/groups) can be synced with an identity provider to maintain consistency and reduce manual management.
@@ -41,3 +41,16 @@ Dynamic secrets are particularly useful in environments with stringent security
4. [Oracle](./oracle) 4. [Oracle](./oracle)
6. [Redis](./redis) 6. [Redis](./redis)
5. [AWS IAM](./aws-iam) 5. [AWS IAM](./aws-iam)
**FAQ**
<AccordionGroup>
<Accordion title="Why is my SQL dynamic secret failing when I generate a lease?">
This usually happens when the SQL statements defined for creating or revoking the secret are not compatible with your database provider.
Different SQL engines have different expectations for quoting identifiers and values. For example, some use backticks (`` `username` ``), others use single quotes (`'username'`), and some expect double quotes (`"username"`). A statement that works on one provider might fail on another.
**Recommendation:**
Make sure to adjust your SQL statements to follow the syntax required by your specific database provider. Always test them directly on your target database to ensure they execute without errors.
</Accordion>
</AccordionGroup>
@@ -19,7 +19,7 @@ Before you begin, you'll first need to choose a method of authentication with AW
![IAM Role Creation](/images/integrations/aws/integration-aws-iam-assume-role.png) ![IAM Role Creation](/images/integrations/aws/integration-aws-iam-assume-role.png)
2. Select **AWS Account** as the **Trusted Entity Type**. 2. Select **AWS Account** as the **Trusted Entity Type**.
3. Choose **Another AWS Account** and enter **381492033652** (Infisical AWS Account ID). This restricts the role to be assumed only by Infisical. If you are self-hosting, provide the AWS account number where Infisical is hosted. 3. Select **Another AWS Account** and provide the appropriate Infisical AWS Account ID: use **381492033652** for the **US region**, and **345594589636** for the **EU region**. This restricts the role to be assumed only by Infisical. If you are self-hosting, provide the AWS account number where Infisical is hosted.
4. Optionally, enable **Require external ID** and enter your Infisical **project ID** to further enhance security. 4. Optionally, enable **Require external ID** and enter your Infisical **project ID** to further enhance security.
</Step> </Step>
<Step title="Add Required Permissions for the IAM Role"> <Step title="Add Required Permissions for the IAM Role">
Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

+2 -1
View File
@@ -55,7 +55,7 @@ Infisical supports two methods for connecting to AWS.
![IAM Role Creation](/images/integrations/aws/integration-aws-iam-assume-role.png) ![IAM Role Creation](/images/integrations/aws/integration-aws-iam-assume-role.png)
2. Select **AWS Account** as the **Trusted Entity Type**. 2. Select **AWS Account** as the **Trusted Entity Type**.
3. Choose **Another AWS Account** and enter **381492033652** (Infisical AWS Account ID). This restricts the role to be assumed only by Infisical. If self-hosting, provide your AWS account number instead. 3. Select **Another AWS Account** and provide the appropriate Infisical AWS Account ID: use **381492033652** for the **US region**, and **345594589636** for the **EU region**. This restricts the role to be assumed only by Infisical. If self-hosting, provide your AWS account number instead.
4. (Recommended) <strong>Enable "Require external ID"</strong> and input your **Organization ID** to strengthen security and mitigate the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html). 4. (Recommended) <strong>Enable "Require external ID"</strong> and input your **Organization ID** to strengthen security and mitigate the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html).
<Warning type="warning" title="Security Best Practice: Use External ID to Prevent Confused Deputy Attacks"> <Warning type="warning" title="Security Best Practice: Use External ID to Prevent Confused Deputy Attacks">
@@ -362,4 +362,5 @@ Infisical supports two methods for connecting to AWS.
</Steps> </Steps>
</Tab> </Tab>
</Tabs> </Tabs>
+9 -1
View File
@@ -314,6 +314,13 @@
"self-hosting/deployment-options/kubernetes-helm" "self-hosting/deployment-options/kubernetes-helm"
] ]
}, },
{
"group": "Linux Package",
"pages": [
"self-hosting/deployment-options/native/linux-package/installation",
"self-hosting/deployment-options/native/linux-package/commands-configuration"
]
},
"self-hosting/guides/upgrading-infisical", "self-hosting/guides/upgrading-infisical",
"self-hosting/configuration/envars", "self-hosting/configuration/envars",
"self-hosting/configuration/requirements", "self-hosting/configuration/requirements",
@@ -330,7 +337,8 @@
"pages": [ "pages": [
"self-hosting/reference-architectures/aws-ecs", "self-hosting/reference-architectures/aws-ecs",
"self-hosting/reference-architectures/linux-deployment-ha", "self-hosting/reference-architectures/linux-deployment-ha",
"self-hosting/reference-architectures/on-prem-k8s-ha" "self-hosting/reference-architectures/on-prem-k8s-ha",
"self-hosting/reference-architectures/google-cloud-run"
] ]
}, },
"self-hosting/ee", "self-hosting/ee",
@@ -0,0 +1,38 @@
---
title: "Configurations"
description: "Learn how to configure and manage the Infisical Linux package"
---
## Configuration Overview
All configuration for the Infisical Linux package is managed through a single file called `infisical.rb`, located in the `/etc/infisical` directory.
This file defines all necessary settings, including encryption keys, database connections, and environment-specific settings.
<Info> After making any changes to the `infisical.rb` file, always run `infisical-ctl reconfigure` to apply them. </Info>
### Example Configuration
```ruby infisical.rb
# Important: Replace these values with secure keys in production
infisical_core['ENCRYPTION_KEY'] = '6c1fe4e407b8911c104518103505b218'
infisical_core['AUTH_SECRET'] = '5lrMXKKWCVocS/uerPsl7V+TX/aaUaI7iDkgl3tSmLE='
# Database connection strings
infisical_core['DB_CONNECTION_URI'] = 'postgres://<username>:<password>@<host>:5432/<database>'
infisical_core['REDIS_URL'] = 'redis://<host>:6379'
```
For a full list of supported configuration variables, refer to the [configuration variables documentation](/self-hosting/configuration/envars).
## All `infisical-ctl` Commands
The Infisical Linux package includes the `infisical-ctl` command-line tool, which allows you to manage your deployment.
The available commands are listed below.
| Command | Description |
|-----------------------------|-----------------------------------------------------------------------------|
| `infisical-ctl reconfigure` | Applies changes from `infisical.rb` and restarts the Infisical services. |
| `infisical-ctl start` | Starts the Infisical services. |
| `infisical-ctl stop` | Stops all running Infisical services. |
| `infisical-ctl status` | Displays the current status of the Infisical services. |
| `infisical-ctl tail` | Streams real-time logs from the Infisical application. |
@@ -0,0 +1,122 @@
---
title: "Installation"
description: "Learn how to deploy Infisical using the Linux package"
---
Infisical can be deployed on Linux virtual machines without the need for containers using our standalone Linux packages.
These packages are available in both .deb (for Debian-based systems) and .rpm (for RHEL-based systems) formats.
The installation includes the Infisical service, along with a CLI tool (infisical-ctl) to help you manage configurations, startup, and application logging.
This approach is ideal for environments where containerization isn't desired, while still providing a lightweight deployment option.
## Prerequisites
This installation method only provides the Infisical application. You are responsible for configuring both PostgreSQL and Redis, either by using managed services (e.g., AWS RDS, Azure Database, GCP Cloud SQL/Memorystore) or by deploying them manually in your on-prem environment.
Please ensure you have the following before beginning installation of Infisical:
- A Linux server running a Debian/Ubuntu or RHEL-based distribution
- A running PostgreSQL database instance (version 14 and up)
- A running Redis database instance (versions 6.x or 7.x)
## Installation Steps
<Steps>
<Step title="Install the Infisical Package">
Select your Linux distribution to get started. Only AMD64-based systems are supported at this time, ARM support is coming soon.
<Tabs>
<Tab title="Debian/Ubuntu">
Add the Infisical repository:
```bash
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-core/setup.deb.sh' | sudo -E bash
```
Install Infisical:
```bash
sudo apt-get update && sudo apt-get install -y infisical-core
```
> **Note**: For production use, we recommend locking to a specific version to ensure consistency. [View available versions](https://cloudsmith.io/~infisical/repos/infisical-core/packages/).
</Tab>
<Tab title="RedHat/CentOS/Amazon Linux">
Add the Infisical repository:
```bash
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-core/setup.rpm.sh' | sudo -E bash
```
Install Infisical:
```bash
sudo yum install infisical-core
```
> **Note**: For production use, we recommend locking to a specific version to ensure consistency. [View available versions](https://cloudsmith.io/~infisical/repos/infisical-core/packages/).
</Tab>
</Tabs>
Verify the installation:
```bash
infisical-ctl help
```
</Step>
<Step title="Create the Configuration File">
Create an `infisical.rb` file at `/etc/infisical`. This file contains your database connection strings and other runtime settings.
```ruby
# Important: Replace with secure values in production
infisical_core['ENCRYPTION_KEY'] = '6c1fe4e407b8911c104518103505b218'
infisical_core['AUTH_SECRET'] = '5lrMXKKWCVocS/uerPsl7V+TX/aaUaI7iDkgl3tSmLE='
# Example database connection strings
infisical_core['DB_CONNECTION_URI'] = 'postgres://<db-username>:<db-password>@<db-host>:<db-port>/<db-name>'
infisical_core['REDIS_URL'] = 'redis://<redis-host>:<redis-port>'
```
See the full list of options in our [configuration documentation](/self-hosting/configuration/envars).
</Step>
<Step title="Start Infisical">
1. Start the Infisical service:
```bash
infisical-ctl reconfigure
```
The server runs on port `8080` by default (customizable in `infisical.rb`).
2. Check the service status:
```bash
infisical-ctl status
```
View the service logs in real-time:
```bash
infisical-ctl tail
```
</Step>
</Steps>
## Platform Support
### Microsoft Windows
Infisical is built for Linux-based systems. It is not supported on Microsoft Windows, and we do not plan to support it in the near future. For Windows users, consider running Infisical in a virtual machine or WSL2 environment.
### Unsupported Linux Distributions and Unix-like Systems
Infisical is not tested or officially supported on the following:
- Arch Linux
- Fedora
- FreeBSD
- Gentoo
- macOS
We recommend sticking to officially supported distributions for the best experience.
## Linux vs Containerized Deployments
Infisical is a stateless application, which means it can be easily scaled and redeployed without maintaining internal state between instances.
If your use case requires rolling updates, self-healing, or auto-scaling, we recommend deploying Infisical in a containerized environment such as Kubernetes/OpenShift, or using managed container orchestration services like AWS ECS or Google Cloud Run.
These platforms offer built-in capabilities for high availability and help simplify operational overhead for your deployment.
+5 -16
View File
@@ -33,21 +33,10 @@ Choose from a number of deployment options listed below to get started.
Use our Helm chart to Install Infisical on your Kubernetes cluster. Use our Helm chart to Install Infisical on your Kubernetes cluster.
</Card> </Card>
</CardGroup> </CardGroup>
{/* <CardGroup cols={2}> <Card
<Card title="Linux package"
title="Native Deployment"
color="#000000" color="#000000"
icon="box" href="deployment-options/native/linux-package/installation"
href="deployment-options/native/standalone-binary"
> >
Install Infisical on your Debian-based system without containers using our standalone binary. Install Infisical on your system without containers using our Linux package.
</Card> </Card>
<Card
title="Native Deployment, High Availability"
color="#000000"
icon="boxes-stacked"
href="deployment-options/native/high-availability"
>
Install Infisical on your Debian-based instances without containers using our standalone binary with high availability out of the box.
</Card>
</CardGroup> */}
@@ -0,0 +1,114 @@
---
title: "Google Cloud Run"
description: "Reference architecture for self-hosting Infisical on Google Cloud Run."
---
## Overview
This guide outlines a reference architecture for deploying Infisical in a self-hosted configuration using Google Cloud Run.
It is intended to provide a scalable, secure, and production-ready baseline for organizations choosing Google Cloud Platform (GCP) as their infrastructure provider.
## Core Components
- **Cloud Run:** Infisical service is containerized and deployed as fully managed Cloud Run services.
- **Cloud SQL:** Infisical uses Postgres as its persistence layer. As such, Cloud SQL for PostgreSQL is used.
- **MemoryStore for Redis:** To schedule jobs, process audit logs and cache performance, Infisical requires Redis.
## Securing Infisical's root credential
- **Secrets Manager:** To secure Infisical’s root credentials (database connection string, encryption key, etc.),
we highly recommend that you use Google Secrets Manager and only allow the tasks running Infisical to access them.
## High Availability and Scalability
This architecture leverages Google Cloud's managed services to achieve high availability and scalability out of the box:
**Cloud Run:**
- Automatically scales the number of container instances up or down based on incoming request volume.
- Supports rapid scaling during traffic spikes, ensuring low latency.
- Configurable minimum and maximum instances to handle baseline and peak loads.
**Cloud SQL:**
- Provides high availability configurations (regional instances with automatic failover) to ensure database uptime.
- Automated backups, point-in-time recovery, and maintenance.
**MemoryStore:**
- Offers highly available Redis configurations with replication.
- Fully managed with automatic scaling and patching.
**Cloud Load Balancer:**
- Distributes user traffic across available Cloud Run instances.
- Provides SSL termination, global load balancing, and health checks.
<Info>
**Note:** To further improve performance and availability, consider enabling multi-region deployment strategies,
regional VPC Connectors, and database replicas for read-heavy workloads.
</Info>
## Configuration
<Steps>
<Step title="Provision Core Infrastructure">
**Cloud SQL (PostgreSQL):**
- Create a Cloud SQL instance.
- Under `Zonal availability`, select the `Multiple zones` option to ensure High Availability.
- Configure private IP access.
**MemoryStore (Redis):**
- Deploy a Redis instance.
- Configure VPC access.
</Step>
<Step title="Get the Infisical Docker image">
Visit [Docker Hub](https://hub.docker.com/r/infisical/infisical/tags) and select a version of Infisical image you would like to deploy.
Then, within Cloud Run, paste the URL of the specific Infisical Docker image you would like to use within the `Container image URL` field.
![Cloud Run container image settings UI](/images/self-hosting/reference-architectures/google-cloud-run/cloud-run-container-image.png)
Remember to replace `<version>` with the docker image tag of your choice.
</Step>
<Step title="Set the environment variables">
For a minimal installation of Infisical, you must configure the following environment variables:
```bash
ENCRYPTION_KEY=<your_encryption_key>
AUTH_SECRET=<your_auth_secret>
DB_CONNECTION_URI="<your_db_connection_uri>"
SITE_URL="<your_site_url>"
REDIS_URL="<your_redis_url>"
```
[View all available configurations](/self-hosting/configuration/envars).
You will want to setup Postgres and Redis within Google Cloud Platform to connect to Infisical.
Once you have added the required environment variables to the `Environment Variables` section within Cloud Run,
create the container to get Infisical up and running.
![Cloud Run container environment variables settings UI](/images/self-hosting/reference-architectures/google-cloud-run/container-env-vars.png)
<Warning>
The above environment variable values are only to be used as an example and should not be used in production
</Warning>
</Step>
<Step title="Network Configuration">
Enable `Connect to a VPC for outbound traffic`: This enables the service to talk to private resources (e.g., a Cloud SQL database, Redis instance on a private IP) inside your Google Cloud VPC network.
Select `Send traffic directly to a VPC`: It gives lower latency and better performance, but uses more IPs from the subnet.
<Info>
Your Cloud Run revision must be in the same VPC network
</Info>
![Cloud Run container network settings UI](/images/self-hosting/reference-architectures/google-cloud-run/container-network-configuration.png)
Once the container is running, verify the installation by opening your web browser and navigating to the Site URL.
</Step>
</Steps>
File diff suppressed because one or more lines are too long
+8
View File
@@ -281,6 +281,14 @@ export const ROUTE_PATHS = Object.freeze({
"/cert-manager/$projectId/overview", "/cert-manager/$projectId/overview",
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview" "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/overview"
), ),
CertificateAuthoritiesPage: setRoute(
"/cert-manager/$projectId/certificate-authorities",
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/certificate-authorities"
),
AlertingPage: setRoute(
"/cert-manager/$projectId/alerting",
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/alerting"
),
PkiCollectionDetailsByIDPage: setRoute( PkiCollectionDetailsByIDPage: setRoute(
"/cert-manager/$projectId/pki-collections/$collectionId", "/cert-manager/$projectId/pki-collections/$collectionId",
"/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/pki-collections/$collectionId" "/_authenticate/_inject-org-details/_org-layout/cert-manager/$projectId/_cert-manager-layout/pki-collections/$collectionId"
@@ -84,6 +84,7 @@ export const eventToNameMap: { [K in EventType]: string } = {
[EventType.ADD_PKI_COLLECTION_ITEM]: "Add PKI collection item", [EventType.ADD_PKI_COLLECTION_ITEM]: "Add PKI collection item",
[EventType.DELETE_PKI_COLLECTION_ITEM]: "Delete PKI collection item", [EventType.DELETE_PKI_COLLECTION_ITEM]: "Delete PKI collection item",
[EventType.ORG_ADMIN_ACCESS_PROJECT]: "Org admin accessed project", [EventType.ORG_ADMIN_ACCESS_PROJECT]: "Org admin accessed project",
[EventType.ORG_ADMIN_BYPASS_SSO]: "Org admin bypassed SSO enforcement",
[EventType.CREATE_CERTIFICATE_TEMPLATE]: "Create certificate template", [EventType.CREATE_CERTIFICATE_TEMPLATE]: "Create certificate template",
[EventType.UPDATE_CERTIFICATE_TEMPLATE]: "Update certificate template", [EventType.UPDATE_CERTIFICATE_TEMPLATE]: "Update certificate template",
[EventType.DELETE_CERTIFICATE_TEMPLATE]: "Delete certificate template", [EventType.DELETE_CERTIFICATE_TEMPLATE]: "Delete certificate template",
@@ -90,6 +90,7 @@ export enum EventType {
ADD_PKI_COLLECTION_ITEM = "add-pki-collection-item", ADD_PKI_COLLECTION_ITEM = "add-pki-collection-item",
DELETE_PKI_COLLECTION_ITEM = "delete-pki-collection-item", DELETE_PKI_COLLECTION_ITEM = "delete-pki-collection-item",
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project", ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso",
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template", CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template", UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template", DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
@@ -718,6 +718,11 @@ interface OrgAdminAccessProjectEvent {
}; // no metadata yet }; // no metadata yet
} }
interface OrgAdminBypassSSOEvent {
type: EventType.ORG_ADMIN_BYPASS_SSO;
metadata: Record<string, string>; // no metadata yet
}
interface CreateCertificateTemplate { interface CreateCertificateTemplate {
type: EventType.CREATE_CERTIFICATE_TEMPLATE; type: EventType.CREATE_CERTIFICATE_TEMPLATE;
metadata: { metadata: {
@@ -885,6 +890,7 @@ export type Event =
| AddPkiCollectionItem | AddPkiCollectionItem
| DeletePkiCollectionItem | DeletePkiCollectionItem
| OrgAdminAccessProjectEvent | OrgAdminAccessProjectEvent
| OrgAdminBypassSSOEvent
| CreateCertificateTemplate | CreateCertificateTemplate
| UpdateCertificateTemplate | UpdateCertificateTemplate
| GetCertificateTemplate | GetCertificateTemplate
@@ -92,18 +92,46 @@ export const ProjectLayout = () => {
</Link> </Link>
)} )}
{isCertManager && ( {isCertManager && (
<Link <>
to={`/${ProjectType.CertificateManager}/$projectId/overview` as const} <Link
params={{ to={`/${ProjectType.CertificateManager}/$projectId/overview` as const}
projectId: currentWorkspace.id params={{
}} projectId: currentWorkspace.id
> }}
{({ isActive }) => ( >
<MenuItem isSelected={isActive} icon="lock-closed"> {({ isActive }) => (
Overview <MenuItem isSelected={isActive} icon="certificate">
</MenuItem> Certificates
)} </MenuItem>
</Link> )}
</Link>
<Link
to={
`/${ProjectType.CertificateManager}/$projectId/certificate-authorities` as const
}
params={{
projectId: currentWorkspace.id
}}
>
{({ isActive }) => (
<MenuItem isSelected={isActive} icon="certificate-authority">
Certificate Authorities
</MenuItem>
)}
</Link>
<Link
to={`/${ProjectType.CertificateManager}/$projectId/alerting` as const}
params={{
projectId: currentWorkspace.id
}}
>
{({ isActive }) => (
<MenuItem isSelected={isActive} icon="notification-bell">
Alerting
</MenuItem>
)}
</Link>
</>
)} )}
{isCmek && ( {isCmek && (
<Link <Link
@@ -0,0 +1,29 @@
import { Helmet } from "react-helmet";
import { useTranslation } from "react-i18next";
import { ProjectPermissionCan } from "@app/components/permissions";
import { PageHeader } from "@app/components/v2";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
import { PkiAlertsSection } from "./components";
export const AlertingPage = () => {
const { t } = useTranslation();
return (
<div className="container mx-auto flex h-full flex-col justify-between bg-bunker-800 text-white">
<Helmet>
<title>{t("common.head-title", { title: "Alerting" })}</title>
</Helmet>
<div className="mx-auto mb-6 w-full max-w-7xl">
<PageHeader title="Alerting" />
<ProjectPermissionCan
renderGuardBanner
I={ProjectPermissionActions.Read}
a={ProjectPermissionSub.PkiAlerts}
>
<PkiAlertsSection />
</ProjectPermissionCan>
</div>
</div>
);
};

Some files were not shown because too many files have changed in this diff Show More