Compare commits

..

68 Commits

Author SHA1 Message Date
c64e6310a6 fix(delete-project): Add tooltip for delete project button when it has protection enabled 2025-04-24 10:26:54 -03:00
0e488d840f Merge pull request #3479 from Infisical/update-org-structure-blueprint
Update the organization structure guide to include organizations and …
2025-04-23 21:18:43 -07:00
d6186f1fe8 Update organization-structure.mdx 2025-04-23 17:48:26 -07:00
cd199f9d3e Update the organization structure guide to include organizations and clusters 2025-04-23 17:44:51 -07:00
71258b6ea7 Merge pull request #3477 from Infisical/native-integration-deleted-import-fix
Fix: Filter Out Deleted Imports with Replication
2025-04-23 17:22:04 -07:00
49c90c801e fix: filter out deleted imports with replication 2025-04-23 17:03:33 -07:00
024a1891d3 Merge pull request #3450 from Infisical/google-cloud-run-guide
Adding a guide on deploying Infisical using Google Cloud Run
2025-04-23 16:08:26 -07:00
ac7ac79463 add to nav bar 2025-04-23 16:00:30 -07:00
317b15157d Update google-cloud-run.mdx 2025-04-23 10:44:39 -07:00
f145a00ef5 Merge pull request #3451 from Infisical/daniel/kms-improvements
improvement(kms): return kms key id in project response
2025-04-23 21:35:51 +04:00
2e34167a24 Update google-cloud-run.mdx 2025-04-23 10:29:13 -07:00
0fc7d04455 Merge pull request #3475 from akhilmhdh/feat/secret-cache-v2
feat(api): implemented secret caching version 2
2025-04-23 09:58:00 -07:00
=
af12518f54 fix: resolved lints, addressed feedback from rabbit, reptile and maidul 2025-04-23 22:23:32 +05:30
cc193b9a9f Merge pull request #3459 from Infisical/ENG-2635
Moved certificate manager overview tabs to left sidebar
2025-04-23 12:42:48 -04:00
0e95600db3 Merge pull request #3469 from Infisical/misc/reordered-kube-auth-not-found-check
misc: reordered kube auth not found check
2025-04-23 22:18:54 +08:00
=
b60172f2be feat(api): implemented secret caching version 2 2025-04-23 19:15:50 +05:30
bc1cce62ab Adding more architecture detail to the Cloud Run document 2025-04-22 18:50:45 -07:00
b20e6a9265 Merge pull request #3473 from Infisical/add-winget-dcs
docs: add winget docs
2025-04-22 15:43:36 -07:00
5de9bf25e0 add winget docs 2025-04-22 15:37:45 -07:00
4e10f51e50 Merge pull request #3455 from akhilmhdh/feat/hide-swagger
Hide non public endpoints in swagger
2025-04-22 10:42:29 -07:00
26c14119be Merge pull request #3463 from Infisical/fix-enterprise-plan-display
Fix: Correct Enterprise Plan Display
2025-04-22 09:33:31 -07:00
778d6b9bbf misc: reordered kube auth not found check 2025-04-22 23:06:47 +08:00
b4e831d3e2 Merge pull request #3468 from akhilmhdh/fix/remove-banner
feat: removed banner on ui for subscription crossing
2025-04-22 19:38:02 +05:30
=
8818d5c94b feat: removed banner for now 2025-04-22 19:32:48 +05:30
=
8bfbac153c feat: nit fixing 2025-04-22 12:44:45 +05:30
d7af9e84be added more validation to region 2025-04-21 22:09:52 -07:00
f2a984e6b6 fix: correct plan check for when to display enterprise plan 2025-04-21 19:39:13 -07:00
2cff90913b Merge pull request #3461 from Infisical/ENG-2623
Removed low entropy password regexes that threw false positives
2025-04-21 22:25:58 -04:00
c783fa32e9 Merge pull request #3462 from Infisical/daniel/fix-saml-sso-creation
fix: stuck on saml sso creation page
2025-04-22 06:19:52 +04:00
109971916b fix: stuck on saml sso creation page 2025-04-22 06:07:14 +04:00
x
f7d35e61f7 removed low entropy password regexes that threw false positives 2025-04-21 19:40:20 -04:00
x
ddd46acbde replace alerting icon with notification bell, add new notification bell lotties icon, update permission check wrapper to display access restricted popup 2025-04-21 19:01:12 -04:00
x
e6165f7790 remove commented code, combine a UI if-check, split permission check for cert section and pki collection section 2025-04-21 17:39:42 -04:00
x
ac12f9fc66 update file and export names to be accurate 2025-04-21 16:59:37 -04:00
6107adcc15 Merge pull request #3460 from Infisical/improve-sql-connection-valdiation-error-propogtation
Improvement: Improve SQL Connection Validation Error Propogation
2025-04-21 13:54:41 -07:00
x
7408d38065 fix an import issue 2025-04-21 16:51:30 -04:00
a4eb2e77c2 improvement: move client instantation to try/catch for sql connection validation for error propogation 2025-04-21 13:49:09 -07:00
x
e0c458df4b Merge branch 'ENG-2635' of https://github.com/Infisical/infisical into ENG-2635 2025-04-21 16:21:56 -04:00
x
6a751e720c Changed cert-manager overview tabs to be proper routes 2025-04-21 16:16:47 -04:00
40d119b462 Merge pull request #3457 from Infisical/misc/moved-regex-use-to-re2
misc: moved regex use to re2
2025-04-22 04:02:54 +08:00
6f738d7ed0 Merge pull request #3458 from Infisical/fix/SamlRemovalCornerCase
Allow user to remove SAML config
2025-04-21 15:45:36 -03:00
7f4d4b931b Add entryPoint zod validation 2025-04-21 15:28:59 -03:00
ac2ee6884c misc: updated to use regex literal 2025-04-22 02:10:56 +08:00
608e9a644c Make entryPoint mandatory on SSOModal and check all fields on isSamlConfigured check 2025-04-21 14:52:33 -03:00
c15a1c6ed3 misc: moved regex use to re2 2025-04-22 01:38:21 +08:00
35f0e8f49a Merge pull request #3456 from Infisical/fix/secretVersionReferenceIssue
Fix SecretVersionV2 reference issue blocking users and identities deletion
2025-04-21 10:20:54 -07:00
efb8b69777 Fix SecretVersionV2 reference issue blocking users and identities deletion 2025-04-21 14:06:33 -03:00
b4226e7e1b Merge pull request #3427 from akhilmhdh/feat/block-user-on-trail
Block user on crossing the identity limit
2025-04-21 20:06:22 +05:30
=
ca1f7d3448 feat: reptile and rabbit changes 2025-04-21 15:23:48 +05:30
=
4d569d70d6 fix: broken docs 2025-04-21 14:36:33 +05:30
=
5fccc62213 feat: updated docs to include various endpoints in cli only 2025-04-21 13:22:42 +05:30
eba12912f8 Merge pull request #3396 from akhilmhdh/feat/msg-crct
Updated error message on update org for saml/oidc enforcement
2025-04-20 12:07:07 -04:00
80edccc953 Update org-service.ts 2025-04-20 12:06:34 -04:00
39ff7fddee improvement: add ID to external KMS list and add copy button 2025-04-19 00:20:18 +04:00
a0014230f9 improvement: include kms secret manager key ID on project response 2025-04-19 00:19:57 +04:00
60d0bc827c Update google-cloud-run.mdx 2025-04-18 12:37:18 -07:00
6e9651d188 Adding a guide on deploying Infisical using Google Cloud Run 2025-04-18 11:35:59 -07:00
f1b1d6f480 Merge pull request #3449 from Infisical/rbac-developer-role-correction
Documentation: Correct Developer Role Description
2025-04-18 14:19:09 -04:00
07d6616f3c Merge pull request #3448 from akhilmhdh/feat/better-saml-error-message
Improved saml error messages
2025-04-18 22:36:59 +05:30
=
7364717f60 feat: added an additional 10 as threshold 2025-04-18 22:35:41 +05:30
28d056cf7a documentation: correct developer description 2025-04-18 09:54:58 -07:00
=
f5d7809515 feat: improved saml error messages 2025-04-18 22:24:01 +05:30
233740e029 Merge pull request #3429 from Infisical/windmill-connection-and-sync
Feature: Windmill Connection and Sync
2025-04-17 17:53:19 -07:00
=
5b20c1feba feat: reptile jaw spaced 2025-04-16 00:30:11 +05:30
=
ac73800acb feat: added banner on crossing user/identity limit 2025-04-16 00:25:21 +05:30
=
dd323eccd4 feat: added banner on projects when limit reached 2025-04-15 22:00:22 +05:30
=
7dcd3d24aa feat: corrected oidc message 2025-04-11 23:11:23 +05:30
=
3c5c6aeca8 feat: updated error message on update org for saml/oidc enforcement 2025-04-11 23:09:27 +05:30
161 changed files with 2305 additions and 649 deletions

View File

@ -104,6 +104,7 @@
"pkijs": "^3.2.4",
"posthog-node": "^3.6.2",
"probot": "^13.3.8",
"re2": "^1.21.4",
"safe-regex": "^2.1.1",
"scim-patch": "^0.8.3",
"scim2-parse-filter": "^0.2.10",
@ -6860,6 +6861,79 @@
"node": ">= 8"
}
},
"node_modules/@npmcli/agent": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz",
"integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==",
"license": "ISC",
"dependencies": {
"agent-base": "^7.1.0",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.1",
"lru-cache": "^10.0.1",
"socks-proxy-agent": "^8.0.3"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/@npmcli/agent/node_modules/agent-base": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/@npmcli/agent/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@npmcli/agent/node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/@npmcli/agent/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
"node_modules/@npmcli/fs": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz",
"integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==",
"license": "ISC",
"dependencies": {
"semver": "^7.3.5"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/@octokit/auth-app": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-7.1.1.tgz",
@ -11863,6 +11937,115 @@
"node": ">=8"
}
},
"node_modules/cacache": {
"version": "18.0.4",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz",
"integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==",
"license": "ISC",
"dependencies": {
"@npmcli/fs": "^3.1.0",
"fs-minipass": "^3.0.0",
"glob": "^10.2.2",
"lru-cache": "^10.0.1",
"minipass": "^7.0.3",
"minipass-collect": "^2.0.1",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
"p-map": "^4.0.0",
"ssri": "^10.0.0",
"tar": "^6.1.11",
"unique-filename": "^3.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/cacache/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/cacache/node_modules/fs-minipass": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
"integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==",
"license": "ISC",
"dependencies": {
"minipass": "^7.0.3"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/cacache/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/cacache/node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/cacache/node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
"node_modules/cacache/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/cacache/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
@ -12842,6 +13025,16 @@
"node": ">= 0.8"
}
},
"node_modules/encoding": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"license": "MIT",
"optional": true,
"dependencies": {
"iconv-lite": "^0.6.2"
}
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@ -12874,6 +13067,21 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/err-code": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
"integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
"license": "MIT"
},
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@ -13644,6 +13852,12 @@
"node": ">=0.10.0"
}
},
"node_modules/exponential-backoff": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
"integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==",
"license": "Apache-2.0"
},
"node_modules/express": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
@ -15221,6 +15435,12 @@
],
"license": "MIT"
},
"node_modules/http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
"license": "BSD-2-Clause"
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@ -15403,7 +15623,6 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
"engines": {
"node": ">=0.8.19"
}
@ -15436,6 +15655,16 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
"node_modules/install-artifact-from-github": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/install-artifact-from-github/-/install-artifact-from-github-1.3.5.tgz",
"integrity": "sha512-gZHC7f/cJgXz7MXlHFBxPVMsvIbev1OQN1uKQYKVJDydGNm9oYf9JstbU4Atnh/eSvk41WtEovoRm+8IF686xg==",
"license": "BSD-3-Clause",
"bin": {
"install-from-cache": "bin/install-from-cache.js",
"save-to-github-cache": "bin/save-to-github-cache.js"
}
},
"node_modules/internal-slot": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
@ -15518,6 +15747,19 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/ip-address": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
"license": "MIT",
"dependencies": {
"jsbn": "1.1.0",
"sprintf-js": "^1.1.3"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/ip-num": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/ip-num/-/ip-num-1.5.1.tgz",
@ -15717,6 +15959,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-lambda": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
"integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
"license": "MIT"
},
"node_modules/is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@ -16860,6 +17108,38 @@
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/make-fetch-happen": {
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz",
"integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==",
"license": "ISC",
"dependencies": {
"@npmcli/agent": "^2.0.0",
"cacache": "^18.0.0",
"http-cache-semantics": "^4.1.1",
"is-lambda": "^1.0.1",
"minipass": "^7.0.2",
"minipass-fetch": "^3.0.0",
"minipass-flush": "^1.0.5",
"minipass-pipeline": "^1.2.4",
"negotiator": "^0.6.3",
"proc-log": "^4.2.0",
"promise-retry": "^2.0.1",
"ssri": "^10.0.0"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/make-fetch-happen/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@ -17033,6 +17313,125 @@
"node": ">=8"
}
},
"node_modules/minipass-collect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz",
"integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==",
"license": "ISC",
"dependencies": {
"minipass": "^7.0.3"
},
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/minipass-collect/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/minipass-fetch": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz",
"integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==",
"license": "MIT",
"dependencies": {
"minipass": "^7.0.3",
"minipass-sized": "^1.0.3",
"minizlib": "^2.1.2"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
},
"optionalDependencies": {
"encoding": "^0.1.13"
}
},
"node_modules/minipass-fetch/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/minipass-flush": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
"integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
"license": "ISC",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/minipass-flush/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minipass-pipeline": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
"integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
"license": "ISC",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minipass-pipeline/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minipass-sized": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
"integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
"license": "ISC",
"dependencies": {
"minipass": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minipass-sized/node_modules/minipass": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
@ -17354,6 +17753,12 @@
"node": ">=12"
}
},
"node_modules/nan": {
"version": "2.22.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz",
"integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==",
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
@ -17444,6 +17849,30 @@
}
}
},
"node_modules/node-gyp": {
"version": "10.3.1",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.3.1.tgz",
"integrity": "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==",
"license": "MIT",
"dependencies": {
"env-paths": "^2.2.0",
"exponential-backoff": "^3.1.1",
"glob": "^10.3.10",
"graceful-fs": "^4.2.6",
"make-fetch-happen": "^13.0.0",
"nopt": "^7.0.0",
"proc-log": "^4.1.0",
"semver": "^7.3.5",
"tar": "^6.2.1",
"which": "^4.0.0"
},
"bin": {
"node-gyp": "bin/node-gyp.js"
},
"engines": {
"node": "^16.14.0 || >=18.0.0"
}
},
"node_modules/node-gyp-build": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.9.0.tgz",
@ -17465,6 +17894,122 @@
"node-gyp-build-optional-packages-test": "build-test.js"
}
},
"node_modules/node-gyp/node_modules/abbrev": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
"license": "ISC",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/node-gyp/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/node-gyp/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"license": "ISC",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/node-gyp/node_modules/isexe": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"license": "ISC",
"engines": {
"node": ">=16"
}
},
"node_modules/node-gyp/node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/node-gyp/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/node-gyp/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/node-gyp/node_modules/nopt": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
"license": "ISC",
"dependencies": {
"abbrev": "^2.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/node-gyp/node_modules/which": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
"license": "ISC",
"dependencies": {
"isexe": "^3.1.1"
},
"bin": {
"node-which": "bin/which.js"
},
"engines": {
"node": "^16.13.0 || >=18.0.0"
}
},
"node_modules/node-releases": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
@ -18125,6 +18670,21 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-map": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
"integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
"license": "MIT",
"dependencies": {
"aggregate-error": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-queue": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz",
@ -19202,6 +19762,15 @@
"real-require": "^0.2.0"
}
},
"node_modules/proc-log": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
"integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
"license": "ISC",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@ -19230,6 +19799,28 @@
"node": ">=0.4.0"
}
},
"node_modules/promise-retry": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
"integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
"license": "MIT",
"dependencies": {
"err-code": "^2.0.2",
"retry": "^0.12.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/promise-retry/node_modules/retry": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
"integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/prompt-sync": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/prompt-sync/-/prompt-sync-4.2.0.tgz",
@ -19501,6 +20092,18 @@
"node": ">=0.10.0"
}
},
"node_modules/re2": {
"version": "1.21.4",
"resolved": "https://registry.npmjs.org/re2/-/re2-1.21.4.tgz",
"integrity": "sha512-MVIfXWJmsP28mRsSt8HeL750ifb8H5+oF2UDIxGaiJCr8fkMqhLZ7kcX9ADRk2dC8qeGKedB7UVYRfBVpEiLfA==",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
"install-artifact-from-github": "^1.3.5",
"nan": "^2.20.0",
"node-gyp": "^10.2.0"
}
},
"node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
@ -20422,6 +21025,16 @@
"node": ">=8"
}
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"license": "MIT",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/smee-client": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/smee-client/-/smee-client-2.0.0.tgz",
@ -20625,6 +21238,60 @@
"uuid": "dist/bin/uuid"
}
},
"node_modules/socks": {
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
"integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==",
"license": "MIT",
"dependencies": {
"ip-address": "^9.0.5",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks-proxy-agent": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
"integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "^4.3.4",
"socks": "^2.8.3"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/socks-proxy-agent/node_modules/agent-base": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/socks-proxy-agent/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/sonic-boom": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.7.0.tgz",
@ -20680,6 +21347,27 @@
"node": ">= 0.6"
}
},
"node_modules/ssri": {
"version": "10.0.6",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz",
"integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==",
"license": "ISC",
"dependencies": {
"minipass": "^7.0.3"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/ssri/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
@ -22482,6 +23170,30 @@
"node": ">=4"
}
},
"node_modules/unique-filename": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
"integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
"license": "ISC",
"dependencies": {
"unique-slug": "^4.0.0"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/unique-slug": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
"integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
"license": "ISC",
"dependencies": {
"imurmurhash": "^0.1.4"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/universal-github-app-jwt": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-2.2.0.tgz",

View File

@ -221,6 +221,7 @@
"pkijs": "^3.2.4",
"posthog-node": "^3.6.2",
"probot": "^13.3.8",
"re2": "^1.21.4",
"safe-regex": "^2.1.1",
"scim-patch": "^0.8.3",
"scim2-parse-filter": "^0.2.10",

View File

@ -136,7 +136,7 @@ declare module "fastify" {
rateLimits: RateLimitConfiguration;
// passport data
passportUser: {
isUserCompleted: string;
isUserCompleted: boolean;
providerAuthToken: string;
};
kmipUser: {

View File

@ -0,0 +1,29 @@
import { Knex } from "knex";
import { TableName } from "@app/db/schemas";
export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.SecretVersionV2, (table) => {
table.dropForeign(["userActorId"]);
table.dropForeign(["identityActorId"]);
});
await knex.schema.alterTable(TableName.SecretVersionV2, (table) => {
table.foreign("userActorId").references("id").inTable(TableName.Users).onDelete("SET NULL");
table.foreign("identityActorId").references("id").inTable(TableName.Identity).onDelete("SET NULL");
});
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.SecretVersionV2, (table) => {
table.dropForeign(["userActorId"]);
table.dropForeign(["identityActorId"]);
});
await knex.schema.alterTable(TableName.SecretVersionV2, (table) => {
table.foreign("userActorId").references("id").inTable(TableName.Users);
table.foreign("identityActorId").references("id").inTable(TableName.Identity);
});
}

View File

@ -1,7 +1,7 @@
import { z } from "zod";
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
import { DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
import { ApiDocsTags, DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn";
import { ms } from "@app/lib/ms";
@ -18,6 +18,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
body: z.object({
dynamicSecretName: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.dynamicSecretName).toLowerCase(),
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.projectSlug),
@ -65,6 +67,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.leaseId)
}),
@ -107,6 +111,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.leaseId)
}),
@ -160,6 +166,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.leaseId)
}),

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/providers/models";
import { DYNAMIC_SECRETS } from "@app/lib/api-docs";
import { ApiDocsTags, DYNAMIC_SECRETS } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn";
import { ms } from "@app/lib/ms";
@ -21,6 +21,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
body: z.object({
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.CREATE.projectSlug),
provider: DynamicSecretProviderSchema.describe(DYNAMIC_SECRETS.CREATE.provider),
@ -111,6 +113,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.UPDATE.name)
}),
@ -179,6 +183,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.DELETE.name)
}),
@ -215,6 +221,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({
name: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.name)
}),
@ -253,6 +261,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
querystring: z.object({
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST.projectSlug),
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.LIST.path),
@ -284,18 +294,20 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.DynamicSecrets],
params: z.object({
name: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.name)
name: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.name)
}),
querystring: z.object({
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.projectSlug),
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.projectSlug),
path: z
.string()
.trim()
.default("/")
.transform(removeTrailingSlash)
.describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.path),
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.environmentSlug)
.describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.path),
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.environmentSlug)
}),
response: {
200: z.object({

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { GroupsSchema, OrgMembershipRole, UsersSchema } from "@app/db/schemas";
import { EFilterReturnedUsers } from "@app/ee/services/group/group-types";
import { GROUPS } from "@app/lib/api-docs";
import { ApiDocsTags, GROUPS } from "@app/lib/api-docs";
import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -13,6 +13,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "POST",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Groups],
body: z.object({
name: z.string().trim().min(1).max(50).describe(GROUPS.CREATE.name),
slug: slugSchema({ min: 5, max: 36 }).optional().describe(GROUPS.CREATE.slug),
@ -40,6 +42,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "GET",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({
id: z.string().trim().describe(GROUPS.GET_BY_ID.id)
}),
@ -65,6 +69,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "GET",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Groups],
response: {
200: GroupsSchema.array()
}
@ -87,6 +93,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "PATCH",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({
id: z.string().trim().describe(GROUPS.UPDATE.id)
}),
@ -120,6 +128,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
method: "DELETE",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({
id: z.string().trim().describe(GROUPS.DELETE.id)
}),
@ -145,6 +155,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
url: "/:id/users",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({
id: z.string().trim().describe(GROUPS.LIST_USERS.id)
}),
@ -194,6 +206,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
url: "/:id/users/:username",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({
id: z.string().trim().describe(GROUPS.ADD_USER.id),
username: z.string().trim().describe(GROUPS.ADD_USER.username)
@ -227,6 +241,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
url: "/:id/users/:username",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Groups],
params: z.object({
id: z.string().trim().describe(GROUPS.DELETE_USER.id),
username: z.string().trim().describe(GROUPS.DELETE_USER.username)

View File

@ -3,7 +3,7 @@ import { z } from "zod";
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-types";
import { backfillPermissionV1SchemaToV2Schema } from "@app/ee/services/permission/project-permission";
import { IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
import { ApiDocsTags, IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
import { UnauthorizedError } from "@app/lib/errors";
import { ms } from "@app/lib/ms";
import { alphaNumericNanoId } from "@app/lib/nanoid";
@ -25,6 +25,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Create a permanent or a non expiry specific privilege for identity.",
security: [
{
@ -85,6 +87,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Create a temporary or a expiring specific privilege for identity.",
security: [
{
@ -157,6 +161,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Update a specific privilege of an identity.",
security: [
{
@ -240,6 +246,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Delete a specific privilege of an identity.",
security: [
{
@ -279,6 +287,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "Retrieve details of a specific privilege by privilege slug.",
security: [
{
@ -319,6 +329,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
description: "List of a specific privilege of an identity in a project.",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
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 { ApiDocsTags, AUDIT_LOGS, PROJECTS } from "@app/lib/api-docs";
import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -17,6 +17,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Return project secret snapshots ids",
security: [
{

View File

@ -5,7 +5,7 @@ import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { ProjectTemplateDefaultEnvironments } from "@app/ee/services/project-template/project-template-constants";
import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
import { ProjectTemplates } from "@app/lib/api-docs";
import { ApiDocsTags, ProjectTemplates } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -101,6 +101,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "List project templates for the current organization.",
response: {
200: z.object({
@ -137,6 +139,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "Get a project template by ID.",
params: z.object({
templateId: z.string().uuid()
@ -176,6 +180,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "Create a project template.",
body: z.object({
name: slugSchema({ field: "name" })
@ -219,6 +225,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "Update a project template.",
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.UPDATE.templateId) }),
body: z.object({
@ -269,6 +277,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectTemplates],
description: "Delete a project template.",
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.DELETE.templateId) }),

View File

@ -223,12 +223,18 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
samlConfigId: z.string().trim()
})
},
preValidation: passport.authenticate("saml", {
session: false,
failureFlash: true,
failureRedirect: "/login/provider/error"
// this is due to zod type difference
}) as any,
preValidation: passport.authenticate(
"saml",
{
session: false
},
async (req, res, err, user) => {
if (err) {
throw new BadRequestError({ message: `Saml authentication failed. ${err?.message}`, error: err });
}
req.passportUser = user as { isUserCompleted: boolean; providerAuthToken: string };
}
) as any, // this is due to zod type difference
handler: (req, res) => {
if (req.passportUser.isUserCompleted) {
return res.redirect(

View File

@ -1,7 +1,7 @@
import { z } from "zod";
import { SecretSnapshotsSchema } from "@app/db/schemas";
import { PROJECTS } from "@app/lib/api-docs";
import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { SanitizedTagSchema, secretRawSchema } from "@app/server/routes/sanitizedSchemas";
@ -65,6 +65,8 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Roll back project secrets to those captured in a secret snapshot version.",
security: [
{

View File

@ -6,7 +6,7 @@ import { sanitizedSshCa } from "@app/ee/services/ssh/ssh-certificate-authority-s
import { SshCaKeySource, SshCaStatus } from "@app/ee/services/ssh/ssh-certificate-authority-types";
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema";
import { SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { ApiDocsTags, SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -20,6 +20,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Create SSH CA",
body: z
.object({
@ -92,6 +94,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Get SSH CA",
params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET.sshCaId)
@ -138,6 +142,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Get public key of SSH CA",
params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_PUBLIC_KEY.sshCaId)
@ -163,6 +169,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Update SSH CA",
params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.UPDATE.sshCaId)
@ -216,6 +224,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Delete SSH CA",
params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.DELETE.sshCaId)
@ -261,6 +271,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
description: "Get list of certificate templates for the SSH CA",
params: z.object({
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_CERTIFICATE_TEMPLATES.sshCaId)

View File

@ -3,7 +3,7 @@ import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { SshCertType } from "@app/ee/services/ssh/ssh-certificate-authority-types";
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
import { SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { ApiDocsTags, SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@ -20,6 +20,8 @@ export const registerSshCertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificates],
description: "Sign SSH public key",
body: z.object({
certificateTemplateId: z
@ -100,6 +102,8 @@ export const registerSshCertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificates],
description: "Issue SSH credentials (certificate + key)",
body: z.object({
certificateTemplateId: z

View File

@ -8,7 +8,7 @@ import {
isValidHostPattern,
isValidUserPattern
} from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-validators";
import { SSH_CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
import { ApiDocsTags, SSH_CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -22,6 +22,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
params: z.object({
certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
}),
@ -61,6 +63,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
body: z
.object({
sshCaId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.CREATE.sshCaId),
@ -141,6 +145,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
body: z.object({
status: z.nativeEnum(SshCertTemplateStatus).optional(),
name: z
@ -224,6 +230,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
params: z.object({
certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
}),

View File

@ -4,7 +4,7 @@ import { z } from "zod";
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-types";
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs";
import { ApiDocsTags, IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
@ -21,6 +21,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Add an additional privilege for identity.",
security: [
{
@ -84,6 +86,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Update a specific identity privilege.",
security: [
{
@ -148,6 +152,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Delete the specified identity privilege.",
security: [
{
@ -183,6 +189,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Retrieve details of a specific privilege by id.",
security: [
{
@ -218,6 +226,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "Retrieve details of a specific privilege by slug.",
security: [
{
@ -258,6 +268,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
description: "List privileges for the specified identity by project.",
security: [
{

View File

@ -4,7 +4,7 @@ import { z } from "zod";
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
import { PROJECT_ROLE } from "@app/lib/api-docs";
import { ApiDocsTags, PROJECT_ROLE } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -20,6 +20,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
description: "Create a project role",
security: [
{
@ -75,6 +77,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
description: "Update a project role",
security: [
{
@ -130,6 +134,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
description: "Delete a project role",
security: [
{
@ -166,6 +172,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
description: "List project role",
security: [
{
@ -204,6 +212,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectRoles],
params: z.object({
projectId: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.projectId),
roleSlug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.roleSlug)

View File

@ -9,7 +9,7 @@ import {
TSecretRotationV2GeneratedCredentials,
TSecretRotationV2Input
} from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-types";
import { SecretRotations } from "@app/lib/api-docs";
import { ApiDocsTags, SecretRotations } from "@app/lib/api-docs";
import { startsWithVowel } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -66,6 +66,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `List the ${rotationType} Rotations for the specified project.`,
querystring: z.object({
projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST(type).projectId)
@ -109,6 +111,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Get the specified ${rotationType} Rotation by ID.`,
params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.GET_BY_ID(type).rotationId)
@ -151,6 +155,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Get the specified ${rotationType} Rotation by name, secret path, environment and project ID.`,
params: z.object({
rotationName: z
@ -215,6 +221,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Create ${
startsWithVowel(rotationType) ? "an" : "a"
} ${rotationType} Rotation for the specified project.`,
@ -254,6 +262,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Update the specified ${rotationType} Rotation.`,
params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.UPDATE(type).rotationId)
@ -296,6 +306,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Delete the specified ${rotationType} Rotation.`,
params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.DELETE(type).rotationId)
@ -349,6 +361,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Get the generated credentials for the specified ${rotationType} Rotation.`,
params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.GET_GENERATED_CREDENTIALS_BY_ID(type).rotationId)
@ -402,6 +416,8 @@ export const registerSecretRotationEndpoints = <
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: `Rotate the generated credentials for the specified ${rotationType} Rotation.`,
params: z.object({
rotationId: z.string().uuid().describe(SecretRotations.ROTATE(type).rotationId)

View File

@ -5,7 +5,7 @@ import { Auth0ClientSecretRotationListItemSchema } from "@app/ee/services/secret
import { MsSqlCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/mssql-credentials";
import { PostgresCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/postgres-credentials";
import { SecretRotationV2Schema } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-union-schema";
import { SecretRotations } from "@app/lib/api-docs";
import { ApiDocsTags, SecretRotations } 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";
@ -24,6 +24,8 @@ export const registerSecretRotationV2Router = async (server: FastifyZodProvider)
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: "List the available Secret Rotation Options.",
response: {
200: z.object({
@ -45,6 +47,8 @@ export const registerSecretRotationV2Router = async (server: FastifyZodProvider)
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretRotations],
description: "List all the Secret Rotations for the specified project.",
querystring: z.object({
projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST().projectId)

View File

@ -2,6 +2,7 @@ import handlebars from "handlebars";
import ldapjs from "ldapjs";
import ldif from "ldif";
import { customAlphabet } from "nanoid";
import RE2 from "re2";
import { z } from "zod";
import { BadRequestError } from "@app/lib/errors";
@ -194,7 +195,8 @@ export const LdapProvider = (): TDynamicProviderFns => {
const client = await $getClient(providerInputs);
if (providerInputs.credentialType === LdapCredentialType.Static) {
const dnMatch = providerInputs.rotationLdif.match(/^dn:\s*(.+)/m);
const dnRegex = new RE2("^dn:\\s*(.+)", "m");
const dnMatch = dnRegex.exec(providerInputs.rotationLdif);
if (dnMatch) {
const username = dnMatch[1];
@ -238,7 +240,8 @@ export const LdapProvider = (): TDynamicProviderFns => {
const client = await $getClient(providerInputs);
if (providerInputs.credentialType === LdapCredentialType.Static) {
const dnMatch = providerInputs.rotationLdif.match(/^dn:\s*(.+)/m);
const dnRegex = new RE2("^dn:\\s*(.+)", "m");
const dnMatch = dnRegex.exec(providerInputs.rotationLdif);
if (dnMatch) {
const username = dnMatch[1];

View File

@ -1,6 +1,5 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { ormify } from "@app/lib/knex";
export type TOidcConfigDALFactory = ReturnType<typeof oidcConfigDALFactory>;
@ -8,22 +7,5 @@ export type TOidcConfigDALFactory = ReturnType<typeof oidcConfigDALFactory>;
export const oidcConfigDALFactory = (db: TDbClient) => {
const oidcCfgOrm = ormify(db, TableName.OidcConfig);
const findEnforceableOidcCfg = async (orgId: string) => {
try {
const oidcCfg = await db
.replicaNode()(TableName.OidcConfig)
.where({
orgId,
isActive: true
})
.whereNotNull("lastUsed")
.first();
return oidcCfg;
} catch (error) {
throw new DatabaseError({ error, name: "Find org by id" });
}
};
return { ...oidcCfgOrm, findEnforceableOidcCfg };
return oidcCfgOrm;
};

View File

@ -1,6 +1,5 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { ormify } from "@app/lib/knex";
export type TSamlConfigDALFactory = ReturnType<typeof samlConfigDALFactory>;
@ -8,25 +7,5 @@ export type TSamlConfigDALFactory = ReturnType<typeof samlConfigDALFactory>;
export const samlConfigDALFactory = (db: TDbClient) => {
const samlCfgOrm = ormify(db, TableName.SamlConfig);
const findEnforceableSamlCfg = async (orgId: string) => {
try {
const samlCfg = await db
.replicaNode()(TableName.SamlConfig)
.where({
orgId,
isActive: true
})
.whereNotNull("lastUsed")
.first();
return samlCfg;
} catch (error) {
throw new DatabaseError({ error, name: "Find org by id" });
}
};
return {
...samlCfgOrm,
findEnforceableSamlCfg
};
return samlCfgOrm;
};

View File

@ -267,7 +267,6 @@ export const secretReplicationServiceFactory = ({
const sourceLocalSecrets = await secretV2BridgeDAL.find({ folderId: folder.id, type: SecretType.Shared });
const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id });
const sourceImportedSecrets = await fnSecretsV2FromImports({
projectId,
secretImports: sourceSecretImports,
secretDAL: secretV2BridgeDAL,
folderDAL,

View File

@ -1,4 +1,5 @@
import { isIP } from "net";
import RE2 from "re2";
import { isFQDN } from "@app/lib/validator/validate-url";
@ -10,7 +11,7 @@ export const isValidUserPattern = (value: string): boolean => {
if (value === "*") return true; // Handle wildcard separately
// Simpler, more specific pattern for usernames
const userRegex = /^[a-z_][a-z0-9_-]*$/i;
const userRegex = new RE2(/^[a-z_][a-z0-9_-]*$/i);
return userRegex.test(value);
};

View File

@ -4,6 +4,7 @@ import { promises as fs } from "fs";
import { Knex } from "knex";
import os from "os";
import path from "path";
import RE2 from "re2";
import { promisify } from "util";
import { TSshCertificateTemplates } from "@app/db/schemas";
@ -156,14 +157,14 @@ export const validateSshCertificatePrincipals = (
});
}
if (/\r|\n|\t|\0/.test(sanitized)) {
if (new RE2(/\r|\n|\t|\0/).test(sanitized)) {
throw new BadRequestError({
message: `Principal '${sanitized}' contains invalid whitespace or control characters.`
});
}
// disallow whitespace anywhere
if (/\s/.test(sanitized)) {
if (new RE2(/\s/).test(sanitized)) {
throw new BadRequestError({
message: `Principal '${sanitized}' cannot contain whitespace.`
});

View File

@ -8,6 +8,51 @@ import { APP_CONNECTION_NAME_MAP } from "@app/services/app-connection/app-connec
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
export enum ApiDocsTags {
Identities = "Identities",
TokenAuth = "Token Auth",
UniversalAuth = "Universal Auth",
GcpAuth = "GCP Auth",
AwsAuth = "AWS Auth",
AzureAuth = "Azure Auth",
KubernetesAuth = "Kubernetes Auth",
JwtAuth = "JWT Auth",
OidcAuth = "OIDC Auth",
Groups = "Groups",
Organizations = "Organizations",
Projects = "Projects",
ProjectUsers = "Project Users",
ProjectGroups = "Project Groups",
ProjectIdentities = "Project Identities",
ProjectRoles = "Project Roles",
ProjectTemplates = "Project Templates",
Environments = "Environments",
Folders = "Folders",
SecretTags = "Secret Tags",
Secrets = "Secrets",
DynamicSecrets = "Dynamic Secrets",
SecretImports = "Secret Imports",
SecretRotations = "Secret Rotations",
IdentitySpecificPrivilegesV1 = "Identity Specific Privileges",
IdentitySpecificPrivilegesV2 = "Identity Specific Privileges V2",
AppConnections = "App Connections",
SecretSyncs = "Secret Syncs",
Integrations = "Integrations",
ServiceTokens = "Service Tokens",
AuditLogs = "Audit Logs",
PkiCertificateAuthorities = "PKI Certificate Authorities",
PkiCertificates = "PKI Certificates",
PkiCertificateTemplates = "PKI Certificate Templates",
PkiCertificateCollections = "PKI Certificate Collections",
PkiAlerting = "PKI Alerting",
SshCertificates = "SSH Certificates",
SshCertificateAuthorities = "SSH Certificate Authorities",
SshCertificateTemplates = "SSH Certificate Templates",
KmsKeys = "KMS Keys",
KmsEncryption = "KMS Encryption",
KmsSigning = "KMS Signing"
}
export const GROUPS = {
CREATE: {
name: "The name of the group to create.",
@ -888,7 +933,7 @@ export const DYNAMIC_SECRETS = {
environmentSlug: "The slug of the environment to list folders from.",
path: "The path to list folders from."
},
LIST_LEAES_BY_NAME: {
LIST_LEASES_BY_NAME: {
projectSlug: "The slug of the project to create dynamic secret in.",
environmentSlug: "The slug of the environment to list folders from.",
path: "The path to list folders from.",

View File

@ -1,12 +1,16 @@
import RE2 from "re2";
type Base64Options = {
urlSafe?: boolean;
padding?: boolean;
};
const base64WithPadding = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/;
const base64WithoutPadding = /^[A-Za-z0-9+/]+$/;
const base64UrlWithPadding = /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2}==|[A-Za-z0-9_-]{3}=|[A-Za-z0-9_-]{4})$/;
const base64UrlWithoutPadding = /^[A-Za-z0-9_-]+$/;
const base64WithPadding = new RE2(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/);
const base64WithoutPadding = new RE2(/^[A-Za-z0-9+/]+$/);
const base64UrlWithPadding = new RE2(
/^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2}==|[A-Za-z0-9_-]{3}=|[A-Za-z0-9_-]{4})$/
);
const base64UrlWithoutPadding = new RE2(/^[A-Za-z0-9_-]+$/);
export const isBase64 = (str: string, options: Base64Options = {}): boolean => {
if (typeof str !== "string") {

View File

@ -1,4 +1,5 @@
import path from "path";
import RE2 from "re2";
// given two paths irrespective of ending with / or not
// this will return true if its equal
@ -15,4 +16,6 @@ export const prefixWithSlash = (str: string) => {
return `/${str}`;
};
export const startsWithVowel = (str: string) => /^[aeiou]/i.test(str);
const vowelRegex = new RE2(/^[aeiou]/i);
export const startsWithVowel = (str: string) => vowelRegex.test(str);

View File

@ -1,3 +1,4 @@
import RE2 from "re2";
import { z } from "zod";
export enum CharacterType {
@ -92,7 +93,7 @@ export const characterValidator = (allowedCharacters: CharacterType[]) => {
const combinedPattern = allowedCharacters.map((char) => patternMap[char]).join("");
// Create a regex that matches only the allowed characters
const regex = new RegExp(`^[${combinedPattern}]+$`);
const regex = new RE2(`^[${combinedPattern}]+$`);
/**
* Validates if the input string contains only the allowed character types

View File

@ -1,6 +1,7 @@
import dns from "node:dns/promises";
import { isIPv4 } from "net";
import RE2 from "re2";
import { getConfig } from "@app/lib/config/env";
@ -80,42 +81,47 @@ export const isFQDN = (str: string, options: FQDNOptions = {}): boolean => {
if (
!opts.allow_numeric_tld &&
!/^([a-z\u00A1-\u00A8\u00AA-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}|xn[a-z0-9-]{2,})$/i.test(tld)
!new RE2(/^([a-z\u00A1-\u00A8\u00AA-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{2,}|xn[a-z0-9-]{2,})$/i).test(tld)
) {
return false;
}
// disallow spaces
if (/\s/.test(tld)) {
if (new RE2(/\s/).test(tld)) {
return false;
}
}
// reject numeric TLDs
if (!opts.allow_numeric_tld && /^\d+$/.test(tld)) {
if (!opts.allow_numeric_tld && new RE2(/^\d+$/).test(tld)) {
return false;
}
const partRegex = new RE2(/^[a-z_\u00a1-\uffff0-9-]+$/i);
const fullWidthRegex = new RE2(/[\uff01-\uff5e]/);
const hyphenRegex = new RE2(/^-|-$/);
const underscoreRegex = new RE2(/_/);
return parts.every((part) => {
if (part.length > 63 && !opts.ignore_max_length) {
return false;
}
if (!/^[a-z_\u00a1-\uffff0-9-]+$/i.test(part)) {
if (!partRegex.test(part)) {
return false;
}
// disallow full-width chars
if (/[\uff01-\uff5e]/.test(part)) {
if (fullWidthRegex.test(part)) {
return false;
}
// disallow parts starting or ending with hyphen
if (/^-|-$/.test(part)) {
if (hyphenRegex.test(part)) {
return false;
}
if (!opts.allow_underscores && /_/.test(part)) {
if (!opts.allow_underscores && underscoreRegex.test(part)) {
return false;
}

View File

@ -1,3 +1,4 @@
import RE2 from "re2";
import { z, ZodTypeAny } from "zod";
// this is a patched zod string to remove empty string to undefined
@ -11,3 +12,8 @@ export const zpStr = <T extends ZodTypeAny>(schema: T, opt: { stripNull: boolean
export const zodBuffer = z.custom<Buffer>((data) => Buffer.isBuffer(data) || data instanceof Uint8Array, {
message: "Expected binary data (Buffer Or Uint8Array)"
});
export const re2Validator = (pattern: string | RegExp) => {
const re2Pattern = new RE2(pattern);
return (value: string) => re2Pattern.test(value);
};

View File

@ -73,6 +73,7 @@ const run = async () => {
// eslint-disable-next-line
process.on("SIGINT", async () => {
await server.close();
await queue.shutdown();
await db.destroy();
await removeTemporaryBaseDirectory();
hsmModule.finalize();
@ -82,19 +83,22 @@ const run = async () => {
// eslint-disable-next-line
process.on("SIGTERM", async () => {
await server.close();
await queue.shutdown();
await db.destroy();
await removeTemporaryBaseDirectory();
hsmModule.finalize();
process.exit(0);
});
process.on("uncaughtException", (error) => {
logger.error(error, "CRITICAL ERROR: Uncaught Exception");
});
if (!envConfig.isDevelopmentMode) {
process.on("uncaughtException", (error) => {
logger.error(error, "CRITICAL ERROR: Uncaught Exception");
});
process.on("unhandledRejection", (error) => {
logger.error(error, "CRITICAL ERROR: Unhandled Promise Rejection");
});
process.on("unhandledRejection", (error) => {
logger.error(error, "CRITICAL ERROR: Unhandled Promise Rejection");
});
}
await server.listen({
port: envConfig.PORT,

View File

@ -49,14 +49,17 @@ function resolveSchema(maybeSchema: ZodAny | { properties: ZodAny }): Pick<ZodAn
}
export const createJsonSchemaTransform = ({ skipList }: { skipList: readonly string[] }) => {
return ({ schema, url }: { schema: Schema; url: string }) => {
return ({ schema = {}, url }: { schema: Schema; url: string }) => {
if (!schema) {
return {
schema,
schema: { hide: true },
url
};
}
if (typeof schema.hide === "undefined") {
schema.hide = true;
}
const { response, headers, querystring, body, params, hide, ...rest } = schema;
const transformed: FreeformRecord = {};

View File

@ -1089,7 +1089,8 @@ export const registerRoutes = async (
secretApprovalRequestSecretDAL,
kmsService,
snapshotService,
resourceMetadataDAL
resourceMetadataDAL,
keyStore
});
const secretApprovalRequestService = secretApprovalRequestServiceFactory({

View File

@ -1,7 +1,7 @@
import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { AppConnections } from "@app/lib/api-docs";
import { ApiDocsTags, AppConnections } from "@app/lib/api-docs";
import { startsWithVowel } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -43,6 +43,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `List the ${appName} Connections for the current organization.`,
response: {
200: z.object({ appConnections: sanitizedResponseSchema.array() })
@ -76,6 +78,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `List the ${appName} Connections the current user has permission to establish connections with.`,
response: {
200: z.object({
@ -120,6 +124,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Get the specified ${appName} Connection by ID.`,
params: z.object({
connectionId: z.string().uuid().describe(AppConnections.GET_BY_ID(app).connectionId)
@ -160,6 +166,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Get the specified ${appName} Connection by name.`,
params: z.object({
connectionName: z
@ -204,6 +212,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Create ${
startsWithVowel(appName) ? "an" : "a"
} ${appName} Connection for the current organization.`,
@ -247,6 +257,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Update the specified ${appName} Connection.`,
params: z.object({
connectionId: z.string().uuid().describe(AppConnections.UPDATE(app).connectionId)
@ -292,6 +304,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: `Delete the specified ${appName} Connection.`,
params: z.object({
connectionId: z.string().uuid().describe(AppConnections.DELETE(app).connectionId)

View File

@ -1,6 +1,7 @@
import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApiDocsTags } from "@app/lib/api-docs";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { Auth0ConnectionListItemSchema, SanitizedAuth0ConnectionSchema } from "@app/services/app-connection/auth0";
@ -86,6 +87,8 @@ export const registerAppConnectionRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: "List the available App Connection Options.",
response: {
200: z.object({
@ -107,6 +110,8 @@ export const registerAppConnectionRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AppConnections],
description: "List all the App Connections for the current organization.",
response: {
200: z.object({ appConnections: SanitizedAppConnectionSchema.array() })

View File

@ -3,7 +3,7 @@ import { z } from "zod";
import { CertificateAuthoritiesSchema, CertificateTemplatesSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { ApiDocsTags, CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@ -26,6 +26,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Create CA",
body: z
.object({
@ -105,6 +107,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET.caId)
@ -151,6 +155,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get DER-encoded certificate of CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caId),
@ -177,6 +183,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Update CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.UPDATE.caId)
@ -231,6 +239,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Delete CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.DELETE.caId)
@ -276,6 +286,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get CA CSR",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CSR.caId)
@ -321,6 +333,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Perform CA certificate renewal",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.caId)
@ -376,6 +390,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get list of past and current CA certificates for a CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.caId)
@ -424,6 +440,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get current CA cert and cert chain of a CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT.caId)
@ -473,6 +491,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Create intermediate CA certificate from parent CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.caId)
@ -536,6 +556,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Import certificate and chain to CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.IMPORT_CERT.caId)
@ -588,6 +610,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Issue certificate from CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.caId)
@ -679,6 +703,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Sign certificate from CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId)
@ -770,6 +796,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get list of certificate templates for the CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId)
@ -815,6 +843,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
description: "Get list of CRLs of the CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CRLS.caId)

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { CertificatesSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { CERTIFICATE_AUTHORITIES, CERTIFICATES } from "@app/lib/api-docs";
import { ApiDocsTags, CERTIFICATE_AUTHORITIES, CERTIFICATES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@ -24,6 +24,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Get certificate",
params: z.object({
serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber)
@ -70,6 +72,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Issue certificate",
body: z
.object({
@ -181,6 +185,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Sign certificate",
body: z
.object({
@ -292,6 +298,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Revoke",
params: z.object({
serialNumber: z.string().trim().describe(CERTIFICATES.REVOKE.serialNumber)
@ -346,6 +354,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Delete certificate",
params: z.object({
serialNumber: z.string().trim().describe(CERTIFICATES.DELETE.serialNumber)
@ -392,6 +402,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
description: "Get certificate body of certificate",
params: z.object({
serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber)

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { CertificateTemplateEstConfigsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
import { ApiDocsTags, CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -26,6 +26,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: z.object({
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
}),
@ -65,6 +67,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
body: z.object({
caId: z.string().describe(CERTIFICATE_TEMPLATES.CREATE.caId),
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.CREATE.pkiCollectionId),
@ -132,6 +136,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
body: z.object({
caId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.caId),
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.pkiCollectionId),
@ -198,6 +204,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: z.object({
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
}),
@ -238,6 +246,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
description: "Create Certificate Template EST configuration",
params: z.object({
certificateTemplateId: z.string().trim()
@ -292,6 +302,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
description: "Update Certificate Template EST configuration",
params: z.object({
certificateTemplateId: z.string().trim()
@ -340,6 +352,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
description: "Get Certificate Template EST configuration",
params: z.object({
certificateTemplateId: z.string().trim()

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { KMS } from "@app/lib/api-docs";
import { ApiDocsTags, KMS } from "@app/lib/api-docs";
import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64";
import { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign";
@ -46,6 +46,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Create KMS key",
body: z
.object({
@ -138,6 +140,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Update KMS key",
params: z.object({
keyId: z.string().uuid().describe(KMS.UPDATE_KEY.keyId)
@ -187,6 +191,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Delete KMS key",
params: z.object({
keyId: z.string().uuid().describe(KMS.DELETE_KEY.keyId)
@ -229,6 +235,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "List KMS keys",
querystring: z.object({
projectId: z.string().describe(KMS.LIST_KEYS.projectId),
@ -280,6 +288,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Get KMS key by ID",
params: z.object({
keyId: z.string().uuid().describe(KMS.GET_KEY_BY_ID.keyId)
@ -321,6 +331,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsKeys],
description: "Get KMS key by name",
params: z.object({
keyName: slugSchema({ field: "Key name" }).describe(KMS.GET_KEY_BY_NAME.keyName)
@ -367,6 +379,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsEncryption],
description: "Encrypt data with KMS key",
params: z.object({
keyId: z.string().uuid().describe(KMS.ENCRYPT.keyId)
@ -412,6 +426,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsSigning],
description:
"Get the public key for a KMS key that is used for signing and verifying data. This endpoint is only available for asymmetric keys.",
params: z.object({
@ -454,6 +470,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsSigning],
description: "List all available signing algorithms for a KMS key",
params: z.object({
keyId: z.string().uuid().describe(KMS.LIST_SIGNING_ALGORITHMS.keyId)
@ -495,6 +513,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsSigning],
description: "Sign data with a KMS key.",
params: z.object({
keyId: z.string().uuid().describe(KMS.SIGN.keyId)
@ -548,6 +568,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsSigning],
description: "Verify data signatures with a KMS key.",
params: z.object({
keyId: z.string().uuid().describe(KMS.VERIFY.keyId)
@ -604,6 +626,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KmsEncryption],
description: "Decrypt data with KMS key",
params: z.object({
keyId: z.string().uuid().describe(KMS.DECRYPT.keyId)

View File

@ -1,6 +1,6 @@
import { z } from "zod";
import { UNIVERSAL_AUTH } from "@app/lib/api-docs";
import { ApiDocsTags, UNIVERSAL_AUTH } from "@app/lib/api-docs";
import { writeLimit } from "@app/server/config/rateLimiter";
export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => {
@ -11,6 +11,8 @@ export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvid
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Renew access token",
body: z.object({
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.RENEW_ACCESS_TOKEN.accessToken)
@ -44,6 +46,8 @@ export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvid
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Revoke access token",
body: z.object({
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.REVOKE_ACCESS_TOKEN.accessToken)

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityAwsAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { AWS_AUTH } from "@app/lib/api-docs";
import { ApiDocsTags, AWS_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -21,6 +21,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Login with AWS Auth",
body: z.object({
identityId: z.string().trim().describe(AWS_AUTH.LOGIN.identityId),
@ -71,6 +73,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Attach AWS Auth configuration onto identity",
security: [
{
@ -165,6 +169,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Update AWS Auth configuration on identity",
security: [
{
@ -247,6 +253,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Retrieve AWS Auth configuration on identity",
security: [
{
@ -293,6 +301,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AwsAuth],
description: "Delete AWS Auth configuration on identity",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityAzureAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { AZURE_AUTH } from "@app/lib/api-docs";
import { ApiDocsTags, AZURE_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -18,6 +18,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Login with Azure Auth",
body: z.object({
identityId: z.string().trim().describe(AZURE_AUTH.LOGIN.identityId),
@ -66,6 +68,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Attach Azure Auth configuration onto identity",
security: [
{
@ -159,6 +163,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Update Azure Auth configuration on identity",
security: [
{
@ -247,6 +253,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Retrieve Azure Auth configuration on identity",
security: [
{
@ -294,6 +302,8 @@ export const registerIdentityAzureAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AzureAuth],
description: "Delete Azure Auth configuration on identity",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityGcpAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { GCP_AUTH } from "@app/lib/api-docs";
import { ApiDocsTags, GCP_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -18,9 +18,11 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Login with GCP Auth",
body: z.object({
identityId: z.string().trim().describe(GCP_AUTH.LOGIN.identityId).trim(),
identityId: z.string().trim().describe(GCP_AUTH.LOGIN.identityId),
jwt: z.string()
}),
response: {
@ -66,6 +68,8 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Attach GCP Auth configuration onto identity",
security: [
{
@ -157,6 +161,8 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Update GCP Auth configuration on identity",
security: [
{
@ -241,6 +247,8 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Retrieve GCP Auth configuration on identity",
security: [
{
@ -288,6 +296,8 @@ export const registerIdentityGcpAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.GcpAuth],
description: "Delete GCP Auth configuration on identity",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityJwtAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { JWT_AUTH } from "@app/lib/api-docs";
import { ApiDocsTags, JWT_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -94,6 +94,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Login with JWT Auth",
body: z.object({
identityId: z.string().trim().describe(JWT_AUTH.LOGIN.identityId),
@ -144,6 +146,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Attach JWT Auth configuration onto identity",
security: [
{
@ -211,6 +215,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Update JWT Auth configuration on identity",
security: [
{
@ -275,6 +281,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Retrieve JWT Auth configuration on identity",
security: [
{
@ -322,6 +330,8 @@ export const registerIdentityJwtAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.JwtAuth],
description: "Delete JWT Auth configuration on identity",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityKubernetesAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { KUBERNETES_AUTH } from "@app/lib/api-docs";
import { ApiDocsTags, KUBERNETES_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -35,6 +35,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Login with Kubernetes Auth",
body: z.object({
identityId: z.string().trim().describe(KUBERNETES_AUTH.LOGIN.identityId),
@ -85,6 +87,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Attach Kubernetes Auth configuration onto identity",
security: [
{
@ -182,6 +186,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Update Kubernetes Auth configuration on identity",
security: [
{
@ -278,6 +284,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Retrieve Kubernetes Auth configuration on identity",
security: [
{
@ -325,6 +333,8 @@ export const registerIdentityKubernetesRouter = async (server: FastifyZodProvide
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.KubernetesAuth],
description: "Delete Kubernetes Auth configuration on identity",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityOidcAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { OIDC_AUTH } from "@app/lib/api-docs";
import { ApiDocsTags, OIDC_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -42,6 +42,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Login with OIDC Auth",
body: z.object({
identityId: z.string().trim().describe(OIDC_AUTH.LOGIN.identityId),
@ -96,6 +98,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Attach OIDC Auth configuration onto identity",
security: [
{
@ -195,6 +199,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Update OIDC Auth configuration on identity",
security: [
{
@ -292,6 +298,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Retrieve OIDC Auth configuration on identity",
security: [
{
@ -339,6 +347,8 @@ export const registerIdentityOidcAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.OidcAuth],
description: "Delete OIDC Auth configuration on identity",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgMembershipRole, OrgRolesSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { IDENTITIES } from "@app/lib/api-docs";
import { ApiDocsTags, IDENTITIES } from "@app/lib/api-docs";
import { buildSearchZodSchema, SearchResourceOperators } from "@app/lib/search-resource/search";
import { OrderByDirection } from "@app/lib/types";
import { CharacterType, zodValidateCharacters } from "@app/lib/validator/validate-string";
@ -32,6 +32,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Create identity",
security: [
{
@ -100,6 +102,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Update identity",
security: [
{
@ -158,6 +162,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Delete identity",
security: [
{
@ -205,6 +211,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Get an identity by id",
security: [
{
@ -260,6 +268,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "List identities",
security: [
{
@ -308,6 +318,8 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Identities],
description: "Search identities",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { IdentityAccessTokensSchema, IdentityTokenAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { TOKEN_AUTH } from "@app/lib/api-docs";
import { ApiDocsTags, TOKEN_AUTH } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -18,6 +18,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Attach Token Auth configuration onto identity",
security: [
{
@ -108,6 +110,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Update Token Auth configuration on identity",
security: [
{
@ -192,6 +196,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Retrieve Token Auth configuration on identity",
security: [
{
@ -239,6 +245,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Delete Token Auth configuration on identity",
security: [
{
@ -287,6 +295,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Create token for identity with Token Auth",
security: [
{
@ -349,6 +359,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Get tokens for identity with Token Auth",
security: [
{
@ -402,6 +414,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Update token for identity with Token Auth",
security: [
{
@ -456,6 +470,8 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.TokenAuth],
description: "Revoke token for identity with Token Auth",
security: [
{

View File

@ -2,7 +2,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 { ApiDocsTags, 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";
@ -30,6 +30,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Login with Universal Auth",
body: z.object({
clientId: z.string().trim().describe(UNIVERSAL_AUTH.LOGIN.clientId),
@ -78,6 +80,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Attach Universal Auth configuration onto identity",
security: [
{
@ -175,6 +179,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Update Universal Auth configuration on identity",
security: [
{
@ -271,6 +277,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Retrieve Universal Auth configuration on identity",
security: [
{
@ -318,6 +326,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Delete Universal Auth configuration on identity",
security: [
{
@ -365,6 +375,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Create Universal Auth Client Secret for identity",
security: [
{
@ -421,6 +433,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "List Universal Auth Client Secrets for identity",
security: [
{
@ -469,6 +483,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Get Universal Auth Client Secret for identity",
security: [
{
@ -519,6 +535,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.UniversalAuth],
description: "Revoke Universal Auth Client Secrets for identity",
security: [
{

View File

@ -1,7 +1,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 { ApiDocsTags, 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";
@ -19,6 +19,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "List of integrations available.",
security: [
{
@ -57,6 +59,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Get details of an integration authorization by auth object id.",
security: [
{
@ -92,6 +96,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Update the integration authentication object required for syncing secrets.",
security: [
{
@ -153,6 +159,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Remove all integration's auth object from the project.",
security: [
{
@ -202,6 +210,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Remove an integration auth object by object id.",
security: [
{
@ -294,6 +304,8 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Create the integration authentication object required for syncing secrets.",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
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 { ApiDocsTags, INTEGRATION } from "@app/lib/api-docs";
import { removeTrailingSlash, shake } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@ -22,6 +22,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Create an integration to sync secrets.",
security: [
{
@ -119,6 +121,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Update an integration by integration id",
security: [
{
@ -178,6 +182,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Get an integration by integration id",
security: [
{
@ -247,6 +253,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Remove an integration using the integration object ID",
security: [
{
@ -315,6 +323,8 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "Manually trigger sync of an integration by integration id",
security: [
{

View File

@ -9,7 +9,7 @@ import {
UsersSchema
} from "@app/db/schemas";
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
import { AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
import { ApiDocsTags, AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { GenericResourceNameSchema, slugSchema } from "@app/server/lib/schemas";
@ -109,6 +109,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AuditLogs],
description: "Get all audit logs for an organization",
querystring: z.object({
projectId: z.string().optional().describe(AUDIT_LOGS.EXPORT.projectId),

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { PkiAlertsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ALERTS } from "@app/lib/api-docs";
import { ALERTS, ApiDocsTags } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -16,6 +16,8 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
description: "Create PKI alert",
body: z.object({
projectId: z.string().trim().describe(ALERTS.CREATE.projectId),
@ -68,6 +70,8 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
description: "Get PKI alert",
params: z.object({
alertId: z.string().trim().describe(ALERTS.GET.alertId)
@ -108,6 +112,8 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
description: "Update PKI alert",
params: z.object({
alertId: z.string().trim().describe(ALERTS.UPDATE.alertId)
@ -164,6 +170,8 @@ export const registerPkiAlertRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiAlerting],
description: "Delete PKI alert",
params: z.object({
alertId: z.string().trim().describe(ALERTS.DELETE.alertId)

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { PkiCollectionItemsSchema, PkiCollectionsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PKI_COLLECTIONS } from "@app/lib/api-docs";
import { ApiDocsTags, PKI_COLLECTIONS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -17,6 +17,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Create PKI collection",
body: z.object({
projectId: z.string().trim().describe(PKI_COLLECTIONS.CREATE.projectId),
@ -60,6 +62,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Get PKI collection",
params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.GET.collectionId)
@ -100,6 +104,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Update PKI collection",
params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.UPDATE.collectionId)
@ -146,6 +152,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Delete PKI collection",
params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.DELETE.collectionId)
@ -186,6 +194,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Get items in PKI collection",
params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.LIST_ITEMS.collectionId)
@ -247,6 +257,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Add item to PKI collection",
params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.ADD_ITEM.collectionId)
@ -298,6 +310,8 @@ export const registerPkiCollectionRouter = async (server: FastifyZodProvider) =>
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateCollections],
description: "Remove item from PKI collection",
params: z.object({
collectionId: z.string().trim().describe(PKI_COLLECTIONS.DELETE_ITEM.collectionId),

View File

@ -2,7 +2,7 @@ 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 { ApiDocsTags, ENVIRONMENTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -13,9 +13,11 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
method: "GET",
url: "/:workspaceId/environments/:envId",
config: {
rateLimit: writeLimit
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Get Environment",
security: [
{
@ -65,6 +67,8 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Get Environment by ID",
security: [
{
@ -112,6 +116,8 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Create environment",
security: [
{
@ -171,6 +177,8 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Update environment",
security: [
{
@ -237,6 +245,8 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Environments],
description: "Delete environment",
security: [
{

View File

@ -8,7 +8,7 @@ import {
UsersSchema
} from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECT_USERS } from "@app/lib/api-docs";
import { ApiDocsTags, PROJECT_USERS } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -23,6 +23,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Return project user memberships",
security: [
{
@ -141,6 +143,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Return project user memberships",
security: [
{
@ -255,6 +259,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Update project user membership",
security: [
{

View File

@ -13,8 +13,9 @@ import {
UsersSchema
} from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECTS } from "@app/lib/api-docs";
import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
import { CharacterType, characterValidator } from "@app/lib/validator/validate-string";
import { re2Validator } from "@app/lib/zod";
import { 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";
@ -176,6 +177,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Get project",
security: [
{
@ -214,6 +217,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Delete project",
security: [
{
@ -289,6 +294,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Update project",
security: [
{
@ -316,11 +323,11 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
slug: z
.string()
.trim()
.regex(
/^[a-z0-9]+(?:[_-][a-z0-9]+)*$/,
"Project slug can only contain lowercase letters and numbers, with optional single hyphens (-) or underscores (_) between words. Cannot start or end with a hyphen or underscore."
)
.max(64, { message: "Slug must be 64 characters or fewer" })
.refine(re2Validator(/^[a-z0-9]+(?:[_-][a-z0-9]+)*$/), {
message:
"Project slug can only contain lowercase letters and numbers, with optional single hyphens (-) or underscores (_) between words. Cannot start or end with a hyphen or underscore."
})
.optional()
.describe(PROJECTS.UPDATE.slug)
}),
@ -512,6 +519,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "List integrations for a project.",
security: [
{
@ -555,6 +564,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Integrations],
description: "List integration auth objects for a workspace.",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
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 { ApiDocsTags, FOLDERS } from "@app/lib/api-docs";
import { prefixWithSlash, removeTrailingSlash } from "@app/lib/fn";
import { isValidFolderName } from "@app/lib/validator";
import { readLimit, secretsLimit } from "@app/server/config/rateLimiter";
@ -19,6 +19,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Create folders",
security: [
{
@ -98,6 +100,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Update folder",
security: [
{
@ -181,6 +185,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Update folders by batch",
security: [
{
@ -259,6 +265,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Delete a folder",
security: [
{
@ -332,6 +340,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Get folders",
security: [
{
@ -390,6 +400,8 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
description: "Get folder by id",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
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 { ApiDocsTags, 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";
@ -18,6 +18,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Create secret imports",
security: [
{
@ -83,6 +85,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Update secret imports",
security: [
{
@ -157,6 +161,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Delete secret imports",
security: [
{
@ -263,6 +269,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Get secret imports",
security: [
{
@ -319,6 +327,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
description: "Get single secret import",
security: [
{
@ -421,6 +431,8 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretImports],
querystring: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),

View File

@ -1,7 +1,7 @@
import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { SecretSyncs } from "@app/lib/api-docs";
import { ApiDocsTags, SecretSyncs } from "@app/lib/api-docs";
import { startsWithVowel } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -51,6 +51,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `List the ${destinationName} Syncs for the specified project.`,
querystring: z.object({
projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.LIST(destination).projectId)
@ -94,6 +96,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Get the specified ${destinationName} Sync by ID.`,
params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.GET_BY_ID(destination).syncId)
@ -134,6 +138,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Get the specified ${destinationName} Sync by name and project ID.`,
params: z.object({
syncName: z.string().trim().min(1, "Sync name required").describe(SecretSyncs.GET_BY_NAME(destination).syncName)
@ -182,6 +188,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Create ${
startsWithVowel(destinationName) ? "an" : "a"
} ${destinationName} Sync for the specified project environment.`,
@ -221,6 +229,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Update the specified ${destinationName} Sync.`,
params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.UPDATE(destination).syncId)
@ -263,6 +273,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Delete the specified ${destinationName} Sync.`,
params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.DELETE(destination).syncId)
@ -312,6 +324,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Trigger a sync for the specified ${destinationName} Sync.`,
params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.SYNC_SECRETS(destination).syncId)
@ -344,6 +358,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Import secrets from the specified ${destinationName} Sync destination.`,
params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.IMPORT_SECRETS(destination).syncId)
@ -382,6 +398,8 @@ export const registerSyncSecretsEndpoints = <T extends TSecretSync, I extends TS
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: `Remove previously synced secrets from the specified ${destinationName} Sync destination.`,
params: z.object({
syncId: z.string().uuid().describe(SecretSyncs.REMOVE_SECRETS(destination).syncId)

View File

@ -1,7 +1,7 @@
import { z } from "zod";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { SecretSyncs } from "@app/lib/api-docs";
import { ApiDocsTags, SecretSyncs } from "@app/lib/api-docs";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -65,6 +65,8 @@ export const registerSecretSyncRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: "List the available Secret Sync Options.",
response: {
200: z.object({
@ -86,6 +88,8 @@ export const registerSecretSyncRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SecretSyncs],
description: "List all the Secret Syncs for the specified project.",
querystring: z.object({
projectId: z.string().trim().min(1, "Project ID required").describe(SecretSyncs.LIST().projectId)

View File

@ -1,7 +1,7 @@
import { z } from "zod";
import { SecretTagsSchema } from "@app/db/schemas";
import { SECRET_TAGS } from "@app/lib/api-docs";
import { ApiDocsTags, SECRET_TAGS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -15,6 +15,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.LIST.projectId)
}),
@ -44,6 +46,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_ID.projectId),
tagId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_ID.tagId)
@ -75,6 +79,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_SLUG.projectId),
tagSlug: z.string().trim().describe(SECRET_TAGS.GET_TAG_BY_SLUG.tagSlug)
@ -107,6 +113,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.CREATE.projectId)
}),
@ -141,6 +149,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.UPDATE.projectId),
tagId: z.string().trim().describe(SECRET_TAGS.UPDATE.tagId)
@ -176,6 +186,8 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Folders],
params: z.object({
projectId: z.string().trim().describe(SECRET_TAGS.DELETE.projectId),
tagId: z.string().trim().describe(SECRET_TAGS.DELETE.tagId)

View File

@ -6,7 +6,7 @@ import {
ProjectMembershipRole,
ProjectUserMembershipRolesSchema
} from "@app/db/schemas";
import { PROJECTS } from "@app/lib/api-docs";
import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -22,6 +22,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Add group to project",
security: [
{
@ -88,6 +90,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
url: "/:projectId/groups/:groupId",
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Update group in project",
security: [
{
@ -147,6 +151,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Remove group from project",
security: [
{
@ -185,6 +191,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Return list of groups in project",
security: [
{
@ -243,6 +251,8 @@ export const registerGroupProjectRouter = async (server: FastifyZodProvider) =>
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectGroups],
description: "Return project group",
security: [
{

View File

@ -1,7 +1,7 @@
import { z } from "zod";
import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
import { ORGANIZATIONS } from "@app/lib/api-docs";
import { ApiDocsTags, ORGANIZATIONS } from "@app/lib/api-docs";
import { OrderByDirection } from "@app/lib/types";
import { readLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -17,6 +17,8 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Return organization identity memberships",
security: [
{

View File

@ -6,7 +6,7 @@ import {
ProjectMembershipRole,
ProjectUserMembershipRolesSchema
} from "@app/db/schemas";
import { ORGANIZATIONS, PROJECT_IDENTITIES } from "@app/lib/api-docs";
import { ApiDocsTags, ORGANIZATIONS, PROJECT_IDENTITIES } from "@app/lib/api-docs";
import { BadRequestError } from "@app/lib/errors";
import { ms } from "@app/lib/ms";
import { OrderByDirection } from "@app/lib/types";
@ -27,6 +27,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Create project identity membership",
security: [
{
@ -101,6 +103,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Update project identity memberships",
security: [
{
@ -170,6 +174,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Delete project identity memberships",
security: [
{
@ -207,6 +213,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Return project identity memberships",
security: [
{
@ -300,6 +308,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
description: "Return project identity membership",
security: [
{
@ -360,6 +370,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.ProjectIdentities],
params: z.object({
identityMembershipId: z.string().trim()
}),

View File

@ -8,7 +8,7 @@ import {
UserEncryptionKeysSchema,
UsersSchema
} from "@app/db/schemas";
import { ORGANIZATIONS } from "@app/lib/api-docs";
import { ApiDocsTags, ORGANIZATIONS } from "@app/lib/api-docs";
import { getConfig } from "@app/lib/config/env";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { GenericResourceNameSchema } from "@app/server/lib/schemas";
@ -24,6 +24,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Return organization user memberships",
security: [
{
@ -72,6 +74,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Return projects in organization that user is apart of",
security: [
{
@ -179,6 +183,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Update organization user memberships",
security: [
{
@ -229,6 +235,8 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Organizations],
description: "Delete organization user memberships",
security: [
{

View File

@ -2,7 +2,7 @@ import { z } from "zod";
import { OrgMembershipRole, ProjectMembershipRole, ProjectMembershipsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { PROJECT_USERS } from "@app/lib/api-docs";
import { ApiDocsTags, PROJECT_USERS } from "@app/lib/api-docs";
import { writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -15,6 +15,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Invite members to project",
security: [
{
@ -78,6 +80,8 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.ProjectUsers],
description: "Remove members from project",
security: [
{

View File

@ -14,7 +14,7 @@ import { sanitizedSshCa } from "@app/ee/services/ssh/ssh-certificate-authority-s
import { sanitizedSshCertificate } from "@app/ee/services/ssh-certificate/ssh-certificate-schema";
import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema";
import { loginMappingSchema, sanitizedSshHost } from "@app/ee/services/ssh-host/ssh-host-schema";
import { PROJECTS } from "@app/lib/api-docs";
import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
@ -29,7 +29,8 @@ import { SanitizedProjectSchema } from "../sanitizedSchemas";
const projectWithEnv = SanitizedProjectSchema.extend({
_id: z.string(),
environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array()
environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array(),
kmsSecretManagerKeyId: z.string().nullable().optional()
});
export const registerProjectRouter = async (server: FastifyZodProvider) => {
@ -150,6 +151,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Create a new project",
security: [
{
@ -224,6 +227,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Projects],
description: "Delete project",
security: [
{
@ -342,6 +347,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateAuthorities],
params: z.object({
slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CAS.slug)
}),
@ -383,6 +390,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
params: z.object({
slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CERTIFICATES.slug)
}),
@ -551,6 +560,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateTemplates],
params: z.object({
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CERTIFICATE_TEMPLATES.projectId)
}),
@ -581,6 +592,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.SshCertificateAuthorities],
params: z.object({
projectId: z.string().trim().describe(PROJECTS.LIST_SSH_CAS.projectId)
}),

View File

@ -2,6 +2,7 @@ import { z } from "zod";
import { ServiceTokensSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApiDocsTags } from "@app/lib/api-docs";
import { removeTrailingSlash } from "@app/lib/fn";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@ -25,6 +26,8 @@ export const registerServiceTokenRouter = async (server: FastifyZodProvider) =>
},
onRequest: verifyAuth([AuthMode.SERVICE_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.ServiceTokens],
description: "Return Infisical Token data",
security: [
{

View File

@ -3,7 +3,7 @@ import { z } from "zod";
import { SecretApprovalRequestsSchema, SecretsSchema, SecretType, ServiceTokenScopes } from "@app/db/schemas";
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
import { RAW_SECRETS, SECRETS } from "@app/lib/api-docs";
import { ApiDocsTags, RAW_SECRETS, SECRETS } from "@app/lib/api-docs";
import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { removeTrailingSlash } from "@app/lib/fn";
import { secretsLimit, writeLimit } from "@app/server/config/rateLimiter";
@ -48,6 +48,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Attach tags to a secret",
security: [
{
@ -103,6 +105,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Detach tags from a secret",
security: [
{
@ -158,6 +162,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "List secrets",
security: [
{
@ -355,6 +361,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
params: z.object({
secretId: z.string()
}),
@ -390,6 +398,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Get a secret by name",
security: [
{
@ -496,6 +506,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Create secret",
security: [
{
@ -609,6 +621,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Update secret",
security: [
{
@ -729,6 +743,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Delete secret",
security: [
{
@ -1486,6 +1502,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
body: z.object({
projectSlug: z.string().trim(),
sourceEnvironment: z.string().trim(),
@ -1911,6 +1929,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Create many secrets",
security: [
{
@ -2017,6 +2037,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Update many secrets",
security: [
{
@ -2170,6 +2192,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Delete many secrets",
security: [
{
@ -2266,6 +2290,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
rateLimit: secretsLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.Secrets],
description: "Get secret reference tree",
security: [
{

View File

@ -77,20 +77,22 @@ export const getSqlConnectionClient = async (appConnection: Pick<TSqlConnection,
export const validateSqlConnectionCredentials = async (config: TSqlConnectionConfig) => {
const { credentials, app } = config;
const client = await getSqlConnectionClient({ app, credentials });
let client: Knex | undefined;
try {
client = await getSqlConnectionClient({ app, credentials });
await client.raw(`Select 1`);
return credentials;
} catch (error) {
throw new BadRequestError({
message:
(error as Error)?.message?.replaceAll(credentials.password, "********************") ??
"Unable to validate connection: verify credentials"
message: `Unable to validate connection: ${
(error as Error)?.message?.replaceAll(credentials.password, "********************") ?? "verify credentials"
}`
});
} finally {
await client.destroy();
await client?.destroy();
}
};

View File

@ -1,3 +1,5 @@
import RE2 from "re2";
import { TCertificateTemplates } from "@app/db/schemas";
import { BadRequestError } from "@app/lib/errors";
import { ms } from "@app/lib/ms";
@ -12,7 +14,7 @@ export const validateCertificateDetailsAgainstTemplate = (
template: TCertificateTemplates
) => {
// these are validated in router using validateTemplateRegexField
const commonNameRegex = new RegExp(template.commonName);
const commonNameRegex = new RE2(template.commonName);
if (!commonNameRegex.test(cert.commonName)) {
throw new BadRequestError({
message: "Invalid common name based on template policy"
@ -25,7 +27,7 @@ export const validateCertificateDetailsAgainstTemplate = (
});
}
const subjectAlternativeNameRegex = new RegExp(template.subjectAlternativeName);
const subjectAlternativeNameRegex = new RE2(template.subjectAlternativeName);
cert.altNames.forEach((altName) => {
if (!subjectAlternativeNameRegex.test(altName)) {
throw new BadRequestError({

View File

@ -2,6 +2,7 @@
import { ForbiddenError } from "@casl/ability";
import axios from "axios";
import jwt from "jsonwebtoken";
import RE2 from "re2";
import { IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
@ -67,6 +68,15 @@ const awsRegionFromHeader = (authorizationHeader: string): string | null => {
return null;
};
function isValidAwsRegion(region: string | null): boolean {
const validRegionPattern = new RE2("^[a-z0-9-]+$");
if (typeof region !== "string" || region.length === 0 || region.length > 20) {
return false;
}
return validRegionPattern.test(region);
}
export const identityAwsAuthServiceFactory = ({
identityAccessTokenDAL,
identityAwsAuthDAL,
@ -84,8 +94,12 @@ export const identityAwsAuthServiceFactory = ({
const headers: TAwsGetCallerIdentityHeaders = JSON.parse(Buffer.from(iamRequestHeaders, "base64").toString());
const body: string = Buffer.from(iamRequestBody, "base64").toString();
const region = headers.Authorization ? awsRegionFromHeader(headers.Authorization) : null;
if (!isValidAwsRegion(region)) {
throw new BadRequestError({ message: "Invalid AWS region" });
}
const url = region ? `https://sts.${region}.amazonaws.com` : identityAwsAuth.stsEndpoint;
const {
@ -125,7 +139,7 @@ export const identityAwsAuthServiceFactory = ({
// convert wildcard ARN to a regular expression: "arn:aws:iam::123456789012:*" -> "^arn:aws:iam::123456789012:.*$"
// considers exact matches + wildcard matches
// heavily validated in router
const regex = new RegExp(`^${principalArn.replaceAll("*", ".*")}$`);
const regex = new RE2(`^${principalArn.replaceAll("*", ".*")}$`);
return regex.test(extractPrincipalArn(Arn));
});

View File

@ -1,9 +1,10 @@
import RE2 from "re2";
import safe from "safe-regex";
import { z } from "zod";
const twelveDigitRegex = /^\d{12}$/;
const twelveDigitRegex = new RE2(/^\d{12}$/);
// akhilmhdh: change this to a normal function later. Checked no redosable at the moment
const arnRegex = /^arn:aws:iam::\d{12}:(user\/[a-zA-Z0-9_.@+*/-]+|role\/[a-zA-Z0-9_.@+*/-]+|\*)$/;
const arnRegex = new RE2(/^arn:aws:iam::\d{12}:(user\/[a-zA-Z0-9_.@+*/-]+|role\/[a-zA-Z0-9_.@+*/-]+|\*)$/);
export const validateAccountIds = z
.string()

View File

@ -435,12 +435,16 @@ export const identityKubernetesAuthServiceFactory = ({
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
if (!identityKubernetesAuth) {
throw new NotFoundError({ message: `Failed to find Kubernetes Auth for identity with ID ${identityId}` });
}
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
throw new BadRequestError({
message: "The identity does not have Kubernetes Auth attached"
});
}
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
const { permission } = await permissionService.getOrgPermission(
actor,

View File

@ -50,7 +50,7 @@ const getIntegrationSecretsV2 = async (
}
// process secrets in current folder
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId, projectId: dto.projectId });
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId });
secrets.forEach((secret) => {
const secretKey = secret.key;
@ -63,7 +63,6 @@ const getIntegrationSecretsV2 = async (
// if no imports then return secrets in the current folder
if (!secretImports.length) return content;
const importedSecrets = await fnSecretsV2FromImports({
projectId: dto.projectId,
decryptor: dto.decryptor,
folderDAL,
secretDAL: secretV2BridgeDAL,

View File

@ -27,6 +27,7 @@ import { randomUUID } from "crypto";
import https from "https";
import sodium from "libsodium-wrappers";
import isEqual from "lodash.isequal";
import RE2 from "re2";
import { z } from "zod";
import { SecretType, TIntegrationAuths, TIntegrations } from "@app/db/schemas";
@ -4151,7 +4152,7 @@ const syncSecretsWindmill = async ({
);
// eslint-disable-next-line
const pattern = new RegExp("^(u/|f/)[a-zA-Z0-9_-]+/([a-zA-Z0-9_-]+/)*[a-zA-Z0-9_-]*[^/]$");
const pattern = new RE2("^(u/|f/)[a-zA-Z0-9_-]+/([a-zA-Z0-9_-]+/)*[a-zA-Z0-9_-]*[^/]$");
for await (const key of Object.keys(secrets)) {
if ((key.startsWith("u/") || key.startsWith("f/")) && pattern.test(key)) {
if (!(key in res)) {

View File

@ -110,8 +110,8 @@ type TOrgServiceFactoryDep = {
projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "delete" | "insertMany" | "findLatestProjectKey" | "create">;
orgMembershipDAL: Pick<TOrgMembershipDALFactory, "findOrgMembershipById" | "findOne" | "findById">;
incidentContactDAL: TIncidentContactsDALFactory;
samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne" | "findEnforceableSamlCfg">;
oidcConfigDAL: Pick<TOidcConfigDALFactory, "findOne" | "findEnforceableOidcCfg">;
samlConfigDAL: Pick<TSamlConfigDALFactory, "findOne">;
oidcConfigDAL: Pick<TOidcConfigDALFactory, "findOne">;
smtpService: TSmtpService;
tokenService: TAuthTokenServiceFactory;
permissionService: TPermissionServiceFactory;
@ -403,13 +403,33 @@ export const orgServiceFactory = ({
}
if (authEnforced) {
const samlCfg = await samlConfigDAL.findEnforceableSamlCfg(orgId);
const oidcCfg = await oidcConfigDAL.findEnforceableOidcCfg(orgId);
const samlCfg = await samlConfigDAL.findOne({
orgId,
isActive: true
});
const oidcCfg = await oidcConfigDAL.findOne({
orgId,
isActive: true
});
if (!samlCfg && !oidcCfg)
throw new NotFoundError({
message: `SAML or OIDC configuration for organization with ID '${orgId}' not found`
});
if (samlCfg && !samlCfg.lastUsed) {
throw new BadRequestError({
message:
"To apply the new SAML auth enforcement, please log in via SAML at least once. This step is required to enforce SAML-based authentication."
});
}
if (oidcCfg && !oidcCfg.lastUsed) {
throw new BadRequestError({
message:
"To apply the new OIDC auth enforcement, please log in via OIDC at least once. This step is required to enforce OIDC-based authentication."
});
}
}
let defaultMembershipRole: string | undefined;

View File

@ -159,8 +159,7 @@ export const fnSecretsV2FromImports = async ({
decryptor,
expandSecretReferences,
hasSecretAccess,
viewSecretValue,
projectId
viewSecretValue
}: {
secretImports: (Omit<TSecretImports, "importEnv"> & {
importEnv: { id: string; slug: string; name: string };
@ -177,7 +176,6 @@ export const fnSecretsV2FromImports = async ({
environment: string;
}) => Promise<string | undefined>;
hasSecretAccess: (environment: string, secretPath: string, secretName: string, secretTagSlugs: string[]) => boolean;
projectId: string;
}) => {
const cyclicDetector = new Set();
const stack: {
@ -209,7 +207,10 @@ export const fnSecretsV2FromImports = async ({
);
if (!importedFolders.length) continue;
const importedFolderIds = importedFolders.map((el) => el?.id) as string[];
const importedFolderIds = importedFolders.filter(Boolean).map((el) => el?.id) as string[];
if (!importedFolderIds.length) continue;
const importedFolderGroupBySourceImport = groupBy(importedFolders, (i) => `${i?.envId}-${i?.path}`);
const importedSecrets = await secretDAL.find(
@ -218,8 +219,7 @@ export const fnSecretsV2FromImports = async ({
type: SecretType.Shared
},
{
sort: [["id", "asc"]],
useCache: { projectId }
sort: [["id", "asc"]]
}
);
const importedSecretsGroupByFolderId = groupBy(importedSecrets, (i) => i.folderId);

View File

@ -698,7 +698,6 @@ export const secretImportServiceFactory = ({
projectId
});
const importedSecrets = await fnSecretsV2FromImports({
projectId,
secretImports,
folderDAL,
viewSecretValue: true,

View File

@ -214,7 +214,7 @@ export const secretSyncQueueFactory = ({
canExpandValue: () => true
});
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId, projectId });
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId });
await Promise.allSettled(
secrets.map(async (secret) => {
@ -244,7 +244,6 @@ export const secretSyncQueueFactory = ({
if (secretImports.length) {
const importedSecrets = await fnSecretsV2FromImports({
projectId,
decryptor: decryptSecretValue,
folderDAL,
secretDAL: secretV2BridgeDAL,

View File

@ -1,3 +1,4 @@
import { MongoAbility } from "@casl/ability";
import { Knex } from "knex";
import { validate as uuidValidate } from "uuid";
@ -15,46 +16,29 @@ import {
TFindFilter,
TFindOpt
} from "@app/lib/knex";
import { BufferKeysToString, OrderByDirection } from "@app/lib/types";
import { OrderByDirection } from "@app/lib/types";
import { SecretsOrderBy } from "@app/services/secret/secret-types";
import type { TFindSecretsByFolderIdsFilter } from "@app/services/secret-v2-bridge/secret-v2-bridge-types";
import type {
TFindSecretsByFolderIdsFilter,
TGetSecretsDTO
} from "@app/services/secret-v2-bridge/secret-v2-bridge-types";
export const SecretDalCacheKeys = {
export const SecretServiceCacheKeys = {
get productKey() {
const { INFISICAL_PLATFORM_VERSION } = getConfig();
return `${ProjectType.SecretManager}:${INFISICAL_PLATFORM_VERSION || 0}`;
},
getSecretDalVersion: (projectId: string) => {
return `${SecretDalCacheKeys.productKey}:${projectId}:${TableName.SecretV2}-dal-version`;
return `${SecretServiceCacheKeys.productKey}:${projectId}:${TableName.SecretV2}-dal-version`;
},
findByFolderIds: (
getSecretsOfServiceLayer: (
projectId: string,
version: number,
{ useCache, tx, ...cacheKey }: Parameters<TSecretV2BridgeDALFactory["findByFolderIds"]>[0]
dto: TGetSecretsDTO & { permissionRules: MongoAbility["rules"] }
) => {
return `${SecretDalCacheKeys.productKey}:${projectId}:${
return `${SecretServiceCacheKeys.productKey}:${projectId}:${
TableName.SecretV2
}-dal:v${version}:find-by-folder-ids:${generateCacheKeyFromData(cacheKey)}`;
},
findByFolderId: (
projectId: string,
version: number,
{ useCache, tx, ...cacheKey }: Parameters<TSecretV2BridgeDALFactory["findByFolderId"]>[0]
) => {
return `${SecretDalCacheKeys.productKey}:${projectId}:${
TableName.SecretV2
}-dal:v${version}:find-by-folder-id:${generateCacheKeyFromData(cacheKey)}`;
},
find: (projectId: string, version: number, ...args: Parameters<TSecretV2BridgeDALFactory["find"]>) => {
const [filter, opts] = args;
delete opts?.tx;
delete opts?.useCache;
return `${SecretDalCacheKeys.productKey}:${projectId}:${
TableName.SecretV2
}-dal:v${version}:find:${generateCacheKeyFromData({
filter,
opts
})}`;
}-dal:v${version}:get-secrets-service-layer:${dto.actorId}-${generateCacheKeyFromData(dto)}`;
}
};
@ -64,14 +48,14 @@ interface TSecretV2DalArg {
keyStore: TKeyStoreFactory;
}
const SECRET_DAL_TTL = 5 * 60;
const SECRET_DAL_VERSION_TTL = 15 * 60;
const MAX_SECRET_CACHE_BYTES = 25 * 1024 * 1024;
export const SECRET_DAL_TTL = 5 * 60;
export const SECRET_DAL_VERSION_TTL = 15 * 60;
export const MAX_SECRET_CACHE_BYTES = 25 * 1024 * 1024;
export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
const secretOrm = ormify(db, TableName.SecretV2);
const invalidateSecretCacheByProjectId = async (projectId: string) => {
const secretDalVersionKey = SecretDalCacheKeys.getSecretDalVersion(projectId);
const secretDalVersionKey = SecretServiceCacheKeys.getSecretDalVersion(projectId);
await keyStore.incrementBy(secretDalVersionKey, 1);
await keyStore.setExpiry(secretDalVersionKey, SECRET_DAL_VERSION_TTL);
};
@ -128,35 +112,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
}
};
const find = async (
filter: TFindFilter<TSecretsV2>,
opts: TFindOpt<TSecretsV2> & { useCache?: { projectId: string } } = {}
) => {
const { offset, limit, sort, tx, useCache } = opts;
const find = async (filter: TFindFilter<TSecretsV2>, opts: TFindOpt<TSecretsV2> = {}) => {
const { offset, limit, sort, tx } = opts;
try {
let secretDalVersion = 0;
if (useCache) {
const cachedSecretDalVersion = await keyStore.getItem(
SecretDalCacheKeys.getSecretDalVersion(useCache.projectId)
);
secretDalVersion = Number(cachedSecretDalVersion || 0);
const cacheKey = SecretDalCacheKeys.find(useCache.projectId, secretDalVersion, filter, opts);
const cachedSecrets = await keyStore.getItem(cacheKey);
if (cachedSecrets) {
await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL);
const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[];
const sanitizedSecrets = unsanitizedSecrets.map((el) => {
const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null;
const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null;
const createdAt = new Date(el.createdAt);
const updatedAt = new Date(el.updatedAt);
return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt };
});
return sanitizedSecrets;
}
}
const query = (tx || db)(TableName.SecretV2)
// eslint-disable-next-line @typescript-eslint/no-misused-promises
.where(buildFindFilter(filter))
@ -225,22 +183,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
]
});
if (useCache) {
const cachedSecrets = data.map((el) => {
const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null;
const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null;
return { ...el, encryptedValue, encryptedComment };
});
const cache = JSON.stringify(cachedSecrets);
if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(
SecretDalCacheKeys.find(useCache.projectId, secretDalVersion, filter, opts),
SECRET_DAL_TTL,
cache
);
}
}
return data;
} catch (error) {
throw new DatabaseError({ error, name: `${TableName.SecretV2}: Find` });
@ -345,15 +287,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
}
};
const findByFolderId = async (dto: {
folderId: string;
userId?: string;
tx?: Knex;
projectId: string;
useCache?: boolean;
}) => {
const findByFolderId = async (dto: { folderId: string; userId?: string; tx?: Knex }) => {
try {
const { folderId, tx, projectId } = dto;
const { folderId, tx } = dto;
let { userId } = dto;
// check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo
if (userId && !uuidValidate(userId)) {
@ -361,27 +297,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
userId = undefined;
}
const cachedSecretDalVersion = await keyStore.getItem(SecretDalCacheKeys.getSecretDalVersion(projectId));
const secretDalVersion = Number(cachedSecretDalVersion || 0);
if (dto.useCache) {
const cacheKey = SecretDalCacheKeys.findByFolderId(projectId, secretDalVersion, dto);
const cachedSecrets = await keyStore.getItem(cacheKey);
if (cachedSecrets) {
await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL);
const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[];
const sanitizedSecrets = unsanitizedSecrets.map((el) => {
const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null;
const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null;
const createdAt = new Date(el.createdAt);
const updatedAt = new Date(el.updatedAt);
return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt };
});
return sanitizedSecrets;
}
}
const secs = await (tx || db.replicaNode())(TableName.SecretV2)
.where({ folderId })
.where((bd) => {
@ -437,22 +352,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
}
]
});
if (dto.useCache) {
const newCachedSecrets = data.map((el) => {
const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null;
const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null;
return { ...el, encryptedValue, encryptedComment };
});
const cache = JSON.stringify(newCachedSecrets);
if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(
SecretDalCacheKeys.findByFolderId(projectId, secretDalVersion, dto),
SECRET_DAL_TTL,
cache
);
}
}
return data;
} catch (error) {
throw new DatabaseError({ error, name: "get all secret" });
@ -542,11 +441,9 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
folderIds: string[];
userId?: string;
tx?: Knex;
projectId: string;
filters?: TFindSecretsByFolderIdsFilter;
useCache?: boolean;
}) => {
const { folderIds, tx, filters, useCache, projectId } = dto;
const { folderIds, tx, filters } = dto;
let { userId } = dto;
try {
// check if not uui then userId id is null (corner case because service token's ID is not UUI in effort to keep backwards compatibility from mongo)
@ -555,26 +452,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
userId = undefined;
}
const cachedSecretDalVersion = await keyStore.getItem(SecretDalCacheKeys.getSecretDalVersion(projectId));
const secretDalVersion = Number(cachedSecretDalVersion || 0);
if (useCache) {
const cacheKey = SecretDalCacheKeys.findByFolderIds(projectId, secretDalVersion, dto);
const cachedSecrets = await keyStore.getItem(cacheKey);
if (cachedSecrets) {
await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL);
const unsanitizedSecrets = JSON.parse(cachedSecrets) as BufferKeysToString<(typeof data)[number]>[];
const sanitizedSecrets = unsanitizedSecrets.map((el) => {
const encryptedValue = el.encryptedValue ? Buffer.from(el.encryptedValue, "base64") : null;
const encryptedComment = el.encryptedComment ? Buffer.from(el.encryptedComment, "base64") : null;
const createdAt = new Date(el.createdAt);
const updatedAt = new Date(el.updatedAt);
return { ...el, encryptedComment, encryptedValue, createdAt, updatedAt };
});
return sanitizedSecrets;
}
}
const query = (tx || db.replicaNode())(TableName.SecretV2)
.whereIn(`${TableName.SecretV2}.folderId`, folderIds)
.where((bd) => {
@ -700,22 +577,6 @@ export const secretV2BridgeDALFactory = ({ db, keyStore }: TSecretV2DalArg) => {
}
]
});
if (useCache) {
const cachedSecrets = data.map((el) => {
const encryptedValue = el.encryptedValue ? el.encryptedValue.toString("base64") : null;
const encryptedComment = el.encryptedComment ? el.encryptedComment.toString("base64") : null;
return { ...el, encryptedValue, encryptedComment };
});
const cache = JSON.stringify(cachedSecrets);
if (Buffer.byteLength(cache, "utf8") < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(
SecretDalCacheKeys.findByFolderIds(projectId, secretDalVersion, dto),
SECRET_DAL_TTL,
cache
);
}
}
return data;
} catch (error) {

View File

@ -1,5 +1,7 @@
import path from "node:path";
import RE2 from "re2";
import { TableName, TSecretFolders, TSecretsV2 } from "@app/db/schemas";
import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { groupBy } from "@app/lib/fn";
@ -13,9 +15,8 @@ import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal";
import { TFnSecretBulkDelete, TFnSecretBulkInsert, TFnSecretBulkUpdate } from "./secret-v2-bridge-types";
const INTERPOLATION_SYNTAX_REG = /\${([a-zA-Z0-9-_.]+)}/g;
// akhilmhdh: JS regex with global save state in .test
const INTERPOLATION_SYNTAX_REG_NON_GLOBAL = /\${([a-zA-Z0-9-_.]+)}/;
const INTERPOLATION_PATTERN_STRING = String.raw`\${([a-zA-Z0-9-_.]+)}`;
const INTERPOLATION_TEST_REGEX = new RE2(INTERPOLATION_PATTERN_STRING);
export const shouldUseSecretV2Bridge = (version: number) => version === 3;
@ -36,7 +37,14 @@ export const shouldUseSecretV2Bridge = (version: number) => version === 3;
* // ]
*/
export const getAllSecretReferences = (maybeSecretReference: string) => {
const references = Array.from(maybeSecretReference.matchAll(INTERPOLATION_SYNTAX_REG), (m) => m[1]);
const references = [];
let match;
const regex = new RE2(INTERPOLATION_PATTERN_STRING, "g");
// eslint-disable-next-line no-cond-assign
while ((match = regex.exec(maybeSecretReference)) !== null) {
references.push(match[1]);
}
const nestedReferences = references
.filter((el) => el.includes("."))
@ -501,7 +509,7 @@ export const expandSecretReferencesFactory = ({
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
if (!folder) return { value: "", tags: [] };
const secrets = await secretDAL.findByFolderId({ folderId: folder.id, projectId, useCache: true });
const secrets = await secretDAL.findByFolderId({ folderId: folder.id });
const decryptedSecret = secrets.reduce<Record<string, { value: string; tags: string[] }>>((prev, secret) => {
// eslint-disable-next-line no-param-reassign
@ -531,9 +539,17 @@ export const expandSecretReferencesFactory = ({
// eslint-disable-next-line no-continue
if (depth > MAX_SECRET_REFERENCE_DEPTH) continue;
const refs = value?.match(INTERPOLATION_SYNTAX_REG);
if (refs) {
const matchRegex = new RE2(INTERPOLATION_PATTERN_STRING, "g");
const refs = [];
let match;
// eslint-disable-next-line no-cond-assign
while ((match = matchRegex.exec(value || "")) !== null) {
refs.push(match[0]);
}
if (refs.length > 0) {
for (const interpolationSyntax of refs) {
const interpolationKey = interpolationSyntax.slice(2, interpolationSyntax.length - 1);
const entities = interpolationKey.trim().split(".");
@ -592,7 +608,7 @@ export const expandSecretReferencesFactory = ({
trace
};
const shouldExpandMore = INTERPOLATION_SYNTAX_REG_NON_GLOBAL.test(referencedSecretValue);
const shouldExpandMore = INTERPOLATION_TEST_REGEX.test(referencedSecretValue);
if (dto.shouldStackTrace) {
const stackTraceNode = { ...node, children: [], key: referencedSecretKey, trace: null };
trace?.children.push(stackTraceNode);
@ -626,7 +642,7 @@ export const expandSecretReferencesFactory = ({
}) => {
if (!inputSecret.value) return inputSecret.value;
const shouldExpand = Boolean(inputSecret.value?.match(INTERPOLATION_SYNTAX_REG));
const shouldExpand = INTERPOLATION_TEST_REGEX.test(inputSecret.value);
if (!shouldExpand) return inputSecret.value;
const { expandedValue } = await recursivelyExpandSecret(inputSecret);

View File

@ -25,6 +25,7 @@ import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-app
import { TSecretApprovalRequestDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-dal";
import { TSecretApprovalRequestSecretDALFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-secret-dal";
import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/secret-snapshot-service";
import { TKeyStoreFactory } from "@app/keystore/keystore";
import { DatabaseErrorCode } from "@app/lib/error-codes";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { diff, groupBy } from "@app/lib/fn";
@ -43,7 +44,12 @@ import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns";
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal";
import {
MAX_SECRET_CACHE_BYTES,
SECRET_DAL_TTL,
SecretServiceCacheKeys,
TSecretV2BridgeDALFactory
} from "./secret-v2-bridge-dal";
import {
buildHierarchy,
expandSecretReferencesFactory,
@ -105,6 +111,7 @@ type TSecretV2BridgeServiceFactoryDep = {
>;
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
keyStore: Pick<TKeyStoreFactory, "getItem" | "setExpiry" | "setItemWithExpiry" | "deleteItem">;
};
export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>;
@ -127,7 +134,8 @@ export const secretV2BridgeServiceFactory = ({
secretApprovalRequestDAL,
secretApprovalRequestSecretDAL,
kmsService,
resourceMetadataDAL
resourceMetadataDAL,
keyStore
}: TSecretV2BridgeServiceFactoryDep) => {
const $validateSecretReferences = async (
projectId: string,
@ -800,12 +808,10 @@ export const secretV2BridgeServiceFactory = ({
const groupedFolderMappings = groupBy(folderMappings, (folderMapping) => folderMapping.folderId);
const secrets = await secretDAL.findByFolderIds({
projectId,
folderIds: folderMappings.map((folderMapping) => folderMapping.folderId),
userId,
tx: undefined,
filters,
useCache: true
filters
});
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
@ -909,21 +915,22 @@ export const secretV2BridgeServiceFactory = ({
return decryptedSecrets;
};
const getSecrets = async ({
actorId,
path,
environment,
projectId,
actor,
actorOrgId,
viewSecretValue,
actorAuthMethod,
includeImports,
recursive,
expandSecretReferences: shouldExpandSecretReferences,
throwOnMissingReadValuePermission = true,
...params
}: TGetSecretsDTO) => {
const getSecrets = async (dto: TGetSecretsDTO) => {
const {
actorId,
path,
environment,
projectId,
actor,
actorOrgId,
viewSecretValue,
actorAuthMethod,
includeImports,
recursive,
expandSecretReferences: shouldExpandSecretReferences,
throwOnMissingReadValuePermission = true,
...params
} = dto;
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
@ -934,6 +941,42 @@ export const secretV2BridgeServiceFactory = ({
});
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret);
const cachedSecretDalVersion = await keyStore.getItem(SecretServiceCacheKeys.getSecretDalVersion(projectId));
const secretDalVersion = Number(cachedSecretDalVersion || 0);
const cacheKey = SecretServiceCacheKeys.getSecretsOfServiceLayer(projectId, secretDalVersion, {
...dto,
permissionRules: permission.rules
});
const { decryptor: secretManagerDecryptor, encryptor: secretManagerEncryptor } =
await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.SecretManager,
projectId
});
const encryptedCachedSecrets = await keyStore.getItem(cacheKey);
if (encryptedCachedSecrets) {
try {
await keyStore.setExpiry(cacheKey, SECRET_DAL_TTL);
const cachedSecrets = secretManagerDecryptor({ cipherTextBlob: Buffer.from(encryptedCachedSecrets, "base64") });
const { secrets, imports = [] } = JSON.parse(cachedSecrets.toString("utf8")) as {
secrets: typeof decryptedSecrets;
imports: typeof importedSecrets;
};
return {
secrets: secrets.map((el) => ({
...el,
createdAt: new Date(el.createdAt),
updatedAt: new Date(el.updatedAt)
})),
imports
};
} catch (err) {
logger.error(err, "Secret service layer cache miss");
await keyStore.deleteItem(cacheKey);
}
}
let paths: { folderId: string; path: string }[] = [];
if (recursive) {
@ -958,17 +1001,10 @@ export const secretV2BridgeServiceFactory = ({
const groupedPaths = groupBy(paths, (p) => p.folderId);
const secrets = await secretDAL.findByFolderIds({
projectId,
folderIds: paths.map((p) => p.folderId),
userId: actorId,
tx: undefined,
filters: params,
useCache: true
});
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.SecretManager,
projectId
filters: params
});
// scott: if any of this changes it also needs to be mirrored in secret rotation for getting dashboard secrets
@ -1086,15 +1122,19 @@ export const secretV2BridgeServiceFactory = ({
}
if (!includeImports) {
return {
secrets: decryptedSecrets
};
const payload = { secrets: decryptedSecrets, imports: [] };
const encryptedUpdatedCachedSecrets = secretManagerEncryptor({
plainText: Buffer.from(JSON.stringify(payload))
}).cipherTextBlob;
if (encryptedUpdatedCachedSecrets.byteLength < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(cacheKey, SECRET_DAL_TTL, encryptedUpdatedCachedSecrets.toString("base64"));
}
return payload;
}
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
const allowedImports = secretImports.filter(({ isReplication }) => !isReplication);
const importedSecrets = await fnSecretsV2FromImports({
projectId,
viewSecretValue,
secretImports: allowedImports,
secretDAL,
@ -1129,10 +1169,14 @@ export const secretV2BridgeServiceFactory = ({
}
});
return {
secrets: decryptedSecrets,
imports: importedSecrets
};
const payload = { secrets: decryptedSecrets, imports: importedSecrets };
const encryptedUpdatedCachedSecrets = secretManagerEncryptor({
plainText: Buffer.from(JSON.stringify(payload))
}).cipherTextBlob;
if (encryptedUpdatedCachedSecrets.byteLength < MAX_SECRET_CACHE_BYTES) {
await keyStore.setItemWithExpiry(cacheKey, SECRET_DAL_TTL, encryptedUpdatedCachedSecrets.toString("base64"));
}
return payload;
};
const getSecretById = async ({ actorId, actor, actorOrgId, actorAuthMethod, secretId }: TGetASecretByIdDTO) => {
@ -1312,7 +1356,6 @@ export const secretV2BridgeServiceFactory = ({
if (!secret && includeImports) {
const secretImports = await secretImportDAL.find({ folderId, isReplication: false });
const importedSecrets = await fnSecretsV2FromImports({
projectId,
secretImports,
viewSecretValue,
secretDAL,
@ -2729,7 +2772,7 @@ export const secretV2BridgeServiceFactory = ({
generatePaths(folderMap).map(({ folderId, path }) => [folderId, path === "/" ? path : path.substring(1)])
);
const secrets = await secretDAL.findByFolderIds({ folderIds: folders.map((f) => f.id), projectId, useCache: true });
const secrets = await secretDAL.findByFolderIds({ folderIds: folders.map((f) => f.id) });
const { decryptor: secretManagerDecryptor } = await kmsService.createCipherPairWithDataKey({
type: KmsDataKey.SecretManager,

View File

@ -1,5 +1,6 @@
/* eslint-disable no-await-in-loop */
import path from "path";
import RE2 from "re2";
import {
ActionProjectType,
@ -218,7 +219,9 @@ type TInterpolateSecretArg = {
};
const MAX_SECRET_REFERENCE_DEPTH = 5;
const INTERPOLATION_SYNTAX_REG = /\${([a-zA-Z0-9-_.]+)}/g;
const INTERPOLATION_PATTERN_STRING = String.raw`\${([a-zA-Z0-9-_.]+)}`;
const INTERPOLATION_TEST_REGEX = new RE2(INTERPOLATION_PATTERN_STRING);
export const interpolateSecrets = ({ projectId, secretEncKey, secretDAL, folderDAL }: TInterpolateSecretArg) => {
const secretCache: Record<string, Record<string, string>> = {};
const getCacheUniqueKey = (environment: string, secretPath: string) => `${environment}-${secretPath}`;
@ -273,9 +276,17 @@ export const interpolateSecrets = ({ projectId, secretEncKey, secretDAL, folderD
if (!value) return "";
if (depth > MAX_SECRET_REFERENCE_DEPTH) return "";
const refs = value.match(INTERPOLATION_SYNTAX_REG);
const refs = [];
let match;
const execRegex = new RE2(INTERPOLATION_PATTERN_STRING, "g");
// eslint-disable-next-line no-cond-assign
while ((match = execRegex.exec(value)) !== null) {
refs.push(match[0]);
}
let expandedValue = value;
if (refs) {
if (refs.length > 0) {
for (const interpolationSyntax of refs) {
const interpolationKey = interpolationSyntax.slice(2, interpolationSyntax.length - 1);
const entities = interpolationKey.trim().split(".");
@ -284,7 +295,7 @@ export const interpolateSecrets = ({ projectId, secretEncKey, secretDAL, folderD
const [secretKey] = entities;
// eslint-disable-next-line
let referenceValue = await fetchSecret(environment, secretPath, secretKey);
if (INTERPOLATION_SYNTAX_REG.test(referenceValue)) {
if (INTERPOLATION_TEST_REGEX.test(referenceValue)) {
// eslint-disable-next-line
referenceValue = await recursivelyExpandSecret({
environment,
@ -305,7 +316,7 @@ export const interpolateSecrets = ({ projectId, secretEncKey, secretDAL, folderD
// eslint-disable-next-line
let referenceValue = await fetchSecret(secretReferenceEnvironment, secretReferencePath, secretReferenceKey);
if (INTERPOLATION_SYNTAX_REG.test(referenceValue)) {
if (INTERPOLATION_TEST_REGEX.test(referenceValue)) {
// eslint-disable-next-line
referenceValue = await recursivelyExpandSecret({
environment: secretReferenceEnvironment,
@ -332,7 +343,7 @@ export const interpolateSecrets = ({ projectId, secretEncKey, secretDAL, folderD
}) => {
if (!inputSecret.value) return inputSecret.value;
const shouldExpand = Boolean(inputSecret.value?.match(INTERPOLATION_SYNTAX_REG));
const shouldExpand = INTERPOLATION_TEST_REGEX.test(inputSecret.value);
if (!shouldExpand) return inputSecret.value;
const expandedSecretValue = await recursivelyExpandSecret(inputSecret);
@ -451,7 +462,18 @@ export const fnSecretBlindIndexCheckV2 = async ({
* // ]
*/
export const getAllNestedSecretReferences = (maybeSecretReference: string) => {
const references = Array.from(maybeSecretReference.matchAll(INTERPOLATION_SYNTAX_REG), (m) => m[1]);
const matches = [];
let match;
const execRegex = new RE2(INTERPOLATION_PATTERN_STRING, "g");
// eslint-disable-next-line no-cond-assign
while ((match = execRegex.exec(maybeSecretReference)) !== null) {
matches.push(match);
}
const references = matches.map((m) => m[1]);
return references
.filter((el) => el.includes("."))
.map((el) => {

View File

@ -367,7 +367,7 @@ export const secretQueueFactory = ({
canExpandValue: () => true
});
// process secrets in current folder
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId, projectId: dto.projectId });
const secrets = await secretV2BridgeDAL.findByFolderId({ folderId: dto.folderId });
await Promise.allSettled(
secrets.map(async (secret) => {
@ -397,7 +397,6 @@ export const secretQueueFactory = ({
// if no imports then return secrets in the current folder
if (!secretImports.length) return content;
const importedSecrets = await fnSecretsV2FromImports({
projectId: dto.projectId,
decryptor: dto.decryptor,
folderDAL,
secretDAL: secretV2BridgeDAL,

View File

@ -1,4 +1,4 @@
---
title: "Create Project Membership"
openapi: "POST /api/v2/workspace/{projectId}/groups/{groupId}"
openapi: "POST /api/v2/workspace/{projectId}/groups/{groupIdOrName}"
---

View File

@ -1,8 +1,10 @@
---
title: "Create"
openapi: "POST /api/v1/workspace/{projectSlug}/roles"
openapi: "POST /api/v2/workspace/{projectId}/roles"
---
<Note>
You can read more about the permissions field in the [permissions documentation](/internals/permissions).
</Note>
You can read more about the permissions field in the [permissions
documentation](/internals/permissions).
</Note>

View File

@ -1,4 +1,4 @@
---
title: "Delete"
openapi: "DELETE /api/v1/workspace/{projectSlug}/roles/{roleId}"
openapi: "DELETE /api/v2/workspace/{projectId}/roles/{roleId}"
---

View File

@ -1,4 +1,4 @@
---
title: "Get By Slug"
openapi: "GET /api/v1/workspace/{projectSlug}/roles/slug/{slug}"
openapi: "GET /api/v2/workspace/{projectId}/roles/slug/{roleSlug}"
---

View File

@ -1,4 +1,4 @@
---
title: "List"
openapi: "GET /api/v1/workspace/{projectSlug}/roles"
openapi: "GET /api/v2/workspace/{projectId}/roles"
---

View File

@ -1,4 +1,4 @@
---
title: "Update"
openapi: "PATCH /api/v1/workspace/{projectSlug}/roles/{roleId}"
openapi: "PATCH /api/v2/workspace/{projectId}/roles/{roleId}"
---

View File

@ -28,21 +28,32 @@ You can use it across various environments, whether it's local development, CI/C
```
</Tab>
<Tab title="Windows">
Use [Scoop](https://scoop.sh/) package manager
```bash
scoop bucket add org https://github.com/Infisical/scoop-infisical.git
```
<Accordion title="Scoop package manager">
Use [Scoop](https://scoop.sh/) package manager
```bash
scoop install infisical
```
```bash
scoop bucket add org https://github.com/Infisical/scoop-infisical.git
```
### Updates
```bash
scoop install infisical
```
```bash
scoop update infisical
```
### Updates
```bash
scoop update infisical
```
</Accordion>
<Accordion title="Winget package manager">
Use [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/) package manager
```bash
winget install infisical
```
</Accordion>
</Tab>
<Tab title="NPM">

View File

@ -6,40 +6,55 @@ description: "Learn how to structure your projects, secrets, and other resources
Infisical is designed to provide comprehensive, centralized, and efficient management of secrets, certificates, and encryption keys within organizations. Below is an overview of Infisical's structured components, which developers and administrators can leverage for optimal project management and security posture.
### 1. Projects
### 0. Cluster/Instance
- **Best Practice**: In most cases, a single Infisical instance or cluster is sufficient. Multiple clusters are typically only necessary for large, globally distributed organizations.
- **Use Cases**:
- **Cloud-hosted** deployments typically use a single cluster. While technically possible, using multiple clusters is not a common practice and is generally unnecessary.
- **Self-hosted** deployments can be configured with multiple clusters if needed.
### 1. Organization
- **Definition**: An Infisical [organization](/documentation/platform/organization) is a set of projects that use the same billing.
- **Use Cases**:
- In **self-hosted** setups, you can create multiple organizations (e.g., one for each department or business unit).
- In **cloud-hosted deployments**, it's standard to use a single organization.
### 2. Projects
- **Definition and Role**: [Projects](/documentation/platform/project) are the highest-level construct within an [organization](/documentation/platform/organization) in Infisical. They serve as the primary container for all functionalities.
- **Correspondence to Code Repositories**: Projects typically align with specific code repositories.
- **Functional Capabilities**: Each project encompasses features for managing secrets, certificates, and encryption keys, serving as the central hub for these resources.
### 2. Environments
### 3. Environments
- **Purpose**: Environments are designed for organizing and compartmentalizing secrets within projects.
- **Customization Options**: Environments can be tailored to align with existing infrastructure setups of any project. Default options include **Development**, **Staging**, and **Production**.
- **Structure**: Each environment inherently has a root level for storing secrets, but additional sub-organizations can be created through [folders](/documentation/platform/folder) for better secret management.
### 3. Folders
### 4. Folders
- **Use Case**: Folders are available for more advanced organizational needs, allowing logical separation of secrets.
- **Typical Structure**: Folders can correspond to specific logical units, such as microservices or different layers of an application, providing refined control over secrets.
### 4. Imports
### 5. Imports
- **Purpose and Benefits**: To promote reusability and avoid redundancy, Infisical supports the use of imports. This allows secrets, folders, or entire environments to be referenced across multiple projects as needed.
- **Best Practice**: Utilizing [secret imports](/documentation/platform/secret-reference#secret-imports) or [references](/documentation/platform/secret-reference#secret-referencing) ensures consistency and minimizes manual overhead.
### 5. Approval Workflows
### 6. Approval Workflows
- **Importance**: Implementing approval workflows is recommended for organizations aiming to enhance efficiency and strengthen their security posture.
- **Types of Workflows**:
- **[Access Requests](/documentation/platform/pr-workflows)**: This workflow allows developers to request access to sensitive resources. Such access can be configured for temporary use, a practice known as "just-in-time" access.
- **[Change Requests](/documentation/platform/access-controls/access-requests)**: Facilitates reviews and approvals when changes are proposed for sensitive environments or specific folders, ensuring proper oversight.
### 6. Access Controls
### 7. Access Controls
Infisicals access control framework is unified for both human users and machine identities, ensuring consistent management across the board.
### 6.1 Roles
### 7.1 Roles
- **2 Role Types**:
- **Organization-Level Roles**: Provide broad access across the organization (e.g., ability to manage billing, configure settings, etc.).
@ -49,17 +64,17 @@ Infisicals access control framework is unified for both human users and machi
<Note>Project access is defined not via an organization-level role, but rather through specific project memberships of both human and machine identities. Admin roles bypass this by default. </Note>
### 6.2 Additional Privileges
### 7.2 Additional Privileges
[Additional privileges](/documentation/platform/access-controls/additional-privileges) can be assigned to users and machines on an ad-hoc basis for specific scenarios where roles alone are insufficient. If you find yourself using additional privileges too much, it is recommended to create custom roles. Additional privileges can be temporary or permanent.
### 6.3 Attribute-Based Access Control (ABAC)
### 7.3 Attribute-Based Access Control (ABAC)
[Attribute-based Access Controls](/documentation/platform/access-controls/attribute-based-access-controls) allow restrictions based on tags or attributes linked to secrets. These can be integrated with SAML assertions and other security frameworks for dynamic access management.
### 6.4 User Groups
### 7.4 User Groups
- **Application**: Organizations should use users groups in situations when they have a lot of developers with the same level of access (e.g., separated by team, department, seniority, etc.).
- **Synchronization**: [User groups](/documentation/platform/groups) can be synced with an identity provider to maintain consistency and reduce manual management.

View File

@ -25,7 +25,7 @@ By default, every user in a project is either a **viewer**, **developer**, or an
As such:
- **Admin**: This role enables identities to have access to all environments, folders, secrets, and actions within the project.
- **Developers**: This role restricts identities from performing project control actions, updating Approval Workflow policies, managing roles/members, and more.
- **Developers**: This role restricts identities from performing project control actions, updating Approval Workflow policies, managing roles, editing and removing project members, and more.
- **Viewer**: The most limiting bulit-in role on the project level  it forbids user and machine identities to perform any action and rather shows them in the read-only mode.
![Project member role](/images/platform/access-controls/rbac.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

View File

@ -329,7 +329,8 @@
"pages": [
"self-hosting/reference-architectures/aws-ecs",
"self-hosting/reference-architectures/linux-deployment-ha",
"self-hosting/reference-architectures/on-prem-k8s-ha"
"self-hosting/reference-architectures/on-prem-k8s-ha",
"self-hosting/reference-architectures/google-cloud-run"
]
},
"self-hosting/ee",

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