Compare commits

...

36 Commits

Author SHA1 Message Date
Maidul Islam
e143a31e79 Merge pull request #1670 from JunedKhan101/main
docs:fixed broken link
2024-04-08 17:45:51 -07:00
Maidul Islam
f6cc20b08b remove link from docs 2024-04-08 12:00:11 -07:00
Maidul Islam
90e125454e remove docs for e2ee 2024-04-08 11:58:48 -07:00
Maidul Islam
fbdf3dc9ce Merge pull request #1647 from akhilmhdh/doc/integration-api-guide
docs: added guide to setup integration with api
2024-04-08 11:56:19 -07:00
Maidul Islam
f333c905d9 revise generic integration docs 2024-04-08 11:55:38 -07:00
Maidul Islam
71e60df39a Merge pull request #1659 from agilesyndrome/fix_universalAuth_operatorinstall
fix: Run make kubectl-install
2024-04-08 10:18:00 -07:00
Maidul Islam
8b4d050d05 updated original value in replace script 2024-04-08 10:15:09 -07:00
Maidul Islam
3b4bb591a3 set default for NEXT_PUBLIC_SAML_ORG_SLUG 2024-04-08 09:25:37 -07:00
Maidul Islam
54f1a4416b add default value 2024-04-08 09:06:42 -07:00
Maidul Islam
47e3f1b510 Merge pull request #1661 from Infisical/saml-auto-redirect
add automatic SAML redirect
2024-04-08 08:22:04 -07:00
Juned Khan
5810b76027 docs:fixed broken link 2024-04-08 16:55:11 +05:30
Daniel Hougaard
246e6c64d1 Merge pull request #1668 from JunedKhan101/main
removed extra whitespace from error message
2024-04-07 16:05:31 -07:00
Juned Khan
4e836c5dca removed extra whitespace from error message 2024-04-07 17:41:39 +05:30
Maidul Islam
63a289c3be add saml org clug to standalone 2024-04-06 11:58:50 -07:00
Maidul Islam
0a52bbd55d add render once to use effect 2024-04-06 11:40:13 -07:00
Maidul Islam
593bdf74b8 patch notice 2024-04-06 10:57:08 -07:00
Maidul Islam
1f3742e619 update april_2024_db_update_closed 2024-04-06 10:39:21 -07:00
Maidul Islam
d6e5ac2133 maintenance postponed 2024-04-06 10:01:13 -07:00
Vladyslav Matsiiako
fea48518a3 removed new tag from identities 2024-04-05 19:01:54 -07:00
Vladyslav Matsiiako
94d509eb01 fixed search bar with folders 2024-04-05 18:37:12 -07:00
Vladyslav Matsiiako
055fd34c33 added baked env var 2024-04-05 17:25:25 -07:00
Vladyslav Matsiiako
74fefa9879 add automatic SAML redirect 2024-04-05 14:39:31 -07:00
Vladyslav Matsiiako
ff2c8d017f add automatic SAML redirect 2024-04-05 14:29:50 -07:00
Daniel Hougaard
ba1f8f4564 Merge pull request #1660 from Infisical/fix/delete-role-error
Fix: Error handling when deleting roles that are assigned to identities or users
2024-04-05 11:15:25 -07:00
Daniel Hougaard
e26df005c2 Fix: Typo 2024-04-05 11:11:32 -07:00
Daniel Hougaard
aca9b47f82 Fix: Typo 2024-04-05 11:11:26 -07:00
Daniel Hougaard
a16ce8899b Fix: Check for identities and project users who has the selected role before deleting 2024-04-05 11:11:15 -07:00
Daniel Hougaard
b61511d100 Update index.ts 2024-04-05 11:10:54 -07:00
Vladyslav Matsiiako
a945bdfc4c update docs style 2024-04-05 10:07:42 -07:00
Drew Easley
f6d7ec52c2 fix: Run make kubectl-install 2024-04-05 08:10:38 -04:00
Daniel Hougaard
3f6999b2e3 Merge pull request #1657 from Infisical/rate-limit
Add new rate limits for API
2024-04-04 19:53:31 -07:00
Maidul Islam
9128461409 Merge pull request #1658 from Infisical/daniel/delete-duplicate-org-memberships-migration
Feat: Delete duplicate memberships migration
2024-04-04 19:19:39 -07:00
Daniel Hougaard
893235c40f Update 20240405000045_org-memberships-unique-constraint.ts 2024-04-04 18:43:32 -07:00
Tuan Dang
d3cdaa8449 Add new rate limits 2024-04-04 18:12:23 -07:00
BlackMagiq
e0f655ae30 Merge pull request #1656 from Infisical/fix/duplicate-org-memberships
Fix: Duplicate organization memberships
2024-04-04 17:10:55 -07:00
Akhil Mohan
40bb9668fe docs: added guide to setup integration with api 2024-04-03 01:12:30 +05:30
79 changed files with 1302 additions and 1232 deletions

View File

@@ -1,6 +1,7 @@
ARG POSTHOG_HOST=https://app.posthog.com
ARG POSTHOG_API_KEY=posthog-api-key
ARG INTERCOM_ID=intercom-id
ARG SAML_ORG_SLUG=saml-org-slug-default
FROM node:20-alpine AS base
@@ -35,6 +36,8 @@ ARG INTERCOM_ID
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
ARG INFISICAL_PLATFORM_VERSION
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
ARG SAML_ORG_SLUG
ENV NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG
# Build
RUN npm run build
@@ -100,6 +103,9 @@ ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
ARG INTERCOM_ID=intercom-id
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
ARG SAML_ORG_SLUG
ENV NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG \
BAKED_NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG
WORKDIR /

View File

@@ -103,11 +103,15 @@ export const ${dalName} = (db: TDbClient) => {
`import { z } from "zod";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { readLimit } from "@app/server/config/rateLimiter";
export const register${pascalCase}Router = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({}),
response: {

View File

@@ -1,8 +1,104 @@
import { Knex } from "knex";
import { z } from "zod";
import { TableName } from "../schemas";
import { TableName, TOrgMemberships } from "../schemas";
const validateOrgMembership = (membershipToValidate: TOrgMemberships, firstMembership: TOrgMemberships) => {
const firstOrgId = firstMembership.orgId;
const firstUserId = firstMembership.userId;
if (membershipToValidate.id === firstMembership.id) {
return;
}
if (membershipToValidate.inviteEmail !== firstMembership.inviteEmail) {
throw new Error(`Invite emails are different for the same userId and orgId: ${firstUserId}, ${firstOrgId}`);
}
if (membershipToValidate.orgId !== firstMembership.orgId) {
throw new Error(`OrgIds are different for the same userId and orgId: ${firstUserId}, ${firstOrgId}`);
}
if (membershipToValidate.role !== firstMembership.role) {
throw new Error(`Roles are different for the same userId and orgId: ${firstUserId}, ${firstOrgId}`);
}
if (membershipToValidate.roleId !== firstMembership.roleId) {
throw new Error(`RoleIds are different for the same userId and orgId: ${firstUserId}, ${firstOrgId}`);
}
if (membershipToValidate.status !== firstMembership.status) {
throw new Error(`Statuses are different for the same userId and orgId: ${firstUserId}, ${firstOrgId}`);
}
if (membershipToValidate.userId !== firstMembership.userId) {
throw new Error(`UserIds are different for the same userId and orgId: ${firstUserId}, ${firstOrgId}`);
}
};
export async function up(knex: Knex): Promise<void> {
const RowSchema = z.object({
userId: z.string(),
orgId: z.string(),
cnt: z.string()
});
// Transactional find and delete duplicate rows
await knex.transaction(async (tx) => {
const duplicateRows = await tx(TableName.OrgMembership)
.select("userId", "orgId") // Select the userId and orgId so we can group by them
.count("* as cnt") // Count the number of rows for each userId and orgId, so we can make sure there are more than 1 row (a duplicate)
.groupBy("userId", "orgId")
.havingRaw("count(*) > ?", [1]); // Using havingRaw for direct SQL expressions
// Parse the rows to ensure they are in the correct format, and for type safety
const parsedRows = RowSchema.array().parse(duplicateRows);
// For each of the duplicate rows, loop through and find the actual memberships to delete
for (const row of parsedRows) {
const count = Number(row.cnt);
// An extra check to ensure that the count is actually a number, and the number is greater than 2
if (typeof count !== "number" || count < 2) {
// eslint-disable-next-line no-continue
continue;
}
// Find all the organization memberships that have the same userId and orgId
// eslint-disable-next-line no-await-in-loop
const rowsToDelete = await tx(TableName.OrgMembership).where({
userId: row.userId,
orgId: row.orgId
});
// Ensure that all the rows have exactly the same value, except id, createdAt, updatedAt
for (const rowToDelete of rowsToDelete) {
validateOrgMembership(rowToDelete, rowsToDelete[0]);
}
// Find the row with the latest createdAt, which we will keep
let lowestCreatedAt: number | null = null;
let latestCreatedRow: TOrgMemberships | null = null;
for (const rowToDelete of rowsToDelete) {
if (lowestCreatedAt === null || rowToDelete.createdAt.getTime() < lowestCreatedAt) {
lowestCreatedAt = rowToDelete.createdAt.getTime();
latestCreatedRow = rowToDelete;
}
}
if (!latestCreatedRow) {
throw new Error("Failed to find last created membership");
}
// Filter out the latest row from the rows to delete
const membershipIdsToDelete = rowsToDelete.map((r) => r.id).filter((id) => id !== latestCreatedRow!.id);
// eslint-disable-next-line no-await-in-loop
const numberOfRowsDeleted = await tx(TableName.OrgMembership).whereIn("id", membershipIdsToDelete).delete();
// eslint-disable-next-line no-console
console.log(
`Deleted ${numberOfRowsDeleted} duplicate organization memberships for ${row.userId} and ${row.orgId}`
);
}
});
await knex.schema.alterTable(TableName.OrgMembership, (table) => {
table.unique(["userId", "orgId"]);
});

View File

@@ -5,14 +5,18 @@ import { DynamicSecretLeasesSchema } from "@app/db/schemas";
import { DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { SanitizedDynamicSecretSchema } from "@app/server/routes/sanitizedSchemas";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "POST",
url: "/",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
dynamicSecretName: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.dynamicSecretName).toLowerCase(),
@@ -55,8 +59,11 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
});
server.route({
url: "/:leaseId",
method: "DELETE",
url: "/:leaseId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.leaseId)
@@ -94,8 +101,11 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
});
server.route({
url: "/:leaseId/renew",
method: "POST",
url: "/:leaseId/renew",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.leaseId)
@@ -146,6 +156,9 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
server.route({
url: "/:leaseId",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.leaseId)

View File

@@ -7,14 +7,18 @@ import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/pro
import { DYNAMIC_SECRETS } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { SanitizedDynamicSecretSchema } from "@app/server/routes/sanitizedSchemas";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerDynamicSecretRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "POST",
url: "/",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.CREATE.projectSlug),
@@ -74,8 +78,11 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
});
server.route({
url: "/:name",
method: "PATCH",
url: "/:name",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.UPDATE.name)
@@ -138,8 +145,11 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
});
server.route({
url: "/:name",
method: "DELETE",
url: "/:name",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.DELETE.name)
@@ -173,6 +183,9 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
server.route({
url: "/:name",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
name: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.name)
@@ -207,6 +220,9 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
server.route({
url: "/",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST.projectSlug),
@@ -235,6 +251,9 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
server.route({
url: "/:name/leases",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
name: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.name)

View File

@@ -9,13 +9,17 @@ import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/service
import { ProjectPermissionSet } from "@app/ee/services/permission/project-permission";
import { IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/permanent",
method: "POST",
url: "/permanent",
config: {
rateLimit: writeLimit
},
schema: {
description: "Create a permanent or a non expiry specific privilege for identity.",
security: [
@@ -62,8 +66,11 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
});
server.route({
url: "/temporary",
method: "POST",
url: "/temporary",
config: {
rateLimit: writeLimit
},
schema: {
description: "Create a temporary or a expiring specific privilege for identity.",
security: [
@@ -121,8 +128,11 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
});
server.route({
url: "/",
method: "PATCH",
url: "/",
config: {
rateLimit: writeLimit
},
schema: {
description: "Update a specific privilege of an identity.",
security: [
@@ -190,8 +200,11 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
});
server.route({
url: "/",
method: "DELETE",
url: "/",
config: {
rateLimit: writeLimit
},
schema: {
description: "Delete a specific privilege of an identity.",
security: [
@@ -226,8 +239,11 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
});
server.route({
url: "/:privilegeSlug",
method: "GET",
url: "/:privilegeSlug",
config: {
rateLimit: readLimit
},
schema: {
description: "Retrieve details of a specific privilege by privilege slug.",
security: [
@@ -263,8 +279,11 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
});
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
description: "List of a specific privilege of an identity in a project.",
security: [

View File

@@ -17,6 +17,7 @@ import { z } from "zod";
import { LdapConfigsSchema } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env";
import { logger } from "@app/lib/logger";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -97,8 +98,11 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/config",
method: "GET",
url: "/config",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
querystring: z.object({
@@ -130,8 +134,11 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/config",
method: "POST",
url: "/config",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z.object({
@@ -164,6 +171,9 @@ export const registerLdapRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/config",
method: "PATCH",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z

View File

@@ -3,13 +3,17 @@
// TODO(akhilmhdh): Fix this when licence service gets it type
import { z } from "zod";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerLicenseRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:organizationId/plans/table",
method: "GET",
url: "/:organizationId/plans/table",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({ billingCycle: z.enum(["monthly", "yearly"]) }),
params: z.object({ organizationId: z.string().trim() }),
@@ -32,8 +36,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/plan",
method: "GET",
url: "/:organizationId/plan",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -54,8 +61,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/plans",
method: "GET",
url: "/:organizationId/plans",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
querystring: z.object({ workspaceId: z.string().trim().optional() }),
@@ -77,8 +87,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/session/trial",
method: "POST",
url: "/:organizationId/session/trial",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
body: z.object({ success_url: z.string().trim() }),
@@ -103,6 +116,9 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:organizationId/customer-portal-session",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -123,8 +139,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/plan/billing",
method: "GET",
url: "/:organizationId/plan/billing",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -145,8 +164,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/plan/table",
method: "GET",
url: "/:organizationId/plan/table",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -167,8 +189,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/billing-details",
method: "GET",
url: "/:organizationId/billing-details",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -189,8 +214,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/billing-details",
method: "PATCH",
url: "/:organizationId/billing-details",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
body: z.object({
@@ -217,8 +245,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/billing-details/payment-methods",
method: "GET",
url: "/:organizationId/billing-details/payment-methods",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -239,8 +270,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/billing-details/payment-methods",
method: "POST",
url: "/:organizationId/billing-details/payment-methods",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
body: z.object({
@@ -267,8 +301,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/billing-details/payment-methods/:pmtMethodId",
method: "DELETE",
url: "/:organizationId/billing-details/payment-methods/:pmtMethodId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
organizationId: z.string().trim(),
@@ -293,8 +330,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/billing-details/tax-ids",
method: "GET",
url: "/:organizationId/billing-details/tax-ids",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()
@@ -317,8 +357,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/billing-details/tax-ids",
method: "POST",
url: "/:organizationId/billing-details/tax-ids",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()
@@ -347,8 +390,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/billing-details/tax-ids/:taxId",
method: "DELETE",
url: "/:organizationId/billing-details/tax-ids/:taxId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
organizationId: z.string().trim(),
@@ -373,8 +419,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/invoices",
method: "GET",
url: "/:organizationId/invoices",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()
@@ -397,8 +446,11 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:organizationId/licenses",
method: "GET",
url: "/:organizationId/licenses",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()

View File

@@ -2,6 +2,7 @@ import slugify from "@sindresorhus/slugify";
import { z } from "zod";
import { OrgMembershipRole, OrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -9,6 +10,9 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/:organizationId/roles",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()
@@ -51,6 +55,9 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "PATCH",
url: "/:organizationId/roles/:roleId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
organizationId: z.string().trim(),
@@ -95,6 +102,9 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/:organizationId/roles/:roleId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
organizationId: z.string().trim(),
@@ -122,6 +132,9 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:organizationId/roles",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()
@@ -151,6 +164,9 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:organizationId/permissions",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()

View File

@@ -1,6 +1,7 @@
import { z } from "zod";
import { ProjectMembershipsSchema, ProjectRolesSchema } from "@app/db/schemas";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -8,6 +9,9 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/:projectId/roles",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().trim()
@@ -41,6 +45,9 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "PATCH",
url: "/:projectId/roles/:roleId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().trim(),
@@ -76,6 +83,9 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/:projectId/roles/:roleId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().trim(),
@@ -104,6 +114,9 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:projectId/roles",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
projectId: z.string().trim()
@@ -134,6 +147,9 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:projectId/permissions",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
projectId: z.string().trim()

View File

@@ -4,6 +4,7 @@ import { AuditLogsSchema, SecretSnapshotsSchema } from "@app/db/schemas";
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
import { AUDIT_LOGS, PROJECTS } from "@app/lib/api-docs";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -11,6 +12,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:workspaceId/secret-snapshots",
config: {
rateLimit: readLimit
},
schema: {
description: "Return project secret snapshots ids",
security: [
@@ -51,6 +55,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:workspaceId/secret-snapshots/count",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -83,6 +90,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:workspaceId/audit-logs",
config: {
rateLimit: readLimit
},
schema: {
description: "Return audit logs",
security: [
@@ -145,6 +155,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:workspaceId/audit-logs/filters/actors",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()

View File

@@ -17,6 +17,7 @@ import { SamlProviders, TGetSamlCfgDTO } from "@app/ee/services/saml-config/saml
import { getConfig } from "@app/lib/config/env";
import { BadRequestError } from "@app/lib/errors";
import { logger } from "@app/lib/logger";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -203,8 +204,11 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/config",
method: "GET",
url: "/config",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
querystring: z.object({
@@ -240,8 +244,11 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/config",
method: "POST",
url: "/config",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z.object({
@@ -270,8 +277,11 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/config",
method: "PATCH",
url: "/config",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z

View File

@@ -1,6 +1,7 @@
import { z } from "zod";
import { ScimTokensSchema } from "@app/db/schemas";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -20,6 +21,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/scim-tokens",
method: "POST",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z.object({
@@ -51,6 +55,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/scim-tokens",
method: "GET",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
querystring: z.object({
@@ -78,6 +85,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/scim-tokens/:scimTokenId",
method: "DELETE",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({

View File

@@ -1,6 +1,7 @@
import { nanoid } from "nanoid";
import { z } from "zod";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { sapPubSchema } from "@app/server/routes/sanitizedSchemas";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -9,6 +10,9 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
server.route({
url: "/",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
body: z
.object({
@@ -47,6 +51,9 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
server.route({
url: "/:sapId",
method: "PATCH",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
sapId: z.string()
@@ -85,6 +92,9 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
server.route({
url: "/:sapId",
method: "DELETE",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
sapId: z.string()
@@ -111,6 +121,9 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
server.route({
url: "/",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({
workspaceId: z.string().trim()
@@ -137,6 +150,9 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
server.route({
url: "/board",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({
workspaceId: z.string().trim(),

View File

@@ -10,13 +10,17 @@ import {
} from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApprovalStatus, RequestState } from "@app/ee/services/secret-approval-request/secret-approval-request-types";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretApprovalRequestRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({
workspaceId: z.string().trim(),
@@ -62,8 +66,11 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
});
server.route({
url: "/count",
method: "GET",
url: "/count",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({
workspaceId: z.string().trim()
@@ -93,6 +100,9 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
server.route({
url: "/:id/merge",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
id: z.string()
@@ -117,8 +127,11 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
});
server.route({
url: "/:id/review",
method: "POST",
url: "/:id/review",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
id: z.string()
@@ -147,8 +160,11 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
});
server.route({
url: "/:id/status",
method: "POST",
url: "/:id/status",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
id: z.string()
@@ -203,8 +219,11 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
.array()
.optional();
server.route({
url: "/:id",
method: "GET",
url: "/:id",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
id: z.string()

View File

@@ -1,12 +1,16 @@
import { z } from "zod";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretRotationProviderRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:workspaceId",
method: "GET",
url: "/:workspaceId",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()

View File

@@ -2,13 +2,17 @@ import { z } from "zod";
import { SecretRotationOutputsSchema, SecretRotationsSchema, SecretsSchema } from "@app/db/schemas";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretRotationRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "POST",
url: "/",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
workspaceId: z.string().trim(),
@@ -52,6 +56,9 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
server.route({
url: "/restart",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
id: z.string().trim()
@@ -86,6 +93,9 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
server.route({
url: "/",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({
workspaceId: z.string().trim()
@@ -136,8 +146,11 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
});
server.route({
url: "/:id",
method: "DELETE",
url: "/:id",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
id: z.string().trim()

View File

@@ -2,13 +2,17 @@ import { z } from "zod";
import { GitAppOrgSchema, SecretScanningGitRisksSchema } from "@app/db/schemas";
import { SecretScanningRiskStatus } from "@app/ee/services/secret-scanning/secret-scanning-types";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretScanningRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/create-installation-session/organization",
method: "POST",
url: "/create-installation-session/organization",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({ organizationId: z.string().trim() }),
response: {
@@ -31,8 +35,11 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
});
server.route({
url: "/link-installation",
method: "POST",
url: "/link-installation",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
installationId: z.string(),
@@ -56,8 +63,11 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
});
server.route({
url: "/installation-status/organization/:organizationId",
method: "GET",
url: "/installation-status/organization/:organizationId",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -80,6 +90,9 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
server.route({
url: "/organization/:organizationId/risks",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -100,8 +113,11 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
});
server.route({
url: "/organization/:organizationId/risks/:riskId/status",
method: "POST",
url: "/organization/:organizationId/risks/:riskId/status",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({ organizationId: z.string().trim(), riskId: z.string().trim() }),
body: z.object({ status: z.nativeEnum(SecretScanningRiskStatus) }),

View File

@@ -1,13 +1,17 @@
import { z } from "zod";
import { SecretVersionsSchema } from "@app/db/schemas";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretVersionRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:secretId/secret-versions",
method: "GET",
url: "/:secretId/secret-versions",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
secretId: z.string()

View File

@@ -2,6 +2,7 @@ import { z } from "zod";
import { SecretSnapshotsSchema, SecretTagsSchema, SecretVersionsSchema } from "@app/db/schemas";
import { PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -9,6 +10,9 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:secretSnapshotId",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
secretSnapshotId: z.string().trim()
@@ -58,6 +62,9 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/:secretSnapshotId/rollback",
config: {
rateLimit: writeLimit
},
schema: {
description: "Roll back project secrets to those captured in a secret snapshot version.",
security: [

View File

@@ -2,13 +2,17 @@ import { z } from "zod";
import { TrustedIpsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:workspaceId/trusted-ips",
method: "GET",
url: "/:workspaceId/trusted-ips",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -33,8 +37,11 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/trusted-ips",
method: "POST",
url: "/:workspaceId/trusted-ips",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -78,8 +85,11 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/trusted-ips/:trustedIpId",
method: "PATCH",
url: "/:workspaceId/trusted-ips/:trustedIpId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim(),
@@ -124,8 +134,11 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/trusted-ips/:trustedIpId",
method: "DELETE",
url: "/:workspaceId/trusted-ips/:trustedIpId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim(),

View File

@@ -6,6 +6,7 @@ import { ProjectUserAdditionalPrivilegeSchema } from "@app/db/schemas";
import { ProjectUserAdditionalPrivilegeTemporaryMode } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-types";
import { PROJECT_USER_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -13,6 +14,9 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
server.route({
url: "/permanent",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
projectMembershipId: z.string().min(1).describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.CREATE.projectMembershipId),
@@ -52,8 +56,11 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
});
server.route({
url: "/temporary",
method: "POST",
url: "/temporary",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
projectMembershipId: z.string().min(1).describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.CREATE.projectMembershipId),
@@ -104,8 +111,11 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
});
server.route({
url: "/:privilegeId",
method: "PATCH",
url: "/:privilegeId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
privilegeId: z.string().min(1).describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.UPDATE.privilegeId)
@@ -158,8 +168,11 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
});
server.route({
url: "/:privilegeId",
method: "DELETE",
url: "/:privilegeId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
privilegeId: z.string().describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.DELETE.privilegeId)
@@ -184,8 +197,11 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
});
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({
projectMembershipId: z.string().describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.LIST.projectMembershipId)
@@ -210,8 +226,11 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
});
server.route({
url: "/:privilegeId",
method: "GET",
url: "/:privilegeId",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
privilegeId: z.string().describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.GET_BY_PRIVILEGEID.privilegeId)

View File

@@ -18,6 +18,28 @@ export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
};
};
// GET endpoints
export const readLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: 600,
keyGenerator: (req) => req.realIp
};
// POST, PATCH, PUT, DELETE endpoints
export const writeLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: 50,
keyGenerator: (req) => req.realIp
};
// special endpoints
export const secretsLimit: RateLimitOptions = {
// secrets, folders, secret imports
timeWindow: 60 * 1000,
max: 600,
keyGenerator: (req) => req.realIp
};
export const authRateLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: 60,
@@ -26,12 +48,13 @@ export const authRateLimit: RateLimitOptions = {
export const inviteUserRateLimit: RateLimitOptions = {
timeWindow: 60 * 1000,
max: 10,
max: 30,
keyGenerator: (req) => req.realIp
};
export const passwordRateLimit: RateLimitOptions = {
export const creationLimit: RateLimitOptions = {
// identity, project, org
timeWindow: 60 * 1000,
max: 600,
max: 30,
keyGenerator: (req) => req.realIp
};

View File

@@ -4,6 +4,7 @@ import SmeeClient from "smee-client";
import { getConfig } from "@app/lib/config/env";
import { logger } from "@app/lib/logger";
import { writeLimit } from "@app/server/config/rateLimiter";
export const registerSecretScannerGhApp = async (server: FastifyZodProvider) => {
const probotApp = (app: Probot) => {
@@ -49,6 +50,9 @@ export const registerSecretScannerGhApp = async (server: FastifyZodProvider) =>
server.route({
method: "POST",
url: "/",
config: {
rateLimit: writeLimit
},
handler: async (req, res) => {
const eventName = req.headers["x-github-event"];
const signatureSHA256 = req.headers["x-hub-signature-256"] as string;

View File

@@ -49,6 +49,7 @@ import { trustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-
import { TKeyStoreFactory } from "@app/keystore/keystore";
import { getConfig } from "@app/lib/config/env";
import { TQueueServiceFactory } from "@app/queue";
import { readLimit } from "@app/server/config/rateLimiter";
import { apiKeyDALFactory } from "@app/services/api-key/api-key-dal";
import { apiKeyServiceFactory } from "@app/services/api-key/api-key-service";
import { authDALFactory } from "@app/services/auth/auth-dal";
@@ -410,7 +411,12 @@ export const registerRoutes = async (
folderDAL
});
const projectRoleService = projectRoleServiceFactory({ permissionService, projectRoleDAL });
const projectRoleService = projectRoleServiceFactory({
permissionService,
projectRoleDAL,
projectUserMembershipRoleDAL,
identityProjectMembershipRoleDAL
});
const snapshotService = secretSnapshotServiceFactory({
permissionService,
@@ -671,8 +677,11 @@ export const registerRoutes = async (
await server.register(injectAuditLogInfo);
server.route({
url: "/api/status",
method: "GET",
url: "/api/status",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: z.object({

View File

@@ -3,6 +3,7 @@ import { z } from "zod";
import { OrganizationsSchema, SuperAdminSchema, UsersSchema } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env";
import { UnauthorizedError } from "@app/lib/errors";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifySuperAdmin } from "@app/server/plugins/auth/superAdmin";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -11,8 +12,11 @@ import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
export const registerAdminRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/config",
method: "GET",
url: "/config",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: z.object({
@@ -30,8 +34,11 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/config",
method: "PATCH",
url: "/config",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
allowSignUp: z.boolean().optional(),
@@ -55,8 +62,11 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/signup",
method: "POST",
url: "/signup",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
email: z.string().email().trim(),

View File

@@ -3,7 +3,7 @@ import { z } from "zod";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { authRateLimit } from "@app/server/config/rateLimiter";
import { authRateLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode, AuthModeRefreshJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
@@ -38,8 +38,11 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
});
server.route({
url: "/checkAuth",
method: "POST",
url: "/checkAuth",
config: {
rateLimit: writeLimit
},
schema: {
response: {
200: z.object({
@@ -52,8 +55,11 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
});
server.route({
url: "/token",
method: "POST",
url: "/token",
config: {
rateLimit: writeLimit
},
schema: {
response: {
200: z.object({

View File

@@ -1,13 +1,17 @@
import { z } from "zod";
import { ProjectBotsSchema } from "@app/db/schemas";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:projectId",
method: "GET",
url: "/:projectId",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
projectId: z.string().trim()
@@ -38,8 +42,11 @@ export const registerProjectBotRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:botId/active",
method: "PATCH",
url: "/:botId/active",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
isActive: z.boolean(),

View File

@@ -1,11 +1,15 @@
import { z } from "zod";
import { UNIVERSAL_AUTH } from "@app/lib/api-docs";
import { writeLimit } from "@app/server/config/rateLimiter";
export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/token/renew",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
description: "Renew access token",
body: z.object({

View File

@@ -3,6 +3,7 @@ import { z } from "zod";
import { IdentitiesSchema, OrgMembershipRole } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { IDENTITIES } from "@app/lib/api-docs";
import { creationLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -12,6 +13,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/",
config: {
rateLimit: creationLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Create identity",
@@ -71,6 +75,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
server.route({
method: "PATCH",
url: "/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Update identity",
@@ -121,6 +128,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Delete identity",

View File

@@ -3,6 +3,7 @@ import { z } from "zod";
import { IdentityUaClientSecretsSchema, IdentityUniversalAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { UNIVERSAL_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { TIdentityTrustedIp } from "@app/services/identity/identity-types";
@@ -22,8 +23,11 @@ export const sanitizedClientSecretSchema = IdentityUaClientSecretsSchema.pick({
export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/universal-auth/login",
method: "POST",
url: "/universal-auth/login",
config: {
rateLimit: writeLimit
},
schema: {
description: "Login with Universal Auth",
body: z.object({
@@ -66,8 +70,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/universal-auth/identities/:identityId",
method: "POST",
url: "/universal-auth/identities/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Attach Universal Auth configuration onto identity",
@@ -156,8 +163,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/universal-auth/identities/:identityId",
method: "PATCH",
url: "/universal-auth/identities/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Update Universal Auth configuration on identity",
@@ -239,8 +249,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/universal-auth/identities/:identityId",
method: "GET",
url: "/universal-auth/identities/:identityId",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Retrieve Universal Auth configuration on identity",
@@ -283,8 +296,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/universal-auth/identities/:identityId/client-secrets",
method: "POST",
url: "/universal-auth/identities/:identityId/client-secrets",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Create Universal Auth Client Secret for identity",
@@ -335,8 +351,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/universal-auth/identities/:identityId/client-secrets",
method: "GET",
url: "/universal-auth/identities/:identityId/client-secrets",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "List Universal Auth Client Secrets for identity",
@@ -378,8 +397,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/universal-auth/identities/:identityId/client-secrets/:clientSecretId/revoke",
method: "POST",
url: "/universal-auth/identities/:identityId/client-secrets/:clientSecretId/revoke",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Revoke Universal Auth Client Secrets for identity",

View File

@@ -2,6 +2,7 @@ import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { INTEGRATION_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -9,8 +10,11 @@ import { integrationAuthPubSchema } from "../sanitizedSchemas";
export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/integration-options",
method: "GET",
url: "/integration-options",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "List of integrations available.",
@@ -43,8 +47,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId",
method: "GET",
url: "/:integrationAuthId",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Get details of an integration authorization by auth object id.",
@@ -75,8 +82,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/",
method: "DELETE",
url: "/",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Remove all integration's auth object from the project.",
@@ -121,8 +131,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId",
method: "DELETE",
url: "/:integrationAuthId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Remove an integration auth object by object id.",
@@ -165,8 +178,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/oauth-token",
method: "POST",
url: "/oauth-token",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z.object({
@@ -206,8 +222,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/access-token",
method: "POST",
url: "/access-token",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Create the integration authentication object required for syncing secrets.",
@@ -256,8 +275,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/apps",
method: "GET",
url: "/:integrationAuthId/apps",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -293,8 +315,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/teams",
method: "GET",
url: "/:integrationAuthId/teams",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -324,8 +349,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/vercel/branches",
method: "GET",
url: "/:integrationAuthId/vercel/branches",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -354,8 +382,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/checkly/groups",
method: "GET",
url: "/:integrationAuthId/checkly/groups",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -384,8 +415,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/github/orgs",
method: "GET",
url: "/:integrationAuthId/github/orgs",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -412,8 +446,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/github/envs",
method: "GET",
url: "/:integrationAuthId/github/envs",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -446,8 +483,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/qovery/orgs",
method: "GET",
url: "/:integrationAuthId/qovery/orgs",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -472,8 +512,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/qovery/projects",
method: "GET",
url: "/:integrationAuthId/qovery/projects",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -502,8 +545,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/qovery/environments",
method: "GET",
url: "/:integrationAuthId/qovery/environments",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -532,8 +578,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/qovery/apps",
method: "GET",
url: "/:integrationAuthId/qovery/apps",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -562,8 +611,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/qovery/containers",
method: "GET",
url: "/:integrationAuthId/qovery/containers",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -592,8 +644,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/qovery/jobs",
method: "GET",
url: "/:integrationAuthId/qovery/jobs",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -622,8 +677,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/heroku/pipelines",
method: "GET",
url: "/:integrationAuthId/heroku/pipelines",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -654,8 +712,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/railway/environments",
method: "GET",
url: "/:integrationAuthId/railway/environments",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -684,8 +745,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/railway/services",
method: "GET",
url: "/:integrationAuthId/railway/services",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -714,8 +778,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/bitbucket/workspaces",
method: "GET",
url: "/:integrationAuthId/bitbucket/workspaces",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -750,8 +817,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/northflank/secret-groups",
method: "GET",
url: "/:integrationAuthId/northflank/secret-groups",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -785,8 +855,11 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:integrationAuthId/teamcity/build-configs",
method: "GET",
url: "/:integrationAuthId/teamcity/build-configs",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({

View File

@@ -4,6 +4,7 @@ import { IntegrationsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { INTEGRATION } from "@app/lib/api-docs";
import { removeTrailingSlash, shake } from "@app/lib/fn";
import { writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -11,8 +12,11 @@ import { PostHogEventTypes, TIntegrationCreatedEvent } from "@app/services/telem
export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "POST",
url: "/",
config: {
rateLimit: writeLimit
},
schema: {
description: "Create an integration to sync secrets.",
security: [
@@ -112,8 +116,11 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:integrationId",
method: "PATCH",
url: "/:integrationId",
config: {
rateLimit: writeLimit
},
schema: {
description: "Update an integration by integration id",
security: [
@@ -159,8 +166,11 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:integrationId",
method: "DELETE",
url: "/:integrationId",
config: {
rateLimit: writeLimit
},
schema: {
description: "Remove an integration using the integration object ID",
security: [

View File

@@ -56,6 +56,9 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/verify",
method: "POST",
config: {
rateLimit: inviteUserRateLimit
},
schema: {
body: z.object({
email: z.string().trim().email(),

View File

@@ -1,6 +1,7 @@
import { z } from "zod";
import { IncidentContactsSchema, OrganizationsSchema, OrgMembershipsSchema, UsersSchema } from "@app/db/schemas";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -8,6 +9,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: z.object({
@@ -25,6 +29,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:organizationId",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()
@@ -50,6 +57,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:organizationId/users",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()
@@ -87,6 +97,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "PATCH",
url: "/:organizationId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
body: z.object({
@@ -128,6 +141,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:organizationId/incidentContactOrg",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
@@ -151,6 +167,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/:organizationId/incidentContactOrg",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({ organizationId: z.string().trim() }),
body: z.object({ email: z.string().email().trim() }),
@@ -176,6 +195,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/:organizationId/incidentContactOrg/:incidentContactId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({ organizationId: z.string().trim(), incidentContactId: z.string().trim() }),
response: {

View File

@@ -2,7 +2,7 @@ import { z } from "zod";
import { BackupPrivateKeySchema, UsersSchema } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env";
import { passwordRateLimit } from "@app/server/config/rateLimiter";
import { authRateLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { validateSignUpAuthorization } from "@app/services/auth/auth-fns";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -12,7 +12,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
method: "POST",
url: "/srp1",
config: {
rateLimit: passwordRateLimit
rateLimit: authRateLimit
},
schema: {
body: z.object({
@@ -39,7 +39,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
method: "POST",
url: "/change-password",
config: {
rateLimit: passwordRateLimit
rateLimit: authRateLimit
},
schema: {
body: z.object({
@@ -78,7 +78,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
method: "POST",
url: "/email/password-reset",
config: {
rateLimit: passwordRateLimit
rateLimit: authRateLimit
},
schema: {
body: z.object({
@@ -103,7 +103,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
method: "POST",
url: "/email/password-reset-verify",
config: {
rateLimit: passwordRateLimit
rateLimit: authRateLimit
},
schema: {
body: z.object({
@@ -133,7 +133,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
method: "POST",
url: "/backup-private-key",
config: {
rateLimit: passwordRateLimit
rateLimit: authRateLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
@@ -168,7 +168,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
method: "GET",
url: "/backup-private-key",
config: {
rateLimit: passwordRateLimit
rateLimit: authRateLimit
},
schema: {
response: {
@@ -190,6 +190,9 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/password-reset",
config: {
rateLimit: authRateLimit
},
schema: {
body: z.object({
protectedKey: z.string().trim(),

View File

@@ -3,13 +3,17 @@ import { z } from "zod";
import { ProjectEnvironmentsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ENVIRONMENTS } from "@app/lib/api-docs";
import { writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:workspaceId/environments",
method: "POST",
url: "/:workspaceId/environments",
config: {
rateLimit: writeLimit
},
schema: {
description: "Create environment",
security: [
@@ -64,8 +68,11 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/environments/:id",
method: "PATCH",
url: "/:workspaceId/environments/:id",
config: {
rateLimit: writeLimit
},
schema: {
description: "Update environment",
security: [
@@ -128,8 +135,11 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/environments/:id",
method: "DELETE",
url: "/:workspaceId/environments/:id",
config: {
rateLimit: writeLimit
},
schema: {
description: "Delete environment",
security: [

View File

@@ -1,5 +1,6 @@
import { z } from "zod";
import { writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -7,6 +8,9 @@ export const registerProjectKeyRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:workspaceId/key",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()

View File

@@ -10,14 +10,18 @@ import {
} from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { ProjectUserMembershipTemporaryMode } from "@app/services/project-membership/project-membership-types";
export const registerProjectMembershipRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:workspaceId/memberships",
method: "GET",
url: "/:workspaceId/memberships",
config: {
rateLimit: readLimit
},
schema: {
description: "Return project user memberships",
security: [
@@ -75,8 +79,11 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
});
server.route({
url: "/:workspaceId/memberships",
method: "POST",
url: "/:workspaceId/memberships",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -126,8 +133,11 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
});
server.route({
url: "/:workspaceId/memberships/:membershipId",
method: "PATCH",
url: "/:workspaceId/memberships/:membershipId",
config: {
rateLimit: writeLimit
},
schema: {
description: "Update project user membership",
security: [
@@ -197,8 +207,11 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
});
server.route({
url: "/:workspaceId/memberships/:membershipId",
method: "DELETE",
url: "/:workspaceId/memberships/:membershipId",
config: {
rateLimit: writeLimit
},
schema: {
description: "Delete project user membership",
security: [

View File

@@ -8,6 +8,7 @@ import {
UsersSchema
} from "@app/db/schemas";
import { INTEGRATION_AUTH, PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { ProjectFilterType } from "@app/services/project/project-types";
@@ -24,8 +25,11 @@ const projectWithEnv = ProjectsSchema.merge(
export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:workspaceId/keys",
method: "GET",
url: "/:workspaceId/keys",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -55,8 +59,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/users",
method: "GET",
url: "/:workspaceId/users",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -108,8 +115,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: z.object({
@@ -125,8 +135,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId",
method: "GET",
url: "/:workspaceId",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim().describe(PROJECTS.GET.workspaceId)
@@ -154,8 +167,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId",
method: "DELETE",
url: "/:workspaceId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim().describe(PROJECTS.DELETE.workspaceId)
@@ -185,6 +201,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:workspaceId/name",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -217,8 +236,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId",
method: "PATCH",
url: "/:workspaceId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim().describe(PROJECTS.UPDATE.workspaceId)
@@ -261,8 +283,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/auto-capitalization",
method: "POST",
url: "/:workspaceId/auto-capitalization",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -295,8 +320,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/integrations",
method: "GET",
url: "/:workspaceId/integrations",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()
@@ -329,8 +357,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/authorizations",
method: "GET",
url: "/:workspaceId/authorizations",
config: {
rateLimit: readLimit
},
schema: {
description: "List integration auth objects for a workspace.",
security: [
@@ -361,8 +392,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:workspaceId/service-token-data",
method: "GET",
url: "/:workspaceId/service-token-data",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
workspaceId: z.string().trim()

View File

@@ -4,6 +4,7 @@ import { SecretFoldersSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { FOLDERS } from "@app/lib/api-docs";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, secretsLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -11,6 +12,9 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
server.route({
url: "/",
method: "POST",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Create folders",
security: [
@@ -65,6 +69,9 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
server.route({
url: "/:folderId",
method: "PATCH",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Update folder",
security: [
@@ -124,8 +131,11 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
// TODO(daniel): Expose this route in api reference and write docs for it.
server.route({
url: "/:folderIdOrName",
method: "DELETE",
url: "/:folderIdOrName",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Delete a folder",
security: [
@@ -181,8 +191,11 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
});
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
description: "Get folders",
security: [

View File

@@ -4,13 +4,17 @@ import { SecretImportsSchema, SecretsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { SECRET_IMPORTS } from "@app/lib/api-docs";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, secretsLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretImportRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "POST",
url: "/",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Create secret imports",
security: [
@@ -71,8 +75,11 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
});
server.route({
url: "/:secretImportId",
method: "PATCH",
url: "/:secretImportId",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Update secret imports",
security: [
@@ -143,8 +150,11 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
});
server.route({
url: "/:secretImportId",
method: "DELETE",
url: "/:secretImportId",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Delete secret imports",
security: [
@@ -204,8 +214,11 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
});
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
description: "Get secret imports",
security: [
@@ -262,6 +275,9 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
server.route({
url: "/secrets",
method: "GET",
config: {
rateLimit: secretsLimit
},
schema: {
querystring: z.object({
workspaceId: z.string().trim(),

View File

@@ -2,13 +2,17 @@ import { z } from "zod";
import { SecretTagsSchema } from "@app/db/schemas";
import { SECRET_TAGS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:projectId/tags",
method: "GET",
url: "/:projectId/tags",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.LIST.projectId)
@@ -33,8 +37,11 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:projectId/tags",
method: "POST",
url: "/:projectId/tags",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.CREATE.projectId)
@@ -65,8 +72,11 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:projectId/tags/:tagId",
method: "DELETE",
url: "/:projectId/tags/:tagId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.DELETE.projectId),

View File

@@ -1,6 +1,7 @@
import { z } from "zod";
import { UserActionsSchema } from "@app/db/schemas";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -8,6 +9,9 @@ export const registerUserActionRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
action: z.string().trim()
@@ -29,6 +33,9 @@ export const registerUserActionRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
querystring: z.object({
action: z.string().trim()

View File

@@ -1,6 +1,7 @@
import { z } from "zod";
import { UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -8,6 +9,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: z.object({

View File

@@ -3,6 +3,7 @@ import { z } from "zod";
import { WebhooksSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -27,6 +28,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z.object({
@@ -75,6 +79,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
server.route({
method: "PATCH",
url: "/:webhookId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -122,6 +129,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/:webhookId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -159,6 +169,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/:webhookId/test",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
@@ -186,6 +199,9 @@ export const registerWebhookRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
querystring: z.object({

View File

@@ -2,6 +2,7 @@ import { z } from "zod";
import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
import { ORGANIZATIONS } from "@app/lib/api-docs";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -9,6 +10,9 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:orgId/identity-memberships",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Return organization identity memberships",

View File

@@ -8,6 +8,7 @@ import {
ProjectUserMembershipRolesSchema
} from "@app/db/schemas";
import { PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { ProjectUserMembershipTemporaryMode } from "@app/services/project-membership/project-membership-types";
@@ -16,6 +17,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
server.route({
method: "POST",
url: "/:projectId/identity-memberships/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
params: z.object({
@@ -48,6 +52,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
server.route({
method: "PATCH",
url: "/:projectId/identity-memberships/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Update project identity memberships",
@@ -103,6 +110,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
server.route({
method: "DELETE",
url: "/:projectId/identity-memberships/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Delete project identity memberships",
@@ -137,6 +147,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
server.route({
method: "GET",
url: "/:projectId/identity-memberships",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
description: "Return project identity memberships",

View File

@@ -2,6 +2,7 @@ import jwt from "jsonwebtoken";
import { z } from "zod";
import { getConfig } from "@app/lib/config/env";
import { writeLimit } from "@app/server/config/rateLimiter";
import { AuthModeMfaJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
export const registerMfaRouter = async (server: FastifyZodProvider) => {
@@ -30,8 +31,11 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/mfa/send",
method: "POST",
url: "/mfa/send",
config: {
rateLimit: writeLimit
},
schema: {
response: {
200: z.object({
@@ -48,6 +52,9 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/mfa/verify",
method: "POST",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
mfaToken: z.string().trim()

View File

@@ -2,6 +2,7 @@ import { z } from "zod";
import { OrganizationsSchema, OrgMembershipsSchema, UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
import { ORGANIZATIONS } from "@app/lib/api-docs";
import { creationLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
@@ -9,6 +10,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:organizationId/memberships",
config: {
rateLimit: readLimit
},
schema: {
description: "Return organization user memberships",
security: [
@@ -55,6 +59,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:organizationId/workspaces",
config: {
rateLimit: readLimit
},
schema: {
description: "Return projects in organization that user is part of",
security: [
@@ -101,6 +108,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "PATCH",
url: "/:organizationId/memberships/:membershipId",
config: {
rateLimit: writeLimit
},
schema: {
description: "Update organization user memberships",
security: [
@@ -141,6 +151,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/:organizationId/memberships/:membershipId",
config: {
rateLimit: writeLimit
},
schema: {
description: "Delete organization user memberships",
security: [
@@ -177,6 +190,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/",
config: {
rateLimit: creationLimit
},
schema: {
body: z.object({
name: z.string().trim()
@@ -204,6 +220,9 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/:organizationId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
organizationId: z.string().trim()

View File

@@ -3,6 +3,7 @@ import { z } from "zod";
import { ProjectMembershipsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECTS } from "@app/lib/api-docs";
import { writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -10,6 +11,9 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
server.route({
method: "POST",
url: "/:projectId/memberships",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().describe(PROJECTS.INVITE_MEMBER.projectId)
@@ -56,6 +60,9 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
server.route({
method: "DELETE",
url: "/:projectId/memberships",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().describe(PROJECTS.REMOVE_MEMBER.projectId)

View File

@@ -4,6 +4,7 @@ import { z } from "zod";
import { ProjectKeysSchema, ProjectsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECTS } from "@app/lib/api-docs";
import { creationLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -28,8 +29,11 @@ const slugSchema = z
export const registerProjectRouter = async (server: FastifyZodProvider) => {
/* Get project key */
server.route({
url: "/:workspaceId/encrypted-key",
method: "GET",
url: "/:workspaceId/encrypted-key",
config: {
rateLimit: readLimit
},
schema: {
description: "Return encrypted project key",
security: [
@@ -77,8 +81,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
/* Start upgrade of a project */
server.route({
url: "/:projectId/upgrade",
method: "POST",
url: "/:projectId/upgrade",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().trim()
@@ -107,6 +114,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:projectId/upgrade/status",
method: "GET",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
projectId: z.string().trim()
@@ -135,6 +145,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/",
config: {
rateLimit: creationLimit
},
schema: {
body: z.object({
projectName: z.string().trim().describe(PROJECTS.CREATE.projectName),
@@ -183,6 +196,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/:slug",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
slug: slugSchema.describe("The slug of the project to delete.")
@@ -214,6 +230,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/:slug",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
slug: slugSchema.describe("The slug of the project to get.")
@@ -244,6 +263,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
server.route({
method: "PATCH",
url: "/:slug",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
slug: slugSchema.describe("The slug of the project to update.")

View File

@@ -3,6 +3,7 @@ import { z } from "zod";
import { ServiceTokensSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -17,8 +18,11 @@ export const sanitizedServiceTokenSchema = ServiceTokensSchema.omit({
export const registerServiceTokenRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.SERVICE_TOKEN]),
schema: {
description: "Return Infisical Token data",
@@ -69,8 +73,11 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
});
server.route({
url: "/",
method: "POST",
url: "/",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
body: z.object({
@@ -122,8 +129,11 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
});
server.route({
url: "/:serviceTokenId",
method: "DELETE",
url: "/:serviceTokenId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({

View File

@@ -2,13 +2,17 @@ import { z } from "zod";
import { AuthTokenSessionsSchema, OrganizationsSchema, UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
import { ApiKeysSchema } from "@app/db/schemas/api-keys";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMethod, AuthMode } from "@app/services/auth/auth-type";
export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/me/mfa",
method: "PATCH",
url: "/me/mfa",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
isMfaEnabled: z.boolean()
@@ -27,8 +31,11 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/me/name",
method: "PATCH",
url: "/me/name",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
firstName: z.string().trim(),
@@ -48,8 +55,11 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/me/auth-methods",
method: "PUT",
url: "/me/auth-methods",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
authMethods: z.nativeEnum(AuthMethod).array().min(1)
@@ -70,6 +80,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/me/organizations",
config: {
rateLimit: readLimit
},
schema: {
description: "Return organizations that current user is part of",
security: [
@@ -93,6 +106,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/me/api-keys",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: ApiKeysSchema.omit({ secretHash: true }).array()
@@ -108,6 +124,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/me/api-keys",
config: {
rateLimit: writeLimit
},
schema: {
body: z.object({
name: z.string().trim(),
@@ -130,6 +149,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/me/api-keys/:apiKeyDataId",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
apiKeyDataId: z.string().trim()
@@ -150,6 +172,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/me/sessions",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: AuthTokenSessionsSchema.array()
@@ -165,6 +190,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/me/sessions",
config: {
rateLimit: writeLimit
},
schema: {
response: {
200: z.object({
@@ -184,6 +212,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/me",
config: {
rateLimit: readLimit
},
schema: {
description: "Retrieve the current user on the request",
security: [
@@ -207,6 +238,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "DELETE",
url: "/me",
config: {
rateLimit: writeLimit
},
schema: {
response: {
200: z.object({

View File

@@ -1,13 +1,17 @@
import { z } from "zod";
import { SecretsSchema } from "@app/db/schemas";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:projectId/secrets/blind-index-status",
method: "GET",
url: "/:projectId/secrets/blind-index-status",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
projectId: z.string().trim()
@@ -30,8 +34,11 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:projectId/secrets",
method: "GET",
url: "/:projectId/secrets",
config: {
rateLimit: readLimit
},
schema: {
params: z.object({
projectId: z.string().trim()
@@ -63,8 +70,11 @@ export const registerSecretBlindIndexRouter = async (server: FastifyZodProvider)
});
server.route({
url: "/:projectId/secrets/names",
method: "POST",
url: "/:projectId/secrets/names",
config: {
rateLimit: writeLimit
},
schema: {
params: z.object({
projectId: z.string().trim()

View File

@@ -13,6 +13,7 @@ import { CommitType } from "@app/ee/services/secret-approval-request/secret-appr
import { RAW_SECRETS, SECRETS } from "@app/lib/api-docs";
import { BadRequestError } from "@app/lib/errors";
import { removeTrailingSlash } from "@app/lib/fn";
import { secretsLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { getUserAgentType } from "@app/server/plugins/audit-log";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -24,8 +25,11 @@ import { secretRawSchema } from "../sanitizedSchemas";
export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/tags/:secretName",
method: "POST",
url: "/tags/:secretName",
config: {
rateLimit: writeLimit
},
schema: {
description: "Attach tags to a secret",
security: [
@@ -83,8 +87,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/tags/:secretName",
method: "DELETE",
url: "/tags/:secretName",
config: {
rateLimit: writeLimit
},
schema: {
description: "Detach tags from a secret",
security: [
@@ -142,8 +149,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/raw",
method: "GET",
url: "/raw",
config: {
rateLimit: secretsLimit
},
schema: {
description: "List secrets",
security: [
@@ -261,8 +271,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/raw/:secretName",
method: "GET",
url: "/raw/:secretName",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Get a secret by name",
security: [
@@ -353,8 +366,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/raw/:secretName",
method: "POST",
url: "/raw/:secretName",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Create secret",
security: [
@@ -439,8 +455,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/raw/:secretName",
method: "PATCH",
url: "/raw/:secretName",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Update secret",
security: [
@@ -522,8 +541,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/raw/:secretName",
method: "DELETE",
url: "/raw/:secretName",
config: {
rateLimit: secretsLimit
},
schema: {
description: "Delete secret",
security: [
@@ -599,8 +621,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/",
method: "GET",
url: "/",
config: {
rateLimit: secretsLimit
},
schema: {
querystring: z.object({
workspaceId: z.string().trim(),
@@ -711,8 +736,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:secretName",
method: "GET",
url: "/:secretName",
config: {
rateLimit: secretsLimit
},
schema: {
params: z.object({
secretName: z.string().trim()
@@ -789,6 +817,9 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/:secretName",
method: "POST",
config: {
rateLimit: secretsLimit
},
schema: {
body: z.object({
workspaceId: z.string().trim(),
@@ -955,8 +986,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:secretName",
method: "PATCH",
url: "/:secretName",
config: {
rateLimit: secretsLimit
},
schema: {
params: z.object({
secretName: z.string()
@@ -1139,8 +1173,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/:secretName",
method: "DELETE",
url: "/:secretName",
config: {
rateLimit: secretsLimit
},
schema: {
params: z.object({
secretName: z.string()
@@ -1260,8 +1297,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/batch",
method: "POST",
url: "/batch",
config: {
rateLimit: secretsLimit
},
schema: {
body: z.object({
workspaceId: z.string().trim(),
@@ -1383,8 +1423,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/batch",
method: "PATCH",
url: "/batch",
config: {
rateLimit: secretsLimit
},
schema: {
body: z.object({
workspaceId: z.string().trim(),
@@ -1506,8 +1549,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/batch",
method: "DELETE",
url: "/batch",
config: {
rateLimit: secretsLimit
},
schema: {
body: z.object({
workspaceId: z.string().trim(),

View File

@@ -1,6 +1,7 @@
import { z } from "zod";
import { ApiKeysSchema } from "@app/db/schemas/api-keys";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -8,6 +9,9 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
server.route({
method: "GET",
url: "/me/api-keys",
config: {
rateLimit: readLimit
},
schema: {
response: {
200: z.object({

View File

@@ -153,7 +153,7 @@ export const authLoginServiceFactory = ({
username: email
});
if (!userEnc || (userEnc && !userEnc.isAccepted)) {
throw new Error("Failed to find user");
throw new Error("Failed to find user");
}
if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) {
validateProviderAuthToken(providerAuthToken as string, email);

View File

@@ -192,7 +192,7 @@ export const authPaswordServiceFactory = ({
}: TCreateBackupPrivateKeyDTO) => {
const userEnc = await userDAL.findUserEncKeyByUserId(userId);
if (!userEnc || (userEnc && !userEnc.isAccepted)) {
throw new Error("Failed to find user");
throw new Error("Failed to find user");
}
if (!userEnc.clientPublicKey || !userEnc.serverPrivateKey) throw new Error("failed to create backup key");
@@ -239,7 +239,7 @@ export const authPaswordServiceFactory = ({
const getBackupPrivateKeyOfUser = async (userId: string) => {
const user = await userDAL.findUserEncKeyByUserId(userId);
if (!user || (user && !user.isAccepted)) {
throw new Error("Failed to find user");
throw new Error("Failed to find user");
}
const backupKey = await authDAL.getBackupPrivateKeyByUserId(userId);
if (!backupKey) throw new Error("Failed to find user backup key");

View File

@@ -14,16 +14,25 @@ import {
import { BadRequestError } from "@app/lib/errors";
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
import { TIdentityProjectMembershipRoleDALFactory } from "../identity-project/identity-project-membership-role-dal";
import { TProjectUserMembershipRoleDALFactory } from "../project-membership/project-user-membership-role-dal";
import { TProjectRoleDALFactory } from "./project-role-dal";
type TProjectRoleServiceFactoryDep = {
projectRoleDAL: TProjectRoleDALFactory;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getUserProjectPermission">;
identityProjectMembershipRoleDAL: TIdentityProjectMembershipRoleDALFactory;
projectUserMembershipRoleDAL: TProjectUserMembershipRoleDALFactory;
};
export type TProjectRoleServiceFactory = ReturnType<typeof projectRoleServiceFactory>;
export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }: TProjectRoleServiceFactoryDep) => {
export const projectRoleServiceFactory = ({
projectRoleDAL,
permissionService,
identityProjectMembershipRoleDAL,
projectUserMembershipRoleDAL
}: TProjectRoleServiceFactoryDep) => {
const createRole = async (
actor: ActorType,
actorId: string,
@@ -96,8 +105,25 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role);
const identityRole = await identityProjectMembershipRoleDAL.findOne({ customRoleId: roleId });
const projectUserRole = await projectUserMembershipRoleDAL.findOne({ customRoleId: roleId });
if (identityRole) {
throw new BadRequestError({
message: "The role is assigned to one or more identities. Make sure to unassign them before deleting the role.",
name: "Delete role"
});
}
if (projectUserRole) {
throw new BadRequestError({
message: "The role is assigned to one or more users. Make sure to unassign them before deleting the role.",
name: "Delete role"
});
}
const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId });
if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Delete role" });
return deletedRole;
};

View File

@@ -1,180 +0,0 @@
---
title: "E2EE Disabled"
---
Using Infisical's API to read/write secrets with E2EE disabled allows you to create, update, and retrieve secrets
in plaintext. Effectively, this means each such secret operation only requires 1 HTTP call.
<AccordionGroup>
<Accordion title="Retrieve secrets">
Retrieve all secrets for an Infisical project and environment.
<Tabs>
<Tab title="cURL">
```bash
curl --location --request GET 'https://app.infisical.com/api/v3/secrets/raw?environment=environment&workspaceId=workspaceId' \
--header 'Authorization: Bearer serviceToken'
```
</Tab>
</Tabs>
####
<Info>
When using a [service token](../../../documentation/platform/token) with access to a single environment and path, you don't need to provide request parameters because the server will automatically scope the request to the defined environment/secrets path of the service token used.
For all other cases, request parameters are required.
</Info>
####
<ParamField query="workspaceId" type="string" required>
The ID of the workspace
</ParamField>
<ParamField query="environment" type="string" required>
The environment slug
</ParamField>
<ParamField query="secretPath" type="string" default="/" optional>
Path to secrets in workspace
</ParamField>
</Accordion>
<Accordion title="Create secret">
Create a secret in Infisical.
<Tabs>
<Tab title="cURL">
```bash
curl --location --request POST 'https://app.infisical.com/api/v3/secrets/raw/secretName' \
--header 'Authorization: Bearer serviceToken' \
--header 'Content-Type: application/json' \
--data-raw '{
"workspaceId": "workspaceId",
"environment": "environment",
"type": "shared",
"secretValue": "secretValue",
"secretPath": "/"
}'
```
</Tab>
</Tabs>
<ParamField path="secretName" type="string" required>
Name of secret to create
</ParamField>
<ParamField body="workspaceId" type="string" required>
The ID of the workspace
</ParamField>
<ParamField body="environment" type="string" required>
The environment slug
</ParamField>
<ParamField body="secretValue" type="string" required>
Value of secret
</ParamField>
<ParamField body="secretComment" type="string" optional>
Comment of secret
</ParamField>
<ParamField body="secretPath" type="string" default="/" optional>
Path to secret in workspace
</ParamField>
<ParamField query="type" type="string" optional default="shared">
The type of the secret. Valid options are “shared” or “personal”
</ParamField>
</Accordion>
<Accordion title="Retrieve secret">
Retrieve a secret from Infisical.
<Tabs>
<Tab title="cURL">
```bash
curl --location --request GET 'https://app.infisical.com/api/v3/secrets/raw/secretName?workspaceId=workspaceId&environment=environment' \
--header 'Authorization: Bearer serviceToken'
```
</Tab>
</Tabs>
<ParamField path="secretName" type="string" required>
Name of secret to retrieve
</ParamField>
<ParamField query="workspaceId" type="string" required>
The ID of the workspace
</ParamField>
<ParamField query="environment" type="string" required>
The environment slug
</ParamField>
<ParamField query="secretPath" type="string" default="/" optional>
Path to secrets in workspace
</ParamField>
<ParamField query="type" type="string" optional default="personal">
The type of the secret. Valid options are “shared” or “personal”
</ParamField>
</Accordion>
<Accordion title="Update secret">
Update an existing secret in Infisical.
<Tabs>
<Tab title="cURL">
```bash
curl --location --request PATCH 'https://app.infisical.com/api/v3/secrets/raw/secretName' \
--header 'Authorization: Bearer serviceToken' \
--header 'Content-Type: application/json' \
--data-raw '{
"workspaceId": "workspaceId",
"environment": "environment",
"type": "shared",
"secretValue": "secretValue",
"secretPath": "/"
}'
```
</Tab>
</Tabs>
<ParamField path="secretName" type="string" required>
Name of secret to update
</ParamField>
<ParamField body="workspaceId" type="string" required>
The ID of the workspace
</ParamField>
<ParamField body="environment" type="string" required>
The environment slug
</ParamField>
<ParamField body="secretValue" type="string" required>
Value of secret
</ParamField>
<ParamField body="secretPath" type="string" default="/" optional>
Path to secret in workspace.
</ParamField>
<ParamField query="type" type="string" optional default="shared">
The type of the secret. Valid options are “shared” or “personal”
</ParamField>
</Accordion>
<Accordion title="Delete secret">
Delete a secret in Infisical.
<Tabs>
<Tab title="cURL">
```bash
curl --location --request DELETE 'https://app.infisical.com/api/v3/secrets/raw/secretName' \
--header 'Authorization: Bearer serviceToken' \
--header 'Content-Type: application/json' \
--data-raw '{
"workspaceId": "workspaceId",
"environment": "environment",
"type": "shared",
"secretPath": "/"
}'
```
</Tab>
</Tabs>
<ParamField path="secretName" type="string" required>
Name of secret to update
</ParamField>
<ParamField body="workspaceId" type="string" required>
The ID of the workspace
</ParamField>
<ParamField body="environment" type="string" required>
The environment slug
</ParamField>
<ParamField body="secretPath" type="string" default="/" optional>
Path to secret in workspace.
</ParamField>
<ParamField query="type" type="string" optional default="personal">
The type of the secret. Valid options are “shared” or “personal”
</ParamField>
</Accordion>
</AccordionGroup>

View File

@@ -1,862 +0,0 @@
---
title: "E2EE Enabled"
---
<Note>
E2EE enabled mode only works with [Service Tokens](/documentation/platform/token) and cannot be used with [Identities](/documentation/platform/identities/overview).
</Note>
Using Infisical's API to read/write secrets with E2EE enabled allows you to create, update, and retrieve secrets
but requires you to perform client-side encryption/decryption operations. For this reason, we recommend using one of the available
SDKs instead.
<AccordionGroup>
<Accordion title="Retrieve secrets">
<Tabs>
<Tab title="Javascript">
Retrieve all secrets for an Infisical project and environment.
```js
const crypto = require('crypto');
const axios = require('axios');
const BASE_URL = 'https://app.infisical.com';
const ALGORITHM = 'aes-256-gcm';
const decrypt = ({ ciphertext, iv, tag, secret}) => {
const decipher = crypto.createDecipheriv(
ALGORITHM,
secret,
Buffer.from(iv, 'base64')
);
decipher.setAuthTag(Buffer.from(tag, 'base64'));
let cleartext = decipher.update(ciphertext, 'base64', 'utf8');
cleartext += decipher.final('utf8');
return cleartext;
}
const getSecrets = async () => {
const serviceToken = 'your_service_token';
const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1);
// 1. Get your Infisical Token data
const { data: serviceTokenData } = await axios.get(
`${BASE_URL}/api/v2/service-token`,
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
// 2. Get secrets for your project and environment
const { data } = await axios.get(
`${BASE_URL}/api/v3/secrets?${new URLSearchParams({
environment: serviceTokenData.environment,
workspaceId: serviceTokenData.workspace
})}`,
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
const encryptedSecrets = data.secrets;
// 3. Decrypt the (encrypted) project key with the key from your Infisical Token
const projectKey = decrypt({
ciphertext: serviceTokenData.encryptedKey,
iv: serviceTokenData.iv,
tag: serviceTokenData.tag,
secret: serviceTokenSecret
});
// 4. Decrypt the (encrypted) secrets
const secrets = encryptedSecrets.map((secret) => {
const secretKey = decrypt({
ciphertext: secret.secretKeyCiphertext,
iv: secret.secretKeyIV,
tag: secret.secretKeyTag,
secret: projectKey
});
const secretValue = decrypt({
ciphertext: secret.secretValueCiphertext,
iv: secret.secretValueIV,
tag: secret.secretValueTag,
secret: projectKey
});
return ({
secretKey,
secretValue
});
});
console.log('secrets: ', secrets);
}
getSecrets();
```
</Tab>
<Tab title="Python">
```Python
import requests
import base64
from Cryptodome.Cipher import AES
BASE_URL = "http://app.infisical.com"
def decrypt(ciphertext, iv, tag, secret):
secret = bytes(secret, "utf-8")
iv = base64.standard_b64decode(iv)
tag = base64.standard_b64decode(tag)
ciphertext = base64.standard_b64decode(ciphertext)
cipher = AES.new(secret, AES.MODE_GCM, iv)
cipher.update(tag)
cleartext = cipher.decrypt(ciphertext).decode("utf-8")
return cleartext
def get_secrets():
service_token = "your_service_token"
service_token_secret = service_token[service_token.rindex(".") + 1 :]
# 1. Get your Infisical Token data
service_token_data = requests.get(
f"{BASE_URL}/api/v2/service-token",
headers={"Authorization": f"Bearer {service_token}"},
).json()
# 2. Get secrets for your project and environment
data = requests.get(
f"{BASE_URL}/api/v3/secrets",
params={
"environment": service_token_data["environment"],
"workspaceId": service_token_data["workspace"],
},
headers={"Authorization": f"Bearer {service_token}"},
).json()
encrypted_secrets = data["secrets"]
# 3. Decrypt the (encrypted) project key with the key from your Infisical Token
project_key = decrypt(
ciphertext=service_token_data["encryptedKey"],
iv=service_token_data["iv"],
tag=service_token_data["tag"],
secret=service_token_secret,
)
# 4. Decrypt the (encrypted) secrets
secrets = []
for secret in encrypted_secrets:
secret_key = decrypt(
ciphertext=secret["secretKeyCiphertext"],
iv=secret["secretKeyIV"],
tag=secret["secretKeyTag"],
secret=project_key,
)
secret_value = decrypt(
ciphertext=secret["secretValueCiphertext"],
iv=secret["secretValueIV"],
tag=secret["secretValueTag"],
secret=project_key,
)
secrets.append(
{
"secret_key": secret_key,
"secret_value": secret_value,
}
)
print("secrets:", secrets)
get_secrets()
```
</Tab>
</Tabs>
</Accordion>
<Accordion title="Create secret">
<Tabs>
<Tab title="Javascript">
Create a secret in Infisical.
```js
const crypto = require('crypto');
const axios = require('axios');
const nacl = require('tweetnacl');
const BASE_URL = 'https://app.infisical.com';
const ALGORITHM = 'aes-256-gcm';
const BLOCK_SIZE_BYTES = 16;
const encrypt = ({ text, secret }) => {
const iv = crypto.randomBytes(BLOCK_SIZE_BYTES);
const cipher = crypto.createCipheriv(ALGORITHM, secret, iv);
let ciphertext = cipher.update(text, 'utf8', 'base64');
ciphertext += cipher.final('base64');
return {
ciphertext,
iv: iv.toString('base64'),
tag: cipher.getAuthTag().toString('base64')
};
}
const decrypt = ({ ciphertext, iv, tag, secret}) => {
const decipher = crypto.createDecipheriv(
ALGORITHM,
secret,
Buffer.from(iv, 'base64')
);
decipher.setAuthTag(Buffer.from(tag, 'base64'));
let cleartext = decipher.update(ciphertext, 'base64', 'utf8');
cleartext += decipher.final('utf8');
return cleartext;
}
const createSecrets = async () => {
const serviceToken = '';
const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1);
const secretType = 'shared'; // 'shared' or 'personal'
const secretKey = 'some_key';
const secretValue = 'some_value';
const secretComment = 'some_comment';
// 1. Get your Infisical Token data
const { data: serviceTokenData } = await axios.get(
`${BASE_URL}/api/v2/service-token`,
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
// 2. Decrypt the (encrypted) project key with the key from your Infisical Token
const projectKey = decrypt({
ciphertext: serviceTokenData.encryptedKey,
iv: serviceTokenData.iv,
tag: serviceTokenData.tag,
secret: serviceTokenSecret
});
// 3. Encrypt your secret with the project key
const {
ciphertext: secretKeyCiphertext,
iv: secretKeyIV,
tag: secretKeyTag
} = encrypt({
text: secretKey,
secret: projectKey
});
const {
ciphertext: secretValueCiphertext,
iv: secretValueIV,
tag: secretValueTag
} = encrypt({
text: secretValue,
secret: projectKey
});
const {
ciphertext: secretCommentCiphertext,
iv: secretCommentIV,
tag: secretCommentTag
} = encrypt({
text: secretComment,
secret: projectKey
});
// 4. Send (encrypted) secret to Infisical
await axios.post(
`${BASE_URL}/api/v3/secrets/${secretKey}`,
{
workspaceId: serviceTokenData.workspace,
environment: serviceTokenData.environment,
type: secretType,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag
},
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
}
createSecrets();
```
</Tab>
<Tab title="Python">
```Python
import base64
import requests
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
BASE_URL = "https://app.infisical.com"
BLOCK_SIZE_BYTES = 16
def encrypt(text, secret):
iv = get_random_bytes(BLOCK_SIZE_BYTES)
secret = bytes(secret, "utf-8")
cipher = AES.new(secret, AES.MODE_GCM, iv)
ciphertext, tag = cipher.encrypt_and_digest(text.encode("utf-8"))
return {
"ciphertext": base64.standard_b64encode(ciphertext).decode("utf-8"),
"tag": base64.standard_b64encode(tag).decode("utf-8"),
"iv": base64.standard_b64encode(iv).decode("utf-8"),
}
def decrypt(ciphertext, iv, tag, secret):
secret = bytes(secret, "utf-8")
iv = base64.standard_b64decode(iv)
tag = base64.standard_b64decode(tag)
ciphertext = base64.standard_b64decode(ciphertext)
cipher = AES.new(secret, AES.MODE_GCM, iv)
cipher.update(tag)
cleartext = cipher.decrypt(ciphertext).decode("utf-8")
return cleartext
def create_secrets():
service_token = "your_service_token"
service_token_secret = service_token[service_token.rindex(".") + 1 :]
secret_type = "shared" # "shared or "personal"
secret_key = "some_key"
secret_value = "some_value"
secret_comment = "some_comment"
# 1. Get your Infisical Token data
service_token_data = requests.get(
f"{BASE_URL}/api/v2/service-token",
headers={"Authorization": f"Bearer {service_token}"},
).json()
# 2. Decrypt the (encrypted) project key with the key from your Infisical Token
project_key = decrypt(
ciphertext=service_token_data["encryptedKey"],
iv=service_token_data["iv"],
tag=service_token_data["tag"],
secret=service_token_secret,
)
# 3. Encrypt your secret with the project key
encrypted_key_data = encrypt(text=secret_key, secret=project_key)
encrypted_value_data = encrypt(text=secret_value, secret=project_key)
encrypted_comment_data = encrypt(text=secret_comment, secret=project_key)
# 4. Send (encrypted) secret to Infisical
requests.post(
f"{BASE_URL}/api/v3/secrets/{secret_key}",
json={
"workspaceId": service_token_data["workspace"],
"environment": service_token_data["environment"],
"type": secret_type,
"secretKeyCiphertext": encrypted_key_data["ciphertext"],
"secretKeyIV": encrypted_key_data["iv"],
"secretKeyTag": encrypted_key_data["tag"],
"secretValueCiphertext": encrypted_value_data["ciphertext"],
"secretValueIV": encrypted_value_data["iv"],
"secretValueTag": encrypted_value_data["tag"],
"secretCommentCiphertext": encrypted_comment_data["ciphertext"],
"secretCommentIV": encrypted_comment_data["iv"],
"secretCommentTag": encrypted_comment_data["tag"]
},
headers={"Authorization": f"Bearer {service_token}"},
)
create_secrets()
```
</Tab>
</Tabs>
</Accordion>
<Accordion title="Retrieve secret">
<Tabs>
<Tab title="Javascript">
Retrieve a secret from Infisical.
```js
const crypto = require('crypto');
const axios = require('axios');
const BASE_URL = 'https://app.infisical.com';
const ALGORITHM = 'aes-256-gcm';
const decrypt = ({ ciphertext, iv, tag, secret}) => {
const decipher = crypto.createDecipheriv(
ALGORITHM,
secret,
Buffer.from(iv, 'base64')
);
decipher.setAuthTag(Buffer.from(tag, 'base64'));
let cleartext = decipher.update(ciphertext, 'base64', 'utf8');
cleartext += decipher.final('utf8');
return cleartext;
}
const getSecret = async () => {
const serviceToken = 'your_service_token';
const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1);
const secretType = 'shared' // 'shared' or 'personal'
const secretKey = 'some_key';
// 1. Get your Infisical Token data
const { data: serviceTokenData } = await axios.get(
`${BASE_URL}/api/v2/service-token`,
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
// 2. Get the secret from your project and environment
const { data } = await axios.get(
`${BASE_URL}/api/v3/secrets/${secretKey}?${new URLSearchParams({
environment: serviceTokenData.environment,
workspaceId: serviceTokenData.workspace,
type: secretType // optional, defaults to 'shared'
})}`,
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
const encryptedSecret = data.secret;
// 3. Decrypt the (encrypted) project key with the key from your Infisical Token
const projectKey = decrypt({
ciphertext: serviceTokenData.encryptedKey,
iv: serviceTokenData.iv,
tag: serviceTokenData.tag,
secret: serviceTokenSecret
});
// 4. Decrypt the (encrypted) secret value
const secretValue = decrypt({
ciphertext: encryptedSecret.secretValueCiphertext,
iv: encryptedSecret.secretValueIV,
tag: encryptedSecret.secretValueTag,
secret: projectKey
});
console.log('secret: ', ({
secretKey,
secretValue
}));
}
getSecret();
```
</Tab>
<Tab title="Python">
```Python
import requests
import base64
from Cryptodome.Cipher import AES
BASE_URL = "http://app.infisical.com"
def decrypt(ciphertext, iv, tag, secret):
secret = bytes(secret, "utf-8")
iv = base64.standard_b64decode(iv)
tag = base64.standard_b64decode(tag)
ciphertext = base64.standard_b64decode(ciphertext)
cipher = AES.new(secret, AES.MODE_GCM, iv)
cipher.update(tag)
cleartext = cipher.decrypt(ciphertext).decode("utf-8")
return cleartext
def get_secret():
service_token = "your_service_token"
service_token_secret = service_token[service_token.rindex(".") + 1 :]
secret_type = "shared" # "shared" or "personal"
secret_key = "some_key"
# 1. Get your Infisical Token data
service_token_data = requests.get(
f"{BASE_URL}/api/v2/service-token",
headers={"Authorization": f"Bearer {service_token}"},
).json()
# 2. Get secret from your project and environment
data = requests.get(
f"{BASE_URL}/api/v3/secrets/{secret_key}",
params={
"environment": service_token_data["environment"],
"workspaceId": service_token_data["workspace"],
"type": secret_type # optional, defaults to "shared"
},
headers={"Authorization": f"Bearer {service_token}"},
).json()
encrypted_secret = data["secret"]
# 3. Decrypt the (encrypted) project key with the key from your Infisical Token
project_key = decrypt(
ciphertext=service_token_data["encryptedKey"],
iv=service_token_data["iv"],
tag=service_token_data["tag"],
secret=service_token_secret,
)
# 4. Decrypt the (encrypted) secret value
secret_value = decrypt(
ciphertext=encrypted_secret["secretValueCiphertext"],
iv=encrypted_secret["secretValueIV"],
tag=encrypted_secret["secretValueTag"],
secret=project_key,
)
print("secret: ", {
"secret_key": secret_key,
"secret_value": secret_value
})
get_secret()
```
</Tab>
</Tabs>
</Accordion>
<Accordion title="Update secret">
<Tabs>
<Tab title="Javascript">
Update an existing secret in Infisical.
```js
const crypto = require('crypto');
const axios = require('axios');
const BASE_URL = 'https://app.infisical.com';
const ALGORITHM = 'aes-256-gcm';
const BLOCK_SIZE_BYTES = 16;
const encrypt = ({ text, secret }) => {
const iv = crypto.randomBytes(BLOCK_SIZE_BYTES);
const cipher = crypto.createCipheriv(ALGORITHM, secret, iv);
let ciphertext = cipher.update(text, 'utf8', 'base64');
ciphertext += cipher.final('base64');
return {
ciphertext,
iv: iv.toString('base64'),
tag: cipher.getAuthTag().toString('base64')
};
}
const decrypt = ({ ciphertext, iv, tag, secret}) => {
const decipher = crypto.createDecipheriv(
ALGORITHM,
secret,
Buffer.from(iv, 'base64')
);
decipher.setAuthTag(Buffer.from(tag, 'base64'));
let cleartext = decipher.update(ciphertext, 'base64', 'utf8');
cleartext += decipher.final('utf8');
return cleartext;
}
const updateSecrets = async () => {
const serviceToken = 'your_service_token';
const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1);
const secretType = 'shared' // 'shared' or 'personal'
const secretKey = 'some_key';
const secretValue = 'updated_value';
const secretComment = 'updated_comment';
// 1. Get your Infisical Token data
const { data: serviceTokenData } = await axios.get(
`${BASE_URL}/api/v2/service-token`,
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
// 2. Decrypt the (encrypted) project key with the key from your Infisical Token
const projectKey = decrypt({
ciphertext: serviceTokenData.encryptedKey,
iv: serviceTokenData.iv,
tag: serviceTokenData.tag,
secret: serviceTokenSecret
});
// 3. Encrypt your updated secret with the project key
const {
ciphertext: secretKeyCiphertext,
iv: secretKeyIV,
tag: secretKeyTag
} = encrypt({
text: secretKey,
secret: projectKey
});
const {
ciphertext: secretValueCiphertext,
iv: secretValueIV,
tag: secretValueTag
} = encrypt({
text: secretValue,
secret: projectKey
});
const {
ciphertext: secretCommentCiphertext,
iv: secretCommentIV,
tag: secretCommentTag
} = encrypt({
text: secretComment,
secret: projectKey
});
// 4. Send (encrypted) updated secret to Infisical
await axios.patch(
`${BASE_URL}/api/v3/secrets/${secretKey}`,
{
workspaceId: serviceTokenData.workspace,
environment: serviceTokenData.environment,
type: secretType,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext,
secretCommentIV,
secretCommentTag
},
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
}
updateSecrets();
```
</Tab>
<Tab title="Python">
```Python
import base64
import requests
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
BASE_URL = "https://app.infisical.com"
BLOCK_SIZE_BYTES = 16
def encrypt(text, secret):
iv = get_random_bytes(BLOCK_SIZE_BYTES)
secret = bytes(secret, "utf-8")
cipher = AES.new(secret, AES.MODE_GCM, iv)
ciphertext, tag = cipher.encrypt_and_digest(text.encode("utf-8"))
return {
"ciphertext": base64.standard_b64encode(ciphertext).decode("utf-8"),
"tag": base64.standard_b64encode(tag).decode("utf-8"),
"iv": base64.standard_b64encode(iv).decode("utf-8"),
}
def decrypt(ciphertext, iv, tag, secret):
secret = bytes(secret, "utf-8")
iv = base64.standard_b64decode(iv)
tag = base64.standard_b64decode(tag)
ciphertext = base64.standard_b64decode(ciphertext)
cipher = AES.new(secret, AES.MODE_GCM, iv)
cipher.update(tag)
cleartext = cipher.decrypt(ciphertext).decode("utf-8")
return cleartext
def update_secret():
service_token = "your_service_token"
service_token_secret = service_token[service_token.rindex(".") + 1 :]
secret_type = "shared" # "shared" or "personal"
secret_key = "some_key"
secret_value = "updated_value"
secret_comment = "updated_comment"
# 1. Get your Infisical Token data
service_token_data = requests.get(
f"{BASE_URL}/api/v2/service-token",
headers={"Authorization": f"Bearer {service_token}"},
).json()
# 2. Decrypt the (encrypted) project key with the key from your Infisical Token
project_key = decrypt(
ciphertext=service_token_data["encryptedKey"],
iv=service_token_data["iv"],
tag=service_token_data["tag"],
secret=service_token_secret,
)
# 3. Encrypt your updated secret with the project key
encrypted_key_data = encrypt(text=secret_key, secret=project_key)
encrypted_value_data = encrypt(text=secret_value, secret=project_key)
encrypted_comment_data = encrypt(text=secret_comment, secret=project_key)
# 4. Send (encrypted) updated secret to Infisical
requests.patch(
f"{BASE_URL}/api/v3/secrets/{secret_key}",
json={
"workspaceId": service_token_data["workspace"],
"environment": service_token_data["environment"],
"type": secret_type,
"secretKeyCiphertext": encrypted_key_data["ciphertext"],
"secretKeyIV": encrypted_key_data["iv"],
"secretKeyTag": encrypted_key_data["tag"],
"secretValueCiphertext": encrypted_value_data["ciphertext"],
"secretValueIV": encrypted_value_data["iv"],
"secretValueTag": encrypted_value_data["tag"],
"secretCommentCiphertext": encrypted_comment_data["ciphertext"],
"secretCommentIV": encrypted_comment_data["iv"],
"secretCommentTag": encrypted_comment_data["tag"]
},
headers={"Authorization": f"Bearer {service_token}"},
)
update_secret()
```
</Tab>
</Tabs>
</Accordion>
<Accordion title="Delete secret">
<Tabs>
<Tab title="Javascript">
Delete a secret in Infisical.
```js
const axios = require('axios');
const BASE_URL = 'https://app.infisical.com';
const deleteSecrets = async () => {
const serviceToken = 'your_service_token';
const secretType = 'shared' // 'shared' or 'personal'
const secretKey = 'some_key'
// 1. Get your Infisical Token data
const { data: serviceTokenData } = await axios.get(
`${BASE_URL}/api/v2/service-token`,
{
headers: {
Authorization: `Bearer ${serviceToken}`
}
}
);
// 2. Delete secret from Infisical
await axios.delete(
`${BASE_URL}/api/v3/secrets/${secretKey}`,
{
workspaceId: serviceTokenData.workspace,
environment: serviceTokenData.environment,
type: secretType
},
{
headers: {
Authorization: `Bearer ${serviceToken}`
},
}
);
};
deleteSecrets();
```
</Tab>
<Tab title="Python">
```Python
import requests
BASE_URL = "https://app.infisical.com"
def delete_secrets():
service_token = "<your_service_token>"
secret_type = "shared" # "shared" or "personal"
secret_key = "some_key"
# 1. Get your Infisical Token data
service_token_data = requests.get(
f"{BASE_URL}/api/v2/service-token",
headers={"Authorization": f"Bearer {service_token}"},
).json()
# 2. Delete secret from Infisical
requests.delete(
f"{BASE_URL}/api/v2/secrets/{secret_key}",
json={
"workspaceId": service_token_data["workspace"],
"environment": service_token_data["environment"],
"type": secret_type
},
headers={"Authorization": f"Bearer {service_token}"},
)
delete_secrets()
```
</Tab>
</Tabs>
<Info>
If using an `API_KEY` to authenticate with the Infisical API, then you should include it in the `X_API_KEY` header.
</Info>
</Accordion>
</AccordionGroup>

View File

@@ -0,0 +1,90 @@
---
title: "Configure native integrations programmatically"
description: "How to use Infisical API to sync secrets to external secret managers"
---
The Infisical API allows you to create programmatic integrations that connect with third-party secret managers to synchronize secrets from Infisical.
This guide will primarily demonstrate the process using AWS Secret Store Manager (AWS SSM), but the steps are generally applicable to other secret management integrations.
<Info>
For details on setting up AWS SSM synchronization and understanding its prerequisites, refer to the [AWS SSM integration setup documentation](../../../integrations/cloud/aws-secret-manager).
</Info>
<Steps>
<Step title="Authenticate with AWS SSM">
Authentication is required for all integrations. Use the [Integration Auth API](../../endpoints/integrations/create-auth) with the following parameters to authenticate.
<ParamField body="integration" type="string" initialValue="aws-secret-manager" required>
Set this parameter to **aws-secret-manager**.
</ParamField>
<ParamField body="workspaceId" type="string" required>
The Infisical project ID for the integration.
</ParamField>
<ParamField body="accessId" type="string" required>
The AWS IAM User Access ID.
</ParamField>
<ParamField body="accessToken" type="string" required>
The AWS IAM User Access Secret Key.
</ParamField>
```bash Request
curl --request POST \
--url https://app.infisical.com/api/v1/integration-auth/access-token \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '{
"workspaceId": "<workspaceid>",
"integration": "aws-secret-manager",
"accessId": "<aws iam user access id>",
"accessToken": "<aws iam user access secret key>"
}'
```
</Step>
<Step title="Configure the Synchronization Setup">
Once authentication between AWS SSM and Infisical is established, you can configure the synchronization behavior.
This involves specifying the source (environment and secret path in Infisical) and the destination in SSM to which the secrets will be synchronized.
Use the [integration API](../../endpoints/integrations/create) with the following parameters to configure the sync source and destination.
<ParamField body="integrationAuthId" type="string" required>
The ID of the integration authentication object used with AWS, obtained from the previous API response.
</ParamField>
<ParamField body="isActive" type="boolean">
Indicates whether the integration should be active or inactive.
</ParamField>
<ParamField body="app" type="string" required>
The secret name for saving in AWS SSM, which can be arbitrarily chosen.
</ParamField>
<ParamField body="region" type="string" required>
The AWS region where the SSM is located, e.g., `us-east-1`.
</ParamField>
<ParamField body="sourceEnvironment" type="string" required>
The Infisical environment slug from which secrets will be synchronized, e.g., `dev`.
</ParamField>
<ParamField body="secretPath" type="string" required>
The Infisical folder path from which secrets will be synchronized, e.g., `/some/path`. The root path is `/`.
</ParamField>
```bash Request
curl --request POST \
--url https://app.infisical.com/api/v1/integration \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '{
"integrationAuthId": "<integrationauthid>",
"sourceEnvironment": "<sourceenvironment>",
"secretPath": "<secret-path, default is '/' >",
"app": "<app>",
"region": "<aws-ssm-region>"
}'
```
</Step>
</Steps>
<Check>
Congratulations! You have successfully set up an integration to synchronize secrets from Infisical with AWS SSM.
For more information, [view the integration API reference](../../endpoints/integrations).
</Check>

View File

@@ -44,7 +44,7 @@ In the above screenshot, you can see that we are creating a token token with `re
of the `/common` path within the development environment of the project; the token expires in 6 months and can be used from any IP address.
<Note>
For a deeper understanding of service tokens, it is recommended to read [this guide](http://localhost:3000/internals/service-tokens).
For a deeper understanding of service tokens, it is recommended to read [this guide](https://infisical.com/docs/internals/service-tokens).
</Note>
**FAQ**

View File

@@ -388,8 +388,7 @@
"group": "Examples",
"pages": [
"api-reference/overview/examples/note",
"api-reference/overview/examples/e2ee-disabled",
"api-reference/overview/examples/e2ee-enabled"
"api-reference/overview/examples/integration"
]
}
]
@@ -472,7 +471,7 @@
]
},
{
"group": "Secret tags",
"group": "Secret Tags",
"pages": [
"api-reference/endpoints/secret-tags/list",
"api-reference/endpoints/secret-tags/create",
@@ -492,7 +491,7 @@
]
},
{
"group": "Secret imports",
"group": "Secret Imports",
"pages": [
"api-reference/endpoints/secret-imports/list",
"api-reference/endpoints/secret-imports/create",

View File

@@ -335,6 +335,10 @@ To login into Infisical with OAuth providers such as Google, configure the assoc
Requires enterprise license. Please contact team@infisical.com to get more information.
</Accordion>
<ParamField query="NEXT_PUBLIC_SAML_ORG_SLUG" type="string">
Configure SAML organization slug to automatically redirect all users of your Infisical instance to the identity provider.
</ParamField>

View File

@@ -63,6 +63,30 @@
border-color: #ebebeb;
}
#content-area .mt-8 .rounded-xl{
border-radius: 0;
}
#content-area .mt-8 .rounded-lg{
border-radius: 0;
}
#content-area .mt-6 .rounded-xl{
border-radius: 0;
}
#content-area .mt-6 .rounded-lg{
border-radius: 0;
}
#content-area .mt-6 .rounded-md{
border-radius: 0;
}
#content-area .mt-8 .rounded-md{
border-radius: 0;
}
#content-area div.my-4{
border-radius: 0;
border-width: 1px;
@@ -78,6 +102,10 @@
border-radius: 0;
}
#content-area a {
border-radius: 0;
}
#content-area .not-prose {
border-radius: 0;
}

View File

@@ -52,6 +52,9 @@ ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
ARG INTERCOM_ID
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
ARG SAML_ORG_SLUG
ENV NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG \
BAKED_NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG
ARG NEXT_INFISICAL_PLATFORM_VERSION
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION=$NEXT_INFISICAL_PLATFORM_VERSION

View File

@@ -4,6 +4,8 @@ scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_POSTHOG_API_KEY
scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_INTERCOM_ID" "$NEXT_PUBLIC_INTERCOM_ID"
scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_SAML_ORG_SLUG" "$NEXT_PUBLIC_SAML_ORG_SLUG"
if [ "$TELEMETRY_ENABLED" != "false" ]; then
echo "Telemetry is enabled"
scripts/set-standalone-build-telemetry.sh true

View File

@@ -4,6 +4,8 @@ scripts/replace-variable.sh "$BAKED_NEXT_PUBLIC_POSTHOG_API_KEY" "$NEXT_PUBLIC_P
scripts/replace-variable.sh "$BAKED_NEXT_PUBLIC_INTERCOM_ID" "$NEXT_PUBLIC_INTERCOM_ID"
scripts/replace-variable.sh "$BAKED_NEXT_SAML_ORG_SLUG" "$NEXT_PUBLIC_SAML_ORG_SLUG"
if [ "$TELEMETRY_ENABLED" != "false" ]; then
echo "Telemetry is enabled"
scripts/set-telemetry.sh true

View File

@@ -483,10 +483,10 @@ const OrganizationPage = withPermission(
const addUsersToProject = useAddUserToWsNonE2EE();
const { data: updateClosed } = useGetUserAction("april_2024_db_update_closed");
const { data: updateClosed } = useGetUserAction("april_13_2024_db_update_closed");
const registerUserAction = useRegisterUserAction();
const closeUpdate = async () => {
await registerUserAction.mutateAsync("april_2024_db_update_closed");
await registerUserAction.mutateAsync("april_13_2024_db_update_closed");
};
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
@@ -594,6 +594,7 @@ const OrganizationPage = withPermission(
</div>
)}
<div className="mb-4 flex flex-col items-start justify-start px-6 py-6 pb-0 text-3xl">
{window.location.origin.includes("https://app.infisical.com") || window.location.origin.includes("http://localhost:8080") && (
<div
className={`${
!updateClosed ? "block" : "hidden"
@@ -601,11 +602,11 @@ const OrganizationPage = withPermission(
>
<FontAwesomeIcon icon={faWarning} className="p-6 text-4xl text-primary" />
<div className="text-sm">
<span className="text-lg font-semibold">Scheduled maintenance on April 6th 2024 </span>{" "}
<span className="text-lg font-semibold">Scheduled maintenance on April 13th 2024 </span>{" "}
<br />
Infisical will undergo scheduled maintenance for approximately 1 hour on Saturday, April 6th, 11am EST. During these hours, read
Infisical will undergo scheduled maintenance for approximately 1 hour on Saturday, April 13th, 11am EST. During these hours, read
operations will continue to function normally but no resources will be editable.
No action is required on your end your applications can continue to fetch secrets.
No action is required on your end your applications will continue to fetch secrets.
<br />
</div>
<button
@@ -616,7 +617,8 @@ const OrganizationPage = withPermission(
>
<FontAwesomeIcon icon={faXmark} />
</button>
</div>
</div>)}
<p className="mr-4 font-semibold text-white">Projects</p>
<div className="mt-6 flex w-full flex-row">
<Input

View File

@@ -1,4 +1,4 @@
import { FormEvent, useState } from "react";
import { FormEvent, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import Link from "next/link";
import { useRouter } from "next/router";
@@ -32,6 +32,18 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
const { config } = useServerConfig();
const queryParams = new URLSearchParams(window.location.search);
useEffect(() => {
if (process.env.NEXT_PUBLIC_SAML_ORG_SLUG && process.env.NEXT_PUBLIC_SAML_ORG_SLUG !== "saml-org-slug-default") {
const callbackPort = queryParams.get("callback_port");
window.open(
`/api/v1/sso/redirect/saml2/organizations/${process.env.NEXT_PUBLIC_SAML_ORG_SLUG}${
callbackPort ? `?callback_port=${callbackPort}` : ""
}`
);
window.close();
}
}, [])
const handleLogin = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
@@ -244,7 +256,7 @@ export const InitialStep = ({ setStep, email, setEmail, password, setPassword }:
</Link>
</div>
) : (
<div />
<div className="mt-4" />
)}
<div className="mt-2 flex flex-row text-sm text-bunker-400">
<Link href="/verify-email">

View File

@@ -23,9 +23,6 @@ export const MembersPage = withPermission(
<Tab value={TabSections.Identities}>
<div className="flex items-center">
<p>Machine Identities</p>
<div className="ml-2 inline-block cursor-default rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
New
</div>
</div>
</Tab>
<Tab value={TabSections.Roles}>Organization Roles</Tab>

View File

@@ -31,7 +31,7 @@ export const OrgRoleTable = ({ onSelectRole }: Props) => {
const [searchRoles, setSearchRoles] = useState("");
const { currentOrg } = useOrganization();
const orgId = currentOrg?.id || "";
const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp(["deleteRole"] as const);
const { data: roles, isLoading: isRolesLoading } = useGetOrgRoles(orgId);
@@ -49,7 +49,7 @@ export const OrgRoleTable = ({ onSelectRole }: Props) => {
handlePopUpClose("deleteRole");
} catch (err) {
console.log(err);
createNotification({ type: "error", text: "Failed to create role" });
createNotification({ type: "error", text: "Failed to delete role" });
}
};

View File

@@ -29,7 +29,7 @@ type Props = {
export const ProjectRoleList = ({ onSelectRole }: Props) => {
const [searchRoles, setSearchRoles] = useState("");
const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp(["deleteRole"] as const);
const { currentWorkspace } = useWorkspace();
const workspaceId = currentWorkspace?.id || "";
@@ -50,7 +50,7 @@ export const ProjectRoleList = ({ onSelectRole }: Props) => {
handlePopUpClose("deleteRole");
} catch (err) {
console.log(err);
createNotification({ type: "error", text: "Failed to create role" });
createNotification({ type: "error", text: "Failed to delete role" });
}
};

View File

@@ -313,6 +313,7 @@ export const SecretMainPage = () => {
workspaceId={workspaceId}
secretPath={secretPath}
sortDir={sortDir}
searchTerm={filter.searchFilter}
/>
{canReadSecret && (
<DynamicSecretListView

View File

@@ -20,12 +20,14 @@ type Props = {
workspaceId: string;
secretPath?: string;
sortDir: SortDir;
searchTerm?: string;
};
export const FolderListView = ({
folders = [],
environment,
workspaceId,
searchTerm,
secretPath = "/",
sortDir = SortDir.ASC
}: Props) => {
@@ -35,8 +37,6 @@ export const FolderListView = ({
] as const);
const router = useRouter();
const { mutateAsync: updateFolder } = useUpdateFolder();
const { mutateAsync: deleteFolder } = useDeleteFolder();
@@ -100,6 +100,7 @@ export const FolderListView = ({
return (
<>
{folders
.filter(({ name }) => name.toUpperCase().includes(String(searchTerm?.toUpperCase())))
.sort((a, b) =>
sortDir === SortDir.ASC
? a.name.toLowerCase().localeCompare(b.name.toLowerCase())

View File

@@ -72,6 +72,12 @@ If you are editing the API definitions, generate the manifests such as CRs or CR
make manifests
```
Also, after editing the API definitions, update the kubectl-install folder:
```sh
make kubectl-install
```
**NOTE:** Run `make --help` for more information on all potential `make` targets
More information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html)

View File

@@ -96,12 +96,47 @@ spec:
- secretsScope
- serviceTokenSecretReference
type: object
universalAuth:
properties:
credentialsRef:
properties:
secretName:
description: The name of the Kubernetes Secret
type: string
secretNamespace:
description: The name space where the Kubernetes Secret is located
type: string
required:
- secretName
- secretNamespace
type: object
secretsScope:
properties:
envSlug:
type: string
projectSlug:
type: string
secretsPath:
type: string
required:
- envSlug
- projectSlug
- secretsPath
type: object
required:
- credentialsRef
- secretsScope
type: object
type: object
hostAPI:
description: Infisical host to pull secrets from
type: string
managedSecretReference:
properties:
creationPolicy:
default: Orphan
description: 'The Kubernetes Secret creation policy. Enum with values: ''Owner'', ''Orphan''. Owner creates the secret and sets .metadata.ownerReferences of the InfisicalSecret CRD that created it. Orphan will not set the secret owner. This will result in the secret being orphaned and not deleted when the resource is deleted.'
type: string
secretName:
description: The name of the Kubernetes Secret
type: string