Compare commits

...

453 Commits

Author SHA1 Message Date
d62e1c3703 Bump Cloudflare IP priority 2024-01-29 16:51:38 +07:00
9bba9ee9b1 Merge pull request #1342 from Infisical/patch-integration-path-sync
Remove async from isSamePath check in integration sync
2024-01-29 16:42:25 +07:00
74ac75b878 Remove async from isSamePath check in integration sync 2024-01-29 16:37:31 +07:00
8478fea52a Merge pull request #1341 from akhilmhdh/feat/add-cloudwatch
feat: added cloudwatch support and removed parsed secret blindindex
2024-01-29 04:25:42 -05:00
703ff2c12b feat: added cloudwatch support and removed parsed secret blindindex nullable 2024-01-29 14:52:20 +05:30
6b4aee2a44 Merge pull request #1340 from Infisical/vercel-issue
Patch Vercel integration for team accounts
2024-01-29 09:25:18 +07:00
5593464287 Patch Vercel integration missing teamId not being passed in from frontend 2024-01-29 09:20:39 +07:00
7d556cb09b Merge pull request #1308 from Tchoupinax/patch-1
Update the path where managing service tokens
2024-01-28 17:00:33 -05:00
dcb6f5891f add license service timeout 2024-01-28 15:32:37 -05:00
1254215b51 Merge pull request #1338 from akhilmhdh/feat/blind-index-fix
feat: changed blind index banner for everyone
2024-01-28 14:37:31 -05:00
a6ead9396c nit: small patch to request error status 2024-01-28 14:36:57 -05:00
d33ef9e4e1 jump cloud patch 2024-01-28 13:53:24 -05:00
4e20735f98 feat: resolved trailing slash in secret paths 2024-01-29 00:21:42 +05:30
f010a3a932 feat: changed blind index banner for everyone 2024-01-28 23:16:04 +05:30
bbf2634e73 prepend sso with site url 2024-01-27 20:20:02 -05:00
1980f802fa update rate limits 2024-01-27 19:05:17 -05:00
6ecd289e6c update rate limits 2024-01-27 18:38:57 -05:00
b8a6f5dc54 add email templates and disposable_emails.text to build 2024-01-27 18:15:12 -05:00
dedbc4fd60 remove unused imports 2024-01-27 17:11:40 -05:00
d14099990f remove notice 2024-01-27 17:04:53 -05:00
3f5ab2a09e remove console.log 2024-01-27 17:04:02 -05:00
a191f437e9 patch blind index route 2024-01-27 17:03:16 -05:00
1a375ec45b patch import * 2024-01-27 12:35:53 -05:00
81f3a6a7a8 add loca host to docker prod 2024-01-27 12:27:15 -05:00
dc8b64708a add debug logs 2024-01-27 11:20:17 -05:00
dd3790c995 patch git workflow 2024-01-27 10:31:30 -05:00
a91b6ebc03 new workflow for releasing standalone 2024-01-27 10:28:49 -05:00
e68d1d06a8 Merge pull request #1334 from akhilmhdh/feat/patch-pg-v2
feat: changed backend-pg to backend
2024-01-27 10:06:34 -05:00
8f754d659a feat: resolved tiny bug secret blind indexing 2024-01-27 20:23:19 +05:30
bef28fea2d Update release-standalone-docker-img.yml 2024-01-27 09:42:20 -05:00
28f15de8df Update build-docker-image-to-prod.yml 2024-01-27 09:40:59 -05:00
66d258f02b feat: changed backend-pg to backend 2024-01-27 19:14:33 +05:30
d13eafcef7 Merge pull request #1332 from akhilmhdh/feat/infisical-pg
Hello world from PG
2024-01-27 02:26:05 -05:00
6db47499de add index for blind index 2024-01-27 12:40:37 +05:30
1cefb036e0 ignore dup user and make email unique 2024-01-27 12:40:37 +05:30
af77ad8b2f update rate limits 2024-01-27 12:40:37 +05:30
dd0f9f5216 patch secret apporval request secrets 2024-01-27 12:40:37 +05:30
29df6f067e remove unnecessary concole 2024-01-27 12:40:37 +05:30
4dc9a3692e add mongo to docker compose 2024-01-27 12:40:37 +05:30
49bb2121b9 update helm values 2024-01-27 12:40:37 +05:30
07679d9318 add postgres helm chart 2024-01-27 12:40:37 +05:30
fb271726fe make emails not unique for now 2024-01-27 12:40:37 +05:30
f9e7d4ddd2 make MI access token have string id 2024-01-27 12:40:37 +05:30
442c454932 make email unique 2024-01-27 12:40:37 +05:30
8b22ee1fac coerce strings to number responses 2024-01-27 12:40:37 +05:30
8a10dc8983 make before and after more clear in roll back 2024-01-27 12:40:37 +05:30
d57920706a patch bug validateAccessTokenExp bug 2024-01-27 12:40:37 +05:30
425611b409 remove uuid from snapshot project response 2024-01-27 12:40:37 +05:30
b20489982d delete unneeded file 2024-01-27 12:40:37 +05:30
4b569ee4b4 make access token non uui 2024-01-27 12:40:37 +05:30
af9661b221 feat(infisical-pg): minor bug fixes in frontend and pg migrator secret approval req 2024-01-27 12:40:37 +05:30
53f16f01b8 feat(infisical-pg): fixed audit log to estimate doc count and resolve cors issue 2024-01-27 12:40:37 +05:30
f519d1cffc remove async from validateAccessTokenExp 2024-01-27 12:40:37 +05:30
b8b28d2710 feat(infisical-pg): resolved linting issues 2024-01-27 12:40:37 +05:30
deab700716 feat(infisical-pg): made api key backward compat 2024-01-27 12:40:37 +05:30
4d184003a8 feat(infisical-pg): made identity ua client sec backward compat 2024-01-27 12:40:37 +05:30
9849312317 remove console 2024-01-27 12:40:37 +05:30
79454a6aea feat(infisical-pg): fixed org bot gone missing 2024-01-27 12:40:37 +05:30
8e0fb9fe9b feat(infisical-pg): wrapped saml get option in try catch 2024-01-27 12:40:37 +05:30
a729114376 remove prefix from redis 2024-01-27 12:40:37 +05:30
0c20cb0f91 JWT_AUTH_SECRET => AUTH_SECRET 2024-01-27 12:40:37 +05:30
d1597ed8da find by id of ormify patch 2024-01-27 12:40:37 +05:30
6cee8dc7e5 uni auth remove auth type 2024-01-27 12:40:37 +05:30
13040439c3 coerce big int from string to number from sql 2024-01-27 12:40:37 +05:30
9a4f294749 add prefix to queue 2024-01-27 12:40:37 +05:30
2436a572f0 revert to only arm build 2024-01-27 12:40:37 +05:30
7cd21e3a93 remove timeout and signal from license requester 2024-01-27 12:40:37 +05:30
e28416b50b patch service token migration backwards with mongo 2024-01-27 12:40:37 +05:30
9677836b76 feat(infisical-pg): added telemtry service 2024-01-27 12:40:37 +05:30
ca858f8e13 rename ci 2024-01-27 12:40:37 +05:30
c2beff493f add linux/amd64,linux/arm64 for standone release 2024-01-27 12:40:37 +05:30
34fafd815c set postgres ci to only linux/arm64 2024-01-27 12:40:37 +05:30
c05ebbb864 set SmtpHost.Sendgrid secure=true 2024-01-27 12:40:37 +05:30
372f2be2f3 increase license server request time out 2024-01-27 12:40:37 +05:30
23e621f557 increase license request timeout 2024-01-27 12:40:36 +05:30
464b80140f add 443 port to docker 2024-01-27 12:40:36 +05:30
01cd496afe update status api 2024-01-27 12:40:36 +05:30
6094940a8b add success message 2024-01-27 12:40:36 +05:30
30b959babb JWT_AUTH_SECRET => AUTH_SECRET 2024-01-27 12:40:36 +05:30
cec14efe86 add logs to license server 2024-01-27 12:40:36 +05:30
b3f090d87e only amd 2024-01-27 12:40:36 +05:30
1deb6827cf add STANDALONE_MODE to docker file 2024-01-27 12:40:36 +05:30
24dbf11962 add back arm 2024-01-27 12:40:36 +05:30
20fb3906aa only amd 2024-01-27 12:40:36 +05:30
e7e2ca0f45 update postgress workflow 2024-01-27 12:40:36 +05:30
caabf2c952 patch bot keys 2024-01-27 12:40:36 +05:30
35eade0206 update to alpine node 20 2024-01-27 12:40:36 +05:30
6d1b79430d lower node alpine 2024-01-27 12:40:36 +05:30
7864524944 remove QEMU 2024-01-27 12:40:36 +05:30
adc90e91fe update build-push-actio version 2024-01-27 12:40:36 +05:30
db7db0cc04 remove version 2024-01-27 12:40:36 +05:30
aa4d9ad267 Revert "update npm time out"
This reverts commit 38a7b1acf1a445ea62dcad5b60e9624733976b78.
2024-01-27 12:40:36 +05:30
27fd857120 update npm time out 2024-01-27 12:40:36 +05:30
205e46571a remove depot 2024-01-27 12:40:36 +05:30
70a6a7cfa1 create CI for standalone image 2024-01-27 12:40:36 +05:30
558315c24b set secret blind index count to Number 2024-01-27 12:40:36 +05:30
a2bd808196 rename project roles message 2024-01-27 12:40:36 +05:30
cfb0d4ee96 add no access to org service role 2024-01-27 12:40:36 +05:30
15fc4fd609 set cascade in trusted ip for project id 2024-01-27 12:40:36 +05:30
83bff9ae14 make protectedKey protectedKeyIV protectedKeyTag nullable 2024-01-27 12:40:36 +05:30
86ba6355cf more patches to migrator 2024-01-27 12:40:36 +05:30
6b427adfe0 feat(infisical-pg): added v3 secret blind index enable feature 2024-01-27 12:40:36 +05:30
01f711ad19 feat(infisical-pg): completed audit log migrator 2024-01-27 12:39:54 +05:30
fa572f7ee0 feat(infisical-pg): completed standalone and docker node version 2024-01-27 12:39:54 +05:30
249edf98e9 remove notNullable from various tables 2024-01-27 12:39:54 +05:30
753a4daf69 remove authType from mi access token 2024-01-27 12:39:54 +05:30
b9320ed9bd comment out corrupt seed files 2024-01-27 12:39:54 +05:30
8eace5528f point migrations to pg backend folder 2024-01-27 12:39:54 +05:30
9407c16e83 Update queue-service.ts 2024-01-27 12:39:54 +05:30
dcdcc40a4a Update smtp-service.ts 2024-01-27 12:39:54 +05:30
edd78eaeba Refactor 2024-01-27 12:39:54 +05:30
c21ea6fb75 Cleanup 2024-01-27 12:39:54 +05:30
a60dbe523b Refactor to secret queue 2024-01-27 12:39:54 +05:30
bb9a6b4272 Update index.ts 2024-01-27 12:39:54 +05:30
eaca1b694a Log 2024-01-27 12:39:54 +05:30
0afb44af29 Handle deletion 2024-01-27 12:39:54 +05:30
3b39e38c89 Secret reminder types 2024-01-27 12:39:54 +05:30
4189d1028d Optional secret reminder typing 2024-01-27 12:39:54 +05:30
f227824fb8 Added secret reminders email 2024-01-27 12:39:54 +05:30
49d6918297 Update secret-service.ts 2024-01-27 12:39:54 +05:30
00212f1c72 Secret reminder queue factory 2024-01-27 12:39:54 +05:30
987f0c9081 Added secret reminder service 2024-01-27 12:39:54 +05:30
e4f00f74e9 Added new special query for getting org from project ID 2024-01-27 12:39:54 +05:30
ce580f417e Registered secret reminder service 2024-01-27 12:39:54 +05:30
c1662d6db5 Added secret reminder to queue service 2024-01-27 12:39:54 +05:30
2dae59c6be Update fastify.d.ts 2024-01-27 12:39:54 +05:30
9bd764e535 feat(infisical-pg): updated pg migrator to new table name changes 2024-01-27 12:39:54 +05:30
e4f32f092a feat(infisical-pg): completed test for secret folder and import 2024-01-27 12:39:54 +05:30
e02c082c7a more patches for migration script 2024-01-27 12:39:54 +05:30
80b6c4ad94 feat(infisical-pg): completed tag support to all secret operations 2024-01-27 12:39:54 +05:30
42eb01e1e2 feat(infisical-pg): completed support for tags in secret snapshot 2024-01-27 12:39:54 +05:30
b8157122e6 patches for dangling data 2024-01-27 12:39:54 +05:30
4f66749430 feat(infisical-pg): added secret version tag 2024-01-27 12:39:54 +05:30
bfe5ee672b patches for migration 2024-01-27 12:39:54 +05:30
32a1a0a9e5 feat(infisical-pg): removed short form names in secret approval to long form 2024-01-27 12:39:54 +05:30
f7e1da65d5 feat(infisical-pg): added slug for org and project, resolved build error 2024-01-27 12:39:53 +05:30
6bf9bc1d2c feat(infisical-pg): changed all dal to DAL as said by maidul 2024-01-27 12:38:23 +05:30
59c747cf72 feat(infisical-pg): added rate limiter and bootstrap 2024-01-27 12:38:23 +05:30
b04030a060 feat(infisical-pg): resolved missing integration auth api 2024-01-27 12:38:23 +05:30
e8fd693da3 feat(infisical-pg): added single scope service token auto filling for get secret by name raw and version option for both get secret by name 2024-01-27 12:38:23 +05:30
6c2803da93 feat(infisical-pg): crct permission for secret approval policy check 2024-01-27 12:38:23 +05:30
4031f4a559 feat(infisical-pg): idempotent folder creation 2024-01-27 12:38:23 +05:30
8ab89bc420 feat(infisical-pg): resolved import secret breaking cli backward compatiability 2024-01-27 12:38:23 +05:30
e46e87d758 feat(infisical-pg): fixed secret deletion not getting triggered 2024-01-27 12:38:23 +05:30
9c2ef15314 feat(infisical-pg): fixed missing secret path and commiter message in frontend 2024-01-27 12:38:23 +05:30
3213dafba9 add check to make sure user can only create service token for secrets they have access to 2024-01-27 12:38:23 +05:30
33c3c5ecc5 add permission check for target env/path for imports 2024-01-27 12:38:23 +05:30
627c8711dc feat(infisical-pg): fixed v3 raw endpoint auto filling based on service token data single scoped 2024-01-27 12:38:23 +05:30
8d3d4f222f feat(infisical-pg): fixed service token cli endpoint 2024-01-27 12:38:23 +05:30
65d3038414 set ignoreTrailingSlash to true in fastify 2024-01-27 12:38:23 +05:30
6b7b888fb4 feat(infisical-pg): fixed service token return body 2024-01-27 12:38:23 +05:30
bf059e0fe5 feat(infisical-pg): fixed secret rotation and secret approval limit offset 2024-01-27 12:38:23 +05:30
28fdf4ed4b Update service-token-router.ts 2024-01-27 12:38:23 +05:30
2606e42079 Correct Cloudflare Pages authorization page 2024-01-27 12:38:23 +05:30
b1285b401b Patch integration issues 2024-01-27 12:38:23 +05:30
3afafbb885 Add Makefile, pg-admin to docker compose 2024-01-27 12:38:23 +05:30
257547ff4d fix delete secret scans after git app uninstall 2024-01-27 12:38:23 +05:30
da4ae3c503 switch getSapOfFolder to check for secrets instead of approval 2024-01-27 12:38:23 +05:30
fb79e9e6fb update project add user text typo 2024-01-27 12:38:23 +05:30
5373cb6afb feat(infisical-pg): added secret version api, fixed pass reset flow, smtp connection issue fixed 2024-01-27 12:38:23 +05:30
31c0bf6831 Fixed UI glitch 2024-01-27 12:38:23 +05:30
67618046c0 Fixed creating service tokens with no expiry 2024-01-27 12:38:23 +05:30
df642179ba fix typo 2024-01-27 12:38:23 +05:30
c7d0f2325c Fixed secret creation 2024-01-27 12:38:23 +05:30
bb6d482ff9 feat(infisical-pg): added global error handler, try catch in oauth passport 2024-01-27 12:38:23 +05:30
4f619d7e48 Fixed signup for gitlab and github 2024-01-27 12:38:23 +05:30
295c1e5d4a feat(infisical-pg): fixed ts issue on passport type change 2024-01-27 12:38:23 +05:30
0be3ad9517 Fixed eslint bug 2024-01-27 12:38:23 +05:30
606ed25104 Fixed GitHub auth registration issue 2024-01-27 12:38:23 +05:30
c880a48749 feat(infisical-pg): fixed radix issue, bugs in oauth and tag cascade on 2024-01-27 12:38:23 +05:30
92f7b45e01 feat(infisical-pg): fixed plan going undefined and resolved project missing on env delete 2024-01-27 12:38:23 +05:30
5fe8bdc00b feat(infisical-pg): completed first version of pg migrator 2024-01-27 12:38:23 +05:30
9f813d72f2 feat(infisical-pg): resolved multi integration auth and ip v6 support in ua 2024-01-27 12:38:23 +05:30
d90fdac5ce feat(infisical-pg): fixed bugs in integrations and self hosted license failure 2024-01-27 12:38:23 +05:30
87709dc86f feat(infisical-pg): first setup for postgres migration script 2024-01-27 12:38:23 +05:30
deb8e74749 feat(infisical-pg): fixed some bugs on org invite missing auth method 2024-01-27 12:38:23 +05:30
3519412639 feat: added secret raw endpoint and include imports 2024-01-27 12:38:23 +05:30
0506389ada feat: added logged in based testing by injecting jwt token logic 2024-01-27 12:38:23 +05:30
dd7c449483 feat: added login test and fixed super admin bug 2024-01-27 12:38:23 +05:30
c7572a3374 feat: completed license server integration 2024-01-27 12:38:23 +05:30
fe416556f2 feat: changed req.auth.userId to permission.id to satisfy type error 2024-01-27 12:38:23 +05:30
20fb99f042 feat: added token based communications 2024-01-27 12:38:23 +05:30
daa94db874 feat(infisical-pg): changed back to old infisical-radar url 2024-01-27 12:38:23 +05:30
850e7bff98 feat(infisical-pg): completed secret scanner 2024-01-27 12:38:23 +05:30
bfaf87c4c2 feat(infisical-pg): completed saml integration 2024-01-27 12:38:23 +05:30
55f1392faf feat(infisical-pg): completed sync in secret approval 2024-01-27 12:38:23 +05:30
0bf658e501 feat(infisical-pg): completed webhook and integration trigger queue 2024-01-27 12:38:23 +05:30
aed94ff5bb feat(infisical-pg): resolved integration invalid cred error 2024-01-27 12:38:23 +05:30
0d3f09d668 feat(infisical-pg): completed checklist run for dashboard 2024-01-27 12:38:23 +05:30
16f0ac6d43 feat(infisical-pg): completed audit log moved ee routes to normal routing pattern 2024-01-27 12:38:23 +05:30
6e6a1c87f2 feat(infisical-pg): completed secrets fetching from imports based on priority 2024-01-27 12:38:23 +05:30
b5aa6c0000 feat(infisical-pg): completed secret rollback 2024-01-27 12:38:23 +05:30
784cdb4201 feat(infisical-pg): completed secret rotation with queue service 2024-01-27 12:38:23 +05:30
17e61bfc68 feat(infisical-pg): completed secret approval policy and services for approval requests 2024-01-27 12:38:23 +05:30
a6a60b7bbb feat(infisical-pg): fixing minor compatiability issues with frontend and backend on identity 2024-01-27 12:38:23 +05:30
d154f68a59 feat(infisical-pg: completed machine identity services 2024-01-27 12:38:23 +05:30
f5159583ae feat(infisical-pg: completed webhook and service token 2024-01-27 12:38:23 +05:30
771bec6d6d feat(infisical-pg): completed integration, integration auth and project bot api migration 2024-01-27 12:38:23 +05:30
010963a80c feat(infisical-pg): completed nested folder support for secret,folder and import operations 2024-01-27 12:38:23 +05:30
0e1191f2ea feat(infisical-pg): completed root folder level secret, secret import and folder 2024-01-27 12:38:23 +05:30
8a6ab7f2f6 feat(infisical-pg): connected project api changes with frontend 2024-01-27 12:38:22 +05:30
4f3582a98b feat(infisical-pg): added routes for workspaces and updated frontend 2024-01-27 12:38:22 +05:30
498a90c484 feat(infisical-pg: linted after import order fix 2024-01-27 12:38:22 +05:30
76e5d61da5 feat(infisical-pg: added services for project, project key and environment 2024-01-27 12:38:22 +05:30
53bb3bc610 feat(infisical-pg): added database schema for project, its membership role and env 2024-01-27 12:38:22 +05:30
1df7b88abf feat(infisical-pg): added e2e test setup 2024-01-27 12:38:22 +05:30
3670b16657 feat(infisical-pg): new org role routes completed 2024-01-27 12:38:22 +05:30
9a4b2f7d81 feat(infisical-pg): resolved type check issue and linted frontend 2024-01-27 12:38:22 +05:30
fadb36edb8 feat(infisical-pg): removed _id with id for new backend 2024-01-27 12:38:22 +05:30
fbe5a1adb0 feat(infisical-pg): added github,gitlab and google oauth 2024-01-27 12:38:22 +05:30
d0695a8998 feat(infisical-pg): added a seed setup with test user creation and org creation 2024-01-27 12:38:22 +05:30
a19e8ad016 feat(infisical-pg): updated names and simplified dal layer using ormify 2024-01-27 12:38:22 +05:30
15b57de0ed feat(infisical-pg): test first milestone one flow 2024-01-27 12:38:22 +05:30
aaba4a0895 feat(infisical-pg): changed frontend api types _id to normal id 2024-01-27 12:38:22 +05:30
f3b37de3f3 feat(infisical-pg): auth injection completed and validation in password router 2024-01-27 12:38:22 +05:30
fcfd6b3fb2 feat(infisical-pg): completed signup, login, password and backup key migration 2024-01-27 12:38:22 +05:30
05205d1eff feat(infisical-pg): added all previous simple server middlewares, swagger support 2024-01-27 12:38:22 +05:30
2243bcb3a4 feat: added dev and prod setup using esbuild 2024-01-27 12:38:22 +05:30
356e981401 Merge pull request #1313 from akhilmhdh/feat/migration-mode
feat(infisical-pg): added migration mode env and page
2024-01-27 00:58:58 -05:00
5b41fb0ff5 update text and patch notice 2024-01-27 00:21:57 -05:00
8893aec213 patch saml sso for rippling 2024-01-23 01:11:29 -05:00
c4cb8f8008 Merge pull request #1319 from Infisical/daniel/better-sdk-docs
(Docs): Improve SDK docs
2024-01-23 08:53:28 +04:00
046557c97f Add .NET 2024-01-23 08:47:29 +04:00
a15ba28c18 Update node guide to reflect new SDK 2024-01-23 08:47:20 +04:00
8386f4dcbd Update python guide to reflect new SDK 2024-01-23 08:47:11 +04:00
ada0fd9c5b Add new item for fallbacks 2024-01-23 08:47:01 +04:00
6376c29e49 update maintenace notice 2024-01-19 17:28:35 -05:00
402692614e updated maintenance page 2024-01-19 12:59:18 -08:00
34de6d4e29 feat(infisical-pg): added migration mode env and page 2024-01-20 01:20:14 +05:30
829e906650 Merge pull request #1311 from Infisical/daniel/changelog-jan-2024
[JAN] Changelog points
2024-01-18 20:25:52 -05:00
b7cbb0f1a8 Update overview.mdx 2024-01-19 00:14:03 +04:00
a50ffbb59d Update overview.mdx 2024-01-19 00:13:57 +04:00
e18abc6e22 Update the path where managing service tokens
I did not find anymore where to manage token and reading the doc did not help me. I found the MR which changes the section of the link and so I update the doc according it
2024-01-17 22:15:07 +01:00
48eda0c684 Update overview.mdx 2024-01-15 15:55:37 +04:00
ed89413689 Merge pull request #1293 from Infisical/update-blog
Update blog notification
2024-01-12 13:52:11 -05:00
0c94f77a6d Merge pull request #1302 from akhilmhdh/feat/banner
feat: added main banner for migration
2024-01-12 10:48:21 -05:00
e6068826f8 update migration notification 2024-01-11 23:34:46 -08:00
cfa0a2044e Merge pull request #1304 from Infisical/add-project-config-flag-for-workspace
add project-config-dir flag for run command
2024-01-11 17:21:03 -05:00
134b503c28 remove log 2024-01-11 17:19:39 -05:00
efcbf1aa88 add project-config-dir flag for run command 2024-01-11 16:39:02 -05:00
284c18db07 Merge pull request #1303 from Infisical/daniel/sdk-seo-improvements
(Docs): SDK SEO Improvements & links to packages/repos
2024-01-11 10:53:08 -08:00
1410a44610 SEO Improvements and links to packages/repos 2024-01-11 22:34:11 +04:00
746ffb3840 feat: added main banner for migration 2024-01-11 23:09:57 +05:30
f9f12eafdf Update saml docs 2024-01-10 15:02:10 -08:00
11470a5a0e Merge pull request #1300 from Infisical/daniel/project-docs-secret-reminders
(Docs): Personal overrides and secret reminders awareness
2024-01-10 17:43:16 -05:00
9fe2190115 Update project.mdx 2024-01-11 02:40:37 +04:00
9e2bd31833 Merge pull request #1298 from Infisical/daniel/csharp-docs
(Docs): .NET SDK documentation & updates existing SDK docs
2024-01-10 16:28:40 -05:00
e88b0ad3c4 Update python.mdx 2024-01-11 01:25:10 +04:00
74644fd8bb Added cryptography docs and fixed formatting 2024-01-11 01:12:38 +04:00
2069ac1554 Added CSharp and removed unfinished SDK's 2024-01-11 01:12:26 +04:00
5a2516e0a7 Removed unsupported languages to remove clutter 2024-01-11 01:12:17 +04:00
b52bc3bed7 Added CSharp docs 2024-01-11 01:12:05 +04:00
4a153e5658 Merge pull request #1295 from akhilmhdh/fix/sec-interpolation-undefined
fix(secret-reference): fixed undefined if value not found
2024-01-10 09:59:09 -05:00
7324822be5 fix(secret-reference): fixed undefined if value not found 2024-01-10 11:45:46 +05:30
766f301aea patch agent config by env 2024-01-09 14:30:29 -05:00
8fbc930012 updated notification text 2024-01-08 13:51:40 -08:00
0e5190a920 added the december update blog 2024-01-08 13:47:58 -08:00
b815e3eb56 Merge pull request #1291 from Infisical/daniel/fix-sdk-contribution-image
(Fix): Image in SDK contribution guide not loading
2024-01-08 14:56:27 -05:00
31231cfcca Update developing.mdx 2024-01-08 23:30:10 +04:00
ee772e4a77 allow reading universal auth creds from env in agent 2024-01-07 17:00:42 -05:00
7bc29c5981 Merge pull request #1285 from Infisical/query-by-secret-version
Add version query param to GET secret raw and regular endpoints
2024-01-07 16:07:49 -05:00
e9a89930da Merge pull request #1284 from Infisical/multi-integration-auth
Enable new integration auth credential for each new integration
2024-01-07 14:49:04 -05:00
b85499859c Merge pull request #1286 from Infisical/identities-ipv6
Add IPv6 consideration to default universal auth IP allowlist
2024-01-07 16:37:06 +01:00
7f17194c0f Add IPv6 consideration to default identities IP allowlist 2024-01-07 16:32:25 +01:00
1e1ad450d2 Add version query param to GET secret endpoint 2024-01-07 14:25:33 +01:00
5287b322d8 Enable new integration auth for each new integration 2024-01-07 12:49:59 +01:00
45d96be1ff added base64 support for config and templates 2024-01-06 23:43:04 -05:00
12840bfdbd add exit after auth setting 2024-01-06 17:17:21 -05:00
fef5369738 Merge pull request #1283 from Infisical/identity-apis
Update various identities items
2024-01-06 17:11:01 +01:00
c94b7d63f6 Update various identities items 2024-01-06 17:04:44 +01:00
485ddc5c50 Merge pull request #1282 from Infisical/patch-railway
Fix client-side railway integration issue
2024-01-06 16:14:16 +01:00
edd9c66e49 Remove commented print statements 2024-01-06 16:11:22 +01:00
0a3b85534b Fix client-side railway integration issue 2024-01-06 16:09:15 +01:00
ec2cc5162e Merge pull request #1279 from Infisical/daniel/sdk-contribution-guide
Contribution guide refactor & SDK contribution guide
2024-01-05 20:26:17 -05:00
7ce472957c Fixed quality 2024-01-06 04:04:09 +04:00
8529e0da3d Update developing.mdx 2024-01-06 03:41:31 +04:00
e5a5433f10 Update developing.mdx 2024-01-06 03:00:14 +04:00
ee6e518ff8 Update link to contribution guide 2024-01-06 02:58:26 +04:00
15a7222505 Update mint.json 2024-01-06 02:58:16 +04:00
25d482cc62 Create sdk-flow.png 2024-01-06 02:58:12 +04:00
785a2bec6a Added SDK guide 2024-01-06 02:58:08 +04:00
449466f326 Restructure 2024-01-06 02:58:02 +04:00
4131e9c3f1 Added getting started section 2024-01-06 02:57:53 +04:00
310595256f Restructured existing guide 2024-01-06 02:57:21 +04:00
1737880e58 Merge pull request #1251 from Infisical/snyk-fix-b96b562a611b0789d0a73c522a261f22
[Snyk] Security upgrade probot from 12.3.1 to 12.3.3
2024-01-05 11:20:43 -05:00
b72483f5f2 Merge pull request #1275 from Emiliaaah/fix-agent-secret-path
fix(cli): secret-path directive for agent
2024-01-05 10:39:39 -05:00
ee14bda706 Merge pull request #1272 from rlaisqls/error-message-typos
Fix error message typos
2024-01-05 18:18:20 +04:00
e56463d52b fix(cli): secret-path directive for agent 2024-01-05 15:05:57 +01:00
ebd3d7c7c4 Merge pull request #1274 from Infisical/fix-vercel-preview-env
Fix: Vercel integration preview environment client side error
2024-01-04 10:18:25 -05:00
9ecbfe201b Update create.tsx 2024-01-04 17:42:31 +04:00
ba2a03897f update secret import create notif 2024-01-04 01:55:34 -05:00
304f14c0ed update service token create notif 2024-01-04 01:52:03 -05:00
51e5c25e16 update imports/service token crud 2024-01-04 00:55:03 -05:00
0f6490b1e7 move cli to bin folder 2024-01-03 20:17:34 -05:00
f894e48fcb remove unused import 2024-01-02 13:55:01 -05:00
37cfa22619 add back macos build 2024-01-02 13:47:15 -05:00
94557344b7 wrap cli into a docker image 2024-01-02 13:43:55 -05:00
d5063018eb Added identities, universal auth, agent to changelog 2024-01-02 10:05:43 +01:00
51d68505d3 Merge pull request #1268 from Infisical/posthog-revamp
removed posthog cli export events
2023-12-29 15:18:59 -05:00
ade27ad072 Fix typos 2023-12-29 13:26:08 +09:00
683c512bce Merge pull request #1266 from Infisical/ui-improvements
ui and docs improvements
2023-12-25 14:33:47 -05:00
43ff28b5fb added terraform useragent 2023-12-24 17:13:29 -08:00
ce41855e84 added sdk useragent and channel 2023-12-24 16:58:48 -08:00
d24461b17c removed posthog cli export events 2023-12-24 15:49:18 -08:00
1797e56f9f fixed sdk guides 2023-12-24 13:30:59 -08:00
74f3ca5356 Merge pull request #1267 from Infisical/sdk/docs-update-2
Sdk/docs update 2
2023-12-24 21:57:52 +04:00
db27beaf0b Update overview.mdx 2023-12-24 21:54:57 +04:00
d6e55f51f2 Updated Python docs 2023-12-24 21:36:47 +04:00
e9b5996567 Updated node caching docs 2023-12-24 21:36:40 +04:00
094fe73917 Updated Java caching docs 2023-12-24 21:36:31 +04:00
dc3f85e92e Re-added an updated FAQ 2023-12-24 17:11:20 +04:00
c463256058 Updated Python docs 2023-12-24 17:11:08 +04:00
8df22302fd Updated Node docs 2023-12-24 17:11:03 +04:00
f37fa2bbf5 Updated Java docs 2023-12-24 17:10:54 +04:00
597c9d6f2a fix docs sdk errors 2023-12-23 17:17:10 -08:00
24d2eea930 ui and docs improvements 2023-12-23 16:06:00 -08:00
382cb910af tps 2023-12-23 17:31:34 -05:00
6725475575 Merge pull request #1264 from Infisical/sdk/docs-update
SDK documentation update
2023-12-23 09:30:35 -08:00
026864951b Updated links 2023-12-23 15:55:20 +04:00
287ed05ab7 Removed FAQ for now 2023-12-23 15:50:14 +04:00
37b036e614 Update overview.mdx 2023-12-23 15:49:03 +04:00
024914c168 Update python.mdx 2023-12-23 15:48:24 +04:00
19e8b6d37b Update node.mdx 2023-12-23 15:48:21 +04:00
b6d648f1f3 Added Java docs 2023-12-23 15:48:14 +04:00
a514a62a29 Fixed typos 2023-12-23 15:48:02 +04:00
2f24956651 Updated coming soon description 2023-12-23 15:47:16 +04:00
13d058025c Formatting and link changes 2023-12-23 15:29:24 +04:00
8ccaa7f29b Updated python docs 2023-12-23 15:29:17 +04:00
b83964051c Added required to required fields 2023-12-23 15:29:08 +04:00
0a2b078bdc Update node.mdx 2023-12-23 15:12:39 +04:00
40d16fa996 Updated Node.js docs 2023-12-23 15:10:30 +04:00
a3739cfe50 Update overview.mdx 2023-12-21 22:24:53 -08:00
a73623258e Update kubernetes-helm.mdx 2023-12-21 17:47:49 -08:00
6da39f41a6 Merge pull request #1263 from Infisical/restyle-self-hosting-docs
Restyle self-hosting docs for Docker / Docker Compose
2023-12-20 19:53:21 +07:00
69bbbfcfd8 Restyle self-hosting docs for Docker / Docker Compose 2023-12-20 19:52:17 +07:00
c9d58ec77d Merge pull request #1262 from Infisical/self-hosting-railway
Add self-hosting docs for Railway
2023-12-20 17:06:54 +07:00
cb364186d8 Add self-hosting docs for Railway 2023-12-20 17:05:28 +07:00
918afe05b6 Merge pull request #1261 from Infisical/self-hosting-aws-lightsail
Finish self-hosting docs for AWS Lightsail
2023-12-20 15:56:05 +07:00
e822820151 Finish self-hosting docs for AWS Lightsail 2023-12-20 15:42:02 +07:00
b5ac49eefe Merge pull request #1258 from akhilmhdh/feat/token-expire-null
fix: made expire optional on service token creation
2023-12-19 09:35:16 -05:00
b21d1a0ed2 Merge pull request #1259 from Infisical/self-hosting-azure-app-service
Add self-hosting docs for Azure App Service
2023-12-19 21:01:06 +07:00
70f1122362 Add self-hosting docs for Azure App Service 2023-12-19 20:57:08 +07:00
ea03db8a2c fix: made expire optional on service token creation 2023-12-19 15:46:03 +05:30
38d9abca17 Merge pull request #1257 from Infisical/self-hosting-azure-container-instances
Add self-hosting docs for Azure Container Instances
2023-12-19 15:21:01 +07:00
5bed2580c3 Add self-hosting docs for Azure Container Instances 2023-12-19 15:19:24 +07:00
d0b899897b Merge pull request #1256 from Infisical/add-crd-owner
add crd owner
2023-12-18 19:26:26 -05:00
1861dc85de add crd owner 2023-12-18 19:25:23 -05:00
bc6bf33674 Merge pull request #1253 from Infisical/self-hosting-gcp-cloud-run
Add docs for deploying Infisical with GCP Cloud Run
2023-12-18 16:54:00 +07:00
44fd35baf5 Add docs for deploying Infisical with GCP Cloud Run 2023-12-18 16:52:28 +07:00
8ddfee4c36 Merge pull request #1252 from Infisical/self-hosting-flyio
Add self-hosting docs for Fly.io
2023-12-18 12:11:32 +07:00
4d0bff4377 Add self-hosting docs for Fly.io 2023-12-18 12:10:18 +07:00
c7b2489d0b fix: backend/package.json & backend/package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-PROBOT-6129524
2023-12-17 14:48:29 +00:00
68eb0f8dd9 throw bad request when max uses reached 2023-12-15 15:40:20 -05:00
5941e8e836 Merge pull request #1248 from akhilmhdh/fix/secret-approval-patch
fix: secret approval loading failed for commiter on approval
2023-12-15 09:29:41 -05:00
80e50d13ec fix: secret approval loading failed for commiter on approval 2023-12-15 18:10:54 +05:30
99c8dda4e1 Merge pull request #1247 from Infisical/sso-docs
Update SSO docs to use Mintlify steps
2023-12-15 13:58:31 +07:00
14c8e3fa3b Update SSO docs to use Mintlify steps 2023-12-15 13:54:28 +07:00
7aa3cb53a2 Merge pull request #1246 from Infisical/patch-5
extract base from template source path
2023-12-14 15:19:39 -05:00
567309e848 extract base from template source path 2023-12-14 15:17:14 -05:00
f264340903 Merge pull request #1245 from Infisical/saml-org-redirect
Update redirect to org after SAML SSO
2023-12-14 23:12:31 +07:00
51b788cc5b Update redirect to org after SSO 2023-12-14 23:07:22 +07:00
8e0f424249 Merge pull request #1244 from Infisical/integrations-docs
Add Mintlify steps to integration pages
2023-12-14 12:08:39 +07:00
f3767d3963 Add Mintlify steps to integration pages 2023-12-14 11:35:50 +07:00
51cbfdbc46 update uni auth doc image paths 2023-12-13 19:32:16 -05:00
f5a580eb72 fix broken link to uni auth 2023-12-13 19:15:06 -05:00
460ebf3296 patch getDistinctId 2023-12-13 19:12:02 -05:00
7f7f11c970 Merge pull request #1243 from Infisical/patch-4
parse bot not found in agent
2023-12-13 18:25:27 -05:00
f799e224a0 use RequestError instead of Error for bot 2023-12-13 18:22:29 -05:00
8a87277fe6 parse bot not found in agent 2023-12-13 18:07:39 -05:00
32805c726a add docs for uni auth in agent 2023-12-13 17:27:30 -05:00
6c4a6d31e4 Merge pull request #1229 from Infisical/identities-docs
Update Identities Documentation + related API Reference Items
2023-12-13 16:57:13 -05:00
e7b89b645f Merge branch 'main' into identities-docs 2023-12-13 16:56:35 -05:00
b60cf2eb07 make minor updates to auth docs 2023-12-13 16:52:57 -05:00
cf5a79995f revert defaults to 30 days 2023-12-13 16:52:23 -05:00
c51f09fd3a Merge pull request #1241 from Infisical/patch-3
sync package.lock frontend
2023-12-13 14:45:48 -05:00
f9444c5205 sync package.lock frontend 2023-12-13 14:31:10 -05:00
7dd0943b2d remove sleep from template engine agent 2023-12-13 14:19:30 -05:00
31a9f032b3 Merge pull request #1236 from akhilmhdh/feat/bring-back-secret-index
feat: brought back secret indexing popup in overview page
2023-12-13 12:59:37 -05:00
9c55d1906d Merge pull request #1239 from Infisical/workspace-key-log
add workspace id and receiver to getWorkspaceKey error
2023-12-13 11:28:14 -05:00
ff54a20ace add workspace id and receiver to getWorkspaceKey error 2023-12-13 11:22:10 -05:00
8bf7eba07b fix: show popup only for admins 2023-12-13 11:55:44 +05:30
bb75ea550a prevent access token ttl=0 2023-12-12 22:17:46 -05:00
344f7276d2 update agent command description 2023-12-12 21:55:41 -05:00
c375662411 Merge pull request #1238 from Infisical/add-universal-auth-to-agent
add universal auth to agent
2023-12-12 20:36:16 -05:00
cc4ad1df4b update docs for agent 2023-12-12 20:24:17 -05:00
c92c0f7288 add universal auth to agent 2023-12-12 19:36:48 -05:00
fbe0cf006f add max ttl to renew and login api responses 2023-12-12 19:35:45 -05:00
d2f959558e fix: resolved recursion issue in select 2023-12-12 22:29:38 +05:30
e50c89e326 feat: brought back secret indexing popup in overview page 2023-12-12 21:03:47 +05:30
6cda14328b Update getting started guide for fetching secrets via API 2023-12-12 17:59:56 +07:00
b551ee50e7 Fix merge conflicts 2023-12-12 15:50:14 +07:00
93aeacc6b6 Add API reference docs for identity / universal auth endpoints 2023-12-12 13:42:17 +07:00
f940f8b79d remove unused methods in cli 2023-12-11 16:52:47 -05:00
72ac2c04b8 Merge pull request #1228 from rawkode/fix/injecting-breaks-env
fix: "Injecting..." status string can be omitted by log levels
2023-12-11 16:41:58 -05:00
bb3d591f21 remove cli update notification delay 2023-12-11 15:14:49 -05:00
763ce1b206 Merge pull request #1230 from Infisical/non-zero-max-ttl
non-zero-max-ttl
2023-12-11 14:39:18 -05:00
1f97ac5192 non-zero-max-ttl 2023-12-11 14:21:51 -05:00
5f29562fad Update existing endpoints in API reference to support Identities, update Identities docs 2023-12-11 20:01:32 +07:00
f3e8ef1537 Merge pull request #1192 from Infisical/stv3-org-roles
Add Identities + Universal Auth Authentication Method
2023-12-10 16:57:39 -05:00
544d37bbc4 fix: "Injecting..." status stirng can be omitted by log levels
When using `infisical run`, I am often running another command
that needs to be processed or consumed by another; such as:

infisical run -- supabase status -o env

The Injecting string was being printed directly to stdout and
stopping such scripting from being successful, without further
adding tail -n+2.

This change defaults the output to the INFO logging level, which
means the behaviour is the exact same for everything; however
those who wish can omit this output with -l error|fatal
2023-12-10 16:13:38 +00:00
4f6adb50d1 Minor UX update to identities 2023-12-10 22:35:12 +07:00
444ce9508d Resolve PR review items, moved identity auth logic into separate controller, etc. 2023-12-10 14:15:25 +07:00
aabd896c37 Updated changelog 2023-12-09 16:58:16 -08:00
50ef23e8a0 Restructure MIs to more generic Identity 2023-12-09 22:18:38 +07:00
b87f51a044 Update Chart.yaml 2023-12-08 17:26:19 -05:00
1233d9c1a0 Merge pull request #1223 from Infisical/patch-k8s-dependency-vulnerability
update resty + patch kube-proxy
2023-12-08 17:25:55 -05:00
ff0b4d7f2b Merge pull request #1225 from Infisical/upgrade-axios
Address axios vulnerability
2023-12-08 17:25:19 -05:00
ef61bc6a40 upgrade axios 2023-12-08 16:26:42 -05:00
13ee8c4e13 Merge pull request #1224 from Infisical/resolve-x/net-vulnerability
Update Resty
2023-12-08 16:01:06 -05:00
6ea9fc7134 update resty 2023-12-08 15:49:48 -05:00
89d0c0e3c3 temporarily disable max access token ttl 2023-12-06 20:45:07 -05:00
a4f6b828ad fix update machine params + default to no max ttl 2023-12-06 20:35:26 -05:00
0fb2056b8b update delete client secret to revoke client secret 2023-12-06 18:16:14 -05:00
ec5cf97f18 Add case for MI token renewal 2023-12-07 00:29:08 +07:00
69b57817d6 Switch access token tracking to be persistent, add num uses, draft token renewal, update docs 2023-12-07 00:11:16 +07:00
aafbe40c02 add machineIdentityAccessToken model 2023-12-05 16:58:21 -05:00
9d9b83f909 fix expired client secret logic 2023-12-05 16:38:43 -05:00
ea1f144b54 add index to machine identity model 2023-12-05 16:37:16 -05:00
591f33ffbe Move MI endpoints from v3 to v1 2023-12-05 22:24:25 +07:00
855158d0bb Allow MI to create another MI test 2023-12-05 19:34:43 +07:00
87e997e7a0 Replace most getUserOrgPermissions with more generic getAuthDataOrgPermissions for MIs in backend 2023-12-05 19:20:30 +07:00
3c449214d1 Add error messages for MI expired client secret, num uses limit reached 2023-12-05 17:53:35 +07:00
d813f0716f Switch RBAC flag 2023-12-05 17:47:46 +07:00
6787c0eaaa Update authz logic for MI 2023-12-05 17:46:50 +07:00
c91f6521c1 Update MI fields numUses, numUsesLimit, ttl, added modal for delete client secret confirmation 2023-12-05 11:15:57 +07:00
0ebd1d3d81 Merge branch 'stv3-org-roles' of https://github.com/Infisical/infisical into stv3-org-roles 2023-12-05 08:57:50 +07:00
d257a449bb add compound index to machineIdentityClientSecretDataSchema 2023-12-04 19:42:09 -05:00
6a744c96e5 add index to workspace to improve query 2023-12-04 19:41:40 -05:00
28b617fd89 Update MI docs for client id/secret 2023-12-04 23:04:04 +07:00
8b1eaad7b5 Fix audit logs UI rendering 2023-12-04 18:23:04 +07:00
c917cf8a18 Add logging to MI secret endpoints 2023-12-04 17:48:32 +07:00
282830e7a2 Fix lint issues 2023-12-04 16:24:55 +07:00
3d6f04b94e Merge remote-tracking branch 'origin' into stv3-org-roles 2023-12-04 16:15:14 +07:00
60a5092947 Merge remote-tracking branch 'origin' into stv3-org-roles 2023-12-04 16:14:31 +07:00
69dae1f0b2 Move MI from refresh token to client id / client secrets approach 2023-12-04 16:13:00 +07:00
6557d7668e Add docs for MIs 2023-11-29 15:55:15 +07:00
77e3d10a64 Flip RBAC 2023-11-27 15:50:59 +07:00
814b71052d Update error-handling, show underprivileged notification error 2023-11-27 15:50:00 +07:00
6579b3c93f Update MI authz logic 2023-11-27 14:19:10 +07:00
99c41bb63b Add no access role, replace ST V3 refs with machine 2023-11-27 09:59:15 +07:00
63df0dba64 Add default org and project-level no access roles 2023-11-26 17:02:03 +07:00
4e050cfe7a Fix frontend lint issues 2023-11-26 13:34:50 +07:00
32f5c96dd2 Move custom role paywall to assignment step 2023-11-26 13:18:49 +07:00
5b923c25b5 Added authz logic to MI 2023-11-25 18:37:20 +07:00
29016fbb23 Fix populate service in getAuthDataProjectPermissions 2023-11-24 20:10:50 +07:00
0c0139ac8f Restyle project members page 2023-11-24 20:00:40 +07:00
180274be34 Add endpoint to update MI project-level roles 2023-11-24 19:50:01 +07:00
595a26a366 Update ST V3 to machine identity 2023-11-24 19:19:31 +07:00
41c41a647f Standardize org members page styling 2023-11-24 14:09:56 +07:00
c3d2b7d3fc Pull main 2023-11-23 18:00:07 +07:00
87984a704a Fix merge conflicts 2023-11-23 15:37:14 +07:00
33e4104e98 Fix merge conflicts 2023-11-23 15:36:19 +07:00
597e1e1ca8 Continue ST V3 roles 2023-11-23 11:56:56 +07:00
1443 changed files with 124750 additions and 72992 deletions

View File

@ -3,6 +3,7 @@ on:
push:
tags:
- "infisical/v*.*.*"
- "!infisical/v*.*.*-postgres"
jobs:
backend-image:

View File

@ -0,0 +1,57 @@
name: Release standalone docker image
on:
push:
tags:
- "infisical/v*.*.*-postgres"
jobs:
infisical-standalone:
name: Build infisical standalone image postgres
runs-on: ubuntu-latest
steps:
- name: Extract version from tag
id: extract_version
run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}"
- name: ☁️ Checkout source
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 📦 Install dependencies to test all dependencies
run: npm ci --only-production
working-directory: backend
- name: version output
run: |
echo "Output Value: ${{ steps.version.outputs.major }}"
echo "Output Value: ${{ steps.version.outputs.minor }}"
echo "Output Value: ${{ steps.version.outputs.patch }}"
echo "Output Value: ${{ steps.version.outputs.version }}"
echo "Output Value: ${{ steps.version.outputs.version_type }}"
echo "Output Value: ${{ steps.version.outputs.increment }}"
- name: Save commit hashes for tag
id: commit
uses: pr-mpt/actions-commit-hash@v2
- name: 🔧 Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: 🐋 Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Depot CLI
uses: depot/setup-action@v1
- name: 📦 Build backend and export to Docker
uses: depot/build-push-action@v1
with:
project: 64mmf0n610
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
push: true
context: .
tags: |
infisical/infisical:latest-postgres
infisical/infisical:${{ steps.commit.outputs.short }}
infisical/infisical:${{ steps.extract_version.outputs.version }}
platforms: linux/amd64,linux/arm64
file: Dockerfile.standalone-infisical
build-args: |
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}

View File

@ -3,6 +3,7 @@ on:
push:
tags:
- "infisical/v*.*.*"
- "!infisical/v*.*.*-postgres"
jobs:
infisical-standalone:

3
.gitignore vendored
View File

@ -1,6 +1,7 @@
# backend
node_modules
.env
.env.test
.env.dev
.env.gamma
.env.prod
@ -61,4 +62,4 @@ yarn-error.log*
# Editor specific
.vscode/*
frontend-build
frontend-build

View File

@ -108,7 +108,7 @@ brews:
zsh_completion.install "completions/infisical.zsh" => "_infisical"
fish_completion.install "completions/infisical.fish"
man1.install "manpages/infisical.1.gz"
- name: 'infisical@{{.Version}}'
- name: "infisical@{{.Version}}"
tap:
owner: Infisical
name: homebrew-get-cli
@ -186,12 +186,14 @@ aurs:
# man pages
install -Dm644 "./manpages/infisical.1.gz" "${pkgdir}/usr/share/man/man1/infisical.1.gz"
# dockers:
# - dockerfile: cli/docker/Dockerfile
# goos: linux
# goarch: amd64
# ids:
# - infisical
# image_templates:
# - "infisical/cli:{{ .Version }}"
# - "infisical/cli:latest"
dockers:
- dockerfile: docker/alpine
goos: linux
goarch: amd64
ids:
- all-other-builds
image_templates:
- "infisical/cli:{{ .Version }}"
- "infisical/cli:{{ .Major }}.{{ .Minor }}"
- "infisical/cli:{{ .Major }}"
- "infisical/cli:latest"

View File

@ -2,7 +2,7 @@ ARG POSTHOG_HOST=https://app.posthog.com
ARG POSTHOG_API_KEY=posthog-api-key
ARG INTERCOM_ID=intercom-id
FROM node:16-alpine AS base
FROM node:20-alpine AS base
FROM base AS frontend-dependencies
@ -73,6 +73,7 @@ RUN npm ci --only-production
COPY /backend .
COPY --chown=non-root-user:nodejs standalone-entrypoint.sh standalone-entrypoint.sh
RUN npm i -D tsconfig-paths
RUN npm run build
# Production stage
@ -103,14 +104,17 @@ ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
WORKDIR /
COPY --from=backend-runner /app /backend
COPY --from=backend-runner /app/dist/services/smtp/templates /backend/dist/templates
COPY --from=frontend-runner /app ./backend/frontend-build
ENV PORT 8080
ENV HOST=0.0.0.0
ENV HTTPS_ENABLED false
ENV NODE_ENV production
ENV STANDALONE_BUILD true
ENV STANDALONE_MODE true
WORKDIR /backend
ENV TELEMETRY_ENABLED true
@ -119,10 +123,8 @@ HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
CMD node healthcheck.js
EXPOSE 8080
EXPOSE 443
USER non-root-user
CMD ["./standalone-entrypoint.sh"]

View File

@ -7,6 +7,9 @@ push:
up-dev:
docker-compose -f docker-compose.dev.yml up --build
up-pg-dev:
docker compose -f docker-compose.pg.yml up --build
i-dev:
infisical run -- docker-compose -f docker-compose.dev.yml up --build

View File

@ -129,7 +129,7 @@ Note that this security address should be used only for undisclosed vulnerabilit
## Contributing
Whether it's big or small, we love contributions. Check out our guide to see how to [get started](https://infisical.com/docs/contributing/overview).
Whether it's big or small, we love contributions. Check out our guide to see how to [get started](https://infisical.com/docs/contributing/getting-started).
Not sure where to get started? You can:

View File

@ -0,0 +1,11 @@
node_modules
.env
.env.*
.git
.gitignore
Dockerfile
.dockerignore
docker-compose.*
.DS_Store
*.swp
*~

View File

@ -0,0 +1,2 @@
node_modules
built

33
backend-mongo/Dockerfile Normal file
View File

@ -0,0 +1,33 @@
# Build stage
FROM node:16-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only-production
COPY . .
RUN npm run build
# Production stage
FROM node:16-alpine
WORKDIR /app
ENV npm_config_cache /home/node/.npm
COPY package*.json ./
RUN npm ci --only-production && npm cache clean --force
COPY --from=build /app .
RUN apk add --no-cache bash curl && curl -1sLf \
'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \
&& apk add infisical=0.8.1 && apk add --no-cache git
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
CMD node healthcheck.js
EXPOSE 4000
CMD ["node", "build/index.js"]

View File

Before

Width:  |  Height:  |  Size: 493 KiB

After

Width:  |  Height:  |  Size: 493 KiB

View File

@ -0,0 +1,6 @@
{
"watch": ["src"],
"ext": ".ts,.js",
"ignore": [],
"exec": "ts-node ./src/index.ts"
}

32861
backend-mongo/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

148
backend-mongo/package.json Normal file
View File

@ -0,0 +1,148 @@
{
"dependencies": {
"@aws-sdk/client-secrets-manager": "^3.319.0",
"@casl/ability": "^6.5.0",
"@casl/mongoose": "^7.2.1",
"@godaddy/terminus": "^4.12.0",
"@node-saml/passport-saml": "^4.0.4",
"@octokit/rest": "^19.0.5",
"@sentry/node": "^7.77.0",
"@sentry/tracing": "^7.48.0",
"@serdnam/pino-cloudwatch-transport": "^1.0.4",
"@types/crypto-js": "^4.1.1",
"@types/libsodium-wrappers": "^0.7.10",
"@ucast/mongo2js": "^1.3.4",
"ajv": "^8.12.0",
"argon2": "^0.30.3",
"aws-sdk": "^2.1364.0",
"axios": "^1.6.0",
"axios-retry": "^3.4.0",
"bcrypt": "^5.1.0",
"bigint-conversion": "^2.4.0",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"crypto-js": "^4.2.0",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express-async-errors": "^3.1.1",
"express-rate-limit": "^6.7.0",
"express-validator": "^6.14.2",
"handlebars": "^4.7.7",
"helmet": "^5.1.1",
"infisical-node": "^1.2.1",
"ioredis": "^5.3.2",
"jmespath": "^0.16.0",
"js-yaml": "^4.1.0",
"jsonwebtoken": "^9.0.0",
"jsrp": "^0.2.4",
"libsodium-wrappers": "^0.7.10",
"lodash": "^4.17.21",
"mongoose": "^7.4.1",
"mysql2": "^3.6.2",
"nanoid": "^3.3.6",
"node-cache": "^5.1.2",
"nodemailer": "^6.8.0",
"ora": "^5.4.1",
"passport": "^0.6.0",
"passport-github": "^1.1.0",
"passport-gitlab2": "^5.0.0",
"passport-google-oauth20": "^2.0.0",
"pg": "^8.11.3",
"pino": "^8.16.1",
"pino-http": "^8.5.1",
"posthog-node": "^2.6.0",
"probot": "^12.3.3",
"query-string": "^7.1.3",
"rate-limit-mongo": "^2.3.2",
"rimraf": "^3.0.2",
"swagger-ui-express": "^4.6.2",
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1",
"typescript": "^4.9.3",
"utility-types": "^3.10.0",
"zod": "^3.22.3"
},
"overrides": {
"rate-limit-mongo": {
"mongodb": "5.8.0"
}
},
"name": "infisical-api",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"start": "node build/index.js",
"dev": "nodemon index.js",
"swagger-autogen": "node ./swagger/index.ts",
"build": "rimraf ./build && tsc && cp -R ./src/templates ./build && cp -R ./src/data ./build",
"lint": "eslint . --ext .ts",
"lint-and-fix": "eslint . --ext .ts --fix",
"lint-staged": "lint-staged",
"pretest": "docker compose -f test-resources/docker-compose.test.yml up -d",
"test": "cross-env NODE_ENV=test jest --verbose --testTimeout=10000 --detectOpenHandles; npm run posttest",
"test:ci": "npm test -- --watchAll=false --ci --reporters=default --reporters=jest-junit --reporters=github-actions --coverage --testLocationInResults --json --outputFile=coverage/report.json",
"posttest": "docker compose -f test-resources/docker-compose.test.yml down"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Infisical/infisical-api.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/Infisical/infisical-api/issues"
},
"homepage": "https://github.com/Infisical/infisical-api#readme",
"description": "",
"devDependencies": {
"@jest/globals": "^29.3.1",
"@posthog/plugin-scaffold": "^1.3.4",
"@swc/core": "^1.3.99",
"@swc/helpers": "^0.5.3",
"@types/bcrypt": "^5.0.0",
"@types/bcryptjs": "^2.4.2",
"@types/bull": "^4.10.0",
"@types/cookie-parser": "^1.4.3",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.14",
"@types/jest": "^29.5.0",
"@types/jmespath": "^0.15.1",
"@types/jsonwebtoken": "^8.5.9",
"@types/lodash": "^4.14.191",
"@types/node": "^18.11.3",
"@types/nodemailer": "^6.4.6",
"@types/passport": "^1.0.12",
"@types/pg": "^8.10.7",
"@types/picomatch": "^2.3.0",
"@types/pino": "^7.0.5",
"@types/supertest": "^2.0.12",
"@types/swagger-jsdoc": "^6.0.1",
"@types/swagger-ui-express": "^4.1.3",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.40.1",
"cross-env": "^7.0.3",
"eslint": "^8.26.0",
"eslint-plugin-unused-imports": "^2.0.0",
"install": "^0.13.0",
"jest": "^29.3.1",
"jest-junit": "^15.0.0",
"nodemon": "^2.0.19",
"npm": "^8.19.3",
"pino-pretty": "^10.2.3",
"regenerator-runtime": "^0.14.0",
"smee-client": "^1.2.3",
"supertest": "^6.3.3",
"swagger-autogen": "^2.23.5",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1"
},
"jest-junit": {
"outputDirectory": "reports",
"outputName": "jest-junit.xml",
"ancestorSeparator": " ",
"uniqueOutputName": "false",
"suiteNameTemplate": "{filepath}",
"classNameTemplate": "{classname}",
"titleTemplate": "{title}"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,9 @@ export const client = new InfisicalClient({
token: process.env.INFISICAL_TOKEN!
});
export const getIsMigrationMode = async () =>
(await client.getSecret("MIGRATION_MODE")).secretValue === "true";
export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000;
export const getEncryptionKey = async () => {
const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue;

View File

@ -3,11 +3,11 @@ import { IServerConfig, ServerConfig } from "../models/serverConfig";
let serverConfig: IServerConfig;
export const serverConfigInit = async () => {
const cfg = await ServerConfig.findOne({});
const cfg = await ServerConfig.findOne({}).lean();
if (!cfg) {
const cfg = new ServerConfig();
await cfg.save();
serverConfig = cfg;
serverConfig = cfg.toObject();
} else {
serverConfig = cfg;
}
@ -19,6 +19,6 @@ export const getServerConfig = () => serverConfig;
export const updateServerConfig = async (data: Partial<IServerConfig>) => {
const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true });
if (!cfg) throw new Error("Failed to update server config");
serverConfig = cfg;
serverConfig = cfg.toObject();
return serverConfig;
};

View File

@ -1,5 +1,5 @@
import { Request, Response } from "express";
import { getHttpsEnabled } from "../../config";
import { getHttpsEnabled, getIsMigrationMode } from "../../config";
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
import { validateRequest } from "../../helpers/validation";
@ -8,9 +8,10 @@ import { TelemetryService } from "../../services";
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
import * as reqValidator from "../../validation/admin";
export const getServerConfigInfo = (_req: Request, res: Response) => {
export const getServerConfigInfo = async (_req: Request, res: Response) => {
const config = getServerConfig();
return res.send({ config });
const isMigrationModeOn = await getIsMigrationMode();
return res.send({ config: { ...config, isMigrationModeOn } });
};
export const updateServerConfig = async (req: Request, res: Response) => {

View File

@ -3,15 +3,22 @@ import jwt from "jsonwebtoken";
import * as bigintConversion from "bigint-conversion";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const jsrp = require("jsrp");
import { LoginSRPDetail, TokenVersion, User } from "../../models";
import {
LoginSRPDetail,
TokenVersion,
User
} from "../../models";
import { clearTokens, createToken, issueAuthTokens } from "../../helpers/auth";
import { checkUserDevice } from "../../helpers/user";
import { AuthTokenType } from "../../variables";
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
import {
BadRequestError,
UnauthorizedRequestError
} from "../../utils/errors";
import {
getAuthSecret,
getHttpsEnabled,
getJwtAuthLifetime
getJwtAuthLifetime,
} from "../../config";
import { ActorType } from "../../ee/models";
import { validateRequest } from "../../helpers/validation";
@ -25,10 +32,11 @@ declare module "jsonwebtoken" {
userId: string;
refreshVersion?: number;
}
export interface ServiceRefreshTokenJwtPayload extends jwt.JwtPayload {
serviceTokenDataId: string;
export interface IdentityAccessTokenJwtPayload extends jwt.JwtPayload {
_id: string;
clientSecretId: string;
identityAccessTokenId: string;
authTokenType: string;
tokenVersion: number;
}
}
@ -266,4 +274,4 @@ export const getNewToken = async (req: Request, res: Response) => {
export const handleAuthProviderCallback = (req: Request, res: Response) => {
res.redirect(`/login/provider/success?token=${encodeURIComponent(req.providerAuthToken)}`);
};
};

View File

@ -1,4 +1,5 @@
import * as authController from "./authController";
import * as universalAuthController from "./universalAuthController";
import * as botController from "./botController";
import * as integrationAuthController from "./integrationAuthController";
import * as integrationController from "./integrationController";
@ -20,6 +21,7 @@ import * as adminController from "./adminController";
export {
authController,
universalAuthController,
botController,
integrationAuthController,
integrationController,

View File

@ -2,7 +2,7 @@ import { Request, Response } from "express";
import { Types } from "mongoose";
import { standardRequest } from "../../config/request";
import { getApps, getTeams, revokeAccess } from "../../integrations";
import { Bot, IntegrationAuth, Workspace } from "../../models";
import { Bot, IIntegrationAuth, Integration, IntegrationAuth, Workspace } from "../../models";
import { EventType } from "../../ee/models";
import { IntegrationService } from "../../services";
import { EEAuditLogService } from "../../ee/services";
@ -130,7 +130,6 @@ export const oAuthExchange = async (req: Request, res: Response) => {
export const saveIntegrationToken = async (req: Request, res: Response) => {
// TODO: refactor
// TODO: check if access token is valid for each integration
let integrationAuth;
const {
body: { workspaceId, integration, url, accessId, namespace, accessToken, refreshToken }
} = await validateRequest(reqValidator.SaveIntegrationAccessTokenV1, req);
@ -152,31 +151,21 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
if (!bot) throw new Error("Bot must be enabled to save integration access token");
integrationAuth = await IntegrationAuth.findOneAndUpdate(
{
workspace: new Types.ObjectId(workspaceId),
integration
},
{
workspace: new Types.ObjectId(workspaceId),
integration,
url,
namespace,
algorithm: ALGORITHM_AES_256_GCM,
keyEncoding: ENCODING_SCHEME_UTF8,
...(integration === INTEGRATION_GCP_SECRET_MANAGER
? {
metadata: {
authMethod: "serviceAccount"
}
let integrationAuth = await new IntegrationAuth({
workspace: new Types.ObjectId(workspaceId),
integration,
url,
namespace,
algorithm: ALGORITHM_AES_256_GCM,
keyEncoding: ENCODING_SCHEME_UTF8,
...(integration === INTEGRATION_GCP_SECRET_MANAGER
? {
metadata: {
authMethod: "serviceAccount"
}
: {})
},
{
new: true,
upsert: true
}
);
}
: {})
}).save();
// encrypt and save integration access details
if (refreshToken) {
@ -188,12 +177,12 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
// encrypt and save integration access details
if (accessId || accessToken) {
integrationAuth = await IntegrationService.setIntegrationAuthAccess({
integrationAuth = (await IntegrationService.setIntegrationAuthAccess({
integrationAuthId: integrationAuth._id.toString(),
accessId,
accessToken,
accessExpiresAt: undefined
});
})) as IIntegrationAuth;
}
if (!integrationAuth) throw new Error("Failed to save integration access token");
@ -1208,13 +1197,64 @@ export const getIntegrationAuthTeamCityBuildConfigs = async (req: Request, res:
});
};
/**
* Delete all integration authorizations and integrations for workspace with id [workspaceId]
* with integration name [integration]
* @param req
* @param res
* @returns
*/
export const deleteIntegrationAuths = async (req: Request, res: Response) => {
const {
query: { integration, workspaceId }
} = await validateRequest(reqValidator.DeleteIntegrationAuthsV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Integrations
);
const integrationAuths = await IntegrationAuth.deleteMany({
integration,
workspace: new Types.ObjectId(workspaceId)
});
const integrations = await Integration.deleteMany({
integration,
workspace: new Types.ObjectId(workspaceId)
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.UNAUTHORIZE_INTEGRATION,
metadata: {
integration
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.status(200).send({
integrationAuths,
integrations
});
}
/**
* Delete integration authorization with id [integrationAuthId]
* @param req
* @param res
* @returns
*/
export const deleteIntegrationAuth = async (req: Request, res: Response) => {
export const deleteIntegrationAuthById = async (req: Request, res: Response) => {
const {
params: { integrationAuthId }
} = await validateRequest(reqValidator.DeleteIntegrationAuthV1, req);

View File

@ -251,6 +251,21 @@ export const deleteIntegration = async (req: Request, res: Response) => {
});
if (!deletedIntegration) throw new Error("Failed to find integration");
const numOtherIntegrationsUsingSameAuth = await Integration.countDocuments({
integrationAuth: deletedIntegration.integrationAuth,
_id: {
$nin: [deletedIntegration._id]
}
});
if (numOtherIntegrationsUsingSameAuth === 0) {
// no other integrations are using the same integration auth
// -> delete integration auth associated with the integration being deleted
await IntegrationAuth.deleteOne({
_id: deletedIntegration.integrationAuth
});
}
await EEAuditLogService.createAuditLog(
req.authData,

View File

@ -4,9 +4,9 @@ import { IUser, Key, Membership, MembershipOrg, User, Workspace } from "../../mo
import { EventType, Role } from "../../ee/models";
import { deleteMembership as deleteMember, findMembership } from "../../helpers/membership";
import { sendMail } from "../../helpers/nodemailer";
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, VIEWER } from "../../variables";
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables";
import { getSiteURL } from "../../config";
import { EEAuditLogService } from "../../ee/services";
import { EEAuditLogService, EELicenseService } from "../../ee/services";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/membership";
import {
@ -129,7 +129,7 @@ export const changeMembershipRole = async (req: Request, res: Response) => {
ProjectPermissionSub.Member
);
const isCustomRole = ![ADMIN, MEMBER, VIEWER].includes(role);
const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role);
if (isCustomRole) {
const wsRole = await Role.findOne({
slug: role,
@ -137,6 +137,13 @@ export const changeMembershipRole = async (req: Request, res: Response) => {
workspace: membershipToChangeRole.workspace
});
if (!wsRole) throw BadRequestError({ message: "Role not found" });
const plan = await EELicenseService.getPlan(wsRole.organization);
if (!plan.rbac) return res.status(400).send({
message: "Failed to assign custom role due to RBAC restriction. Upgrade plan to assign custom role to member."
});
const membership = await Membership.findByIdAndUpdate(membershipId, {
role: CUSTOM,
customRole: wsRole

View File

@ -21,7 +21,7 @@ import { validateRequest } from "../../helpers/validation";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getUserOrgPermissions
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { ForbiddenError } from "@casl/ability";
@ -44,11 +44,12 @@ export const deleteMembershipOrg = async (req: Request, _res: Response) => {
if (!membershipOrgToDelete) {
throw new Error("Failed to delete organization membership that doesn't exist");
}
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: membershipOrgToDelete.organization
});
const { permission, membership: membershipOrg } = await getUserOrgPermissions(
req.user._id,
membershipOrgToDelete.organization.toString()
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Member
@ -60,7 +61,7 @@ export const deleteMembershipOrg = async (req: Request, _res: Response) => {
});
await updateSubscriptionOrgQuantity({
organizationId: membershipOrg.organization.toString()
organizationId: membershipOrgToDelete.organization.toString()
});
return membershipOrgToDelete;
@ -96,7 +97,11 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => {
body: { inviteeEmail, organizationId }
} = await validateRequest(reqValidator.InviteUserToOrgv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Member

View File

@ -1,4 +1,5 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import {
IncidentContactOrg,
Membership,
@ -14,7 +15,7 @@ import { ACCEPTED } from "../../variables";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getUserOrgPermissions
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { OrganizationNotFoundError } from "../../utils/errors";
import { ForbiddenError } from "@casl/ability";
@ -44,7 +45,10 @@ export const getOrganization = async (req: Request, res: Response) => {
} = await validateRequest(reqValidator.GetOrgv1, req);
// ensure user has membership
await getUserOrgPermissions(req.user._id, organizationId);
await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
})
const organization = await Organization.findById(organizationId);
if (!organization) {
@ -68,8 +72,12 @@ export const getOrganizationMembers = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgMembersv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Member
@ -95,7 +103,10 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgWorkspacesv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
})
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Workspace
@ -137,7 +148,10 @@ export const changeOrganizationName = async (req: Request, res: Response) => {
body: { name }
} = await validateRequest(reqValidator.ChangeOrgNamev1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Settings
@ -172,7 +186,10 @@ export const getOrganizationIncidentContacts = async (req: Request, res: Respons
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgIncidentContactv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.IncidentAccount
@ -199,7 +216,10 @@ export const addOrganizationIncidentContact = async (req: Request, res: Response
body: { email }
} = await validateRequest(reqValidator.CreateOrgIncideContact, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.IncidentAccount
@ -228,7 +248,10 @@ export const deleteOrganizationIncidentContact = async (req: Request, res: Respo
body: { email }
} = await validateRequest(reqValidator.DelOrgIncideContact, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.IncidentAccount
@ -257,7 +280,10 @@ export const createOrganizationPortalSession = async (req: Request, res: Respons
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlanBillingInfov1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
@ -321,7 +347,10 @@ export const getOrganizationMembersAndTheirWorkspaces = async (req: Request, res
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgMembersv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Member

View File

@ -111,11 +111,17 @@ export const createSecretImp = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment: secretImport.environment, secretPath: secretImport.secretPath })
);
}
const folders = await Folder.findOne({
@ -323,7 +329,7 @@ export const updateSecretImport = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, {
@ -331,6 +337,13 @@ export const updateSecretImport = async (req: Request, res: Response) => {
secretPath
})
);
secretImports.forEach(({ environment, secretPath }) => {
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
);
})
}
const orderBefore = importSecDoc.imports;
@ -453,7 +466,7 @@ export const deleteSecretImport = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, {
@ -620,7 +633,7 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
@ -677,7 +690,7 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => {
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {

View File

@ -21,7 +21,7 @@ import * as reqValidator from "../../validation/secretScanning";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getUserOrgPermissions
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { ForbiddenError } from "@casl/ability";
@ -37,8 +37,11 @@ export const createInstallationSession = async (req: Request, res: Response) =>
message: "Failed to find organization"
});
}
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.SecretScanning
@ -70,11 +73,12 @@ export const linkInstallationToOrganization = async (req: Request, res: Response
if (!installationSession) {
throw UnauthorizedRequestError();
}
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: installationSession.organization
});
const { permission } = await getUserOrgPermissions(
req.user._id,
installationSession.organization.toString()
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.SecretScanning
@ -142,7 +146,10 @@ export const getRisksForOrganization = async (req: Request, res: Response) => {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgRisksv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.SecretScanning
@ -162,7 +169,10 @@ export const updateRisksStatus = async (req: Request, res: Response) => {
body: { status }
} = await validateRequest(reqValidator.UpdateRiskStatusv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.SecretScanning

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ import { OrganizationNotFoundError } from "../../utils/errors";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getUserOrgPermissions
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { ForbiddenError } from "@casl/ability";
import { validateRequest } from "../../helpers/validation";
@ -152,7 +152,10 @@ export const createWorkspace = async (req: Request, res: Response) => {
});
}
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Workspace

View File

@ -1,6 +1,15 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { Membership, MembershipOrg, Workspace } from "../../models";
import {
IWorkspace,
Identity,
IdentityMembership,
IdentityMembershipOrg,
Membership,
MembershipOrg,
User,
Workspace
} from "../../models";
import { Role } from "../../ee/models";
import { deleteMembershipOrg } from "../../helpers/membershipOrg";
import {
@ -9,15 +18,16 @@ import {
updateSubscriptionOrgQuantity
} from "../../helpers/organization";
import { addMembershipsOrg } from "../../helpers/membershipOrg";
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
import { ACCEPTED, ADMIN, CUSTOM } from "../../variables";
import { BadRequestError, ResourceNotFoundError, UnauthorizedRequestError } from "../../utils/errors";
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS } from "../../variables";
import * as reqValidator from "../../validation/organization";
import { validateRequest } from "../../helpers/validation";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getUserOrgPermissions
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { EELicenseService } from "../../ee/services";
import { ForbiddenError } from "@casl/ability";
/**
@ -27,11 +37,12 @@ import { ForbiddenError } from "@casl/ability";
*/
export const getOrganizationMemberships = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return organization memberships'
#swagger.description = 'Return organization memberships'
#swagger.summary = 'Return organization user memberships'
#swagger.description = 'Return organization user memberships'
#swagger.security = [{
"apiKeyAuth": []
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
@ -63,7 +74,10 @@ export const getOrganizationMemberships = async (req: Request, res: Response) =>
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgMembersv2, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Member
@ -85,11 +99,12 @@ export const getOrganizationMemberships = async (req: Request, res: Response) =>
*/
export const updateOrganizationMembership = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Update organization membership'
#swagger.description = 'Update organization membership'
#swagger.summary = 'Update organization user membership'
#swagger.description = 'Update organization user membership'
#swagger.security = [{
"apiKeyAuth": []
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
@ -141,16 +156,32 @@ export const updateOrganizationMembership = async (req: Request, res: Response)
params: { organizationId, membershipId },
body: { role }
} = await validateRequest(reqValidator.UpdateOrgMemberv2, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Member
);
const isCustomRole = !["admin", "member"].includes(role);
const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role);
if (isCustomRole) {
const orgRole = await Role.findOne({ slug: role, isOrgRole: true });
const orgRole = await Role.findOne({
slug: role,
isOrgRole: true,
organization: new Types.ObjectId(organizationId)
});
if (!orgRole) throw BadRequestError({ message: "Role not found" });
const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId));
if (!plan.rbac) return res.status(400).send({
message:
"Failed to assign custom role due to RBAC restriction. Upgrade plan to assign custom role to member."
});
const membership = await MembershipOrg.findByIdAndUpdate(membershipId, {
role: CUSTOM,
@ -189,11 +220,12 @@ export const updateOrganizationMembership = async (req: Request, res: Response)
*/
export const deleteOrganizationMembership = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Delete organization membership'
#swagger.description = 'Delete organization membership'
#swagger.summary = 'Delete organization user membership'
#swagger.description = 'Delete organization user membership'
#swagger.security = [{
"apiKeyAuth": []
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
@ -227,7 +259,18 @@ export const deleteOrganizationMembership = async (req: Request, res: Response)
const {
params: { organizationId, membershipId }
} = await validateRequest(reqValidator.DeleteOrgMemberv2, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const membershipOrg = await MembershipOrg.findOne({
_id: new Types.ObjectId(membershipId),
organization: new Types.ObjectId(organizationId)
});
if (!membershipOrg) throw ResourceNotFoundError();
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: membershipOrg.organization
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Member
@ -259,7 +302,8 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
#swagger.description = 'Return projects in organization that user is part of'
#swagger.security = [{
"apiKeyAuth": []
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
@ -287,11 +331,16 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
}
}
*/
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgWorkspacesv2, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Workspace
@ -308,13 +357,27 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
).map((w) => w._id.toString())
);
const workspaces = (
await Membership.find({
user: req.user._id
}).populate("workspace")
)
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
.map((m) => m.workspace);
let workspaces: IWorkspace[] = [];
if (req.authData.authPayload instanceof Identity) {
workspaces = (
await IdentityMembership.find({
identity: req.authData.authPayload._id
}).populate<{ workspace: IWorkspace }>("workspace")
)
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
.map((m) => m.workspace);
}
if (req.authData.authPayload instanceof User) {
workspaces = (
await Membership.find({
user: req.authData.authPayload._id
}).populate<{ workspace: IWorkspace }>("workspace")
)
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
.map((m) => m.workspace);
}
return res.status(200).send({
workspaces
@ -377,3 +440,66 @@ export const deleteOrganizationById = async (req: Request, res: Response) => {
organization
});
};
/**
* Return list of identity memberships for organization with id [organizationId]
* @param req
* @param res
* @returns
*/
export const getOrganizationIdentityMemberships = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return organization identity memberships'
#swagger.description = 'Return organization identity memberships'
#swagger.security = [{
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
"description": "ID of organization",
"required": true,
"type": "string",
"in": "path"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"identityMemberships": {
"type": "array",
"items": {
$ref: "#/components/schemas/IdentityMembershipOrg"
},
"description": "Identity memberships of organization"
}
}
}
}
}
}
*/
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgIdentityMembershipsV2, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Identity
);
const identityMemberships = await IdentityMembershipOrg.find({
organization: new Types.ObjectId(organizationId)
}).populate("identity customRole");
return res.status(200).send({
identityMemberships
});
}

View File

@ -13,7 +13,7 @@ import {
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
import { ForbiddenError, subject } from "@casl/ability";
import { Types } from "mongoose";
/**
@ -86,6 +86,14 @@ export const createServiceTokenData = async (req: Request, res: Response) => {
ProjectPermissionSub.ServiceTokens
);
scopes.forEach(({ environment, secretPath }) => {
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: secretPath })
);
})
const secret = crypto.randomBytes(16).toString("hex");
const secretHash = await bcrypt.hash(secret, await getSaltRounds());

View File

@ -0,0 +1,883 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import {
IIdentity,
IdentityMembership,
IdentityMembershipOrg,
Key,
Membership,
ServiceTokenData,
Workspace
} from "../../models";
import { IRole, Role } from "../../ee/models";
import {
pullSecrets as pull,
v2PushSecrets as push,
reformatPullSecrets
} from "../../helpers/secret";
import { pushKeys } from "../../helpers/key";
import { EventService, TelemetryService } from "../../services";
import { eventPushSecrets } from "../../events";
import { EEAuditLogService } from "../../ee/services";
import { EventType } from "../../ee/models";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions,
getWorkspaceRolePermissions,
isAtLeastAsPrivilegedWorkspace
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
import { BadRequestError, ForbiddenRequestError, ResourceNotFoundError } from "../../utils/errors";
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables";
interface V2PushSecret {
type: string; // personal or shared
secretKeyCiphertext: string;
secretKeyIV: string;
secretKeyTag: string;
secretKeyHash: string;
secretValueCiphertext: string;
secretValueIV: string;
secretValueTag: string;
secretValueHash: string;
secretCommentCiphertext?: string;
secretCommentIV?: string;
secretCommentTag?: string;
secretCommentHash?: string;
}
/**
* Upload (encrypted) secrets to workspace with id [workspaceId]
* for environment [environment]
* @param req
* @param res
* @returns
*/
export const pushWorkspaceSecrets = async (req: Request, res: Response) => {
// upload (encrypted) secrets to workspace with id [workspaceId]
const postHogClient = await TelemetryService.getPostHogClient();
let { secrets }: { secrets: V2PushSecret[] } = req.body;
const { keys, environment, channel } = req.body;
const { workspaceId } = req.params;
// validate environment
const workspaceEnvs = req.membership.workspace.environments;
if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) {
throw new Error("Failed to validate environment");
}
// sanitize secrets
secrets = secrets.filter(
(s: V2PushSecret) => s.secretKeyCiphertext !== "" && s.secretValueCiphertext !== ""
);
await push({
userId: req.user._id,
workspaceId,
environment,
secrets,
channel: channel ? channel : "cli",
ipAddress: req.realIP
});
await pushKeys({
userId: req.user._id,
workspaceId,
keys
});
if (postHogClient) {
postHogClient.capture({
event: "secrets pushed",
distinctId: req.user.email,
properties: {
numberOfSecrets: secrets.length,
environment,
workspaceId,
channel: channel ? channel : "cli"
}
});
}
// trigger event - push secrets
EventService.handleEvent({
event: eventPushSecrets({
workspaceId: new Types.ObjectId(workspaceId),
environment,
secretPath: "/"
})
});
return res.status(200).send({
message: "Successfully uploaded workspace secrets"
});
};
/**
* Return (encrypted) secrets for workspace with id [workspaceId]
* for environment [environment]
* @param req
* @param res
* @returns
*/
export const pullSecrets = async (req: Request, res: Response) => {
let secrets;
const postHogClient = await TelemetryService.getPostHogClient();
const environment: string = req.query.environment as string;
const channel: string = req.query.channel as string;
const { workspaceId } = req.params;
let userId;
if (req.user) {
userId = req.user._id.toString();
} else if (req.serviceTokenData) {
userId = req.serviceTokenData.user.toString();
}
// validate environment
const workspaceEnvs = req.membership.workspace.environments;
if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) {
throw new Error("Failed to validate environment");
}
secrets = await pull({
userId,
workspaceId,
environment,
channel: channel ? channel : "cli",
ipAddress: req.realIP
});
if (channel !== "cli") {
secrets = reformatPullSecrets({ secrets });
}
if (postHogClient) {
// capture secrets pushed event in production
postHogClient.capture({
distinctId: req.user.email,
event: "secrets pulled",
properties: {
numberOfSecrets: secrets.length,
environment,
workspaceId,
channel: channel ? channel : "cli"
}
});
}
return res.status(200).send({
secrets
});
};
export const getWorkspaceKey = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return encrypted project key'
#swagger.description = 'Return encrypted project key'
#swagger.security = [{
"apiKeyAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"required": true,
"type": "string"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "array",
"items": {
$ref: "#/components/schemas/ProjectKey"
},
"description": "Encrypted project key for the given project"
}
}
}
}
*/
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceKeyV2, req);
const key = await Key.findOne({
workspace: workspaceId,
receiver: req.user._id
}).populate("sender", "+publicKey");
if (!key) throw new Error(`getWorkspaceKey: Failed to find workspace key [workspaceId=${workspaceId}] [receiver=${req.user._id}]`);
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.GET_WORKSPACE_KEY,
metadata: {
keyId: key._id.toString()
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.status(200).json(key);
};
export const getWorkspaceServiceTokenData = async (req: Request, res: Response) => {
const { workspaceId } = req.params;
const serviceTokenData = await ServiceTokenData.find({
workspace: workspaceId
}).select("+encryptedKey +iv +tag");
return res.status(200).send({
serviceTokenData
});
};
/**
* Return memberships for workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const getWorkspaceMemberships = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return project user memberships'
#swagger.description = 'Return project user memberships'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"required": true,
"type": "string"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"memberships": {
"type": "array",
"items": {
$ref: "#/components/schemas/Membership"
},
"description": "Memberships of project"
}
}
}
}
}
}
*/
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceMembershipsV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Member
);
const memberships = await Membership.find({
workspace: workspaceId
}).populate("user", "+publicKey");
return res.status(200).send({
memberships
});
};
/**
* Update role of membership with id [membershipId] to role [role]
* @param req
* @param res
* @returns
*/
export const updateWorkspaceMembership = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Update project user membership'
#swagger.description = 'Update project user membership'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"required": true,
"type": "string"
}
#swagger.parameters['membershipId'] = {
"description": "ID of project membership to update",
"required": true,
"type": "string"
}
#swagger.requestBody = {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"role": {
"type": "string",
"description": "Role to update to for project membership",
}
}
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"membership": {
$ref: "#/components/schemas/Membership",
"description": "Updated membership"
}
}
}
}
}
}
*/
const {
params: { workspaceId, membershipId },
body: { role }
} = await validateRequest(reqValidator.UpdateWorkspaceMembershipsV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Member
);
const membership = await Membership.findByIdAndUpdate(
membershipId,
{
role
},
{
new: true
}
);
return res.status(200).send({
membership
});
};
/**
* Delete workspace membership with id [membershipId]
* @param req
* @param res
* @returns
*/
export const deleteWorkspaceMembership = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Delete project user membership'
#swagger.description = 'Delete project user membership'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"required": true,
"type": "string"
}
#swagger.parameters['membershipId'] = {
"description": "ID of project membership to delete",
"required": true,
"type": "string"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"membership": {
$ref: "#/components/schemas/Membership",
"description": "Deleted membership"
}
}
}
}
}
}
*/
const {
params: { workspaceId, membershipId }
} = await validateRequest(reqValidator.DeleteWorkspaceMembershipsV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Member
);
const membership = await Membership.findByIdAndDelete(membershipId);
if (!membership) throw new Error("Failed to delete workspace membership");
await Key.deleteMany({
receiver: membership.user,
workspace: membership.workspace
});
return res.status(200).send({
membership
});
};
/**
* Change autoCapitilzation Rule of workspace
* @param req
* @param res
* @returns
*/
export const toggleAutoCapitalization = async (req: Request, res: Response) => {
const {
params: { workspaceId },
body: { autoCapitalization }
} = await validateRequest(reqValidator.ToggleAutoCapitalizationV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Settings
);
const workspace = await Workspace.findOneAndUpdate(
{
_id: workspaceId
},
{
autoCapitalization
},
{
new: true
}
);
return res.status(200).send({
message: "Successfully changed autoCapitalization setting",
workspace
});
};
/**
* Add identity with id [identityId] to workspace
* with id [workspaceId]
* @param req
* @param res
*/
export const addIdentityToWorkspace = async (req: Request, res: Response) => {
const {
params: { workspaceId, identityId },
body: {
role
}
} = await validateRequest(reqValidator.AddIdentityToWorkspaceV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.Identity
);
let identityMembership = await IdentityMembership.findOne({
identity: new Types.ObjectId(identityId),
workspace: new Types.ObjectId(workspaceId)
});
if (identityMembership) throw BadRequestError({
message: `Identity with id ${identityId} already exists in project with id ${workspaceId}`
});
const workspace = await Workspace.findById(workspaceId);
if (!workspace) throw ResourceNotFoundError();
const identityMembershipOrg = await IdentityMembershipOrg.findOne({
identity: new Types.ObjectId(identityId),
organization: workspace.organization
});
if (!identityMembershipOrg) throw ResourceNotFoundError({
message: `Failed to find identity with id ${identityId}`
});
if (!identityMembershipOrg.organization.equals(workspace.organization)) throw BadRequestError({
message: "Failed to add identity to project in another organization"
});
const rolePermission = await getWorkspaceRolePermissions(role, workspaceId);
const isAsPrivilegedAsIntendedRole = isAtLeastAsPrivilegedWorkspace(permission, rolePermission);
if (!isAsPrivilegedAsIntendedRole) throw ForbiddenRequestError({
message: "Failed to add identity to project with more privileged role"
});
let customRole;
if (role) {
const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role);
if (isCustomRole) {
customRole = await Role.findOne({
slug: role,
isOrgRole: false,
workspace: new Types.ObjectId(workspaceId)
});
if (!customRole) throw BadRequestError({ message: "Role not found" });
}
}
identityMembership = await new IdentityMembership({
identity: identityMembershipOrg.identity,
workspace: new Types.ObjectId(workspaceId),
role: customRole ? CUSTOM : role,
customRole
}).save();
return res.status(200).send({
identityMembership
});
}
/**
* Update role of identity with id [identityId] in workspace
* with id [workspaceId] to [role]
* @param req
* @param res
*/
export const updateIdentityWorkspaceRole = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Update project identity membership'
#swagger.description = 'Update project identity membership'
#swagger.security = [{
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"required": true,
"type": "string"
}
#swagger.parameters['identityId'] = {
"description": "ID of identity whose membership to update in project",
"required": true,
"type": "string"
}
#swagger.requestBody = {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"role": {
"type": "string",
"description": "Role to update to for identity project membership",
}
}
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"identityMembership": {
$ref: "#/components/schemas/IdentityMembership",
"description": "Updated identity membership"
}
}
}
}
}
}
*/
const {
params: { workspaceId, identityId },
body: {
role
}
} = await validateRequest(reqValidator.UpdateIdentityWorkspaceRoleV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Identity
);
let identityMembership = await IdentityMembership
.findOne({
identity: new Types.ObjectId(identityId),
workspace: new Types.ObjectId(workspaceId)
})
.populate<{
identity: IIdentity,
customRole: IRole
}>("identity customRole");
if (!identityMembership) throw BadRequestError({
message: `Identity with id ${identityId} does not exist in project with id ${workspaceId}`
});
const identityRolePermission = await getWorkspaceRolePermissions(
identityMembership?.customRole?.slug ?? identityMembership.role,
identityMembership.workspace.toString()
);
const isAsPrivilegedAsIdentity = isAtLeastAsPrivilegedWorkspace(permission, identityRolePermission);
if (!isAsPrivilegedAsIdentity) throw ForbiddenRequestError({
message: "Failed to update role of more privileged identity"
});
const rolePermission = await getWorkspaceRolePermissions(role, workspaceId);
const isAsPrivilegedAsIntendedRole = isAtLeastAsPrivilegedWorkspace(permission, rolePermission);
if (!isAsPrivilegedAsIntendedRole) throw ForbiddenRequestError({
message: "Failed to update identity to a more privileged role"
});
let customRole;
if (role) {
const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role);
if (isCustomRole) {
customRole = await Role.findOne({
slug: role,
isOrgRole: false,
workspace: new Types.ObjectId(workspaceId)
});
if (!customRole) throw BadRequestError({ message: "Role not found" });
}
}
identityMembership = await IdentityMembership.findOneAndUpdate(
{
identity: identityMembership.identity._id,
workspace: new Types.ObjectId(workspaceId),
},
{
role: customRole ? CUSTOM : role,
customRole
},
{
new: true
}
);
return res.status(200).send({
identityMembership
});
}
/**
* Delete identity with id [identityId] from workspace
* with id [workspaceId]
* @param req
* @param res
*/
export const deleteIdentityFromWorkspace = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Delete project identity membership'
#swagger.description = 'Delete project identity membership'
#swagger.security = [{
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"required": true,
"type": "string"
}
#swagger.parameters['identityId'] = {
"description": "ID of identity whose membership to delete in project",
"required": true,
"type": "string"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"identityMembership": {
$ref: "#/components/schemas/IdentityMembership",
"description": "Deleted identity membership"
}
}
}
}
}
}
*/
const {
params: { workspaceId, identityId }
} = await validateRequest(reqValidator.DeleteIdentityFromWorkspaceV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Identity
);
const identityMembership = await IdentityMembership
.findOne({
identity: new Types.ObjectId(identityId),
workspace: new Types.ObjectId(workspaceId)
})
.populate<{
identity: IIdentity,
customRole: IRole
}>("identity customRole");
if (!identityMembership) throw ResourceNotFoundError({
message: `Identity with id ${identityId} does not exist in project with id ${workspaceId}`
});
const identityRolePermission = await getWorkspaceRolePermissions(
identityMembership?.customRole?.slug ?? identityMembership.role,
identityMembership.workspace.toString()
);
const isAsPrivilegedAsIdentity = isAtLeastAsPrivilegedWorkspace(permission, identityRolePermission);
if (!isAsPrivilegedAsIdentity) throw ForbiddenRequestError({
message: "Failed to remove more privileged identity from project"
});
await IdentityMembership.findByIdAndDelete(identityMembership._id);
return res.status(200).send({
identityMembership
});
}
/**
* Return list of identity memberships for workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const getWorkspaceIdentityMemberships = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return project identity memberships'
#swagger.description = 'Return project identity memberships'
#swagger.security = [{
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"required": true,
"type": "string",
"in": "path"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"identityMemberships": {
"type": "array",
"items": {
$ref: "#/components/schemas/IdentityMembership"
},
"description": "Identity memberships of project"
}
}
}
}
}
}
*/
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceIdentityMembersV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Identity
);
const identityMemberships = await IdentityMembership.find({
workspace: new Types.ObjectId(workspaceId)
}).populate("identity customRole");
return res.status(200).send({
identityMemberships
});
}

View File

@ -94,7 +94,7 @@ const checkSecretsPermission = async ({
});
return { authVerifier: () => true };
}
case ActorType.SERVICE_V3: {
case ActorType.IDENTITY: {
const { permission } = await getAuthDataProjectPermissions({
authData,
workspaceId: new Types.ObjectId(workspaceId)
@ -348,7 +348,7 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
}
*/
const {
query: { secretPath, environment, workspaceId, type, include_imports },
query: { secretPath, environment, workspaceId, type, include_imports, version },
params: { secretName }
} = await validateRequest(reqValidator.GetSecretByNameRawV3, req);
@ -371,7 +371,8 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
type,
secretPath,
authData: req.authData,
include_imports
include_imports,
version
});
const key = await BotService.getWorkspaceKeyWithBot({
@ -865,7 +866,7 @@ export const getSecrets = async (req: Request, res: Response) => {
*/
export const getSecretByName = async (req: Request, res: Response) => {
const {
query: { secretPath, environment, workspaceId, type, include_imports },
query: { secretPath, environment, workspaceId, type, include_imports, version },
params: { secretName }
} = await validateRequest(reqValidator.GetSecretByNameV3, req);
@ -888,7 +889,8 @@ export const getSecretByName = async (req: Request, res: Response) => {
type,
secretPath,
authData: req.authData,
include_imports
include_imports,
version
});
return res.status(200).send({

View File

@ -1,7 +1,7 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { validateRequest } from "../../helpers/validation";
import { Membership, Secret, ServiceTokenDataV3, User } from "../../models";
import { Membership, Secret, User } from "../../models";
import { SecretService } from "../../services";
import { getAuthDataProjectPermissions } from "../../ee/services/ProjectRoleService";
import { UnauthorizedRequestError } from "../../utils/errors";
@ -140,17 +140,3 @@ export const nameWorkspaceSecrets = async (req: Request, res: Response) => {
message: "Successfully named workspace secrets"
});
};
export const getWorkspaceServiceTokenData = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceServiceTokenDataV3, req);
const serviceTokenData = await ServiceTokenDataV3.find({
workspace: new Types.ObjectId(workspaceId)
}).populate("customRole");
return res.status(200).send({
serviceTokenData
});
}

View File

@ -0,0 +1,460 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import {
IIdentity,
Identity,
IdentityAccessToken,
IdentityMembership,
IdentityMembershipOrg,
IdentityUniversalAuth,
IdentityUniversalAuthClientSecret,
Organization
} from "../../../models";
import {
EventType,
IRole,
Role
} from "../../models";
import { validateRequest } from "../../../helpers/validation";
import * as reqValidator from "../../../validation/identities";
import {
getAuthDataOrgPermissions,
getOrgRolePermissions,
isAtLeastAsPrivilegedOrg
} from "../../services/RoleService";
import {
BadRequestError,
ForbiddenRequestError,
ResourceNotFoundError,
} from "../../../utils/errors";
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS } from "../../../variables";
import {
OrgPermissionActions,
OrgPermissionSubjects
} from "../../services/RoleService";
import { EEAuditLogService } from "../../services";
import { ForbiddenError } from "@casl/ability";
/**
* Create identity
* @param req
* @param res
* @returns
*/
export const createIdentity = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Create identity'
#swagger.description = 'Create identity'
#swagger.security = [{
"bearerAuth": []
}]
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of entity to create",
"example": "development"
},
"organizationId": {
"type": "string",
"description": "ID of organization where to create identity",
"example": "dev-environment"
},
"role": {
"type": "string",
"description": "Role to assume for organization membership",
"example": "no-access"
}
},
"required": ["name", "organizationId", "role"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"identity": {
$ref: '#/definitions/Identity'
}
},
"description": "Details of the created identity"
}
}
}
}
*/
const {
body: {
name,
organizationId,
role
}
} = await validateRequest(reqValidator.CreateIdentityV1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Identity
);
const rolePermission = await getOrgRolePermissions(role, organizationId);
const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, rolePermission);
if (!hasRequiredPrivileges) throw ForbiddenRequestError({
message: "Failed to create a more privileged identity"
});
const organization = await Organization.findById(organizationId);
if (!organization) throw BadRequestError({ message: `Organization with id ${organizationId} not found` });
const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role);
let customRole;
if (isCustomRole) {
customRole = await Role.findOne({
slug: role,
isOrgRole: true,
organization: new Types.ObjectId(organizationId)
});
if (!customRole) throw BadRequestError({ message: "Role not found" });
}
const identity = await new Identity({
name
}).save();
await new IdentityMembershipOrg({
identity: identity._id,
organization: new Types.ObjectId(organizationId),
role: isCustomRole ? CUSTOM : role,
customRole
}).save();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_IDENTITY,
metadata: {
identityId: identity._id.toString(),
name
}
},
{
organizationId: new Types.ObjectId(organizationId)
}
);
return res.status(200).send({
identity
});
}
/**
* Update identity with id [identityId]
* @param req
* @param res
* @returns
*/
export const updateIdentity = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Update identity'
#swagger.description = 'Update identity'
#swagger.security = [{
"bearerAuth": []
}]
#swagger.parameters['identityId'] = {
"description": "ID of identity to update",
"required": true,
"type": "string",
"in": "path"
}
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of entity to update to",
"example": "development"
},
"role": {
"type": "string",
"description": "Role to update to for organization membership",
"example": "no-access"
}
}
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"identity": {
$ref: '#/definitions/Identity'
}
},
"description": "Details of the updated identity"
}
}
}
}
*/
const {
params: { identityId },
body: {
name,
role
}
} = await validateRequest(reqValidator.UpdateIdentityV1, req);
const identityMembershipOrg = await IdentityMembershipOrg
.findOne({
identity: new Types.ObjectId(identityId)
})
.populate<{
identity: IIdentity,
customRole: IRole
}>("identity customRole");
if (!identityMembershipOrg) throw ResourceNotFoundError({
message: `Failed to find identity with id ${identityId}`
});
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: identityMembershipOrg.organization
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Identity
);
const identityRolePermission = await getOrgRolePermissions(
identityMembershipOrg?.customRole?.slug ?? identityMembershipOrg.role,
identityMembershipOrg.organization.toString()
);
const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, identityRolePermission);
if (!hasRequiredPrivileges) throw ForbiddenRequestError({
message: "Failed to update more privileged identity"
});
if (role) {
const rolePermission = await getOrgRolePermissions(role, identityMembershipOrg.organization.toString());
const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, rolePermission);
if (!hasRequiredPrivileges) throw ForbiddenRequestError({
message: "Failed to update identity to a more privileged role"
});
}
let customRole;
if (role) {
const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role);
if (isCustomRole) {
customRole = await Role.findOne({
slug: role,
isOrgRole: true,
organization: identityMembershipOrg.organization
});
if (!customRole) throw BadRequestError({ message: "Role not found" });
}
}
const identity = await Identity.findByIdAndUpdate(
identityId,
{
name,
},
{
new: true
}
);
if (!identity) throw BadRequestError({
message: `Failed to update identity with id ${identityId}`
});
await IdentityMembershipOrg.findOneAndUpdate(
{
identity: identity._id
},
{
role: customRole ? CUSTOM : role,
...(customRole ? {
customRole
} : {}),
...(role && !customRole ? { // non-custom role
$unset: {
customRole: 1
}
} : {})
},
{
new: true
}
);
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.UPDATE_IDENTITY,
metadata: {
identityId: identity._id.toString(),
name: identity.name,
}
},
{
organizationId: identityMembershipOrg.organization
}
);
return res.status(200).send({
identity
});
}
/**
* Delete identity with id [identityId]
* @param req
* @param res
* @returns
*/
export const deleteIdentity = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Delete identity'
#swagger.description = 'Delete identity'
#swagger.security = [{
"bearerAuth": []
}]
#swagger.parameters['identityId'] = {
"description": "ID of identity",
"required": true,
"type": "string",
"in": "path"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"identity": {
$ref: '#/definitions/Identity'
}
},
"description": "Details of the deleted identity"
}
}
}
}
*/
const {
params: { identityId }
} = await validateRequest(reqValidator.DeleteIdentityV1, req);
const identityMembershipOrg = await IdentityMembershipOrg
.findOne({
identity: new Types.ObjectId(identityId)
})
.populate<{
identity: IIdentity,
customRole: IRole
}>("identity customRole");
if (!identityMembershipOrg) throw ResourceNotFoundError({
message: `Failed to find identity with id ${identityId}`
});
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: identityMembershipOrg.organization
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Identity
);
const identityRolePermission = await getOrgRolePermissions(
identityMembershipOrg?.customRole?.slug ?? identityMembershipOrg.role,
identityMembershipOrg.organization.toString()
);
const hasRequiredPrivileges = isAtLeastAsPrivilegedOrg(permission, identityRolePermission);
if (!hasRequiredPrivileges) throw ForbiddenRequestError({
message: "Failed to delete more privileged identity"
});
const identity = await Identity.findByIdAndDelete(identityMembershipOrg.identity);
if (!identity) throw ResourceNotFoundError({
message: `Identity with id ${identityId} not found`
});
await IdentityMembershipOrg.findByIdAndDelete(identityMembershipOrg._id);
await IdentityMembership.deleteMany({
identity: identityMembershipOrg.identity
});
await IdentityUniversalAuth.deleteMany({
identity: identityMembershipOrg.identity
});
await IdentityUniversalAuthClientSecret.deleteMany({
identity: identityMembershipOrg.identity
});
await IdentityAccessToken.deleteMany({
identity: identityMembershipOrg.identity
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.DELETE_IDENTITY,
metadata: {
identityId: identity._id.toString()
}
},
{
organizationId: identityMembershipOrg.organization
}
);
return res.status(200).send({
identity
});
}

View File

@ -1,3 +1,4 @@
import * as identitiesController from "./identitiesController";
import * as secretController from "./secretController";
import * as secretSnapshotController from "./secretSnapshotController";
import * as organizationsController from "./organizationsController";
@ -13,6 +14,7 @@ import * as secretRotationProviderController from "./secretRotationProviderContr
import * as secretRotationController from "./secretRotationController";
export {
identitiesController,
secretController,
secretSnapshotController,
organizationsController,

View File

@ -8,7 +8,7 @@ import * as reqValidator from "../../../validation/organization";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getUserOrgPermissions
getAuthDataOrgPermissions,
} from "../../services/RoleService";
import { ForbiddenError } from "@casl/ability";
import { Organization } from "../../../models";
@ -20,7 +20,10 @@ export const getOrganizationPlansTable = async (req: Request, res: Response) =>
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlansTablev1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
@ -42,7 +45,10 @@ export const getOrganizationPlan = async (req: Request, res: Response) => {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlanv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
@ -70,7 +76,10 @@ export const startOrganizationTrial = async (req: Request, res: Response) => {
body: { success_url }
} = await validateRequest(reqValidator.StartOrgTrailv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
@ -116,7 +125,10 @@ export const getOrganizationPlanBillingInfo = async (req: Request, res: Response
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlanBillingInfov1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
@ -149,7 +161,10 @@ export const getOrganizationPlanTable = async (req: Request, res: Response) => {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlanTablev1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
@ -176,7 +191,10 @@ export const getOrganizationBillingDetails = async (req: Request, res: Response)
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgBillingDetailsv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
@ -204,7 +222,10 @@ export const updateOrganizationBillingDetails = async (req: Request, res: Respon
body: { name, email }
} = await validateRequest(reqValidator.UpdateOrgBillingDetailsv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
@ -238,7 +259,10 @@ export const getOrganizationPmtMethods = async (req: Request, res: Response) =>
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPmtMethodsv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
@ -271,7 +295,10 @@ export const addOrganizationPmtMethod = async (req: Request, res: Response) => {
body: { success_url, cancel_url }
} = await validateRequest(reqValidator.CreateOrgPmtMethodv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
@ -312,7 +339,10 @@ export const deleteOrganizationPmtMethod = async (req: Request, res: Response) =
params: { organizationId, pmtMethodId }
} = await validateRequest(reqValidator.DelOrgPmtMethodv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Billing
@ -342,7 +372,10 @@ export const getOrganizationTaxIds = async (req: Request, res: Response) => {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgTaxIdsv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
@ -375,7 +408,10 @@ export const addOrganizationTaxId = async (req: Request, res: Response) => {
body: { type, value }
} = await validateRequest(reqValidator.CreateOrgTaxId, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
@ -412,7 +448,10 @@ export const deleteOrganizationTaxId = async (req: Request, res: Response) => {
params: { organizationId, taxId }
} = await validateRequest(reqValidator.DelOrgTaxIdv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Billing
@ -445,7 +484,10 @@ export const getOrganizationInvoices = async (req: Request, res: Response) => {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgInvoicesv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
@ -480,7 +522,10 @@ export const getOrganizationLicenses = async (req: Request, res: Response) => {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgLicencesv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing

View File

@ -15,14 +15,17 @@ import {
adminProjectPermissions,
getAuthDataProjectPermissions,
memberProjectPermissions,
noAccessProjectPermissions,
viewerProjectPermission
} from "../../services/ProjectRoleService";
import {
OrgPermissionActions,
OrgPermissionSubjects,
adminPermissions,
getAuthDataOrgPermissions,
getUserOrgPermissions,
memberPermissions
memberPermissions,
noAccessPermissions
} from "../../services/RoleService";
import { BadRequestError } from "../../../utils/errors";
import { Role } from "../../models";
@ -36,7 +39,11 @@ export const createRole = async (req: Request, res: Response) => {
const isOrgRole = !workspaceId; // if workspaceid is provided then its a workspace rule
if (isOrgRole) {
const { permission } = await getUserOrgPermissions(req.user.id, orgId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(orgId)
});
if (permission.cannot(OrgPermissionActions.Create, OrgPermissionSubjects.Role)) {
throw BadRequestError({ message: "user doesn't have the permission." });
}
@ -80,9 +87,12 @@ export const updateRole = async (req: Request, res: Response) => {
body: { name, description, slug, permissions, workspaceId, orgId }
} = await validateRequest(UpdateRoleSchema, req);
const isOrgRole = !workspaceId; // if workspaceid is provided then its a workspace rule
if (isOrgRole) {
const { permission } = await getUserOrgPermissions(req.user.id, orgId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(orgId)
});
if (permission.cannot(OrgPermissionActions.Edit, OrgPermissionSubjects.Role)) {
throw BadRequestError({ message: "User doesn't have the org permission." });
}
@ -138,7 +148,10 @@ export const deleteRole = async (req: Request, res: Response) => {
const isOrgRole = !role.workspace;
if (isOrgRole) {
const { permission } = await getUserOrgPermissions(req.user.id, role.organization.toString());
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: role.organization
});
if (permission.cannot(OrgPermissionActions.Delete, OrgPermissionSubjects.Role)) {
throw BadRequestError({ message: "User doesn't have the org permission." });
}
@ -170,7 +183,10 @@ export const getRoles = async (req: Request, res: Response) => {
const isOrgRole = !workspaceId;
if (isOrgRole) {
const { permission } = await getUserOrgPermissions(req.user.id, orgId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(orgId)
});
if (permission.cannot(OrgPermissionActions.Read, OrgPermissionSubjects.Role)) {
throw BadRequestError({ message: "User doesn't have the org permission." });
}
@ -195,6 +211,13 @@ export const getRoles = async (req: Request, res: Response) => {
description: "Complete administration access over the organization",
permissions: isOrgRole ? adminPermissions.rules : adminProjectPermissions.rules
},
{
_id: "no-access",
name: "No Access",
slug: "no-access",
description: "No access to any resources in the organization",
permissions: isOrgRole ? noAccessPermissions.rules : noAccessProjectPermissions.rules
},
{
_id: "member",
name: isOrgRole ? "Member" : "Developer",
@ -229,7 +252,7 @@ export const getUserPermissions = async (req: Request, res: Response) => {
const {
params: { orgId }
} = await validateRequest(GetUserPermission, req);
const { permission, membership } = await getUserOrgPermissions(req.user._id, orgId);
res.status(200).json({

View File

@ -17,12 +17,12 @@ export const getSecretApprovalRequestCount = async (req: Request, res: Response)
} = await validateRequest(reqValidator.getSecretApprovalRequestCount, req);
if (!(req.authData.authPayload instanceof User)) return;
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: new Types.ObjectId(workspaceId)
});
if (!membership) throw UnauthorizedRequestError();
const approvalRequestCount = await SecretApprovalRequest.aggregate([
@ -73,12 +73,12 @@ export const getSecretApprovalRequests = async (req: Request, res: Response) =>
} = await validateRequest(reqValidator.getSecretApprovalRequests, req);
if (!(req.authData.authPayload instanceof User)) return;
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: new Types.ObjectId(workspaceId)
});
if (!membership) throw UnauthorizedRequestError();
const query = {
@ -168,13 +168,13 @@ export const getSecretApprovalRequestDetails = async (req: Request, res: Respons
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
// allow to fetch only if its admin or is the committer or approver
if (
membership.role !== "admin" &&
secretApprovalRequest.committer !== membership.id &&
!secretApprovalRequest.committer.equals(membership.id) &&
!secretApprovalRequest.policy.approvers.find(
(approverId) => approverId.toString() === membership._id.toString()
)
@ -215,7 +215,7 @@ export const updateSecretApprovalReviewStatus = async (req: Request, res: Respon
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (
@ -257,7 +257,7 @@ export const mergeSecretApprovalRequest = async (req: Request, res: Response) =>
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (
@ -307,7 +307,7 @@ export const updateSecretApprovalRequestStatus = async (req: Request, res: Respo
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (

View File

@ -13,7 +13,7 @@ import { validateRequest } from "../../../helpers/validation";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getUserOrgPermissions
getAuthDataOrgPermissions
} from "../../services/RoleService";
import { ForbiddenError } from "@casl/ability";
@ -47,7 +47,10 @@ export const getSSOConfig = async (req: Request, res: Response) => {
query: { organizationId }
} = await validateRequest(reqValidator.GetSsoConfigv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Sso
@ -71,7 +74,10 @@ export const updateSSOConfig = async (req: Request, res: Response) => {
body: { organizationId, authProvider, isActive, entryPoint, issuer, cert }
} = await validateRequest(reqValidator.UpdateSsoConfigv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Sso
@ -206,7 +212,10 @@ export const createSSOConfig = async (req: Request, res: Response) => {
body: { organizationId, authProvider, isActive, entryPoint, issuer, cert }
} = await validateRequest(reqValidator.CreateSsoConfigv1, req);
const { permission } = await getUserOrgPermissions(req.user._id, organizationId);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Sso

View File

@ -2,10 +2,11 @@ import { Request, Response } from "express";
import { PipelineStage, Types } from "mongoose";
import {
Folder,
Identity,
IdentityMembership,
Membership,
Secret,
ServiceTokenData,
ServiceTokenDataV3,
TFolderSchema,
User,
Workspace
@ -17,10 +18,10 @@ import {
FolderVersion,
IPType,
ISecretVersion,
IdentityActor,
SecretSnapshot,
SecretVersion,
ServiceActor,
ServiceActorV3,
TFolderRootVersionSchema,
TrustedIP,
UserActor
@ -61,15 +62,30 @@ export const getWorkspaceSecretSnapshots = async (req: Request, res: Response) =
#swagger.description = 'Return project secret snapshots ids'
#swagger.security = [{
"apiKeyAuth": []
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"description": "ID of project where to get secret snapshots for",
"required": true,
"type": "string"
}
#swagger.parameters['environment'] = {
"description": "Slug of environment where to get secret snapshots for",
"required": true,
"type": "string",
"in": "query"
}
#swagger.parameters['directory'] = {
"description": "Path where to get secret snapshots for like / or /foo/bar. Default is /",
"required": false,
"type": "string",
"in": "query"
}
#swagger.parameters['offset'] = {
"description": "Number of secret snapshots to skip",
"required": false,
@ -194,11 +210,12 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons
#swagger.description = 'Roll back project secrets to those captured in a secret snapshot version.'
#swagger.security = [{
"apiKeyAuth": []
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of project",
"description": "ID of project where to roll back",
"required": true,
"type": "string"
}
@ -210,6 +227,14 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons
"schema": {
"type": "object",
"properties": {
"environment": {
"type": "string",
"description": "Slug of environment where to roll back"
},
"directory": {
"type": "string",
"description": "Path where to roll back for like / or /foo/bar. Default is /"
},
"version": {
"type": "integer",
"description": "Version of secret snapshot to roll back to",
@ -669,6 +694,21 @@ export const getWorkspaceAuditLogs = async (req: Request, res: Response) => {
ProjectPermissionSub.AuditLogs
);
let actorMetadataQuery = "";
if (actor) {
switch (actor?.split("-", 2)[0]) {
case ActorType.USER:
actorMetadataQuery = "actor.metadata.userId";
break;
case ActorType.SERVICE:
actorMetadataQuery = "actor.metadata.serviceId";
break;
case ActorType.IDENTITY:
actorMetadataQuery = "actor.metadata.identityId";
break;
}
}
const query = {
workspace: new Types.ObjectId(workspaceId),
...(eventType
@ -684,13 +724,9 @@ export const getWorkspaceAuditLogs = async (req: Request, res: Response) => {
...(actor
? {
"actor.type": actor.substring(0, actor.lastIndexOf("-")),
...(actor.split("-", 2)[0] === ActorType.USER
? {
"actor.metadata.userId": actor.substring(actor.lastIndexOf("-") + 1)
}
: {
"actor.metadata.serviceId": actor.substring(actor.lastIndexOf("-") + 1)
})
...({
[actorMetadataQuery]: actor.substring(actor.lastIndexOf("-") + 1)
})
}
: {}),
...(startDate || endDate
@ -702,7 +738,9 @@ export const getWorkspaceAuditLogs = async (req: Request, res: Response) => {
}
: {})
};
const auditLogs = await AuditLog.find(query).sort({ createdAt: -1 }).skip(offset).limit(limit);
return res.status(200).send({
auditLogs
});
@ -731,6 +769,7 @@ export const getWorkspaceAuditLogActorFilterOpts = async (req: Request, res: Res
const userIds = await Membership.distinct("user", {
workspace: new Types.ObjectId(workspaceId)
});
const userActors: UserActor[] = (
await User.find({
_id: {
@ -757,19 +796,25 @@ export const getWorkspaceAuditLogActorFilterOpts = async (req: Request, res: Res
}
}));
const serviceV3Actors: ServiceActorV3[] = (
await ServiceTokenDataV3.find({
workspace: new Types.ObjectId(workspaceId)
const identityIds = await IdentityMembership.distinct("identity", {
workspace: new Types.ObjectId(workspaceId)
});
const identityActors: IdentityActor[] = (
await Identity.find({
_id: {
$in: identityIds
}
})
).map((serviceTokenData) => ({
type: ActorType.SERVICE_V3,
).map((identity) => ({
type: ActorType.IDENTITY,
metadata: {
serviceId: serviceTokenData._id.toString(),
name: serviceTokenData.name
identityId: identity._id.toString(),
name: identity.name
}
}));
const actors = [...userActors, ...serviceActors, ...serviceV3Actors];
const actors = [...userActors, ...serviceActors, ...identityActors];
return res.status(200).send({
actors

View File

@ -0,0 +1,5 @@
import * as apiKeyDataController from "./apiKeyDataController";
export {
apiKeyDataController
}

View File

@ -10,7 +10,7 @@ export interface IAuditLog {
event: Event;
userAgent: string;
userAgentType: UserAgentType;
expiresAt: Date;
expiresAt?: Date;
}
const auditLogSchema = new Schema<IAuditLog>(

View File

@ -1,15 +1,17 @@
export enum ActorType {
USER = "user",
SERVICE = "service",
SERVICE_V3 = "service-v3",
// Machine = "machine"
export enum ActorType { // would extend to AWS, Azure, ...
USER = "user", // userIdentity
SERVICE = "service",
IDENTITY = "identity"
}
export enum UserAgentType {
WEB = "web",
CLI = "cli",
K8_OPERATOR = "k8-operator",
OTHER = "other"
TERRAFORM = "terraform",
OTHER = "other",
PYTHON_SDK = "InfisicalPythonSDK",
NODE_SDK = "InfisicalNodeSDK"
}
export enum EventType {
@ -32,9 +34,16 @@ export enum EventType {
DELETE_TRUSTED_IP = "delete-trusted-ip",
CREATE_SERVICE_TOKEN = "create-service-token", // v2
DELETE_SERVICE_TOKEN = "delete-service-token", // v2
CREATE_SERVICE_TOKEN_V3 = "create-service-token-v3", // v3
UPDATE_SERVICE_TOKEN_V3 = "update-service-token-v3", // v3
DELETE_SERVICE_TOKEN_V3 = "delete-service-token-v3", // v3
CREATE_IDENTITY = "create-identity",
UPDATE_IDENTITY = "update-identity",
DELETE_IDENTITY = "delete-identity",
LOGIN_IDENTITY_UNIVERSAL_AUTH = "login-identity-universal-auth",
ADD_IDENTITY_UNIVERSAL_AUTH = "add-identity-universal-auth",
UPDATE_IDENTITY_UNIVERSAL_AUTH = "update-identity-universal-auth",
GET_IDENTITY_UNIVERSAL_AUTH = "get-identity-universal-auth",
CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "create-identity-universal-auth-client-secret",
REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "revoke-identity-universal-auth-client-secret",
GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS = "get-identity-universal-auth-client-secret",
CREATE_ENVIRONMENT = "create-environment",
UPDATE_ENVIRONMENT = "update-environment",
DELETE_ENVIRONMENT = "delete-environment",

View File

@ -1,5 +1,5 @@
import { ActorType, EventType } from "./enums";
import { IServiceTokenV3TrustedIp } from "../../../models/serviceTokenDataV3";
import { IIdentityTrustedIp } from "../../../models";
interface UserActorMetadata {
userId: string;
@ -11,6 +11,11 @@ interface ServiceActorMetadata {
name: string;
}
interface IdentityActorMetadata {
identityId: string;
name: string;
}
export interface UserActor {
type: ActorType.USER;
metadata: UserActorMetadata;
@ -21,16 +26,12 @@ export interface ServiceActor {
metadata: ServiceActorMetadata;
}
export interface ServiceActorV3 {
type: ActorType.SERVICE_V3;
metadata: ServiceActorMetadata;
export interface IdentityActor {
type: ActorType.IDENTITY;
metadata: IdentityActorMetadata;
}
// export interface MachineActor {
// type: ActorType.Machine;
// }
export type Actor = UserActor | ServiceActor | ServiceActorV3;
export type Actor = UserActor | ServiceActor | IdentityActor;
interface GetSecretsEvent {
type: EventType.GET_SECRETS;
@ -220,36 +221,91 @@ interface DeleteServiceTokenEvent {
};
}
interface CreateServiceTokenV3Event {
type: EventType.CREATE_SERVICE_TOKEN_V3;
interface CreateIdentityEvent { // note: currently not logging org-role
type: EventType.CREATE_IDENTITY;
metadata: {
identityId: string;
name: string;
isActive: boolean;
role: string;
trustedIps: Array<IServiceTokenV3TrustedIp>;
expiresAt?: Date;
};
}
interface UpdateServiceTokenV3Event {
type: EventType.UPDATE_SERVICE_TOKEN_V3;
interface UpdateIdentityEvent {
type: EventType.UPDATE_IDENTITY;
metadata: {
identityId: string;
name?: string;
isActive?: boolean;
role?: string;
trustedIps?: Array<IServiceTokenV3TrustedIp>;
expiresAt?: Date;
};
}
interface DeleteServiceTokenV3Event {
type: EventType.DELETE_SERVICE_TOKEN_V3;
interface DeleteIdentityEvent {
type: EventType.DELETE_IDENTITY;
metadata: {
name: string;
isActive: boolean;
role: string;
expiresAt?: Date;
trustedIps: Array<IServiceTokenV3TrustedIp>;
identityId: string;
};
}
interface LoginIdentityUniversalAuthEvent {
type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH ;
metadata: {
identityId: string;
identityUniversalAuthId: string;
clientSecretId: string;
identityAccessTokenId: string;
};
}
interface AddIdentityUniversalAuthEvent {
type: EventType.ADD_IDENTITY_UNIVERSAL_AUTH;
metadata: {
identityId: string;
clientSecretTrustedIps: Array<IIdentityTrustedIp>;
accessTokenTTL: number;
accessTokenMaxTTL: number;
accessTokenNumUsesLimit: number;
accessTokenTrustedIps: Array<IIdentityTrustedIp>;
};
}
interface UpdateIdentityUniversalAuthEvent {
type: EventType.UPDATE_IDENTITY_UNIVERSAL_AUTH;
metadata: {
identityId: string;
clientSecretTrustedIps?: Array<IIdentityTrustedIp>;
accessTokenTTL?: number;
accessTokenMaxTTL?: number;
accessTokenNumUsesLimit?: number;
accessTokenTrustedIps?: Array<IIdentityTrustedIp>;
};
}
interface GetIdentityUniversalAuthEvent {
type: EventType.GET_IDENTITY_UNIVERSAL_AUTH;
metadata: {
identityId: string;
};
}
interface CreateIdentityUniversalAuthClientSecretEvent {
type: EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ;
metadata: {
identityId: string;
clientSecretId: string;
};
}
interface GetIdentityUniversalAuthClientSecretsEvent {
type: EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS;
metadata: {
identityId: string;
};
}
interface RevokeIdentityUniversalAuthClientSecretEvent {
type: EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ;
metadata: {
identityId: string;
clientSecretId: string;
};
}
@ -495,9 +551,16 @@ export type Event =
| DeleteTrustedIPEvent
| CreateServiceTokenEvent
| DeleteServiceTokenEvent
| CreateServiceTokenV3Event
| UpdateServiceTokenV3Event
| DeleteServiceTokenV3Event
| CreateIdentityEvent
| UpdateIdentityEvent
| DeleteIdentityEvent
| LoginIdentityUniversalAuthEvent
| AddIdentityUniversalAuthEvent
| UpdateIdentityUniversalAuthEvent
| GetIdentityUniversalAuthEvent
| CreateIdentityUniversalAuthClientSecretEvent
| GetIdentityUniversalAuthClientSecretsEvent
| RevokeIdentityUniversalAuthClientSecretEvent
| CreateEnvironmentEvent
| UpdateEnvironmentEvent
| DeleteEnvironmentEvent

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