Compare commits

..

2297 Commits

Author SHA1 Message Date
Maidul Islam
6ecd289e6c update rate limits 2024-01-27 18:38:57 -05:00
Maidul Islam
b8a6f5dc54 add email templates and disposable_emails.text to build 2024-01-27 18:15:12 -05:00
Maidul Islam
dedbc4fd60 remove unused imports 2024-01-27 17:11:40 -05:00
Maidul Islam
d14099990f remove notice 2024-01-27 17:04:53 -05:00
Maidul Islam
3f5ab2a09e remove console.log 2024-01-27 17:04:02 -05:00
Maidul Islam
a191f437e9 patch blind index route 2024-01-27 17:03:16 -05:00
Maidul Islam
1a375ec45b patch import * 2024-01-27 12:35:53 -05:00
Maidul Islam
81f3a6a7a8 add loca host to docker prod 2024-01-27 12:27:15 -05:00
Maidul Islam
dc8b64708a add debug logs 2024-01-27 11:20:17 -05:00
Maidul Islam
dd3790c995 patch git workflow 2024-01-27 10:31:30 -05:00
Maidul Islam
a91b6ebc03 new workflow for releasing standalone 2024-01-27 10:28:49 -05:00
Maidul Islam
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
Akhil Mohan
8f754d659a feat: resolved tiny bug secret blind indexing 2024-01-27 20:23:19 +05:30
Maidul Islam
bef28fea2d Update release-standalone-docker-img.yml 2024-01-27 09:42:20 -05:00
Maidul Islam
28f15de8df Update build-docker-image-to-prod.yml 2024-01-27 09:40:59 -05:00
Akhil Mohan
66d258f02b feat: changed backend-pg to backend 2024-01-27 19:14:33 +05:30
Maidul Islam
d13eafcef7 Merge pull request #1332 from akhilmhdh/feat/infisical-pg
Hello world from PG
2024-01-27 02:26:05 -05:00
Maidul Islam
6db47499de add index for blind index 2024-01-27 12:40:37 +05:30
Maidul Islam
1cefb036e0 ignore dup user and make email unique 2024-01-27 12:40:37 +05:30
Maidul Islam
af77ad8b2f update rate limits 2024-01-27 12:40:37 +05:30
Maidul Islam
dd0f9f5216 patch secret apporval request secrets 2024-01-27 12:40:37 +05:30
Maidul Islam
29df6f067e remove unnecessary concole 2024-01-27 12:40:37 +05:30
Maidul Islam
4dc9a3692e add mongo to docker compose 2024-01-27 12:40:37 +05:30
Maidul Islam
49bb2121b9 update helm values 2024-01-27 12:40:37 +05:30
Maidul Islam
07679d9318 add postgres helm chart 2024-01-27 12:40:37 +05:30
Maidul Islam
fb271726fe make emails not unique for now 2024-01-27 12:40:37 +05:30
Maidul Islam
f9e7d4ddd2 make MI access token have string id 2024-01-27 12:40:37 +05:30
Maidul Islam
442c454932 make email unique 2024-01-27 12:40:37 +05:30
Maidul Islam
8b22ee1fac coerce strings to number responses 2024-01-27 12:40:37 +05:30
Maidul Islam
8a10dc8983 make before and after more clear in roll back 2024-01-27 12:40:37 +05:30
Maidul Islam
d57920706a patch bug validateAccessTokenExp bug 2024-01-27 12:40:37 +05:30
Maidul Islam
425611b409 remove uuid from snapshot project response 2024-01-27 12:40:37 +05:30
Maidul Islam
b20489982d delete unneeded file 2024-01-27 12:40:37 +05:30
Maidul Islam
4b569ee4b4 make access token non uui 2024-01-27 12:40:37 +05:30
Akhil Mohan
af9661b221 feat(infisical-pg): minor bug fixes in frontend and pg migrator secret approval req 2024-01-27 12:40:37 +05:30
Akhil Mohan
53f16f01b8 feat(infisical-pg): fixed audit log to estimate doc count and resolve cors issue 2024-01-27 12:40:37 +05:30
Maidul Islam
f519d1cffc remove async from validateAccessTokenExp 2024-01-27 12:40:37 +05:30
Akhil Mohan
b8b28d2710 feat(infisical-pg): resolved linting issues 2024-01-27 12:40:37 +05:30
Akhil Mohan
deab700716 feat(infisical-pg): made api key backward compat 2024-01-27 12:40:37 +05:30
Akhil Mohan
4d184003a8 feat(infisical-pg): made identity ua client sec backward compat 2024-01-27 12:40:37 +05:30
Maidul Islam
9849312317 remove console 2024-01-27 12:40:37 +05:30
Akhil Mohan
79454a6aea feat(infisical-pg): fixed org bot gone missing 2024-01-27 12:40:37 +05:30
Akhil Mohan
8e0fb9fe9b feat(infisical-pg): wrapped saml get option in try catch 2024-01-27 12:40:37 +05:30
Maidul Islam
a729114376 remove prefix from redis 2024-01-27 12:40:37 +05:30
Maidul Islam
0c20cb0f91 JWT_AUTH_SECRET => AUTH_SECRET 2024-01-27 12:40:37 +05:30
Maidul Islam
d1597ed8da find by id of ormify patch 2024-01-27 12:40:37 +05:30
Maidul Islam
6cee8dc7e5 uni auth remove auth type 2024-01-27 12:40:37 +05:30
Maidul Islam
13040439c3 coerce big int from string to number from sql 2024-01-27 12:40:37 +05:30
Maidul Islam
9a4f294749 add prefix to queue 2024-01-27 12:40:37 +05:30
Maidul Islam
2436a572f0 revert to only arm build 2024-01-27 12:40:37 +05:30
Maidul Islam
7cd21e3a93 remove timeout and signal from license requester 2024-01-27 12:40:37 +05:30
Maidul Islam
e28416b50b patch service token migration backwards with mongo 2024-01-27 12:40:37 +05:30
Akhil Mohan
9677836b76 feat(infisical-pg): added telemtry service 2024-01-27 12:40:37 +05:30
Maidul Islam
ca858f8e13 rename ci 2024-01-27 12:40:37 +05:30
Maidul Islam
c2beff493f add linux/amd64,linux/arm64 for standone release 2024-01-27 12:40:37 +05:30
Maidul Islam
34fafd815c set postgres ci to only linux/arm64 2024-01-27 12:40:37 +05:30
Maidul Islam
c05ebbb864 set SmtpHost.Sendgrid secure=true 2024-01-27 12:40:37 +05:30
Maidul Islam
372f2be2f3 increase license server request time out 2024-01-27 12:40:37 +05:30
Maidul Islam
23e621f557 increase license request timeout 2024-01-27 12:40:36 +05:30
Maidul Islam
464b80140f add 443 port to docker 2024-01-27 12:40:36 +05:30
Maidul Islam
01cd496afe update status api 2024-01-27 12:40:36 +05:30
Maidul Islam
6094940a8b add success message 2024-01-27 12:40:36 +05:30
Maidul Islam
30b959babb JWT_AUTH_SECRET => AUTH_SECRET 2024-01-27 12:40:36 +05:30
Maidul Islam
cec14efe86 add logs to license server 2024-01-27 12:40:36 +05:30
Maidul Islam
b3f090d87e only amd 2024-01-27 12:40:36 +05:30
Maidul Islam
1deb6827cf add STANDALONE_MODE to docker file 2024-01-27 12:40:36 +05:30
Maidul Islam
24dbf11962 add back arm 2024-01-27 12:40:36 +05:30
Maidul Islam
20fb3906aa only amd 2024-01-27 12:40:36 +05:30
Maidul Islam
e7e2ca0f45 update postgress workflow 2024-01-27 12:40:36 +05:30
Maidul Islam
caabf2c952 patch bot keys 2024-01-27 12:40:36 +05:30
Maidul Islam
35eade0206 update to alpine node 20 2024-01-27 12:40:36 +05:30
Maidul Islam
6d1b79430d lower node alpine 2024-01-27 12:40:36 +05:30
Maidul Islam
7864524944 remove QEMU 2024-01-27 12:40:36 +05:30
Maidul Islam
adc90e91fe update build-push-actio version 2024-01-27 12:40:36 +05:30
Maidul Islam
db7db0cc04 remove version 2024-01-27 12:40:36 +05:30
Maidul Islam
aa4d9ad267 Revert "update npm time out"
This reverts commit 38a7b1acf1a445ea62dcad5b60e9624733976b78.
2024-01-27 12:40:36 +05:30
Maidul Islam
27fd857120 update npm time out 2024-01-27 12:40:36 +05:30
Maidul Islam
205e46571a remove depot 2024-01-27 12:40:36 +05:30
Maidul Islam
70a6a7cfa1 create CI for standalone image 2024-01-27 12:40:36 +05:30
Maidul Islam
558315c24b set secret blind index count to Number 2024-01-27 12:40:36 +05:30
Maidul Islam
a2bd808196 rename project roles message 2024-01-27 12:40:36 +05:30
Maidul Islam
cfb0d4ee96 add no access to org service role 2024-01-27 12:40:36 +05:30
Maidul Islam
15fc4fd609 set cascade in trusted ip for project id 2024-01-27 12:40:36 +05:30
Maidul Islam
83bff9ae14 make protectedKey protectedKeyIV protectedKeyTag nullable 2024-01-27 12:40:36 +05:30
Maidul Islam
86ba6355cf more patches to migrator 2024-01-27 12:40:36 +05:30
Akhil Mohan
6b427adfe0 feat(infisical-pg): added v3 secret blind index enable feature 2024-01-27 12:40:36 +05:30
Akhil Mohan
01f711ad19 feat(infisical-pg): completed audit log migrator 2024-01-27 12:39:54 +05:30
Akhil Mohan
fa572f7ee0 feat(infisical-pg): completed standalone and docker node version 2024-01-27 12:39:54 +05:30
Maidul Islam
249edf98e9 remove notNullable from various tables 2024-01-27 12:39:54 +05:30
Maidul Islam
753a4daf69 remove authType from mi access token 2024-01-27 12:39:54 +05:30
Maidul Islam
b9320ed9bd comment out corrupt seed files 2024-01-27 12:39:54 +05:30
Maidul Islam
8eace5528f point migrations to pg backend folder 2024-01-27 12:39:54 +05:30
Daniel Hougaard
9407c16e83 Update queue-service.ts 2024-01-27 12:39:54 +05:30
Daniel Hougaard
dcdcc40a4a Update smtp-service.ts 2024-01-27 12:39:54 +05:30
Daniel Hougaard
edd78eaeba Refactor 2024-01-27 12:39:54 +05:30
Daniel Hougaard
c21ea6fb75 Cleanup 2024-01-27 12:39:54 +05:30
Daniel Hougaard
a60dbe523b Refactor to secret queue 2024-01-27 12:39:54 +05:30
Daniel Hougaard
bb9a6b4272 Update index.ts 2024-01-27 12:39:54 +05:30
Daniel Hougaard
eaca1b694a Log 2024-01-27 12:39:54 +05:30
Daniel Hougaard
0afb44af29 Handle deletion 2024-01-27 12:39:54 +05:30
Daniel Hougaard
3b39e38c89 Secret reminder types 2024-01-27 12:39:54 +05:30
Daniel Hougaard
4189d1028d Optional secret reminder typing 2024-01-27 12:39:54 +05:30
Daniel Hougaard
f227824fb8 Added secret reminders email 2024-01-27 12:39:54 +05:30
Daniel Hougaard
49d6918297 Update secret-service.ts 2024-01-27 12:39:54 +05:30
Daniel Hougaard
00212f1c72 Secret reminder queue factory 2024-01-27 12:39:54 +05:30
Daniel Hougaard
987f0c9081 Added secret reminder service 2024-01-27 12:39:54 +05:30
Daniel Hougaard
e4f00f74e9 Added new special query for getting org from project ID 2024-01-27 12:39:54 +05:30
Daniel Hougaard
ce580f417e Registered secret reminder service 2024-01-27 12:39:54 +05:30
Daniel Hougaard
c1662d6db5 Added secret reminder to queue service 2024-01-27 12:39:54 +05:30
Daniel Hougaard
2dae59c6be Update fastify.d.ts 2024-01-27 12:39:54 +05:30
Akhil Mohan
9bd764e535 feat(infisical-pg): updated pg migrator to new table name changes 2024-01-27 12:39:54 +05:30
Akhil Mohan
e4f32f092a feat(infisical-pg): completed test for secret folder and import 2024-01-27 12:39:54 +05:30
Maidul Islam
e02c082c7a more patches for migration script 2024-01-27 12:39:54 +05:30
Akhil Mohan
80b6c4ad94 feat(infisical-pg): completed tag support to all secret operations 2024-01-27 12:39:54 +05:30
Akhil Mohan
42eb01e1e2 feat(infisical-pg): completed support for tags in secret snapshot 2024-01-27 12:39:54 +05:30
Maidul Islam
b8157122e6 patches for dangling data 2024-01-27 12:39:54 +05:30
Akhil Mohan
4f66749430 feat(infisical-pg): added secret version tag 2024-01-27 12:39:54 +05:30
Maidul Islam
bfe5ee672b patches for migration 2024-01-27 12:39:54 +05:30
Akhil Mohan
32a1a0a9e5 feat(infisical-pg): removed short form names in secret approval to long form 2024-01-27 12:39:54 +05:30
Akhil Mohan
f7e1da65d5 feat(infisical-pg): added slug for org and project, resolved build error 2024-01-27 12:39:53 +05:30
Akhil Mohan
6bf9bc1d2c feat(infisical-pg): changed all dal to DAL as said by maidul 2024-01-27 12:38:23 +05:30
Akhil Mohan
59c747cf72 feat(infisical-pg): added rate limiter and bootstrap 2024-01-27 12:38:23 +05:30
Akhil Mohan
b04030a060 feat(infisical-pg): resolved missing integration auth api 2024-01-27 12:38:23 +05:30
Akhil Mohan
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
Akhil Mohan
6c2803da93 feat(infisical-pg): crct permission for secret approval policy check 2024-01-27 12:38:23 +05:30
Akhil Mohan
4031f4a559 feat(infisical-pg): idempotent folder creation 2024-01-27 12:38:23 +05:30
Akhil Mohan
8ab89bc420 feat(infisical-pg): resolved import secret breaking cli backward compatiability 2024-01-27 12:38:23 +05:30
Akhil Mohan
e46e87d758 feat(infisical-pg): fixed secret deletion not getting triggered 2024-01-27 12:38:23 +05:30
Akhil Mohan
9c2ef15314 feat(infisical-pg): fixed missing secret path and commiter message in frontend 2024-01-27 12:38:23 +05:30
Maidul Islam
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
Maidul Islam
33c3c5ecc5 add permission check for target env/path for imports 2024-01-27 12:38:23 +05:30
Akhil Mohan
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
Akhil Mohan
8d3d4f222f feat(infisical-pg): fixed service token cli endpoint 2024-01-27 12:38:23 +05:30
Maidul Islam
65d3038414 set ignoreTrailingSlash to true in fastify 2024-01-27 12:38:23 +05:30
Akhil Mohan
6b7b888fb4 feat(infisical-pg): fixed service token return body 2024-01-27 12:38:23 +05:30
Akhil Mohan
bf059e0fe5 feat(infisical-pg): fixed secret rotation and secret approval limit offset 2024-01-27 12:38:23 +05:30
Daniel Hougaard
28fdf4ed4b Update service-token-router.ts 2024-01-27 12:38:23 +05:30
Tuan Dang
2606e42079 Correct Cloudflare Pages authorization page 2024-01-27 12:38:23 +05:30
Tuan Dang
b1285b401b Patch integration issues 2024-01-27 12:38:23 +05:30
Tuan Dang
3afafbb885 Add Makefile, pg-admin to docker compose 2024-01-27 12:38:23 +05:30
Maidul Islam
257547ff4d fix delete secret scans after git app uninstall 2024-01-27 12:38:23 +05:30
Maidul Islam
da4ae3c503 switch getSapOfFolder to check for secrets instead of approval 2024-01-27 12:38:23 +05:30
Maidul Islam
fb79e9e6fb update project add user text typo 2024-01-27 12:38:23 +05:30
Akhil Mohan
5373cb6afb feat(infisical-pg): added secret version api, fixed pass reset flow, smtp connection issue fixed 2024-01-27 12:38:23 +05:30
Daniel Hougaard
31c0bf6831 Fixed UI glitch 2024-01-27 12:38:23 +05:30
Daniel Hougaard
67618046c0 Fixed creating service tokens with no expiry 2024-01-27 12:38:23 +05:30
Maidul Islam
df642179ba fix typo 2024-01-27 12:38:23 +05:30
Daniel Hougaard
c7d0f2325c Fixed secret creation 2024-01-27 12:38:23 +05:30
Akhil Mohan
bb6d482ff9 feat(infisical-pg): added global error handler, try catch in oauth passport 2024-01-27 12:38:23 +05:30
Daniel Hougaard
4f619d7e48 Fixed signup for gitlab and github 2024-01-27 12:38:23 +05:30
Akhil Mohan
295c1e5d4a feat(infisical-pg): fixed ts issue on passport type change 2024-01-27 12:38:23 +05:30
Daniel Hougaard
0be3ad9517 Fixed eslint bug 2024-01-27 12:38:23 +05:30
Daniel Hougaard
606ed25104 Fixed GitHub auth registration issue 2024-01-27 12:38:23 +05:30
Akhil Mohan
c880a48749 feat(infisical-pg): fixed radix issue, bugs in oauth and tag cascade on 2024-01-27 12:38:23 +05:30
Akhil Mohan
92f7b45e01 feat(infisical-pg): fixed plan going undefined and resolved project missing on env delete 2024-01-27 12:38:23 +05:30
Akhil Mohan
5fe8bdc00b feat(infisical-pg): completed first version of pg migrator 2024-01-27 12:38:23 +05:30
Akhil Mohan
9f813d72f2 feat(infisical-pg): resolved multi integration auth and ip v6 support in ua 2024-01-27 12:38:23 +05:30
Akhil Mohan
d90fdac5ce feat(infisical-pg): fixed bugs in integrations and self hosted license failure 2024-01-27 12:38:23 +05:30
Akhil Mohan
87709dc86f feat(infisical-pg): first setup for postgres migration script 2024-01-27 12:38:23 +05:30
Akhil Mohan
deb8e74749 feat(infisical-pg): fixed some bugs on org invite missing auth method 2024-01-27 12:38:23 +05:30
Akhil Mohan
3519412639 feat: added secret raw endpoint and include imports 2024-01-27 12:38:23 +05:30
Akhil Mohan
0506389ada feat: added logged in based testing by injecting jwt token logic 2024-01-27 12:38:23 +05:30
Akhil Mohan
dd7c449483 feat: added login test and fixed super admin bug 2024-01-27 12:38:23 +05:30
Akhil Mohan
c7572a3374 feat: completed license server integration 2024-01-27 12:38:23 +05:30
Akhil Mohan
fe416556f2 feat: changed req.auth.userId to permission.id to satisfy type error 2024-01-27 12:38:23 +05:30
Akhil Mohan
20fb99f042 feat: added token based communications 2024-01-27 12:38:23 +05:30
Akhil Mohan
daa94db874 feat(infisical-pg): changed back to old infisical-radar url 2024-01-27 12:38:23 +05:30
Akhil Mohan
850e7bff98 feat(infisical-pg): completed secret scanner 2024-01-27 12:38:23 +05:30
Akhil Mohan
bfaf87c4c2 feat(infisical-pg): completed saml integration 2024-01-27 12:38:23 +05:30
Akhil Mohan
55f1392faf feat(infisical-pg): completed sync in secret approval 2024-01-27 12:38:23 +05:30
Akhil Mohan
0bf658e501 feat(infisical-pg): completed webhook and integration trigger queue 2024-01-27 12:38:23 +05:30
Akhil Mohan
aed94ff5bb feat(infisical-pg): resolved integration invalid cred error 2024-01-27 12:38:23 +05:30
Akhil Mohan
0d3f09d668 feat(infisical-pg): completed checklist run for dashboard 2024-01-27 12:38:23 +05:30
Akhil Mohan
16f0ac6d43 feat(infisical-pg): completed audit log moved ee routes to normal routing pattern 2024-01-27 12:38:23 +05:30
Akhil Mohan
6e6a1c87f2 feat(infisical-pg): completed secrets fetching from imports based on priority 2024-01-27 12:38:23 +05:30
Akhil Mohan
b5aa6c0000 feat(infisical-pg): completed secret rollback 2024-01-27 12:38:23 +05:30
Akhil Mohan
784cdb4201 feat(infisical-pg): completed secret rotation with queue service 2024-01-27 12:38:23 +05:30
Akhil Mohan
17e61bfc68 feat(infisical-pg): completed secret approval policy and services for approval requests 2024-01-27 12:38:23 +05:30
Akhil Mohan
a6a60b7bbb feat(infisical-pg): fixing minor compatiability issues with frontend and backend on identity 2024-01-27 12:38:23 +05:30
Akhil Mohan
d154f68a59 feat(infisical-pg: completed machine identity services 2024-01-27 12:38:23 +05:30
Akhil Mohan
f5159583ae feat(infisical-pg: completed webhook and service token 2024-01-27 12:38:23 +05:30
Akhil Mohan
771bec6d6d feat(infisical-pg): completed integration, integration auth and project bot api migration 2024-01-27 12:38:23 +05:30
Akhil Mohan
010963a80c feat(infisical-pg): completed nested folder support for secret,folder and import operations 2024-01-27 12:38:23 +05:30
Akhil Mohan
0e1191f2ea feat(infisical-pg): completed root folder level secret, secret import and folder 2024-01-27 12:38:23 +05:30
Akhil Mohan
8a6ab7f2f6 feat(infisical-pg): connected project api changes with frontend 2024-01-27 12:38:22 +05:30
Akhil Mohan
4f3582a98b feat(infisical-pg): added routes for workspaces and updated frontend 2024-01-27 12:38:22 +05:30
Akhil Mohan
498a90c484 feat(infisical-pg: linted after import order fix 2024-01-27 12:38:22 +05:30
Akhil Mohan
76e5d61da5 feat(infisical-pg: added services for project, project key and environment 2024-01-27 12:38:22 +05:30
Akhil Mohan
53bb3bc610 feat(infisical-pg): added database schema for project, its membership role and env 2024-01-27 12:38:22 +05:30
Akhil Mohan
1df7b88abf feat(infisical-pg): added e2e test setup 2024-01-27 12:38:22 +05:30
Akhil Mohan
3670b16657 feat(infisical-pg): new org role routes completed 2024-01-27 12:38:22 +05:30
Akhil Mohan
9a4b2f7d81 feat(infisical-pg): resolved type check issue and linted frontend 2024-01-27 12:38:22 +05:30
Akhil Mohan
fadb36edb8 feat(infisical-pg): removed _id with id for new backend 2024-01-27 12:38:22 +05:30
Akhil Mohan
fbe5a1adb0 feat(infisical-pg): added github,gitlab and google oauth 2024-01-27 12:38:22 +05:30
Akhil Mohan
d0695a8998 feat(infisical-pg): added a seed setup with test user creation and org creation 2024-01-27 12:38:22 +05:30
Akhil Mohan
a19e8ad016 feat(infisical-pg): updated names and simplified dal layer using ormify 2024-01-27 12:38:22 +05:30
Akhil Mohan
15b57de0ed feat(infisical-pg): test first milestone one flow 2024-01-27 12:38:22 +05:30
Akhil Mohan
aaba4a0895 feat(infisical-pg): changed frontend api types _id to normal id 2024-01-27 12:38:22 +05:30
Akhil Mohan
f3b37de3f3 feat(infisical-pg): auth injection completed and validation in password router 2024-01-27 12:38:22 +05:30
Akhil Mohan
fcfd6b3fb2 feat(infisical-pg): completed signup, login, password and backup key migration 2024-01-27 12:38:22 +05:30
Akhil Mohan
05205d1eff feat(infisical-pg): added all previous simple server middlewares, swagger support 2024-01-27 12:38:22 +05:30
Akhil Mohan
2243bcb3a4 feat: added dev and prod setup using esbuild 2024-01-27 12:38:22 +05:30
Maidul Islam
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
Maidul Islam
5b41fb0ff5 update text and patch notice 2024-01-27 00:21:57 -05:00
Maidul Islam
8893aec213 patch saml sso for rippling 2024-01-23 01:11:29 -05:00
Daniel Hougaard
c4cb8f8008 Merge pull request #1319 from Infisical/daniel/better-sdk-docs
(Docs): Improve SDK docs
2024-01-23 08:53:28 +04:00
Daniel Hougaard
046557c97f Add .NET 2024-01-23 08:47:29 +04:00
Daniel Hougaard
a15ba28c18 Update node guide to reflect new SDK 2024-01-23 08:47:20 +04:00
Daniel Hougaard
8386f4dcbd Update python guide to reflect new SDK 2024-01-23 08:47:11 +04:00
Daniel Hougaard
ada0fd9c5b Add new item for fallbacks 2024-01-23 08:47:01 +04:00
Maidul Islam
6376c29e49 update maintenace notice 2024-01-19 17:28:35 -05:00
Vladyslav Matsiiako
402692614e updated maintenance page 2024-01-19 12:59:18 -08:00
Akhil Mohan
34de6d4e29 feat(infisical-pg): added migration mode env and page 2024-01-20 01:20:14 +05:30
vmatsiiako
829e906650 Merge pull request #1311 from Infisical/daniel/changelog-jan-2024
[JAN] Changelog points
2024-01-18 20:25:52 -05:00
Daniel Hougaard
b7cbb0f1a8 Update overview.mdx 2024-01-19 00:14:03 +04:00
Daniel Hougaard
a50ffbb59d Update overview.mdx 2024-01-19 00:13:57 +04:00
Daniel Hougaard
48eda0c684 Update overview.mdx 2024-01-15 15:55:37 +04:00
Maidul Islam
ed89413689 Merge pull request #1293 from Infisical/update-blog
Update blog notification
2024-01-12 13:52:11 -05:00
Maidul Islam
0c94f77a6d Merge pull request #1302 from akhilmhdh/feat/banner
feat: added main banner for migration
2024-01-12 10:48:21 -05:00
Vladyslav Matsiiako
e6068826f8 update migration notification 2024-01-11 23:34:46 -08:00
Maidul Islam
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
Maidul Islam
134b503c28 remove log 2024-01-11 17:19:39 -05:00
Maidul Islam
efcbf1aa88 add project-config-dir flag for run command 2024-01-11 16:39:02 -05:00
vmatsiiako
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
Daniel Hougaard
1410a44610 SEO Improvements and links to packages/repos 2024-01-11 22:34:11 +04:00
Akhil Mohan
746ffb3840 feat: added main banner for migration 2024-01-11 23:09:57 +05:30
vmatsiiako
f9f12eafdf Update saml docs 2024-01-10 15:02:10 -08:00
Maidul Islam
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
Daniel Hougaard
9fe2190115 Update project.mdx 2024-01-11 02:40:37 +04:00
Maidul Islam
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
Daniel Hougaard
e88b0ad3c4 Update python.mdx 2024-01-11 01:25:10 +04:00
Daniel Hougaard
74644fd8bb Added cryptography docs and fixed formatting 2024-01-11 01:12:38 +04:00
Daniel Hougaard
2069ac1554 Added CSharp and removed unfinished SDK's 2024-01-11 01:12:26 +04:00
Daniel Hougaard
5a2516e0a7 Removed unsupported languages to remove clutter 2024-01-11 01:12:17 +04:00
Daniel Hougaard
b52bc3bed7 Added CSharp docs 2024-01-11 01:12:05 +04:00
Maidul Islam
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
Akhil Mohan
7324822be5 fix(secret-reference): fixed undefined if value not found 2024-01-10 11:45:46 +05:30
Maidul Islam
766f301aea patch agent config by env 2024-01-09 14:30:29 -05:00
Vladyslav Matsiiako
8fbc930012 updated notification text 2024-01-08 13:51:40 -08:00
Vladyslav Matsiiako
0e5190a920 added the december update blog 2024-01-08 13:47:58 -08:00
Maidul Islam
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
Daniel Hougaard
31231cfcca Update developing.mdx 2024-01-08 23:30:10 +04:00
Maidul Islam
ee772e4a77 allow reading universal auth creds from env in agent 2024-01-07 17:00:42 -05:00
Maidul Islam
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
Maidul Islam
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
BlackMagiq
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
Tuan Dang
7f17194c0f Add IPv6 consideration to default identities IP allowlist 2024-01-07 16:32:25 +01:00
Tuan Dang
1e1ad450d2 Add version query param to GET secret endpoint 2024-01-07 14:25:33 +01:00
Tuan Dang
5287b322d8 Enable new integration auth for each new integration 2024-01-07 12:49:59 +01:00
Maidul Islam
45d96be1ff added base64 support for config and templates 2024-01-06 23:43:04 -05:00
Maidul Islam
12840bfdbd add exit after auth setting 2024-01-06 17:17:21 -05:00
BlackMagiq
fef5369738 Merge pull request #1283 from Infisical/identity-apis
Update various identities items
2024-01-06 17:11:01 +01:00
Tuan Dang
c94b7d63f6 Update various identities items 2024-01-06 17:04:44 +01:00
BlackMagiq
485ddc5c50 Merge pull request #1282 from Infisical/patch-railway
Fix client-side railway integration issue
2024-01-06 16:14:16 +01:00
Tuan Dang
edd9c66e49 Remove commented print statements 2024-01-06 16:11:22 +01:00
Tuan Dang
0a3b85534b Fix client-side railway integration issue 2024-01-06 16:09:15 +01:00
Maidul Islam
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
Daniel Hougaard
7ce472957c Fixed quality 2024-01-06 04:04:09 +04:00
Daniel Hougaard
8529e0da3d Update developing.mdx 2024-01-06 03:41:31 +04:00
Daniel Hougaard
e5a5433f10 Update developing.mdx 2024-01-06 03:00:14 +04:00
Daniel Hougaard
ee6e518ff8 Update link to contribution guide 2024-01-06 02:58:26 +04:00
Daniel Hougaard
15a7222505 Update mint.json 2024-01-06 02:58:16 +04:00
Daniel Hougaard
25d482cc62 Create sdk-flow.png 2024-01-06 02:58:12 +04:00
Daniel Hougaard
785a2bec6a Added SDK guide 2024-01-06 02:58:08 +04:00
Daniel Hougaard
449466f326 Restructure 2024-01-06 02:58:02 +04:00
Daniel Hougaard
4131e9c3f1 Added getting started section 2024-01-06 02:57:53 +04:00
Daniel Hougaard
310595256f Restructured existing guide 2024-01-06 02:57:21 +04:00
Maidul Islam
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
Maidul Islam
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
Daniel Hougaard
ee14bda706 Merge pull request #1272 from rlaisqls/error-message-typos
Fix error message typos
2024-01-05 18:18:20 +04:00
Emilia
e56463d52b fix(cli): secret-path directive for agent 2024-01-05 15:05:57 +01:00
Maidul Islam
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
Daniel Hougaard
9ecbfe201b Update create.tsx 2024-01-04 17:42:31 +04:00
Maidul Islam
ba2a03897f update secret import create notif 2024-01-04 01:55:34 -05:00
Maidul Islam
304f14c0ed update service token create notif 2024-01-04 01:52:03 -05:00
Maidul Islam
51e5c25e16 update imports/service token crud 2024-01-04 00:55:03 -05:00
Maidul Islam
0f6490b1e7 move cli to bin folder 2024-01-03 20:17:34 -05:00
Maidul Islam
f894e48fcb remove unused import 2024-01-02 13:55:01 -05:00
Maidul Islam
37cfa22619 add back macos build 2024-01-02 13:47:15 -05:00
Maidul Islam
94557344b7 wrap cli into a docker image 2024-01-02 13:43:55 -05:00
Tuan Dang
d5063018eb Added identities, universal auth, agent to changelog 2024-01-02 10:05:43 +01:00
Maidul Islam
51d68505d3 Merge pull request #1268 from Infisical/posthog-revamp
removed posthog cli export events
2023-12-29 15:18:59 -05:00
rlaisqls
ade27ad072 Fix typos 2023-12-29 13:26:08 +09:00
Maidul Islam
683c512bce Merge pull request #1266 from Infisical/ui-improvements
ui and docs improvements
2023-12-25 14:33:47 -05:00
Vladyslav Matsiiako
43ff28b5fb added terraform useragent 2023-12-24 17:13:29 -08:00
Vladyslav Matsiiako
ce41855e84 added sdk useragent and channel 2023-12-24 16:58:48 -08:00
Vladyslav Matsiiako
d24461b17c removed posthog cli export events 2023-12-24 15:49:18 -08:00
Vladyslav Matsiiako
1797e56f9f fixed sdk guides 2023-12-24 13:30:59 -08:00
Daniel Hougaard
74f3ca5356 Merge pull request #1267 from Infisical/sdk/docs-update-2
Sdk/docs update 2
2023-12-24 21:57:52 +04:00
Daniel Hougaard
db27beaf0b Update overview.mdx 2023-12-24 21:54:57 +04:00
Daniel Hougaard
d6e55f51f2 Updated Python docs 2023-12-24 21:36:47 +04:00
Daniel Hougaard
e9b5996567 Updated node caching docs 2023-12-24 21:36:40 +04:00
Daniel Hougaard
094fe73917 Updated Java caching docs 2023-12-24 21:36:31 +04:00
Daniel Hougaard
dc3f85e92e Re-added an updated FAQ 2023-12-24 17:11:20 +04:00
Daniel Hougaard
c463256058 Updated Python docs 2023-12-24 17:11:08 +04:00
Daniel Hougaard
8df22302fd Updated Node docs 2023-12-24 17:11:03 +04:00
Daniel Hougaard
f37fa2bbf5 Updated Java docs 2023-12-24 17:10:54 +04:00
Vladyslav Matsiiako
597c9d6f2a fix docs sdk errors 2023-12-23 17:17:10 -08:00
Vladyslav Matsiiako
24d2eea930 ui and docs improvements 2023-12-23 16:06:00 -08:00
Maidul Islam
382cb910af tps 2023-12-23 17:31:34 -05:00
vmatsiiako
6725475575 Merge pull request #1264 from Infisical/sdk/docs-update
SDK documentation update
2023-12-23 09:30:35 -08:00
Daniel Hougaard
026864951b Updated links 2023-12-23 15:55:20 +04:00
Daniel Hougaard
287ed05ab7 Removed FAQ for now 2023-12-23 15:50:14 +04:00
Daniel Hougaard
37b036e614 Update overview.mdx 2023-12-23 15:49:03 +04:00
Daniel Hougaard
024914c168 Update python.mdx 2023-12-23 15:48:24 +04:00
Daniel Hougaard
19e8b6d37b Update node.mdx 2023-12-23 15:48:21 +04:00
Daniel Hougaard
b6d648f1f3 Added Java docs 2023-12-23 15:48:14 +04:00
Daniel Hougaard
a514a62a29 Fixed typos 2023-12-23 15:48:02 +04:00
Daniel Hougaard
2f24956651 Updated coming soon description 2023-12-23 15:47:16 +04:00
Daniel Hougaard
13d058025c Formatting and link changes 2023-12-23 15:29:24 +04:00
Daniel Hougaard
8ccaa7f29b Updated python docs 2023-12-23 15:29:17 +04:00
Daniel Hougaard
b83964051c Added required to required fields 2023-12-23 15:29:08 +04:00
Daniel Hougaard
0a2b078bdc Update node.mdx 2023-12-23 15:12:39 +04:00
Daniel Hougaard
40d16fa996 Updated Node.js docs 2023-12-23 15:10:30 +04:00
vmatsiiako
a3739cfe50 Update overview.mdx 2023-12-21 22:24:53 -08:00
vmatsiiako
a73623258e Update kubernetes-helm.mdx 2023-12-21 17:47:49 -08:00
BlackMagiq
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
Tuan Dang
69bbbfcfd8 Restyle self-hosting docs for Docker / Docker Compose 2023-12-20 19:52:17 +07:00
BlackMagiq
c9d58ec77d Merge pull request #1262 from Infisical/self-hosting-railway
Add self-hosting docs for Railway
2023-12-20 17:06:54 +07:00
Tuan Dang
cb364186d8 Add self-hosting docs for Railway 2023-12-20 17:05:28 +07:00
BlackMagiq
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
Tuan Dang
e822820151 Finish self-hosting docs for AWS Lightsail 2023-12-20 15:42:02 +07:00
Maidul Islam
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
BlackMagiq
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
Tuan Dang
70f1122362 Add self-hosting docs for Azure App Service 2023-12-19 20:57:08 +07:00
Akhil Mohan
ea03db8a2c fix: made expire optional on service token creation 2023-12-19 15:46:03 +05:30
BlackMagiq
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
Tuan Dang
5bed2580c3 Add self-hosting docs for Azure Container Instances 2023-12-19 15:19:24 +07:00
Maidul Islam
d0b899897b Merge pull request #1256 from Infisical/add-crd-owner
add crd owner
2023-12-18 19:26:26 -05:00
Maidul Islam
1861dc85de add crd owner 2023-12-18 19:25:23 -05:00
BlackMagiq
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
Tuan Dang
44fd35baf5 Add docs for deploying Infisical with GCP Cloud Run 2023-12-18 16:52:28 +07:00
BlackMagiq
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
Tuan Dang
4d0bff4377 Add self-hosting docs for Fly.io 2023-12-18 12:10:18 +07:00
snyk-bot
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
Maidul Islam
68eb0f8dd9 throw bad request when max uses reached 2023-12-15 15:40:20 -05:00
Maidul Islam
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
Akhil Mohan
80e50d13ec fix: secret approval loading failed for commiter on approval 2023-12-15 18:10:54 +05:30
BlackMagiq
99c8dda4e1 Merge pull request #1247 from Infisical/sso-docs
Update SSO docs to use Mintlify steps
2023-12-15 13:58:31 +07:00
Tuan Dang
14c8e3fa3b Update SSO docs to use Mintlify steps 2023-12-15 13:54:28 +07:00
Maidul Islam
7aa3cb53a2 Merge pull request #1246 from Infisical/patch-5
extract base from template source path
2023-12-14 15:19:39 -05:00
Maidul Islam
567309e848 extract base from template source path 2023-12-14 15:17:14 -05:00
BlackMagiq
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
Tuan Dang
51b788cc5b Update redirect to org after SSO 2023-12-14 23:07:22 +07:00
BlackMagiq
8e0f424249 Merge pull request #1244 from Infisical/integrations-docs
Add Mintlify steps to integration pages
2023-12-14 12:08:39 +07:00
Tuan Dang
f3767d3963 Add Mintlify steps to integration pages 2023-12-14 11:35:50 +07:00
Maidul Islam
51cbfdbc46 update uni auth doc image paths 2023-12-13 19:32:16 -05:00
Maidul Islam
f5a580eb72 fix broken link to uni auth 2023-12-13 19:15:06 -05:00
Maidul Islam
460ebf3296 patch getDistinctId 2023-12-13 19:12:02 -05:00
Maidul Islam
7f7f11c970 Merge pull request #1243 from Infisical/patch-4
parse bot not found in agent
2023-12-13 18:25:27 -05:00
Maidul Islam
f799e224a0 use RequestError instead of Error for bot 2023-12-13 18:22:29 -05:00
Maidul Islam
8a87277fe6 parse bot not found in agent 2023-12-13 18:07:39 -05:00
Maidul Islam
32805c726a add docs for uni auth in agent 2023-12-13 17:27:30 -05:00
Maidul Islam
6c4a6d31e4 Merge pull request #1229 from Infisical/identities-docs
Update Identities Documentation + related API Reference Items
2023-12-13 16:57:13 -05:00
Maidul Islam
e7b89b645f Merge branch 'main' into identities-docs 2023-12-13 16:56:35 -05:00
Maidul Islam
b60cf2eb07 make minor updates to auth docs 2023-12-13 16:52:57 -05:00
Maidul Islam
cf5a79995f revert defaults to 30 days 2023-12-13 16:52:23 -05:00
Maidul Islam
c51f09fd3a Merge pull request #1241 from Infisical/patch-3
sync package.lock frontend
2023-12-13 14:45:48 -05:00
Maidul Islam
f9444c5205 sync package.lock frontend 2023-12-13 14:31:10 -05:00
Maidul Islam
7dd0943b2d remove sleep from template engine agent 2023-12-13 14:19:30 -05:00
Maidul Islam
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
Maidul Islam
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
Maidul Islam
ff54a20ace add workspace id and receiver to getWorkspaceKey error 2023-12-13 11:22:10 -05:00
Akhil Mohan
8bf7eba07b fix: show popup only for admins 2023-12-13 11:55:44 +05:30
Maidul Islam
bb75ea550a prevent access token ttl=0 2023-12-12 22:17:46 -05:00
Maidul Islam
344f7276d2 update agent command description 2023-12-12 21:55:41 -05:00
Maidul Islam
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
Maidul Islam
cc4ad1df4b update docs for agent 2023-12-12 20:24:17 -05:00
Maidul Islam
c92c0f7288 add universal auth to agent 2023-12-12 19:36:48 -05:00
Maidul Islam
fbe0cf006f add max ttl to renew and login api responses 2023-12-12 19:35:45 -05:00
Akhil Mohan
d2f959558e fix: resolved recursion issue in select 2023-12-12 22:29:38 +05:30
Akhil Mohan
e50c89e326 feat: brought back secret indexing popup in overview page 2023-12-12 21:03:47 +05:30
Tuan Dang
6cda14328b Update getting started guide for fetching secrets via API 2023-12-12 17:59:56 +07:00
Tuan Dang
b551ee50e7 Fix merge conflicts 2023-12-12 15:50:14 +07:00
Tuan Dang
93aeacc6b6 Add API reference docs for identity / universal auth endpoints 2023-12-12 13:42:17 +07:00
Maidul Islam
f940f8b79d remove unused methods in cli 2023-12-11 16:52:47 -05:00
Maidul Islam
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
Maidul Islam
bb3d591f21 remove cli update notification delay 2023-12-11 15:14:49 -05:00
Maidul Islam
763ce1b206 Merge pull request #1230 from Infisical/non-zero-max-ttl
non-zero-max-ttl
2023-12-11 14:39:18 -05:00
Maidul Islam
1f97ac5192 non-zero-max-ttl 2023-12-11 14:21:51 -05:00
Tuan Dang
5f29562fad Update existing endpoints in API reference to support Identities, update Identities docs 2023-12-11 20:01:32 +07:00
Maidul Islam
f3e8ef1537 Merge pull request #1192 from Infisical/stv3-org-roles
Add Identities + Universal Auth Authentication Method
2023-12-10 16:57:39 -05:00
David Flanagan
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
Tuan Dang
4f6adb50d1 Minor UX update to identities 2023-12-10 22:35:12 +07:00
Tuan Dang
444ce9508d Resolve PR review items, moved identity auth logic into separate controller, etc. 2023-12-10 14:15:25 +07:00
vmatsiiako
aabd896c37 Updated changelog 2023-12-09 16:58:16 -08:00
Tuan Dang
50ef23e8a0 Restructure MIs to more generic Identity 2023-12-09 22:18:38 +07:00
Maidul Islam
b87f51a044 Update Chart.yaml 2023-12-08 17:26:19 -05:00
Maidul Islam
1233d9c1a0 Merge pull request #1223 from Infisical/patch-k8s-dependency-vulnerability
update resty + patch kube-proxy
2023-12-08 17:25:55 -05:00
Maidul Islam
ff0b4d7f2b Merge pull request #1225 from Infisical/upgrade-axios
Address axios vulnerability
2023-12-08 17:25:19 -05:00
Maidul Islam
ef61bc6a40 upgrade axios 2023-12-08 16:26:42 -05:00
Maidul Islam
13ee8c4e13 Merge pull request #1224 from Infisical/resolve-x/net-vulnerability
Update Resty
2023-12-08 16:01:06 -05:00
Maidul Islam
6ea9fc7134 update resty 2023-12-08 15:49:48 -05:00
Maidul Islam
00e1742a30 Merge branch 'main' into patch-k8s-dependency-vulnerability 2023-12-08 15:36:45 -05:00
Maidul Islam
5055b5402c update kube proxy for helm 2023-12-08 15:35:54 -05:00
Maidul Islam
ff9418c0c7 patch: loop variable deployment captured by func literal 2023-12-08 15:35:22 -05:00
Maidul Islam
d03921eef3 update resty + patch kube-proxy 2023-12-08 15:17:01 -05:00
Maidul Islam
602afdefc3 Merge pull request #1221 from Infisical/k8s-doc-update-secret-type
add docs for k8 secret type and label propagation
2023-12-07 20:12:53 -05:00
Maidul Islam
5eb505326b add docs for k8 secret type and label propagation 2023-12-07 20:10:11 -05:00
Maidul Islam
fcf4153d87 Update Chart.yaml 2023-12-07 19:34:08 -05:00
Maidul Islam
097282c5e1 Merge pull request #1182 from Allex1/secret
Make secret type field configurable
2023-12-07 19:31:39 -05:00
Maidul Islam
0eeef9a66c revert managed secret name 2023-12-07 19:30:43 -05:00
Maidul Islam
df0bec8a68 update chart version 2023-12-07 19:28:57 -05:00
Maidul Islam
13014b5345 create separate struct for managed secret + propagate lables/annotations 2023-12-07 19:26:48 -05:00
Maidul Islam
66d0cae066 Merge pull request #1220 from akhilmhdh/fix/update-secret-approval
fix(secret-approval): resolved update failure in secret approval mode
2023-12-07 13:19:34 -05:00
Akhil Mohan
8e82222fc5 fix(secret-approval): resolved update failure in secret approval mode and number not increasing on frontend 2023-12-07 23:48:00 +05:30
Maidul Islam
f822bcd10f Merge pull request #1218 from ntimo/patch-1
Fixed 'SMTP_PASSWORD' default value
2023-12-07 11:54:44 -05:00
Maidul Islam
89d0c0e3c3 temporarily disable max access token ttl 2023-12-06 20:45:07 -05:00
Maidul Islam
a4f6b828ad fix update machine params + default to no max ttl 2023-12-06 20:35:26 -05:00
Maidul Islam
0fb2056b8b update delete client secret to revoke client secret 2023-12-06 18:16:14 -05:00
Timo
c51f8c5838 Fixed 'SMTP_PASSWORD' default value 2023-12-06 21:41:34 +01:00
Tuan Dang
ec5cf97f18 Add case for MI token renewal 2023-12-07 00:29:08 +07:00
Tuan Dang
69b57817d6 Switch access token tracking to be persistent, add num uses, draft token renewal, update docs 2023-12-07 00:11:16 +07:00
Maidul Islam
aafbe40c02 add machineIdentityAccessToken model 2023-12-05 16:58:21 -05:00
Maidul Islam
9d9b83f909 fix expired client secret logic 2023-12-05 16:38:43 -05:00
Maidul Islam
ea1f144b54 add index to machine identity model 2023-12-05 16:37:16 -05:00
Tuan Dang
591f33ffbe Move MI endpoints from v3 to v1 2023-12-05 22:24:25 +07:00
Tuan Dang
855158d0bb Allow MI to create another MI test 2023-12-05 19:34:43 +07:00
Tuan Dang
87e997e7a0 Replace most getUserOrgPermissions with more generic getAuthDataOrgPermissions for MIs in backend 2023-12-05 19:20:30 +07:00
Tuan Dang
3c449214d1 Add error messages for MI expired client secret, num uses limit reached 2023-12-05 17:53:35 +07:00
Tuan Dang
d813f0716f Switch RBAC flag 2023-12-05 17:47:46 +07:00
Tuan Dang
6787c0eaaa Update authz logic for MI 2023-12-05 17:46:50 +07:00
Alex Birca
377a79f17d Make secret type field configurable 2023-12-05 10:13:20 +02:00
Tuan Dang
c91f6521c1 Update MI fields numUses, numUsesLimit, ttl, added modal for delete client secret confirmation 2023-12-05 11:15:57 +07:00
Tuan Dang
0ebd1d3d81 Merge branch 'stv3-org-roles' of https://github.com/Infisical/infisical into stv3-org-roles 2023-12-05 08:57:50 +07:00
Maidul Islam
d257a449bb add compound index to machineIdentityClientSecretDataSchema 2023-12-04 19:42:09 -05:00
Maidul Islam
6a744c96e5 add index to workspace to improve query 2023-12-04 19:41:40 -05:00
vmatsiiako
2a768a7bc4 Update postgres.mdx 2023-12-04 16:18:50 -08:00
Tuan Dang
28b617fd89 Update MI docs for client id/secret 2023-12-04 23:04:04 +07:00
Tuan Dang
8b1eaad7b5 Fix audit logs UI rendering 2023-12-04 18:23:04 +07:00
Tuan Dang
c917cf8a18 Add logging to MI secret endpoints 2023-12-04 17:48:32 +07:00
Tuan Dang
282830e7a2 Fix lint issues 2023-12-04 16:24:55 +07:00
Tuan Dang
3d6f04b94e Merge remote-tracking branch 'origin' into stv3-org-roles 2023-12-04 16:15:14 +07:00
Tuan Dang
60a5092947 Merge remote-tracking branch 'origin' into stv3-org-roles 2023-12-04 16:14:31 +07:00
Tuan Dang
69dae1f0b2 Move MI from refresh token to client id / client secrets approach 2023-12-04 16:13:00 +07:00
Maidul Islam
4b41664fa4 chores: clean login 2023-12-02 13:28:32 -05:00
Maidul Islam
735cf093f0 Merge pull request #1210 from Infisical/hide-blind-index
Hide blind index notice
2023-11-30 18:15:58 -05:00
Maidul Islam
98906f190c Merge pull request #1205 from Infisical/add-docs-for-folders-cli
add docs for folder cli command
2023-11-30 17:28:49 -05:00
Maidul Islam
5f80e2f432 Merge pull request #1205 from Infisical/add-docs-for-folders-cli
add docs for folder cli command
2023-11-29 10:03:06 -05:00
Maidul Islam
afd6a7736a add docs for folder cli command 2023-11-29 09:57:45 -05:00
Tuan Dang
057fcb164d Add missing secret rotation link in changelog 2023-11-29 17:02:57 +07:00
BlackMagiq
b575c0e207 Merge pull request #1203 from Infisical/update-changelog
Update Changelog
2023-11-29 17:00:46 +07:00
Tuan Dang
372afa2111 Update changelog 2023-11-29 16:58:12 +07:00
Tuan Dang
6557d7668e Add docs for MIs 2023-11-29 15:55:15 +07:00
Vladyslav Matsiiako
33017b50f0 add filter for secret pull events 2023-11-28 20:09:32 -08:00
vmatsiiako
f5de501348 Fix typo in docs 2023-11-28 18:17:16 -08:00
Maidul Islam
758c3a2423 Merge pull request #1193 from quinton11/feat/cli-folder-cmd
feat: cli-folders-cmd
2023-11-28 19:31:04 -05:00
Maidul Islam
d01c6e4df9 remove init from folders cmd 2023-11-28 19:30:08 -05:00
Maidul Islam
ed94d218fd move folders to secrets 2023-11-28 19:27:30 -05:00
Daniel Hougaard
adc7be2e84 Merge pull request #1198 from DanielHougaard/daniel/assignment
(feat): Secret reminders
2023-11-28 19:58:40 +04:00
Daniel Hougaard
697485f8ed Requested changes 2023-11-28 19:46:59 +04:00
Maidul Islam
19e2523d0e Merge pull request #1196 from Infisical/infisica-agent
Infisical Agent
2023-11-28 10:24:55 -05:00
Daniel Hougaard
8851987ac4 Update secrets.ts 2023-11-28 13:50:47 +04:00
Daniel Hougaard
64d862ebe9 More typing updates 2023-11-28 13:50:42 +04:00
Daniel Hougaard
70d1cc0e06 Fixed rebase oopsie and updated for days instead of cron 2023-11-28 13:50:33 +04:00
Daniel Hougaard
aee91a9558 Updated jobs to work without cron 2023-11-28 13:50:10 +04:00
Daniel Hougaard
d6218eaa82 Removed cron libs 2023-11-28 13:49:42 +04:00
Daniel Hougaard
8886e57d4f Updated typings 2023-11-28 13:49:28 +04:00
Daniel Hougaard
6efb58da1a Fixed UI jumping 2023-11-28 13:49:08 +04:00
Daniel Hougaard
f187cc2c26 Removed cron functionality completely 2023-11-28 13:28:00 +04:00
Daniel Hougaard
d5c5495475 Fix bug with updating overwritten secrets 2023-11-28 12:07:02 +04:00
Daniel Hougaard
8e33692cda Update package-lock.json 2023-11-28 11:36:49 +04:00
Daniel Hougaard
6c31e70f4f Update code-of-conduct.mdx 2023-11-28 11:17:09 +04:00
Daniel Hougaard
d7026cbbfa Super tiny docs update 2023-11-28 11:13:54 +04:00
Daniel Hougaard
df0e0bf988 Fix issue when saving reminders on personal secrets 2023-11-28 11:00:13 +04:00
Maidul Islam
640366a0ec update path examples 2023-11-28 00:57:12 -05:00
Maidul Islam
ab5514fcf7 add docs for agent auth and template details 2023-11-28 00:55:06 -05:00
Maidul Islam
c8951f347b start agent docs overview 2023-11-27 20:08:04 -05:00
Maidul Islam
d76f556464 remove frontend sv3 changes 2023-11-27 18:32:05 -05:00
Maidul Islam
6ccaa24e59 add agent refresh and template render 2023-11-27 18:15:08 -05:00
Daniel Hougaard
4ec0c9cdbf Merge branch 'daniel/assignment' of https://github.com/DanielHougaard/infisical into daniel/assignment 2023-11-28 01:25:42 +04:00
Daniel Hougaard
75cd3bfa35 Cleanup 2023-11-28 01:22:57 +04:00
Daniel Hougaard
1db7d50a09 Cleanup 2023-11-28 01:22:48 +04:00
Daniel Hougaard
b4980b4a53 Clear when re-opening form 2023-11-28 01:22:35 +04:00
Daniel Hougaard
1351ba936f Some linting 2023-11-28 00:55:52 +04:00
Daniel Hougaard
57bccaefba UI improvements 2023-11-28 00:54:55 +04:00
Daniel Hougaard
86af452888 Removed log 2023-11-28 00:54:55 +04:00
Daniel Hougaard
6cef7532da Update sendSecretReminders.ts 2023-11-28 00:54:55 +04:00
Daniel Hougaard
74e33144a7 Update secret.ts 2023-11-28 00:54:55 +04:00
Daniel Hougaard
a9776eaeb5 Cleanup 2023-11-28 00:54:55 +04:00
Daniel Hougaard
3c2a66f722 Lint 2023-11-28 00:54:55 +04:00
Daniel Hougaard
d92b1d3cd8 Create secretReminder.handlebars 2023-11-28 00:54:55 +04:00
Daniel Hougaard
f560242f1d Sending out the emails 2023-11-28 00:54:55 +04:00
Daniel Hougaard
33fc968055 Reminders 2023-11-28 00:54:55 +04:00
Daniel Hougaard
f289b99cf1 Packages 2023-11-28 00:54:55 +04:00
Daniel Hougaard
019b477d2d Reminder helpers for creating and deleting crons 2023-11-28 00:54:55 +04:00
Daniel Hougaard
9ad2d9d218 Added secret reminder handler on updates 2023-11-28 00:54:55 +04:00
Daniel Hougaard
a575530ddf Package 2023-11-28 00:51:28 +04:00
Daniel Hougaard
33ea019d70 Clear when re-opening form 2023-11-28 00:48:08 +04:00
Daniel Hougaard
5ae3b66e2e Some linting 2023-11-28 00:09:31 +04:00
Daniel Hougaard
20210d7471 UI improvements 2023-11-27 23:57:35 +04:00
Tuan Dang
77e3d10a64 Flip RBAC 2023-11-27 15:50:59 +07:00
Tuan Dang
814b71052d Update error-handling, show underprivileged notification error 2023-11-27 15:50:00 +07:00
Tuan Dang
6579b3c93f Update MI authz logic 2023-11-27 14:19:10 +07:00
Tuan Dang
99c41bb63b Add no access role, replace ST V3 refs with machine 2023-11-27 09:59:15 +07:00
Tuan Dang
63df0dba64 Add default org and project-level no access roles 2023-11-26 17:02:03 +07:00
Tuan Dang
4e050cfe7a Fix frontend lint issues 2023-11-26 13:34:50 +07:00
Tuan Dang
32f5c96dd2 Move custom role paywall to assignment step 2023-11-26 13:18:49 +07:00
Vladyslav Matsiiako
d7262d4291 Added rbac to docs navigation and fixed typos 2023-11-25 18:32:37 -08:00
Vladyslav Matsiiako
7a9221769d Added docs for rbac 2023-11-25 18:03:54 -08:00
Vladyslav Matsiiako
5e5761424a fix typos in docs 2023-11-25 09:12:17 -08:00
Tuan Dang
5b923c25b5 Added authz logic to MI 2023-11-25 18:37:20 +07:00
quinton
46c76e3984 chore: refactor 2023-11-25 10:11:53 +00:00
quinton
b212681d09 feat: cli-folders-cmd 2023-11-25 09:44:51 +00:00
Vladyslav Matsiiako
be67b9b341 Added docs for PR Workflows 2023-11-24 22:08:09 -08:00
Tuan Dang
29016fbb23 Fix populate service in getAuthDataProjectPermissions 2023-11-24 20:10:50 +07:00
Tuan Dang
0c0139ac8f Restyle project members page 2023-11-24 20:00:40 +07:00
Tuan Dang
180274be34 Add endpoint to update MI project-level roles 2023-11-24 19:50:01 +07:00
Tuan Dang
595a26a366 Update ST V3 to machine identity 2023-11-24 19:19:31 +07:00
Tuan Dang
41c41a647f Standardize org members page styling 2023-11-24 14:09:56 +07:00
Tuan Dang
c3d2b7d3fc Pull main 2023-11-23 18:00:07 +07:00
Tuan Dang
84e32faac9 Import express-async-errors 2023-11-23 17:59:05 +07:00
Tuan Dang
87984a704a Fix merge conflicts 2023-11-23 15:37:14 +07:00
Tuan Dang
33e4104e98 Fix merge conflicts 2023-11-23 15:36:19 +07:00
Vladyslav Matsiiako
b5d5eb87a7 fix typo in image path 2023-11-22 22:54:44 -08:00
Vladyslav Matsiiako
bcfb14ca86 added docs for cloudflare workers to the navigation bar 2023-11-22 22:44:25 -08:00
Vladyslav Matsiiako
87e2844499 added docs for cloudflare workers 2023-11-22 22:40:14 -08:00
vmatsiiako
ae4b8ca9b2 Merge pull request #1172 from Shraeyas/cloudflare-workers
Add Integration for Cloudflare Workers
2023-11-22 22:05:35 -08:00
BlackMagiq
0cff39f918 Merge pull request #1186 from akhilmhdh/feat/audit-log-export
feat(audit-log): improvement in loading time
2023-11-23 12:21:56 +07:00
Tuan Dang
53ac05694c Update get/export audit logs spec 2023-11-23 12:18:01 +07:00
Tuan Dang
097a8cae89 Resolve merge conflict 2023-11-23 12:02:41 +07:00
Tuan Dang
597e1e1ca8 Continue ST V3 roles 2023-11-23 11:56:56 +07:00
Shreyas
4757ceb938 Merge branch 'Infisical:main' into cloudflare-workers 2023-11-22 10:41:01 -08:00
Maidul Islam
e3d536ef58 Merge pull request #1187 from akhilmhdh/feat/swc-dev
feat: added swc compiler for ts-node for speed boost
2023-11-22 13:03:45 -05:00
Akhil Mohan
89ae3070ce feat(audit-log): added doc for export endpoint 2023-11-22 17:04:09 +05:30
Akhil Mohan
f3895b70ee feat: added swc compiler for ts-node for speed boost 2023-11-22 13:01:27 +05:30
Maidul Islam
3478d71e99 unblock gamma pipeline 2023-11-21 17:45:01 -05:00
Maidul Islam
1f5e458b64 add log details under msg property 2023-11-21 16:25:48 -05:00
Maidul Islam
6f8373c977 add severity level as string for pino 2023-11-21 16:02:43 -05:00
Maidul Islam
c55a36b291 add logs for v3 secrets 2023-11-21 16:02:03 -05:00
Maidul Islam
e4a04bdf0a set log level to info and output to file 2023-11-21 15:11:19 -05:00
Tuan Dang
4db9a5279f Comment out ST V3 section 2023-11-21 17:32:22 +07:00
BlackMagiq
c37ff79927 Merge pull request #1184 from Infisical/stv3-roles
Add role-based project access controls to ST V3
2023-11-21 12:26:40 +02:00
Tuan Dang
98e299c2ac Update rendering custo role slugs in ST V3 table / modal 2023-11-21 17:11:53 +07:00
Akhil Mohan
9d9e830d73 feat(audit-log): added index over workspace key and changed pagination to load more type 2023-11-21 14:36:06 +05:30
Maidul Islam
d909ff6a97 Merge pull request #1185 from akhilmhdh/feat/pino-cloudwatch
feat(aws-cloudwatch): added support for aws cloudwatch transport in pino
2023-11-20 21:00:55 -05:00
Akhil Mohan
5301bcc91f feat(aws-cloudwatch): added support for aws cloudwatch transport in pino 2023-11-20 16:17:31 +05:30
Tuan Dang
77438f9282 Replace getUserProjectPermissions with more generic getAuthDataProjectPermissions 2023-11-19 18:10:02 +02:00
Tuan Dang
122a1e32e1 Replace scopes with role for ST V3 2023-11-19 15:45:49 +02:00
BlackMagiq
9d2a08dbec Merge pull request #1183 from Infisical/stv3-permissioning
Move ST sections to members page (now access control)
2023-11-18 19:15:51 +02:00
Tuan Dang
87c2e417d2 Fix lint type issues 2023-11-18 19:11:35 +02:00
Tuan Dang
341a745843 Move ST sections to members page (now access control) 2023-11-18 18:29:13 +02:00
Maidul Islam
085ddb2c48 Merge pull request #1178 from akhilmhdh/patch/sign-up
fix: resolved backup key generation in signup, removed owner check and logic race condition error
2023-11-17 10:52:24 -05:00
Akhil Mohan
6734ce50a5 fix: resolved backup key generation in signup, removed owner check in custom role and login race condition 2023-11-16 13:28:30 +05:30
Maidul Islam
94f893017b add env_file: .env to docker compose 2023-11-15 13:21:18 -05:00
Maidul Islam
a0dfa5eedf put svt v3 as feature flag 2023-11-14 15:25:17 -05:00
Maidul Islam
1fea2f1121 remove invite only logic from controller 2023-11-14 14:01:33 -05:00
Maidul Islam
7fe8999432 Merge pull request #1171 from akhilmhdh/feat/onboarding-exp
New onboarding experience
2023-11-14 12:00:22 -05:00
Shreyas
fca5ae9172 Merge branch 'Infisical:main' into cloudflare-workers 2023-11-14 08:02:47 -08:00
Akhil Mohan
4aacbed28b feat(onboarding): added signup disable for sso and post hog event on admin initalization 2023-11-14 13:01:07 +05:30
Maidul Islam
9fbf01c19e update migrationAssignSuperadmin 2023-11-13 16:54:20 -05:00
Maidul Islam
954bc0c5f1 Merge pull request #1174 from RezaRahemtola/main
Docs: Fixing some typos
2023-11-13 12:27:26 -06:00
Akhil Mohan
4ac3669756 feat(onboarding): added migration script for super admin 2023-11-13 23:53:55 +05:30
Reza Rahemtola
6b334b3103 docs: Fixing some typos 2023-11-13 15:42:08 +01:00
Vladyslav Matsiiako
3aae1b8432 added support note to ansible docs 2023-11-12 15:30:41 -06:00
Vladyslav Matsiiako
e462722ec3 updated nsible docs title 2023-11-12 15:29:51 -06:00
Vladyslav Matsiiako
f58c560fc0 Update docs navigation 2023-11-12 14:53:30 -06:00
Vladyslav Matsiiako
d035fe1008 Update docs navigation 2023-11-12 13:00:35 -06:00
Vladyslav Matsiiako
8be0071413 Added docs for ansible and Jenkins 2023-11-12 12:57:38 -06:00
Akhil Mohan
c3ca992777 feat(onboarding): added backup key generation for admin account 2023-11-12 23:30:41 +05:30
Shreyas Singh
829f65cdb7 Update frequent constants for cloudflare workers integration 2023-11-11 01:02:34 +05:30
Shreyas Singh
7785fbafbd Remove target environment input box from cloudflare workers integration 2023-11-11 01:01:11 +05:30
Shreyas Singh
35cff782e1 Add frontend files for cloudflare workers integration 2023-11-11 00:45:17 +05:30
Shreyas Singh
a35643bf6e Add function to sync secrets to cloudflare workers integration 2023-11-11 00:43:54 +05:30
Shreyas Singh
85de985321 Add apps list for cloudflare workers integration 2023-11-11 00:43:13 +05:30
Shreyas Singh
40f5bbbc07 Add window redirects for cloudflare workers integration 2023-11-11 00:41:20 +05:30
Shreyas Singh
85254ba984 Add integration names to DB model schema 2023-11-11 00:36:47 +05:30
Shreyas Singh
4cb586996c Add integration variables 2023-11-11 00:35:00 +05:30
Akhil Mohan
29fa85e499 feat(onboarding): frontend for onboarding users 2023-11-10 13:12:58 +05:30
Akhil Mohan
df7d8e7be9 feat(onboarding): backend api for onboarding users 2023-11-10 13:12:58 +05:30
BlackMagiq
1de5fd28a9 Merge pull request #1169 from Infisical/api-ref
Update API Reference params, responses, etc. for secrets, folders, environments, and secret imports endpoints
2023-11-08 19:41:39 +02:00
Tuan Dang
b3cdc4fdd2 Update API reference responses for secrets, folders, environments, and secret imports 2023-11-08 19:31:59 +02:00
Tuan Dang
5ee79be873 Correct API reference endpoint details/params for secrets, folders, environments, secret imports 2023-11-08 15:58:18 +02:00
BlackMagiq
cae7e1808d Merge pull request #1118 from techemmy/fix/resolve-api-reference-error-on-request
fix: resolve API reference failing requests
2023-11-07 17:14:02 +02:00
BlackMagiq
131d5d7207 Merge pull request #1164 from Infisical/depr-middleware
Remove unused authorization middleware
2023-11-05 18:56:31 +02:00
Tuan Dang
393cfe8953 Remove unused middlewares 2023-11-05 18:51:25 +02:00
BlackMagiq
5098c0731b Merge pull request #1157 from Infisical/depr-service-account
Remove/deprecate service account and old logging resources, endpoints, logic, etc.
2023-11-05 16:06:07 +02:00
Tuan Dang
c9ed5f793a Remove action variables 2023-11-05 15:57:04 +02:00
Tuan Dang
50ce977c55 Remove/deprecate service accounts + old logs/actions 2023-11-05 15:49:24 +02:00
Tuan Dang
c29a11866e Remove IP allowlisting from project sidebar 2023-11-04 21:16:59 +02:00
BlackMagiq
b3a468408e Merge pull request #1144 from Infisical/dependabot/npm_and_yarn/frontend/babel/traverse-and-babel/traverse-and-storybook/addon-essentials-and-storybook/csf-tools-and-storybook-7.23.2
chore(deps): bump @babel/traverse, @storybook/addon-essentials, @storybook/csf-tools and storybook in /frontend
2023-11-04 20:35:32 +02:00
Tuan Dang
d1a26766ca Merge remote-tracking branch 'origin' into dependabot/npm_and_yarn/frontend/babel/traverse-and-babel/traverse-and-storybook/addon-essentials-and-storybook/csf-tools-and-storybook-7.23.2 2023-11-04 20:26:14 +02:00
Maidul Islam
73c8e8dc0f Merge pull request #1152 from akhilmhdh/fix/key-rogue
fix: changed 2 fold operation of member workspace to one api call
2023-11-04 12:33:08 -04:00
BlackMagiq
32882848ba Merge pull request #1126 from Infisical/stv3-update
Multipart Update to Authentication (ST V3, Modularization of Auth Validation Methods, SSO logic)
2023-11-03 22:41:30 +02:00
Tuan Dang
5fb406884d Merge remote-tracking branch 'origin' into stv3-update 2023-11-03 22:38:29 +02:00
Tuan Dang
176d92546c Split ST V3 modal into option tabs, re-modularized authn methods 2023-11-03 22:37:50 +02:00
Maidul Islam
1063c12d25 Merge pull request #1153 from akhilmhdh/feat/secret-blind-index-overview
feat: changed enable blindIndex from settings to overview page for attention
2023-11-03 16:02:28 -04:00
Maidul Islam
3402acb05c update blind indexing message 2023-11-03 16:00:00 -04:00
Akhil Mohan
db7a064961 feat: changed enable blindIndex from settings to overview page for attention 2023-11-03 20:01:51 +05:30
Akhil Mohan
b521d9fa3a fix: changed 2 fold operation of member workspace to one time operation and as batch 2023-11-03 19:11:01 +05:30
Maidul Islam
73c7b917ab update secret rotation intro 2023-11-02 17:17:20 -04:00
Maidul Islam
a8470d2133 Merge pull request #1150 from akhilmhdh/fix/mrg-bug-fixes
fix: resolved error in org settings and integrations page alert hidde…
2023-11-02 12:44:50 -04:00
Maidul Islam
ca8fff320d Merge branch 'main' into fix/mrg-bug-fixes 2023-11-02 12:44:26 -04:00
Tuan Dang
f9c28ab045 Add ST V3 copy to clipboard, default to is active 2023-11-02 12:13:23 +02:00
Tuan Dang
d4a5eb12e8 Patch checkly integration 2023-11-02 11:54:01 +02:00
BlackMagiq
86d82737f4 Merge pull request #1145 from atimapreandrew/checkly-sync-on-group-level
Checkly sync on group level
2023-11-02 11:10:40 +02:00
Akhil Mohan
abbeb67b95 fix: resolved error in org settings and integrations page alert hidden on no integrations 2023-11-02 14:39:13 +05:30
Tuan Dang
c0c96d6407 Update checkly integration docs 2023-11-02 10:00:43 +02:00
Tuan Dang
58ff6a43bc Update Checkly groups integration 2023-11-02 09:37:36 +02:00
Vladyslav Matsiiako
079a09a3d1 Remove create new org 2023-11-01 14:27:46 -07:00
Maidul Islam
a07bd5ad40 add log to secretRotationQueue process 2023-11-01 16:49:31 -04:00
Maidul Islam
9cc99e41b8 Merge pull request #1117 from akhilmhdh/feat/secret-rotation
Secret rotation
2023-11-01 16:39:24 -04:00
Tuan Dang
f256493cb3 Merge remote-tracking branch 'origin' into checkly-sync-on-group-level 2023-11-01 20:37:15 +02:00
Tuan Dang
7bf2e96ad3 Merge remote-tracking branch 'origin' into stv3-update 2023-11-01 18:57:31 +02:00
Akhil Mohan
40238788e5 feat(secret-rotation): changed queue logging to pino 2023-11-01 22:24:58 +05:30
Akhil Mohan
75eeda4278 feat(secret-rotation): changed to mysql2 client and refactored queue util functions 2023-11-01 22:22:46 +05:30
Maidul Islam
c1ea441e3a AJV set strict to false 2023-11-01 22:21:31 +05:30
Akhil Mohan
8b522a3fb5 feat(secret-rotation): updated docs for secret rotation 2023-11-01 22:21:31 +05:30
Akhil Mohan
c36352f05f feat(secret-rotation): updated helper text for options 2023-11-01 22:21:31 +05:30
Akhil Mohan
2de898fdbd feat: backward compatiable enc key 2023-11-01 22:21:31 +05:30
Akhil Mohan
bc68a00265 feat(secret-rotation): updated lottie and added side effect on successfully 2023-11-01 22:21:31 +05:30
Maidul Islam
1382688e58 add secretRotation to feature set 2023-11-01 22:21:31 +05:30
Akhil Mohan
9248f36edb feat(secret-rotation): added db ssl option in test function 2023-11-01 22:21:31 +05:30
Akhil Mohan
c9c40521b2 feat(secret-rotation): added db ssl support 2023-11-01 22:21:31 +05:30
Akhil Mohan
97e4338335 feat(secret-rotation): implemented frontend ui for secret rotation 2023-11-01 22:21:31 +05:30
Akhil Mohan
82e924baff feat(secret-rotation): implemented api and queue for secret rotation 2023-11-01 22:21:31 +05:30
BlackMagiq
2350219cc9 Merge pull request #1148 from Infisical/revert-transactions
Remove transactions from delete organization, workspace, user
2023-11-01 17:51:50 +02:00
Tuan Dang
28d7c72390 Merge remote-tracking branch 'origin' into revert-transactions 2023-11-01 16:41:32 +02:00
Akhil Mohan
e7321e8060 Merge pull request #1146 from Infisical/pino
Replace winston with pino logging
2023-11-01 20:07:33 +05:30
Akhil Mohan
28a2aebe67 chore: removed npx from pino-pretty 2023-11-01 20:06:02 +05:30
Tuan Dang
20d4f16d33 Move pino-pretty to dev-dep, dev script 2023-11-01 13:20:10 +02:00
Tuan Dang
7d802b41a8 Fix lint issue 2023-11-01 11:20:09 +02:00
Tuan Dang
75992e5566 Merge remote-tracking branch 'origin' into pino 2023-11-01 11:16:34 +02:00
Tuan Dang
911aa3fd8a Merge remote-tracking branch 'origin' into stv3-update 2023-11-01 11:10:30 +02:00
Tuan Dang
7622a3f518 Remove transactions from delete organization, workspace, user 2023-11-01 11:06:36 +02:00
Tuan Dang
3b0bd362c9 Refactor requestErrorHandler, adjust request errors to appropriate pino log level 2023-11-01 10:10:39 +02:00
Tuan Dang
ad4513f926 Replace winston with pino 2023-10-31 15:03:36 +02:00
dependabot[bot]
a2c1a17222 chore(deps): bump @babel/traverse, @storybook/addon-essentials, @storybook/csf-tools and storybook
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) to 7.23.2 and updates ancestor dependencies [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse), [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials), [@storybook/csf-tools](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/csf-tools) and [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli). These dependencies need to be updated together.


Updates `@babel/traverse` from 7.21.5 to 7.23.2
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

Updates `@babel/traverse` from 7.22.5 to 7.23.2
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

Updates `@storybook/addon-essentials` from 7.0.23 to 7.5.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.2/code/addons/essentials)

Updates `@storybook/csf-tools` from 7.0.23 to 7.5.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.2/code/lib/csf-tools)

Updates `storybook` from 7.0.23 to 7.5.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.2/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
- dependency-name: "@babel/traverse"
  dependency-type: indirect
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
- dependency-name: "@storybook/csf-tools"
  dependency-type: indirect
- dependency-name: storybook
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-31 09:59:40 +00:00
Andrew Atimapre
279958d54c Checkly group level sync support 2023-10-31 07:18:59 +01:00
Akhil Mohan
1be46b5e57 Merge pull request #1085 from rtpa25/feat/create-multiple-orgs-under-same-account
feat: adds ability to create multiple orgs under the same account
2023-10-31 11:21:56 +05:30
Maidul Islam
98d9dd256b remove image name from k8 docs 2023-10-30 16:59:25 -04:00
Maidul Islam
e5eee14409 Merge pull request #1121 from Infisical/snyk-fix-9c5c22e2d4bdb58631063170328a0670
[Snyk] Security upgrade crypto-js from 4.1.1 to 4.2.0
2023-10-30 14:18:10 -04:00
Andrew Atimapre
f3c76c79ee Checkly group level sync support 2023-10-30 18:23:23 +01:00
Maidul Islam
5bdb6ad6a1 Merge pull request #1141 from akhilmhdh/fix/backward-enc-key
feat: backward compatiable enc key in webhook
2023-10-30 13:19:18 -04:00
Akhil Mohan
c6846f8bf1 feat: updated backward compatiable enc key 2023-10-30 22:41:15 +05:30
Maidul Islam
46f03f33b0 fix approval plan typo 2023-10-30 12:48:06 -04:00
Akhil Mohan
6280d7eb34 feat: backward compatiable enc key in webhook 2023-10-30 21:30:37 +05:30
Maidul Islam
29286d2125 Merge pull request #1138 from Shraeyas:develop
Fix bug with copying secret to clipboard with an override
2023-10-29 22:56:14 -04:00
Shreyas Singh
c9f01ce086 Fix bug with copying secret to clipboard with an override 2023-10-29 21:25:36 +05:30
Maidul Islam
bc43e109eb update zod version for frontend 2023-10-27 18:06:59 -04:00
Maidul Islam
238c43a360 Merge pull request #1131 from akhilmhdh/fix/build-failing-ts
fix: standalone build failure due to ts error
2023-10-27 17:44:10 -04:00
Maidul Islam
040a50d599 Merge pull request #1132 from Tchoupinax/main
feat(helm-chart): repair usage of resources key
2023-10-27 17:42:48 -04:00
Tchoupinax
8a1a3e9ab9 chore(helm-chart): increase the version to 0.4.2 2023-10-27 20:45:35 +02:00
Tchoupinax
2585d50b29 feat(helm-chart): repair usage of resources key 2023-10-27 20:42:35 +02:00
Maidul Islam
4792e752c2 update dependency of rate limiter 2023-10-27 10:48:25 -04:00
Akhil Mohan
1d161f6c97 fix: standalone build failure due to ts error 2023-10-27 20:05:51 +05:30
Maidul Islam
0d94b6deed Merge pull request #1130 from Infisical/revert-1129-revert-1128-mongodb-dep
Revert "Revert "Remove mongodb direct dependency from backend""
2023-10-27 10:26:03 -04:00
Maidul Islam
75428bb750 Revert "Revert "Remove mongodb direct dependency from backend"" 2023-10-27 10:24:49 -04:00
Maidul Islam
d90680cc91 Merge pull request #1129 from Infisical/revert-1128-mongodb-dep
Revert "Remove mongodb direct dependency from backend"
2023-10-27 10:21:04 -04:00
Maidul Islam
031c05b82d Revert "Remove mongodb direct dependency from backend" 2023-10-27 10:20:51 -04:00
Tuan Dang
d414353258 Merge remote-tracking branch 'origin' into stv3-update 2023-10-27 15:19:39 +01:00
BlackMagiq
ffc6dcdeb4 Merge pull request #1128 from Infisical/mongodb-dep
Remove mongodb direct dependency from backend
2023-10-27 15:19:01 +01:00
Tuan Dang
dfc74262ee Remove mongodb direct dependency from backend 2023-10-27 15:16:22 +01:00
Maidul Islam
59e46ef1d0 Merge pull request #1125 from akhilmhdh/fix/deep-main-page
fix: resolved nav header secret path issues
2023-10-27 10:01:57 -04:00
BlackMagiq
36e4cd71d3 Merge pull request #1127 from Infisical/update-node-saml
Update subdependencies, node-saml
2023-10-27 14:54:49 +01:00
Tuan Dang
d60b3d1598 Update subdependencies, node-saml 2023-10-27 14:52:22 +01:00
Tuan Dang
e555a8d313 Merge remote-tracking branch 'origin' into stv3-update 2023-10-27 12:20:03 +01:00
Tuan Dang
44ec88acd6 Finish preliminary refactor/modularization of requireAuth logic 2023-10-27 12:03:25 +01:00
Akhil Mohan
15504346cd fix: resolved nav header secret path issues 2023-10-27 12:16:37 +05:30
Maidul Islam
508ed7f7d6 Merge pull request #1124 from akhilmhdh/fix/folder-create-overview
fix:resolved overview page add secret not working when folder not exist in one level deep
2023-10-26 13:11:23 -04:00
Tuan Dang
52bcee2785 Modularize SSO provider logic 2023-10-26 13:45:40 +01:00
Akhil Mohan
c097e43a4e fix:resolved overview page add secret not working when folder not existing 2023-10-26 15:14:05 +05:30
Tuan Dang
65afaa8177 Update ST V3 impl to (rotating) refresh token impl 2023-10-26 09:57:59 +01:00
Emmanuel Oloyede
01cbd4236d fix: update the api reference from the OpenAPI spec in the /backend folder instead 2023-10-26 04:35:14 +01:00
snyk-bot
40a9a15709 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-CRYPTOJS-6028119
2023-10-25 16:41:52 +00:00
Emmanuel Oloyede
abfc69fc75 fix: resolve API reference failing requests 2023-10-25 15:27:07 +01:00
Daniel Hougaard
3ea20328dc Removed log 2023-10-25 03:52:53 +04:00
Daniel Hougaard
2aa46f5a65 Update sendSecretReminders.ts 2023-10-25 03:47:07 +04:00
Daniel Hougaard
f0ca059b17 Update secret.ts 2023-10-25 03:46:00 +04:00
Daniel Hougaard
b1369d66c2 Cleanup 2023-10-25 03:43:52 +04:00
Daniel Hougaard
151ba2ffc9 Lint 2023-10-25 02:25:58 +04:00
Daniel Hougaard
152feba1fa Create secretReminder.handlebars 2023-10-25 02:25:49 +04:00
Daniel Hougaard
16125157f3 Sending out the emails 2023-10-25 02:25:39 +04:00
Maidul Islam
c0592ad904 remove cypress folder from root 2023-10-24 10:41:16 -04:00
Maidul Islam
32970e4990 Merge pull request #1107 from Infisical/cypress
adding cypress tests
2023-10-24 10:38:47 -04:00
Vladyslav Matsiiako
7487b373fe adding cypress test 2023-10-24 10:38:08 -04:00
Daniel Hougaard
6df678067c Reminders 2023-10-24 05:16:39 +04:00
Daniel Hougaard
b97dc7f599 Packages 2023-10-24 05:16:19 +04:00
Daniel Hougaard
96db649cbc Reminder helpers for creating and deleting crons 2023-10-24 05:16:04 +04:00
Daniel Hougaard
80ce695355 Added secret reminder handler on updates 2023-10-24 05:15:40 +04:00
Daniel Hougaard
93a1725da6 Package 2023-10-24 05:15:01 +04:00
Ronit Panda
619bbf2027 fix: fixes broken nonePage.tsx 2023-10-24 06:09:12 +05:30
Ronit Panda
1476d06b7e feat: adds cancel button and uses zod over yup 2023-10-24 06:02:20 +05:30
Ronit Panda
fb59b02ab4 Merge branch 'Infisical:main' into feat/create-multiple-orgs-under-same-account 2023-10-24 05:42:31 +05:30
BlackMagiq
fc3db93f8b Merge pull request #1102 from G3root/hasura-cloud
feat: add hasura cloud integration
2023-10-23 20:37:52 +01:00
Tuan Dang
120f1cb5dd Remove print statements, clean hasura cloud integration frontend 2023-10-23 20:06:35 +01:00
Tuan Dang
bb9b060fc0 Update syncSecretsHasuraCloud 2023-10-23 19:52:55 +01:00
Maidul Islam
26605638fa Merge pull request #1110 from techemmy/docs/add-REAMDE-for-contributing-to-the-docs
docs: add README file for instructions on how to get the doc started …
2023-10-23 14:52:17 +01:00
BlackMagiq
76758732af Merge pull request #1112 from Infisical/auth-jwt-standardization
API Key V2
2023-10-23 12:30:00 +01:00
Tuan Dang
827d5b25c2 Cleanup comments API Key V2 2023-10-23 12:18:44 +01:00
Tuan Dang
b32b19bcc1 Finish API Key V2 2023-10-23 11:58:16 +01:00
Emmanuel Oloyede
69b9881cbc docs: add README file for instructions on how to get the doc started in local development 2023-10-22 16:40:33 +01:00
Maidul Islam
1084323d6d Merge pull request #1014 from G3root/e2e-warning
feat: display warning message in integrations page when e2e is enabled
2023-10-22 14:42:15 +01:00
Maidul Islam
c98c45157a Merge branch 'main' into e2e-warning 2023-10-22 14:39:09 +01:00
Vladyslav Matsiiako
9a500504a4 adding cypress tests 2023-10-21 09:49:31 -07:00
Akhil Mohan
6009dda2d2 Merge pull request #1105 from G3root/fix-batch-delete-integration
fix: batch deleting secrets not getting synced for integrations
2023-10-21 14:42:23 +05:30
nafees nazik
d4e8162c41 fix: sync deleted secret 2023-10-21 01:39:08 +05:30
nafees nazik
f6ad641858 chore: add logs 2023-10-21 01:38:41 +05:30
nafees nazik
32acc370a4 feat: add delete method 2023-10-21 01:36:23 +05:30
Maidul Islam
ba9b1b45ae update docker docs for self host 2023-10-20 13:36:09 +01:00
Tuan Dang
e05b26c727 Add docs for Hasura Cloud 2023-10-20 11:25:06 +01:00
Maidul Islam
e22557b4bb Merge pull request #1088 from adelowo/support_path_when_generating_sample_env
[ENG-179] Add suport for --path for the secrets generate-example-env command
2023-10-20 11:10:12 +01:00
Maidul Islam
cbbb12c74e Merge pull request #1099 from Infisical/jwt-refactor
Update JWT secret scheme, replace many secrets with one secret
2023-10-20 11:02:58 +01:00
Tuan Dang
60beda604f Merge branch 'jwt-refactor' of https://github.com/Infisical/infisical into jwt-refactor 2023-10-20 10:55:40 +01:00
Tuan Dang
ae50987f91 Default AUTH_SECRET to JWT_AUTH_SECRET for backwards compatibility 2023-10-20 10:55:29 +01:00
Maidul Islam
32977e06f8 add warning text for .env.example 2023-10-20 10:38:42 +01:00
nafees nazik
4d78f4a824 feat: add create page 2023-10-20 13:22:40 +05:30
nafees nazik
47bf483c2e feat: add logo 2023-10-20 13:20:43 +05:30
nafees nazik
40e5ecfd7d feat: add sync 2023-10-20 13:20:00 +05:30
nafees nazik
0fb0744f09 feat: add get apps 2023-10-20 13:18:26 +05:30
Maidul Islam
1510c39631 Update Chart.yaml 2023-10-19 19:19:46 +01:00
Maidul Islam
d0579b383f update readiness probe 2023-10-19 19:19:32 +01:00
Maidul Islam
b4f4c1064d Update values.yaml 2023-10-19 19:10:22 +01:00
Maidul Islam
d72d3940e6 update img name in prod img gha 2023-10-19 17:45:29 +01:00
Maidul Islam
7217bcb3d8 Merge pull request #1100 from Infisical/migrate-to-standalone-infisical
Migrate to standalone infisical
2023-10-19 16:07:55 +01:00
Maidul Islam
2faa9222d8 update gamma gh action 2023-10-19 16:05:41 +01:00
Tuan Dang
058712e8ec Update JWT secret scheme, replace many secrets with one secret 2023-10-19 15:53:36 +01:00
Maidul Islam
589f0bc134 update staging test for img 2023-10-19 13:23:07 +01:00
Maidul Islam
bd6dc3d4c0 update gamma helm values 2023-10-19 13:10:36 +01:00
Maidul Islam
9338babda6 update infisical helm chart read me 2023-10-19 13:03:18 +01:00
Maidul Islam
6f9e8644d7 update infisical helm chart to use standalone img 2023-10-19 12:58:16 +01:00
Maidul Islam
2fdb10277e update docs to use standalone infisical 2023-10-19 12:53:20 +01:00
Maidul Islam
15d2c536ed update prod docker compose 2023-10-19 12:23:20 +01:00
nafees nazik
e13b3f72b1 feat: add authorize page 2023-10-18 23:08:13 +05:30
nafees nazik
a6e02238ad feat: add hasura cloud 2023-10-18 22:40:34 +05:30
nafees nazik
ebe4f70b51 docs: add hasura cloud integration 2023-10-18 22:37:31 +05:30
nafees nazik
c3c7316ec0 feat: add to redirect provider 2023-10-18 22:15:48 +05:30
nafees nazik
2cd791a433 feat: add integration page 2023-10-18 21:51:35 +05:30
BlackMagiq
a304228961 Merge pull request #1095 from akhilmhdh/feat/folder-service-api-key
feat: added api key support for folder and secret import
2023-10-18 12:36:11 +01:00
Akhil Mohan
c865b78b41 feat: added api key support for folder and secret import 2023-10-18 16:38:19 +05:30
BlackMagiq
be80ac999e Merge pull request #1094 from Infisical/fix-azure-saml-flow
Patch Azure SAML Flow
2023-10-18 11:56:45 +01:00
Tuan Dang
076fe58325 Fix azure-saml flow 2023-10-18 11:49:57 +01:00
Maidul Islam
66bfab1994 update platform version env 2023-10-18 10:41:15 +01:00
Maidul Islam
b92c50addd properly add pre baked values 2023-10-18 10:40:34 +01:00
Maidul Islam
8fbca05052 remove extract_version 2023-10-17 23:13:04 +01:00
Maidul Islam
d99830067e bake posthog key in single docker img 2023-10-17 23:08:43 +01:00
Maidul Islam
cdc8ef95ab add platform version to UI 2023-10-17 23:08:43 +01:00
Tuan Dang
072e97b956 Fix azure samlConfig 2023-10-17 16:51:46 +01:00
Tuan Dang
4f26a7cad3 Revert audience change for azure saml 2023-10-17 15:50:31 +01:00
Tuan Dang
7bb6ff3d0c Merge branch 'main' of https://github.com/Infisical/infisical 2023-10-17 15:32:42 +01:00
Tuan Dang
ecccec8e35 Attempt fix azure samlConfig 2023-10-17 15:32:34 +01:00
Maidul Islam
7fd15a06e5 conditionally build standalone infisical 2023-10-17 14:32:56 +01:00
Maidul Islam
5d4a37004e Merge pull request #1089 from G3root/serve-frontend-from-backend
feat: serve frontend from backend
2023-10-17 14:15:41 +01:00
Maidul Islam
aa61fd091d remove redundant file from docker ignore 2023-10-17 14:11:16 +01:00
Maidul Islam
04ac54bcfa run cmd as non root user and update port to non privileged 2023-10-17 14:08:22 +01:00
Tuan Dang
38dbf1e738 Add missing / to samlConfig callbackURL 2023-10-17 14:03:37 +01:00
Tuan Dang
ddf9d7848c Update protocol in samlConfig 2023-10-17 12:57:05 +01:00
Maidul Islam
0b40de49ec remove redis error logs 2023-10-17 12:24:54 +01:00
Maidul Islam
b1d16cab39 remove promise.all from closeDatabaseHelper 2023-10-17 12:24:18 +01:00
Maidul Islam
fb7c7045e9 set telemetry post frontend build in standalone docker img 2023-10-17 12:22:08 +01:00
Tuan Dang
d570828e47 Update path and callbackURL for samlConfig 2023-10-17 12:13:54 +01:00
Maidul Islam
2a92b6c787 Merge pull request #1093 from akhilmhdh/feat/secret-update-id
feat: changed secret update to use id
2023-10-17 11:14:30 +01:00
Akhil Mohan
ee54fdabe1 feat: changed secret update to use id 2023-10-17 15:38:30 +05:30
vmatsiiako
912818eec8 Merge branch 'main' into feat/create-multiple-orgs-under-same-account 2023-10-16 18:55:48 -07:00
nafees nazik
136308f299 revert: temp workaround: remove use of get static prop 2023-10-16 20:37:35 +05:30
nafees nazik
ba41244877 chore: remove next.js 2023-10-16 20:35:47 +05:30
nafees nazik
c4dcf334f0 fix: remove copy config 2023-10-16 20:35:29 +05:30
nafees nazik
66bac3ef48 fix: static props not rendered 2023-10-16 20:35:16 +05:30
Maidul Islam
e5347719c3 temp workaround: remove use of get static prop 2023-10-16 15:03:55 +01:00
Tuan Dang
275416a08f Remove 1-on-1 pairing link from README 2023-10-16 10:23:24 +01:00
Maidul Islam
abe1f54aab remove nginx and pm2 2023-10-15 23:58:04 +01:00
nafees nazik
13c1e2b349 fix: docker file 2023-10-15 12:09:45 +05:30
nafees nazik
f5a9afec61 fix: pm2 config 2023-10-15 11:52:55 +05:30
nafees nazik
d0a85c98b2 chore: add docker ignore and git ignore 2023-10-15 11:47:35 +05:30
nafees nazik
e0669cae7c chore: update path 2023-10-15 11:47:06 +05:30
Lanre Adelowo
e0dfb2548f update flag help text 2023-10-15 02:55:29 +01:00
Lanre Adelowo
01997a5187 support --path when generating sample env files 2023-10-15 02:50:41 +01:00
nafees nazik
2c011b7d53 feat: add custom server 2023-10-14 13:20:27 +05:30
nafees nazik
1b24a9b6e9 chore: add next to gitignore 2023-10-14 13:20:14 +05:30
nafees nazik
00c173aead chore: add next for backend 2023-10-14 13:19:54 +05:30
nafees nazik
2e15ad0625 fix: type 2023-10-14 12:54:26 +05:30
BlackMagiq
3f0b6dc6c1 Merge pull request #1087 from Infisical/self-hosted-sso-docs-clarification
Add FAQ to self-hosted SSO docs for it not working due to misconfigur…
2023-10-13 16:00:52 +01:00
Maidul Islam
f766a1eb29 Merge pull request #1078 from akhilmhdh/feat/secret-bug
feat: added support for recursive file creation
2023-10-13 15:57:50 +01:00
Tuan Dang
543c55b5a6 Add FAQ to self-hosted SSO docs for it not working due to misconfiguration 2023-10-13 15:56:10 +01:00
BlackMagiq
cdb1d38f99 Merge pull request #1086 from Infisical/del-org-stripe
Patch delete user, org, project session impl and account for organizationId in local storage
2023-10-13 12:46:38 +01:00
Tuan Dang
0a53b72cce Patch delete user, org, project session impl and account for orgId in localStorage 2023-10-13 11:22:40 +01:00
Ronit Panda
840eef7bce feat: improves the flow of account creation 2023-10-13 11:05:24 +05:30
Ronit Panda
70b9d435d1 feat: adds ability to create multiple orgs under the same account 2023-10-13 10:42:54 +05:30
Maidul Islam
b921c376b2 Merge pull request #1071 from ragnarbull/improve-logging
Improve-logging
2023-10-12 10:08:39 -04:00
Maidul Islam
b1ec59eb67 polish error handling 2023-10-12 15:06:37 +01:00
Maidul Islam
4e6e12932a Merge pull request #1080 from Tchoupinax/main
feat(helm-chart): allow to provide affinity values for the pods
2023-10-12 06:03:56 -04:00
Maidul Islam
792c382743 update chart version 2023-10-12 11:03:21 +01:00
Maidul Islam
f5c8e537c9 generate documentation 2023-10-12 11:01:21 +01:00
Maidul Islam
4bf09a8efc Merge pull request #1079 from Salman2301/patch-1
docs: fix missing export format `yaml`
2023-10-12 05:02:06 -04:00
Tchoupinax
001265cf2a feat(helm-chart): allow to provide affinity values for the pods 2023-10-11 21:15:21 +02:00
BlackMagiq
a56a135396 Merge pull request #1067 from Infisical/delete-org
Delete user, organization, project capabilities feature/update
2023-10-11 19:26:19 +01:00
Salman K.A.A
9838c29867 docs: fix missing export format yaml 2023-10-11 18:48:56 +05:30
Akhil Mohan
4f5946b252 feat: added support for recursive file creation 2023-10-11 17:19:34 +05:30
Tuan Dang
dc23517133 Merge remote-tracking branch 'origin' into delete-org 2023-10-10 14:54:19 +01:00
BlackMagiq
5e4d4f56e3 Merge pull request #1064 from Infisical/github-checkly-suffixes
allow multiple simultaneous integrations with checkly and github
2023-10-10 14:48:30 +01:00
BlackMagiq
a855a2cee6 Merge pull request #1063 from Infisical/ui-updates
fix styling issues
2023-10-10 13:55:40 +01:00
Tuan Dang
e86258949c Refactor learning note rendering to use react-query 2023-10-10 12:18:59 +01:00
Joel Biddle
f119c921d0 remove comment 2023-10-09 13:38:21 +00:00
Joel Biddle
b6ef55783e Fix: add stack trace errors in logging for prod 2023-10-09 13:37:16 +00:00
Tuan Dang
feade5d029 Clear react-query cache upon user logout, delete account 2023-10-09 09:00:31 +01:00
Tuan Dang
8f74d20e74 Fix redirect to unknown org in login case when user is not part of any orgs 2023-10-09 08:31:13 +01:00
Tuan Dang
0eb7896b59 Merge remote-tracking branch 'origin' into delete-org 2023-10-09 07:47:41 +01:00
Tuan Dang
9fcecc9c92 Finish preliminary delete user, organization, refactor delete project, create org page 2023-10-09 07:47:20 +01:00
Vladyslav Matsiiako
ee6afa8983 allowed creating multiple github integrations to different apps at once 2023-10-08 17:05:26 -07:00
Vladyslav Matsiiako
6f4ac02558 fix ui for env overview empty screen 2023-10-08 14:02:22 -07:00
Vladyslav Matsiiako
5971480ca9 allow multiple simultaneous integrations with checkly and github 2023-10-08 13:53:54 -07:00
Vladyslav Matsiiako
d222b09ba5 changed scroll to auto 2023-10-07 20:25:04 -07:00
Vladyslav Matsiiako
a9fd0374bd fixed signup screen scroll 2023-10-07 20:22:49 -07:00
Vladyslav Matsiiako
ca008c809a added update-blog reference and fixed login 2023-10-07 20:19:10 -07:00
Vladyslav Matsiiako
6df7590051 fix styling issues 2023-10-07 17:13:44 -07:00
vmatsiiako
60bd5e57fc Update README.md 2023-10-06 21:56:27 -07:00
Maidul Islam
703a7a316a Update values.yaml for staging 2023-10-06 16:19:10 -04:00
Maidul Islam
f4de7a2c56 Revert "disable mongo for staging"
This reverts commit 383825672b.
2023-10-06 16:18:28 -04:00
Maidul Islam
383825672b disable mongo for staging 2023-10-06 16:08:58 -04:00
Maidul Islam
c6124d7444 update memory value for backend 2023-10-06 15:56:44 -04:00
Maidul Islam
ee80f4a89b add / after cli callback host 2023-10-05 15:42:21 -04:00
Maidul Islam
0b3b014bf5 Merge pull request #1044 from akhilmhdh/feat/secret-approval-part-2
Policy based secret review system
2023-10-05 15:06:41 -04:00
Akhil Mohan
7f463cabce feat(secret-approval): moved approval code to ee 2023-10-05 21:10:18 +05:30
Maidul Islam
b1962129a3 Merge pull request #1059 from Infisical/potential-cli-login-patch
change broswer based login from localhost to 127.0.0.1
2023-10-05 11:26:59 -04:00
Maidul Islam
28ad403665 change broswer based login from localhost to 127.0.0.1 2023-10-05 11:19:29 -04:00
Akhil Mohan
cb893f71ee feat(secret-approval): conflict ui, request count and secret path in request detail 2023-10-05 20:45:16 +05:30
Maidul Islam
80a3ea42ac minor typo 2023-10-05 20:44:16 +05:30
Maidul Islam
aafd7f0884 add secretApproval to globalFeatureSet 2023-10-05 20:44:16 +05:30
Akhil Mohan
faacb75034 feat(secret-approval): added new audit log and subscription on policy creation 2023-10-05 20:44:16 +05:30
Vladyslav Matsiiako
7caac2e64c minor style updates to approvals 2023-10-05 20:34:50 +05:30
Akhil Mohan
df636c91b4 feat(secret-approval): added permission for policy management and fixed bugs on fellow user reviewing secrets 2023-10-05 20:34:50 +05:30
Akhil Mohan
9dc97f7208 feat(secret-approval): added auto naming policy and minor ux enhancements 2023-10-05 20:34:50 +05:30
Akhil Mohan
4fd227c85f feat(secret-approval): added loading and empty states for request list 2023-10-05 20:34:50 +05:30
Akhil Mohan
04c7d49477 feat(secret-approval): resolved infinite query bug and added support for closing, re-opening request, stale req ui 2023-10-05 20:34:50 +05:30
Akhil Mohan
63588b4e44 feat(secret-approval): implemented the new policy based approval system bare version 2023-10-05 20:34:50 +05:30
Akhil Mohan
fc43511f5d feat(secret-approval): implemented the base 2023-10-05 20:33:48 +05:30
BlackMagiq
a995627815 Merge pull request #1027 from Infisical/service-token-v3
Service Token V3
2023-10-05 15:42:41 +01:00
Tuan Dang
c2f7923c1d Hide ST V3 from UI, switch docs to ST V2 2023-10-05 15:23:32 +01:00
Tuan Dang
abf6034aca Adjust ST V3 2023-10-05 14:53:59 +01:00
Maidul Islam
5fce85ca41 Merge pull request #1037 from scomans/main
fix: renaming environments not updated in `secretimports` model
2023-10-04 23:12:30 -04:00
Tuan Dang
702d28faca Add URL_GITLAB_LOGIN envar to docs 2023-10-04 22:09:09 +01:00
Tuan Dang
dbeafe1f5d Attempt fix gitlab sso docs images 2023-10-04 22:03:18 +01:00
Tuan Dang
46f700023b Update README 2023-10-04 21:49:06 +01:00
BlackMagiq
25b988ca9a Merge pull request #1029 from atimapreandrew/gitlab-sso
Gitlab sso
2023-10-04 21:39:52 +01:00
Tuan Dang
41af5cea93 Move google, github, gitlab auth out of /ee 2023-10-04 21:31:50 +01:00
Tuan Dang
e21daf6771 Add docs for gitlab sso, add support for self-hosted gitlab instance sso 2023-10-04 20:48:42 +01:00
Maidul Islam
c0f81ec84e Merge pull request #1054 from RobinTail:RobinTail-patch-1
Upgrading `zod`
2023-10-04 15:22:04 -04:00
Maidul Islam
c85e2c71ca add NEXT_INFISICAL_PLATFORM_VERSION to staging 2023-10-04 15:06:59 -04:00
Maidul Islam
9ae6e5ea1c Merge pull request #1047 from ragnarbull/display-curr-version
Feat: add version tags to Docker image & display on frontend
2023-10-04 15:01:11 -04:00
Maidul Islam
d3026a98d8 add back infisical/backend:latest 2023-10-04 14:57:30 -04:00
Maidul Islam
14b8c2c12a remove unrelated changes 2023-10-04 14:29:36 -04:00
Anna Bocharova
d9a69441c4 Updating the lock file accordingly. 2023-10-04 14:57:43 +00:00
Anna Bocharova
f46a23dabf Upgrading zod in package.json 2023-10-04 16:54:39 +02:00
Tuan Dang
9e2d6daeba Merge remote-tracking branch 'origin' into gitlab-sso 2023-10-04 11:11:05 +01:00
Tuan Dang
a2bebb5afa Merge remote-tracking branch 'origin' into service-token-v3 2023-10-04 11:02:55 +01:00
BlackMagiq
9fc5303a97 Merge pull request #1053 from Infisical/update-docs
Update Platform Documentation
2023-10-04 11:01:47 +01:00
Tuan Dang
97a5b509b7 Point getting started SDK to SDK repos to avoid docs sprawl 2023-10-04 10:57:11 +01:00
Tuan Dang
7660119584 Merge remote-tracking branch 'origin' into update-docs 2023-10-04 10:44:38 +01:00
Tuan Dang
a51d202d51 Fix merge conflicts 2023-10-04 10:39:50 +01:00
Tuan Dang
34273b30f2 Finish update for platform docs 2023-10-04 10:25:54 +01:00
Joel Biddle
726f38c15f Resolve review comments 2023-10-04 04:50:16 +00:00
Joel Biddle
390c2cc4d9 Changed to pass build arg & create NEXT envar 2023-10-04 02:03:17 +00:00
Maidul Islam
49098b7693 update folder name of build tool integrations 2023-10-03 20:12:03 -04:00
Maidul Islam
501d940558 add Gradle docs 2023-10-03 20:00:50 -04:00
Maidul Islam
7234c014c8 Merge pull request #1048 from akhilmhdh:fix/remove-import-permission-token
fix: resolved permission check on imported secrets when using service token
2023-10-03 12:38:12 -07:00
Akhil Mohan
f3908e6b2a fix: resolved permission check on imported secrets when using service token 2023-10-03 20:14:43 +05:30
Tuan Dang
cf4eb629f2 Start revising project docs 2023-10-03 08:58:13 +01:00
Joel Biddle
95af82963f Add version tags to Docker image & display on frontend 2023-10-03 05:55:36 +00:00
Maidul Islam
bd8c17d720 resolve merge conflict 2023-10-02 18:58:38 -04:00
Tuan Dang
d3bc95560c Merge remote-tracking branch 'origin' into update-docs 2023-10-02 20:57:03 +01:00
Tuan Dang
4a838b788f Start comb docs, integrations, intro, organization 2023-10-02 20:26:16 +01:00
Maidul Islam
01c655699c Merge pull request #1045 from Infisical/proper-server-cleanup
handle siginit and sigterm
2023-10-02 11:44:36 -07:00
Maidul Islam
3456dfbd86 handle siginit and sigterm 2023-10-02 11:40:00 -07:00
Maidul Islam
560bde297c Merge pull request #1040 from akhilmhdh/fix/path-wrong-name
fix: resolved dashboard showing text folderName in nesting folders
2023-10-02 07:45:01 -07:00
Tuan Dang
c2ca4d77fc Add ST V3 docs, update ST-handling recommendation docs 2023-10-01 20:06:36 +01:00
Tuan Dang
3b3f78ee3c Start revising docs 2023-10-01 16:42:40 +01:00
Tuan Dang
d6a5c50fd9 Fix lint issue 2023-09-30 22:04:06 +01:00
Tuan Dang
839fcc2775 Add paywall to ST V3 ip allowlisting 2023-09-30 21:55:18 +01:00
Tuan Dang
eb2f433f43 Add trusted IP rules to ST V3 2023-09-30 20:52:04 +01:00
Akhil Mohan
04c74293ed fix: resolved dashboard showing text folderName in nesting folders 2023-09-30 23:47:38 +05:30
Tuan Dang
cdf4440848 Fix lint issues 2023-09-30 13:45:37 +01:00
Tuan Dang
20b584b7b8 Fix merge conflicts 2023-09-30 12:54:43 +01:00
Tuan Dang
3779209ed5 Update permission implementation for ST V3 2023-09-30 12:52:35 +01:00
nafees nazik
9546916aad fix: add props 2023-09-30 17:12:52 +05:30
nafees nazik
59c861c695 fix: rename variants 2023-09-30 17:07:52 +05:30
Sebastian Comans
105c2e51ee fix: renaming environments not updated in secretimports model 2023-09-30 08:54:51 +02:00
Maidul Islam
66aa218ad9 Merge pull request #1033 from Infisical/snyk-fix-f1bf0685a5c66fa5416b87a6ef8520e1
[Snyk] Security upgrade sharp from 0.32.1 to 0.32.6
2023-09-29 15:05:46 -07:00
Maidul Islam
fb3a386aa3 Merge pull request #1034 from akhilmhdh/feat/patch-dashboardv3
feat(dashboard-v3): patched dashboard copy sec bug
2023-09-29 08:21:12 -07:00
Tuan Dang
d723d26d2e Fix merge conflicts 2023-09-29 11:42:47 +01:00
Tuan Dang
8a576196a3 Return workspaceId in response for service token key copy 2023-09-29 11:16:12 +01:00
Akhil Mohan
2cf5fd80ca feat(dashboard-v3): removed a line at top on empty state 2023-09-29 14:31:31 +05:30
Akhil Mohan
74534cfbaa feat(dashboard-v3): patched dashboard copy sec bug and add secret in empty state 2023-09-29 13:34:44 +05:30
Maidul Islam
66787b1f93 fix secret scanning zod error for installationId 2023-09-28 23:09:12 -07:00
vmatsiiako
890082acbc Update service-token.mdx 2023-09-28 22:11:24 -07:00
Maidul Islam
a364b174e0 add expire time to service token create 2023-09-28 19:31:33 -07:00
Maidul Islam
2bb2ccc19e patch crypto in create service token in cli 2023-09-28 19:27:38 -07:00
Maidul Islam
3bbf770027 bug fixes for v3 secret apis 2023-09-28 12:11:26 -07:00
Maidul Islam
2610356d45 Merge pull request #1018 from akhilmhdh/feat/dashboard-v3
Feat/dashboard v3
2023-09-28 10:35:35 -07:00
Akhil Mohan
67e164e2bb feat(dashboard-v3): z-index change in tooltip for drawer 2023-09-28 22:29:50 +05:30
snyk-bot
84fcb82116 fix: frontend/package.json & frontend/package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-SHARP-5922108
2023-09-28 16:52:33 +00:00
Akhil Mohan
4502d12e46 feat(dashboard-v3): typo fix 2023-09-28 21:28:43 +05:30
Akhil Mohan
ef6ee6b2e6 feat(dashboard-v3): resolved create secret issue and allow empty secret values in create secret 2023-09-28 21:28:43 +05:30
Maidul Islam
e902a54af0 remove deprecated EELogService 2023-09-28 21:28:43 +05:30
Akhil Mohan
50efb8b8bd feat: resolved minor issues with dashboard v3 on feedback 2023-09-28 21:28:43 +05:30
Vladyslav Matsiiako
5450c1126a minor style updates to the dashboard 2023-09-28 21:28:43 +05:30
Akhil Mohan
4929022523 fix: resolved trimming keys but keeping last line break for ssh keys and added skip encoding on integration sync 2023-09-28 21:28:43 +05:30
Akhil Mohan
85378e25aa feat: updated input create secret style and some more updates on style 2023-09-28 21:28:43 +05:30
Akhil Mohan
b54c29fc48 feat(dashboard-v3): implemented new the dashboard with v3 support 2023-09-28 21:28:43 +05:30
Akhil Mohan
fcf3f2837e feat(dashboard-v3): updated ui components and hooks for new migrated apis and v3 apis 2023-09-28 21:28:43 +05:30
Akhil Mohan
0ada343b6f feat(dashboard-v3): migrated folder, imports and snapshots to use only secret path and not folder id 2023-09-28 21:28:06 +05:30
Maidul Islam
d0b8aba990 Merge pull request #1030 from G3root/update-other
fix: renaming environments not updated in some models
2023-09-28 07:58:05 -07:00
Maidul Islam
4365be9b75 Merge pull request #1031 from akhilmhdh/feat/secret-approval
Secret approval policies feature
2023-09-27 23:56:16 -07:00
Akhil Mohan
b0c398688b feat(secret-approval): updated names to secret policy and fixed approval number bug 2023-09-28 12:23:01 +05:30
Maidul Islam
1141408d5b add exit codes for errors 2023-09-27 21:42:34 -07:00
Maidul Islam
b24bff5af6 Update service-token.mdx 2023-09-27 21:17:28 -07:00
Maidul Islam
a1dc405516 Merge pull request #1032 from Infisical/service-token-v2-create-cli
add create service token to cli + docs for it
2023-09-27 21:09:24 -07:00
Maidul Islam
896a34eb65 add create service token to cli + docs for it 2023-09-27 21:07:54 -07:00
Akhil Mohan
c67432a56f feat(secret-approval): implemented frontend ui for secret policies 2023-09-27 23:10:45 +05:30
Akhil Mohan
edeb6bbc66 feat(secret-approval): implemented backend api for secret policies 2023-09-27 23:10:28 +05:30
Andrew Atimapre
f72e240ce5 Merge branch 'main' into gitlab-sso 2023-09-27 12:57:53 +01:00
nafees nazik
77ec17ccd4 fix: update many query 2023-09-27 17:01:02 +05:30
nafees nazik
6e992858aa fix: add renamed fields to other models 2023-09-27 15:12:32 +05:30
Akhil Mohan
9cda85f03e checkpoint 2023-09-27 11:50:52 +05:30
Maidul Islam
ddae305fdb Merge pull request #1026 from akhilmhdh/feat/get-import-sec
feat: added support for getting imported secrets in v3 getSecret api
2023-09-26 22:01:35 -07:00
Maidul Islam
8265d18934 nit: add lean option 2023-09-26 22:00:00 -07:00
Tuan Dang
c65a53f1f7 Add endpoint to get project key for ST V3 2023-09-26 14:24:55 +01:00
Tuan Dang
aa1e0b0f28 Update audit log service actor v3 filter, status toggle permissions, add JWT service token secret, for ST V3 2023-09-26 12:03:00 +01:00
Tuan Dang
4683dc7869 Scope switch cases into blocks for secrets v3 2023-09-26 10:56:08 +01:00
Akhil Mohan
4c1324baa9 feat: added support for getting imported secrets in v3 getSecret api 2023-09-26 12:25:23 +05:30
Andrew Atimapre
bc489e65ca Integrated login with Gitlab 2023-09-26 02:21:27 +01:00
Maidul Islam
5128466233 update go.mod after Infisical/go-keyring update 2023-09-25 15:28:13 -07:00
Maidul Islam
e11abb619a use v1.0.2 of internal keyring in cli 2023-09-25 15:10:59 -07:00
Maidul Islam
f51e9ba8ff add back role migration 2023-09-25 11:51:25 -07:00
Tuan Dang
45b85ab962 Fix merge conflicts 2023-09-25 13:26:09 +01:00
Tuan Dang
698a268b5f Add permissions and audit logging to service tokens v3 2023-09-25 13:24:28 +01:00
Andrew Atimapre
0d74752169 Integrated login with Gitlab 2023-09-24 22:33:00 +01:00
Andrew Atimapre
255705501f Integrated login with Gitlab 2023-09-24 15:21:23 +01:00
BlackMagiq
a255af6ad8 Merge pull request #1022 from Infisical/debug-vercel-integration
Patch Vercel integration for custom preview branches
2023-09-23 11:42:38 +01:00
Tuan Dang
30da2e50b1 Patch Vercel integration for custom preview branches 2023-09-23 11:38:49 +01:00
Maidul Islam
7f9bd93382 Merge pull request #1004 from vwbusguy/bugfix/no-auto-capitalization-support
Fix no Auto-Capitalization for secrets get/set. Fixes #1003
2023-09-22 13:28:15 -07:00
Maidul Islam
e81ea314e1 update go minor version 2023-09-22 13:26:32 -07:00
Maidul Islam
f19aca2904 fix zod type for ToggleAutoCapitalizationV2 2023-09-22 13:10:11 -07:00
vmatsiiako
763bdabd60 Merge pull request #998 from Infisical/qovery-integration
Added Qovery integration
2023-09-22 12:44:06 -07:00
vmatsiiako
7ec708b71d Merge pull request #1019 from akhilmhdh/fix/audit-log
feat: made audit log options back
2023-09-22 12:24:42 -07:00
nafees nazik
2eff06cf06 fix: alert component styles 2023-09-22 23:20:45 +05:30
nafees nazik
a024eecf2c chore: remove utils 2023-09-22 23:10:46 +05:30
nafees nazik
a2ad9e10b4 chore: enable prop types 2023-09-22 22:37:36 +05:30
Akhil Mohan
3c6c1891a8 feat: made audit log options back 2023-09-22 22:07:48 +05:30
BlackMagiq
01d3d84b40 Merge pull request #1017 from Infisical/debug-self-hosted-gitlab
Patch self-hosted gitlab integration
2023-09-22 15:47:05 +01:00
Tuan Dang
32bec03adf Patch self-hosted gitlab integration 2023-09-22 15:19:26 +01:00
Tuan Dang
f59b3b3305 Add separate ServiceTokenV3 auth type 2023-09-22 14:43:42 +01:00
BlackMagiq
5b6c2e05f2 Merge pull request #1016 from Infisical/fix-teamcity
Fix TeamCity integration blank screen issue
2023-09-22 12:11:59 +01:00
Tuan Dang
c623f572b7 Fix TeamCity integration 2023-09-22 12:06:42 +01:00
Tuan Dang
53856ff868 Make more progress on service token v3 2023-09-22 11:19:14 +01:00
Tuan Dang
84d094b4d8 Finish preliminary CRUD ops for service token v3, ServiceTokenV3Key structure 2023-09-21 15:15:22 +01:00
Vladyslav Matsiiako
48f7bd146f added bun docs 2023-09-20 23:53:31 -07:00
Vladyslav Matsiiako
da6fa6d8ce added bun docs 2023-09-20 23:44:15 -07:00
vmatsiiako
cf8e597c7d Update bun.mdx 2023-09-20 23:34:12 -07:00
Vladyslav Matsiiako
43c31332e4 added bun docs 2023-09-20 19:15:58 -07:00
Vladyslav Matsiiako
88fbf6f88e added bun docs 2023-09-20 19:06:45 -07:00
Maidul Islam
119730ac1a Update build-docker-image-to-prod.yml 2023-09-20 17:06:12 -04:00
Maidul Islam
1d66dbbce3 Merge pull request #1010 from akhilmhdh:code-editor-fix
Stable multiline input
2023-09-20 16:26:05 -04:00
Maidul Islam
b0991c33b0 Merge pull request #1013 from Infisical:fix-github-sso-email
Update method to obtain email for GitHub SSO
2023-09-20 16:09:36 -04:00
nafees nazik
7fa4e09874 feat: use alert component 2023-09-20 23:09:03 +05:30
Tuan Dang
efb14ca267 Merge remote-tracking branch 'origin' into service-token-v3 2023-09-20 17:47:55 +01:00
BlackMagiq
d863dece79 Merge pull request #1012 from akhilmhdh/feat/accordion-component
fix: resolved broken style of accordion component and added storybook
2023-09-20 17:46:20 +01:00
Tuan Dang
96fbc6c5a0 Update method to obtain email for GitHub SSO 2023-09-20 17:38:00 +01:00
Tuan Dang
1896442168 Finish basic scaffolding for service token v3 2023-09-20 17:32:33 +01:00
Akhil Mohan
a93631d41c fix: resolved broken style of accordion component and added storybook 2023-09-20 20:59:34 +05:30
Akhil Mohan
2c7aac37a2 feat: resolved trailing whitespace not showing up 2023-09-20 17:05:57 +05:30
nafees nazik
6b8d4c2fea fix: padding 2023-09-20 17:05:57 +05:30
nafees nazik
f84235eea3 fix: scroll 2023-09-20 17:05:57 +05:30
nafees nazik
63e8ecce5b fix: break 2023-09-20 17:05:57 +05:30
nafees nazik
ef7bf09398 fix: trimming 2023-09-20 17:05:57 +05:30
nafees nazik
3be3867579 fix: font size 2023-09-20 17:05:57 +05:30
nafees nazik
7f753b23f8 fix: secret input 2023-09-20 17:05:57 +05:30
nafees nazik
81827e2deb chore: remove content editable 2023-09-20 17:05:57 +05:30
Maidul Islam
f02ea8d9b8 Merge pull request #1006 from vwbusguy/bugfix/helm-chart-frontend-resources
Update cpu default frontend value.  Fixes #1005.
2023-09-19 12:46:13 -04:00
Maidul Islam
1609bd4652 update chart version and frontend cpu 2023-09-19 12:45:07 -04:00
Maidul Islam
a620f1c924 add workspace index for SecretBlindIndexData 2023-09-19 11:46:37 -04:00
BlackMagiq
0a3e7731d9 Merge pull request #1009 from Infisical/google-github-sso-docs
Add Google and GitHub SSO configuration docs
2023-09-19 16:00:52 +01:00
Tuan Dang
0ca8425965 Add enterprise notice to SAML SSO docs 2023-09-19 15:54:56 +01:00
Tuan Dang
14a260b785 Finish adding docs for Google SSO and GitHub SSO configuration 2023-09-19 15:53:19 +01:00
Tuan Dang
b6219e14f0 Finish optimizing qovery integration, add docs for it 2023-09-19 14:43:20 +01:00
BlackMagiq
663c4869b9 Merge pull request #1008 from Infisical/fix-vercel-integration
Patch integrations involving teamId
2023-09-19 14:09:14 +01:00
Tuan Dang
3103075c3f Bring back missing teamId when fetching integrationAuth 2023-09-19 14:06:06 +01:00
Tuan Dang
e3ef826f52 Update qovery integration 2023-09-19 13:50:01 +01:00
nafees nazik
20c4e956aa feat: add warnings 2023-09-19 17:25:37 +05:30
nafees nazik
4a227d05ce feat: add className utility 2023-09-19 17:25:03 +05:30
nafees nazik
6f57ef03d1 feat: add alert component 2023-09-19 17:24:33 +05:30
nafees nazik
257b4b0490 chore: disable prop-types rule 2023-09-19 17:08:54 +05:30
vmatsiiako
215ef0bb29 Merge pull request #975 from JanetEne/update-use-secret-path-across-app
update and use secret path examples where applicable across app
2023-09-18 21:36:46 -07:00
vmatsiiako
9cc220e51f Merge branch 'main' into update-use-secret-path-across-app 2023-09-18 21:31:34 -07:00
Vladyslav Matsiiako
8fa90d94ac Deleted console.log 2023-09-18 21:29:49 -07:00
vmatsiiako
609204f7f6 Merge pull request #987 from Infisical/permissioning-style-improvements
change certain permissioning text
2023-09-18 21:17:35 -07:00
vmatsiiako
d501130e64 Update secret-reference.mdx 2023-09-18 19:30:33 -07:00
Scott Williams
45734d78c0 Update cpu default frontend value. Fixed #1005.
Signed-off-by: Scott Williams <scottwilliams@ucsb.edu>
2023-09-18 19:14:14 -07:00
vmatsiiako
dd9a2dd345 Update secret-reference.mdx 2023-09-18 18:44:08 -07:00
Scott Williams
80bec24219 Fix no Auto-Capitalization for secrets get/set. Fixes https://github.com/Infisical/infisical/issues/1003
Signed-off-by: Scott Williams <scottwilliams@ucsb.edu>
2023-09-18 15:07:58 -07:00
Tuan Dang
1cdd840485 Begin service token v3 2023-09-18 22:15:48 +01:00
Maidul Islam
4765dd0696 remove backfillPermission (no longer needed) 2023-09-18 12:50:40 -04:00
Maidul Islam
0d4cacdc3e remove old ValidateEnvironmentName check 2023-09-18 12:26:09 -04:00
Vladyslav Matsiiako
0b59a92dfb Added Qovery integration 2023-09-17 18:15:47 -07:00
BlackMagiq
64d5a82e1b Merge pull request #988 from Infisical/integrations-uiux-updates
improved ui/ux for checkly, gcp, and vault integrations
2023-09-16 18:40:00 +01:00
Tuan Dang
a89ed40dcd Update Fly.io integration authorization page to use react-form 2023-09-16 18:13:55 +01:00
BlackMagiq
1634f9ec49 Merge pull request #996 from akhilmhdh/fix/integration-revoke
fix: integration bot deactive resolved and redis type error
2023-09-16 14:26:43 +01:00
Akhil Mohan
dd1bb84361 fix: patched auto bot removal for integration 2023-09-16 18:03:13 +05:30
Tuan Dang
0f003e8ab6 Add type assertion for GitLab selfhosted URL 2023-09-16 12:42:23 +01:00
Tuan Dang
14d253d01a Update GCP SM and GitLab integrations to have overwrite popup warning 2023-09-16 12:36:29 +01:00
Akhil Mohan
750c1b46da fix: integration bot deactive resolved and redis type error 2023-09-16 16:47:41 +05:30
Tuan Dang
2e07512bae Merge remote-tracking branch 'origin' into integrations-uiux-updates 2023-09-16 09:27:49 +01:00
Vladyslav Matsiiako
20a6497218 Fixed UI for TeamCity, Fly.io, Render integrations 2023-09-15 22:18:25 -07:00
Vladyslav Matsiiako
72839719fd Fixed UI for the AWS integrations 2023-09-15 21:43:46 -07:00
Maidul Islam
d8d480f2bc edge case: read write for non existing env in deniedPermissions 2023-09-15 22:32:42 -04:00
vmatsiiako
58c3a4ebc1 Merge branch 'main' into integrations-uiux-updates 2023-09-15 18:22:29 -07:00
Vladyslav Matsiiako
0d83954c39 fixed merged conflicts for gitlab and added animation for tabs 2023-09-15 18:18:40 -07:00
Vladyslav Matsiiako
80cee40b39 Updated UI for CircleCI integration 2023-09-15 17:53:58 -07:00
Vladyslav Matsiiako
6059070d29 Updated UI for Vercel, GCP, GitLab, Checkly, Vault integrations 2023-09-15 17:24:30 -07:00
Maidul Islam
f16944024b Update build-staging-img.yml 2023-09-15 20:18:05 -04:00
Maidul Islam
29da8843a3 add prefix for role name 2023-09-15 20:11:06 -04:00
Maidul Islam
8cd6a1f564 no release lock after backfill complete 2023-09-15 18:56:41 -04:00
Maidul Islam
e8fd3c8045 update lock time for permission backfill 2023-09-15 18:14:31 -04:00
Maidul Islam
59cd8580d5 bring back tests for CI 2023-09-15 17:56:12 -04:00
Maidul Islam
859cec49d1 make redis client conditional 2023-09-15 17:55:43 -04:00
Vladyslav Matsiiako
fccbf9810f fixed gcp integration UIUX 2023-09-15 14:30:37 -07:00
Maidul Islam
5494bc6c3c Update build-staging-img.yml 2023-09-15 17:22:54 -04:00
Maidul Islam
95385b1f45 Merge pull request #991 from akhilmhdh/feat/rbac-migratio
feat(rbac): migration script for permission from old permission to new
2023-09-15 17:09:51 -04:00
Maidul Islam
b88a319582 add lock mechanism for backfillPermission script 2023-09-15 16:39:59 -04:00
Vladyslav Matsiiako
db5883ae56 fix merge conflicts 2023-09-15 13:28:11 -07:00
BlackMagiq
26229b07bc Merge pull request #994 from Infisical/integration-options
Finish integration options/react form refactor for GitLab and GCP SM …
2023-09-15 21:00:55 +01:00
Tuan Dang
3ab5db9b2a Finish integration options/react form refactor for GitLab and GCP SM integrations, add docs for it 2023-09-15 20:53:31 +01:00
vmatsiiako
717b831e94 Merge pull request #992 from serin0837/parse-env-file
fix hyphen env variable import bug
2023-09-15 11:45:36 -07:00
Maidul Islam
336b5897f0 update role description 2023-09-15 12:40:40 -04:00
Maidul Islam
0ce5aaf61c add role deduplication logic 2023-09-15 11:44:48 -04:00
Maidul Islam
adfa90340d remove unsetting deniedPermissions 2023-09-15 09:53:17 -04:00
Serion Jeon
444aca0070 fix hyphen env variable import bug 2023-09-15 14:52:30 +01:00
Akhil Mohan
029766c534 feat(rbac): migration script for permission from old permission to new 2023-09-15 16:20:21 +05:30
Vladyslav Matsiiako
bde788c4f6 improved ui/ux for checkly, gcp, and vault integrations 2023-09-14 22:21:59 -07:00
Maidul Islam
9b14b64ec2 Merge pull request #983 from ragnarbull/main
Docs: Update FAQ for Alpine CDN error
2023-09-15 00:31:14 -04:00
Maidul Islam
0a72dccdcf add back defaultOpen="true" 2023-09-15 00:30:15 -04:00
Joel Biddle
7fe94d66cd Create new FAQ page under developer setup docs 2023-09-15 11:59:15 +10:00
Maidul Islam
f503f8c76d Merge pull request #985 from xphyr/main
changing CMD for Dockerfile  to address issue #984
2023-09-14 19:32:09 -04:00
Maidul Islam
7982b1d668 replace owner role for local dev user 2023-09-14 19:27:23 -04:00
Maidul Islam
7a78209613 Merge pull request #977 from akhilmhdh:feat/permission-patch-2
feat(rbac): removed owner role and changed member permissions
2023-09-14 18:57:02 -04:00
Maidul Islam
019024e4ae remove the use of owner everywhere else 2023-09-14 18:23:59 -04:00
Maidul Islam
4d6895a793 Merge pull request #933 from MohamadTahir:add_resource_probs_to_deployments
Add resource specification to frontend and backend deployment containers
2023-09-14 16:36:51 -04:00
Maidul Islam
36b5ba2855 remove change log bc will get replaced by auto generated one soon 2023-09-14 16:35:13 -04:00
xphyr
44d2a6c553 clearing npm cache to save space 2023-09-14 13:57:58 -04:00
xphyr
a073a746f2 changing CMD for Dockerfile to use node instead of npm to address issue #984 2023-09-14 13:33:15 -04:00
Akhil Mohan
edb3e66267 fix(integrations): resolved integration bot deactive revoke bug 2023-09-14 21:56:57 +05:30
Maidul Islam
75be302166 Merge pull request #969 from quinton11:feat/secrets-get-cmd-path
fix: `path` option for `secret get` sub cmd
2023-09-14 12:22:16 -04:00
Maidul Islam
b459d2d5f5 Merge pull request #954 from jessebot/patch-1
Update values.yaml - add `mongodb.auth.existingSecret` parameter to helm chart
2023-09-14 12:08:03 -04:00
Akhil Mohan
942e1a82c2 feat(rbac): removed audit log option for time being, v3 secret patch and reload permission flash screen fix 2023-09-14 21:34:13 +05:30
Maidul Islam
9d2bc25cb4 Merge pull request #978 from hcourdent/patch-1
Backlink to Windmill.dev in windmill.mdx
2023-09-14 11:35:52 -04:00
Maidul Islam
13083d7676 remove link from description - anti pattern in docs 2023-09-14 11:35:33 -04:00
Akhil Mohan
18d843f3e6 feat(rbac): fixed ip allow list api 2023-09-14 20:40:57 +05:30
Joel Biddle
ee96325034 Update FAQ for Alpine CDN error 2023-09-14 23:24:32 +10:00
BlackMagiq
954f15e4df Merge pull request #980 from Infisical/fix-gitlab-integration-self-hosted
Update all GitLab integration URLs to point to self-hosted instances if applicable (else GitLab Cloud)
2023-09-14 11:42:00 +01:00
Tuan Dang
88842951cb Change +metadata to metadata 2023-09-14 11:16:59 +01:00
Tuan Dang
8e88a3a25f Point getTeamsGitLab method to self-hosted GitLab instance if applicable 2023-09-14 10:59:09 +01:00
Henri Courdent
f1e1ca07df Backlink to Windmill.dev in windmill.mdx 2023-09-14 11:20:44 +02:00
Tuan Dang
5bf2c2f52b Point getAppsGitLab method to self-hosted GitLab instance if applicable, fix integration revocation issue related to missing metadata param partly 2023-09-14 10:14:10 +01:00
Akhil Mohan
3d2a2651b8 feat(rbac): removed owner role and changed member permissions 2023-09-14 13:20:42 +05:30
Vladyslav Matsiiako
0f02ef701e change some permissioning text 2023-09-13 19:02:24 -07:00
JanetEne
1c5e80e68a update file naming 2023-09-14 02:33:08 +01:00
JanetEne
c30381edbc uchange component name to globpatternexample 2023-09-14 02:17:33 +01:00
JanetEne
2554ad2b3c update and use secret path examples where applicable across app 2023-09-14 01:51:05 +01:00
Maidul Islam
c3696bdbbc Merge pull request #972 from akhilmhdh/feat/permission-patch
feat(rbac): grouped folder and imports permission into secret permission
2023-09-13 13:33:26 -04:00
vmatsiiako
1be924d210 Update kubernetes.mdx 2023-09-13 10:10:45 -07:00
Akhil Mohan
2333675262 feat(rbac): grouped folder and imports permission into secret permission 2023-09-13 22:30:56 +05:30
BlackMagiq
c3c16f4e42 Merge pull request #966 from serin0837/gcp-secret-manager-add-labels
add label managed by infisical
2023-09-13 10:12:16 +01:00
Tuan Dang
99a2203b38 Update GCP SM docs to include note on Cloud Resource Manager API enabled requirement and label 2023-09-13 10:10:50 +01:00
Tuan Dang
92b64d3553 Merge remote-tracking branch 'origin' into gcp-secret-manager-add-labels 2023-09-13 09:50:26 +01:00
BlackMagiq
533e628183 Merge pull request #973 from Infisical/expose-folders-api
Implement workaround for swagger-autogen edgecase and expose folders,…
2023-09-13 09:44:35 +01:00
Tuan Dang
3b7096710c Fix merge conflicts 2023-09-13 09:42:36 +01:00
Tuan Dang
97b7a5ebdf Fix merge conflicts 2023-09-13 09:35:53 +01:00
Tuan Dang
4f69257595 Implement workaround for swagger-autogen edgecase and expose folders, secret imports API 2023-09-13 09:28:29 +01:00
vmatsiiako
8f93141d54 Merge pull request #962 from G3root/fix-login
fix: overflow issue login page
2023-09-12 16:57:07 -07:00
vmatsiiako
2bbba8a43a Merge pull request #970 from zenorocha/resend
Add Resend instructions
2023-09-12 16:34:45 -07:00
Zeno Rocha
4da251bdfc Add Resend instructions 2023-09-12 16:21:04 -07:00
Maidul Islam
8520ae8d43 Update .infisicalignore 2023-09-12 19:05:29 -04:00
Maidul Islam
e38abb128a Update .infisicalignore 2023-09-12 19:05:03 -04:00
quinton11
d46a6f7270 fix: path option for secret get sub cmd 2023-09-12 22:11:15 +00:00
Serion Jeon
33adbc0f24 add label managed by infisical 2023-09-12 09:57:03 +01:00
Maidul Islam
fc3b0e1de9 Merge pull request #963 from akhilmhdh/feat/move-roles-ee
refactor: moved role folder to ee
2023-09-11 21:38:33 -04:00
vmatsiiako
ba225dd504 Added card tiles to security page 2023-09-11 16:37:17 -07:00
BlackMagiq
d221bf8ae9 Merge pull request #964 from Infisical/update-security-docs
Add/update docs to include internals
2023-09-12 00:04:49 +01:00
Tuan Dang
d7354e1aca Finish docs for internals 2023-09-12 00:02:43 +01:00
MohamadTahir
86b2b95d11 update readme file and values.yaml documentations 2023-09-11 22:10:47 +03:00
Akhil Mohan
e7c5e6a789 refactor: moved role folder to ee 2023-09-11 23:53:05 +05:30
nafees nazik
1ca106279e fix: overflow login page 2023-09-11 22:42:02 +05:30
BlackMagiq
49d6f85f42 Merge pull request #961 from akhilmhdh/fix/folder-bug
fix: resovled batch function not working with folders
2023-09-11 15:25:34 +01:00
Akhil Mohan
c894952e84 fix: resovled batch function not working with folders 2023-09-11 13:01:49 +05:30
vmatsiiako
4ce0eccfa1 Merge pull request #959 from JanetEne/helper-text-for-secret-path
Add helper text and tooltip for secret path
2023-09-09 18:17:24 -07:00
Vladyslav Matsiiako
ad710f4860 fixed the style of the webhook tooltip 2023-09-09 18:10:02 -07:00
JanetEne
45117ba1f4 show tooltip on hover of icon and not onclick 2023-09-09 22:35:55 +01:00
vmatsiiako
1b2b1ca30b Update README.md 2023-09-09 13:24:16 -07:00
BlackMagiq
b89a90066a Merge pull request #958 from Infisical/check-gcp-sm-integration
Patch broken integrations due to permission update
2023-09-09 17:59:31 +01:00
Tuan Dang
83d2a39fb1 Patch broken integratins due to permission update 2023-09-09 17:29:19 +01:00
Tuan Dang
412b1123af Begin security docs revamp 2023-09-09 10:00:09 +01:00
JanetEne
dc91615b43 add helper text and tooltip for secret path 2023-09-09 04:06:16 +01:00
Vladyslav Matsiiako
110153385b permissioning style update 2023-09-08 20:05:02 -07:00
JesseBot
e37810f302 Update Chart.yaml - bump helm chart version after adding mongodb.auth.existingSecret parameter to values.yaml 2023-09-08 18:52:16 +02:00
JesseBot
f02e39e7e3 Merge branch 'Infisical:main' into patch-1 2023-09-08 18:50:24 +02:00
Maidul Islam
305ddd3813 Merge pull request #860 from akhilmhdh/feat/new-permission-system
New Permission System
2023-09-08 11:59:49 -04:00
Akhil Mohan
b023bb1df2 feat(rbac): removed unused variables 2023-09-08 21:26:10 +05:30
Akhil Mohan
63ff669612 feat(rbac): applied subscription banner in custom roles 2023-09-08 21:22:36 +05:30
Akhil Mohan
8003273b2c feat(rbac): changed withpermission hoc text and removed loading on overview pageg 2023-09-08 21:22:36 +05:30
Akhil Mohan
2f9b35b2f9 feat(rbac): resolved submit button getting disabled 2023-09-08 21:22:36 +05:30
Maidul Islam
91c1aca588 add role index 2023-09-08 21:22:36 +05:30
Akhil Mohan
e8f7b0c181 feat(rbac): resolved batch bug in permission check 2023-09-08 21:22:36 +05:30
Akhil Mohan
43735b8183 feat(rbac): updated role controller to check permissions and batch v2 selectively permission check 2023-09-08 21:22:36 +05:30
Maidul Islam
988bb4ffb6 remove created & justify delete buttons to right 2023-09-08 21:22:36 +05:30
Maidul Islam
0f46f53a7d update denied text 2023-09-08 21:22:36 +05:30
Maidul Islam
9c9d46824c only backfill roles for non empty permissions array 2023-09-08 21:22:36 +05:30
Akhil Mohan
43b97b411b feat(rbac): updated helper text on glob pattern in multi env permission field 2023-09-08 21:22:36 +05:30
Akhil Mohan
38c044f9a7 feat(rbac): put back condition matcher for workspace permission check and added migration function 2023-09-08 21:22:36 +05:30
Akhil Mohan
c91a93ef2a feat(rbac): resolved secret import not listing 2023-09-08 21:22:36 +05:30
Akhil Mohan
a4ef829046 feat(rbac): added glob support in permission and revealed settings 2023-09-08 21:22:36 +05:30
Maidul Islam
2ed079830a make org permissions more readable 2023-09-08 21:22:36 +05:30
Akhil Mohan
98893a40f1 feat(rbac): made changes from testing with maidul 2023-09-08 21:22:36 +05:30
Akhil Mohan
252042fb20 feat(rbac): resolved viewer permission in list 2023-09-08 21:22:36 +05:30
Akhil Mohan
4ca95f4d79 feat(rbac): resolved zod validator issues and trim in frontend 2023-09-08 21:22:36 +05:30
Akhil Mohan
26028e7312 feat(rbac): fixed broken view when clicking editing predefined role 2023-09-08 21:22:36 +05:30
Akhil Mohan
6bbdc4a405 feat(rbac): fixed broken invite and role missing in dropdown 2023-09-08 21:22:36 +05:30
Akhil Mohan
cb9ee00ed3 feat(rbac): made org role section permission into one component and fixed some small issues 2023-09-08 21:22:36 +05:30
Akhil Mohan
f1a291a52a feat(rbac): fixed merge conflicts and resolved some more issues with permission checks 2023-09-08 21:22:36 +05:30
Akhil Mohan
bcfe1bda84 feat(rbac): made new permission check for v3 secrets and v2 batch 2023-09-08 21:22:36 +05:30
Tuan Dang
82d4c8f000 Split requireBlindIndicesEnabled, E2EEOff, requireIPAllowlistCheck away from requireWorkspaceAuth 2023-09-08 21:22:36 +05:30
Akhil Mohan
7c698e755a feat(rbac): added frontend permission validation for missing pages and merged new features 2023-09-08 21:22:36 +05:30
Akhil Mohan
4b0bc238fc feat(rbac): changed the action names for org 2023-09-08 21:22:36 +05:30
Akhil Mohan
ea9e638d03 feat(rbac): resolved merge conflict 2023-09-08 21:22:36 +05:30
Akhil Mohan
6671699867 feat(rbac): added new permission check for workspace in frontend 2023-09-08 21:22:36 +05:30
Akhil Mohan
549121f44e feat(rbac): added new validation to all routes and permission check to most 2023-09-08 21:22:36 +05:30
Akhil Mohan
520a553ea1 feat(rbac): implemented project based permission loading and role management 2023-09-08 21:22:36 +05:30
Akhil Mohan
aac3168c80 feat(rbac): implemented granular blocking of actions based on permissions on org level ui 2023-09-08 21:21:43 +05:30
Akhil Mohan
34fb7be1c4 feat(rbac): added org permission context for pulling permission from api 2023-09-08 21:21:43 +05:30
Akhil Mohan
e342e88499 feat(rbac): added new zod validation and permission check for all org level api 2023-09-08 21:20:29 +05:30
Akhil Mohan
96437fd1b7 feat(rbac): added rest of permissions in ui and backend api for org level 2023-09-08 21:20:29 +05:30
Akhil Mohan
c5f76b1e6f feat(rbac): base ui for org rbac management 2023-09-08 21:20:29 +05:30
Akhil Mohan
1167b1bc60 feat(rbac): ui components and hooks for rbac 2023-09-08 21:20:29 +05:30
Akhil Mohan
1bf9041ac9 feat(rbac): implemented backend base apis for rbac permission system 2023-09-08 21:20:29 +05:30
Maidul Islam
6bca7dcc58 update k8 self host image versions examples 2023-09-07 22:33:57 -04:00
Vladyslav Matsiiako
a9f062b469 Merge branch 'main' of https://github.com/Infisical/infisical 2023-09-07 17:35:38 -07:00
Vladyslav Matsiiako
43caccad9f removed intercom 2023-09-07 17:35:26 -07:00
Maidul Islam
9cef1d3b10 Merge pull request #943 from RezaRahemtola/main
docs: Fixing multiple typos
2023-09-07 14:18:05 -04:00
JesseBot
6c126606da Update README.md for helm chart parameters to include mongodb.auth.existingSecret 2023-09-07 20:02:15 +02:00
JesseBot
ae37d80891 Update values.yaml - add mongodb.auth.existingSecret parameter 2023-09-07 19:55:21 +02:00
BlackMagiq
8e6b0ca0a9 Merge pull request #953 from serin0837/patch-1
Update gcp-secret-manager.mdx
2023-09-07 13:58:55 +01:00
Serin Jeon
a288a0bf2a Update gcp-secret-manager.mdx
Just found out that there is a typo for the redirect URL.
2023-09-07 11:03:57 +01:00
BlackMagiq
9dd77ae36e Merge pull request #951 from Infisical/gitlab-integration-selfhosted
Extend GitLab integration to support syncing to self-hosted instances of GitLab
2023-09-06 11:15:39 +01:00
Tuan Dang
1e20715511 Add self-hosted gitlab url to sync function 2023-09-06 11:11:11 +01:00
Tuan Dang
d07b2dafc3 Finish adding support for self-hosted GitLab integration 2023-09-06 10:57:27 +01:00
Tuan Dang
04548313ab Merge remote-tracking branch 'origin' into gitlab-integration-selfhosted 2023-09-06 09:55:19 +01:00
BlackMagiq
86bf2ddd89 Merge pull request #949 from Infisical/aws-ps-integration
Fix null appId argument for creating PAT integration
2023-09-05 20:15:26 +01:00
Tuan Dang
2ad663c021 Update integration app and appId values 2023-09-05 20:10:50 +01:00
Tuan Dang
56317a3f53 Fix null appId argument for creating PAT integration 2023-09-05 19:55:54 +01:00
Tuan Dang
ad0bc4efdc Continue progress on self-hosted gitlab integration 2023-09-05 19:46:59 +01:00
Maidul Islam
bf74b75c4a Merge pull request #932 from daninge98/secret-scan-whole-repo
Secret scanning: scan for leaked secrets in historical commits
2023-09-04 15:49:21 -04:00
BlackMagiq
7f543b635c Merge pull request #944 from Infisical/gcp-sm-integration-auth
Add support for service account JSON authentication method for GCP Secret Manager integration
2023-09-04 14:20:15 +01:00
Tuan Dang
353dfeb2a9 Fix lint issues 2023-09-04 14:15:46 +01:00
Tuan Dang
16196e6343 Fix lint issues 2023-09-04 14:13:16 +01:00
Tuan Dang
3f2b74a28a Merge 2023-09-04 12:49:11 +01:00
Tuan Dang
4a603da425 Finished adding support for service account JSON auth method for GCP secret manager integration 2023-09-04 12:48:15 +01:00
Reza Rahemtola
0d9ce70000 docs: Fixing multiple typos 2023-09-03 23:28:19 +02:00
BlackMagiq
9fa1e415c8 Merge pull request #942 from omahs/patch-1
Fix typos
2023-09-03 14:24:37 +01:00
omahs
09b22f36c0 fix typo 2023-09-03 15:12:13 +02:00
omahs
43c8c42249 fix typo 2023-09-03 15:11:26 +02:00
omahs
d4a7ad713c fix typos 2023-09-03 15:10:19 +02:00
omahs
9afad7df32 fix typos 2023-09-03 15:09:18 +02:00
omahs
3f61a24ef1 fix typos 2023-09-03 15:06:53 +02:00
BlackMagiq
f342c345b7 Merge pull request #934 from Infisical/aws-ps-integration-fix
Add support for syncing secrets containing / to AWS parameter store integration
2023-09-02 11:17:06 +01:00
Tuan Dang
6dd46885f8 Add support for syncing secrets containing / to AWS parameter store integration 2023-09-02 11:11:27 +01:00
MohamadTahir
5704dfb35f add resource specification to frontend and backend deployment containers 2023-09-02 09:29:23 +03:00
Vladyslav Matsiiako
41774fa97c fixed the bug with reading secrets from json 2023-09-01 19:34:38 -07:00
Daniel Inge
32b26c331c Fix gitignore 2023-09-01 23:10:12 +01:00
Daniel Inge
011507b8e0 Small fixes 2023-09-01 23:08:38 +01:00
Daniel Inge
4adb2a623e Merge remote-tracking branch 'origin/main' into secret-scan-whole-repo 2023-09-01 22:43:20 +01:00
Daniel Inge
1d410c8420 Fix type 2023-09-01 22:40:19 +01:00
Daniel Inge
35f3d6c776 Initial implementation 2023-09-01 22:36:52 +01:00
Maidul Islam
5e24b517cc Merge pull request #928 from davidhonig/fix-webhook-status-date-formatting
Fix date-fn format string
2023-09-01 14:05:50 -04:00
Maidul Islam
bf95415a0d Update k8 operator Chart version 2023-09-01 13:33:51 -04:00
Maidul Islam
4025063732 Merge pull request #923 from xphyr/main
Fix for issue#922 - helm chart for secrets-operator
2023-09-01 13:33:13 -04:00
David Hönig
e3ecfbaaa5 Fix date-fn format string 2023-09-01 12:16:44 +02:00
Maidul Islam
a7b3d12844 only capture non sign up secret events 2023-08-31 20:58:07 -04:00
xphyr
f5145c6c39 fixing deployment.yaml file in secrets-operator helm chart. removed extra LF that was breaking the template 2023-08-31 17:43:15 -04:00
Tuan Dang
d9abe671af Start GCP SM integration update 2023-08-31 15:22:26 +01:00
Tuan Dang
37ae05fa2a Update changelog 2023-08-31 14:46:22 +01:00
Maidul Islam
086ce0d2a6 Merge pull request #918 from Infisical/revert-917-snyk-fix-29828c58f69ea88c3d50dad65d7767d2
Revert "[Snyk] Fix for 1 vulnerabilities"
2023-08-30 16:36:22 -04:00
Maidul Islam
06dec29773 Revert "[Snyk] Fix for 1 vulnerabilities" 2023-08-30 16:35:44 -04:00
Tuan Dang
ed8e942a5d Update low entropy password error message 2023-08-30 21:28:35 +01:00
Tuan Dang
e770bdde24 Update low entropy password error message 2023-08-30 21:27:31 +01:00
Maidul Islam
a84dab1219 Merge pull request #917 from Infisical/snyk-fix-29828c58f69ea88c3d50dad65d7767d2
[Snyk] Fix for 1 vulnerabilities
2023-08-30 16:26:20 -04:00
snyk-bot
02d9d7b6a4 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-MONGODB-5871303
2023-08-30 20:05:26 +00:00
Tuan Dang
f21eb3b7c8 Patch GCP secret manager integration edge-case 2023-08-30 21:04:39 +01:00
BlackMagiq
219e3884e7 Merge pull request #912 from Infisical/integration-suffixes
Added suffixes to the Checkly integration
2023-08-30 10:29:08 +01:00
Tuan Dang
41cd8b7408 Move secretSuffix to separate metadata field 2023-08-30 10:04:44 +01:00
Vladyslav Matsiiako
f6be86a26b Added suffixes to integrations 2023-08-29 22:17:48 -07:00
Maidul Islam
85e5822ece Merge pull request #908 from akhilmhdh/fix/sec-override-fail
fix: resolved personal override not showing up
2023-08-29 14:07:09 -04:00
Maidul Islam
5c9e89a8e2 Merge pull request #904 from Infisical/dashboard-get-secrets
Rewire dashboard to pull from v3/secrets with folderId support
2023-08-29 13:54:37 -04:00
BlackMagiq
46a77d5e58 Merge pull request #909 from Infisical/team-city-branch-config
Add support for build-configuration environment variable sync for TeamCity integration
2023-08-29 14:43:17 +01:00
Tuan Dang
a6e9643464 Finish adding support for build-configuration level syncs for TeamCity integration 2023-08-29 14:37:58 +01:00
Akhil Mohan
affa2ee695 fix: resolved personal override not showing up 2023-08-29 12:23:12 +05:30
Tuan Dang
dc0d577cbb Patch TeamCity integration 2023-08-29 07:46:11 +01:00
vmatsiiako
9e8ddd2956 Merge pull request #907 from ragnarbull/patch-1
Update overview.mdx
2023-08-28 17:41:26 -07:00
Joel Biddle
b40b876fb2 Update overview.mdx
New password criteria + keep formatting consistent
2023-08-29 10:20:15 +10:00
Tuan Dang
2ba6a65da4 Change order of password check 2023-08-28 11:43:40 +01:00
BlackMagiq
76cf79d201 Merge pull request #885 from ragnarbull/ragnarbull-auth-pwd-fixes
Password fixes - enforce max length, add checks (pwd breach, PII, low entropy), improved UX, deprecate common-passwords api
2023-08-28 11:33:57 +01:00
Tuan Dang
a79c6227b1 Fix frontend lint issues 2023-08-28 11:25:50 +01:00
Tuan Dang
f1f64e6ff5 Fix flaky regex g flag causing unexpected validation password validation issue 2023-08-28 11:08:00 +01:00
Tuan Dang
d72ddfe315 Rewire dashboard to pull from v3/secrets with folderId support 2023-08-28 09:12:04 +01:00
vmatsiiako
f924d0c02c Update kubernetes-helm.mdx 2023-08-27 22:39:19 -07:00
Maidul Islam
ef1b75d890 remove the use of aggregation for documentDB compatibility 2023-08-27 14:41:35 -04:00
BlackMagiq
d8094b2ab1 Merge pull request #903 from Infisical/integration-setup-docs
Add self-hosted setup/configuration docs for OAuth2 integrations
2023-08-27 12:16:26 +01:00
Tuan Dang
ad61fa845c Add self-hosted configuration docs for GitHub, GitLab, GCP SM, Vercel, Heroku, Netlify, Azure KV 2023-08-27 12:14:17 +01:00
BlackMagiq
6bb5e7078f Merge pull request #902 from Infisical/gcp-integration
GCP Secret Manager Integration
2023-08-26 17:42:59 +01:00
Tuan Dang
a07ddb806d Finish GCP secret manager integration 2023-08-26 17:36:20 +01:00
BlackMagiq
6e7d3d6912 Merge pull request #901 from Infisical/environment-api
Expose CRUD Environment Operations to Public REST API
2023-08-26 08:49:35 +01:00
Tuan Dang
84a866eb88 Add API Key auth method to environment endpoints, add endpoints to public REST API docs 2023-08-26 08:47:36 +01:00
Maidul Islam
9416fca832 update to doc5.0 engine 2023-08-25 17:23:31 -04:00
Maidul Islam
2ea518b107 add redis to cloud formation 2023-08-25 15:35:11 -04:00
Maidul Islam
62399dd293 Merge pull request #897 from akhilmhdh/fix/sec-v3-fail
fix: moved backend get sec to v2 for dashboard
2023-08-25 12:09:04 -04:00
Akhil Mohan
16f1360550 fix: moved backend get sec to v2 for dashboard 2023-08-25 21:37:05 +05:30
Joel Biddle
a99751eb72 Moved pwd checks into a subfolder 2023-08-25 12:36:53 +10:00
Maidul Islam
9ea414fb25 Merge pull request #894 from akhilmhdh/fix/multi-line-html-encode
fix(multi-line): resolved breaking ui when secret value contains < or >
2023-08-24 22:12:42 -04:00
Maidul Islam
a9fa3ebab2 update post hog event name 2023-08-24 19:01:59 -04:00
Maidul Islam
293a62b632 update secrets posthog event logic 2023-08-24 18:48:46 -04:00
Maidul Islam
a1f08b064e add tags support in secret imports 2023-08-24 17:21:14 -04:00
Maidul Islam
50977cf788 reduce k8 events 2023-08-24 15:41:29 -04:00
Akhil Mohan
fccec083a9 fix(multi-line): resolved breaking ui when secret value contains < or > 2023-08-24 23:07:58 +05:30
Tuan Dang
63af7d4a15 Merge remote-tracking branch 'origin' into gcp-integration 2023-08-25 00:35:11 +07:00
Tuan Dang
ab3533ce1c Checkpoint GCP secret manager integration 2023-08-25 00:34:46 +07:00
Joel Biddle
4d6a8f0476 Fixed form (error messages too long). Consolidated tests & errors. Moved regexes to another file. Added regex to check for PII & reject pwd if true. Confirmed hashing & encryption/decryption works with top 50 languages, emojis etc (screen videos & unit tests to come). 2023-08-25 01:44:02 +10:00
Joel Biddle
688cf91eb7 Removed unnecessary validator library & @types/validator in favor of yup 2023-08-24 14:08:11 +10:00
vmatsiiako
8ee6710e9b Merge pull request #889 from EBEN4REAL/custom-tag-colors
Custom tag colors
2023-08-23 21:03:46 -07:00
Joel Biddle
14fc78eaaf Switched to crypto.subtle, cleaned up code, added types & properly cleared sensitive data from memory (even if error) 2023-08-24 14:01:26 +10:00
Ebezer Igbinoba
9fa28f5b5e Fix: added empty string as default for tag color and added regex to resolve issue with multiple spacing in tag names. 2023-08-24 03:59:49 +01:00
Joel Biddle
368855a44e >>> yup for email & url validation, fixed minor err in error msgs 2023-08-24 12:59:24 +10:00
Ebezer Igbinoba
ae375916e8 Fix: added nullable check for adding tag color in project settings 2023-08-24 03:39:46 +01:00
vmatsiiako
21f1648998 Merge pull request #887 from Infisical/signup-secret-tagging
Update signup secret distinction/tagging for better telemetry
2023-08-23 19:23:44 -07:00
vmatsiiako
88695a2f8c Merge pull request #884 from monto7926/sortable-secrets-overview
feat: make secrets overview sortable
2023-08-23 17:47:34 -07:00
Vladyslav Matsiiako
77114e02cf fixed the import linting issues 2023-08-23 17:42:29 -07:00
Maidul Islam
3ac1795a5b Update kubernetes-helm.mdx 2023-08-23 17:42:07 -04:00
Maidul Islam
8d6f59b253 up infisical chart version 2023-08-23 17:15:30 -04:00
Maidul Islam
7fd77b14ff print default connection string in helm 2023-08-23 17:14:09 -04:00
Ebezer Igbinoba
8d3d7d98e3 chore: updated style for tag color label 2023-08-23 18:50:24 +01:00
Ebezer Igbinoba
6cac879ed0 chore: removed console log 2023-08-23 16:46:06 +01:00
Ebezer Igbinoba
ac66834daa chore: fixed error with typings 2023-08-23 16:36:48 +01:00
BlackMagiq
0616f24923 Merge pull request #866 from Killian-Smith/email-case-sensitive
fix: normalize email when inviting memebers and logging in.
2023-08-23 18:08:28 +07:00
Tuan Dang
4e1abc6eba Add login email lowercasing to backend 2023-08-23 18:02:18 +07:00
Tuan Dang
8f57377130 Merge remote-tracking branch 'origin' into email-case-sensitive 2023-08-23 17:50:46 +07:00
Tuan Dang
2d7c7f075e Remove metadata from SecretVersion schema 2023-08-23 17:47:25 +07:00
Tuan Dang
c342b22d49 Fix telemetry issue for signup secrets 2023-08-23 17:37:01 +07:00
BlackMagiq
b8120f7512 Merge pull request #886 from Infisical/audit-log-paywall
Add paywall to Audit Logs V2
2023-08-23 17:00:27 +07:00
Tuan Dang
ca18883bd3 Add paywall for audit logs v2 2023-08-23 16:55:07 +07:00
Tuan Dang
8b381b2b80 Checkpoint add metadata to secret and secret version data structure 2023-08-23 16:30:42 +07:00
Maidul Islam
6bcf5cb54c override secrets before expand 2023-08-22 23:37:32 -04:00
Maidul Islam
51b425dceb swap out v2 login 2023-08-22 23:37:32 -04:00
Joel Biddle
7ec00475c6 +maxRetryAttempts, padding & safer error handling. Improved readability & comments. 2023-08-23 12:59:00 +10:00
Vladyslav Matsiiako
84840bddb5 Merge branch 'main' of https://github.com/Infisical/infisical 2023-08-22 15:10:30 -07:00
Vladyslav Matsiiako
93640c9d69 added tooltips to the sercret overview 2023-08-22 15:10:18 -07:00
Maidul Islam
ec856f0bcc remove return from integration loop 2023-08-22 21:18:18 +00:00
Maidul Islam
3e46bec6f7 add simple api to trigger integration sync 2023-08-22 14:55:08 -04:00
Joel Biddle
25fc508d5e Fixed spelling 2023-08-23 02:56:03 +10:00
Joel Biddle
ea262da505 Added check that password is not an email address 2023-08-23 02:14:22 +10:00
danieltonel
954806d950 chore: code cleanup 2023-08-22 17:59:11 +02:00
Joel Biddle
2960f86647 Fix comments explaining "international" password requirements 2023-08-23 01:41:37 +10:00
Joel Biddle
b2888272f2 Added password criterion support for multiple languages and emojis 2023-08-23 01:27:30 +10:00
danieltonel
d6d3302659 feat: make secrets overview sortable 2023-08-22 17:21:21 +02:00
Joel Biddle
e5c87442e5 Changed to use ES2018 rather than load scripts 2023-08-23 01:04:52 +10:00
Joel Biddle
be08417c8b internationalize password requirements 2023-08-23 00:48:45 +10:00
Joel Biddle
61e44e152c optimised import 2023-08-22 23:47:33 +10:00
Joel Biddle
52c4f64655 Removed log and fixed comments 2023-08-22 23:36:24 +10:00
Maidul Islam
81743d55ab fix infisical radar app name 2023-08-22 09:35:31 -04:00
Joel Biddle
3e36adcf5c Removed all references to commonPasswords & the data file. This api route can be deprecated in favor of the client-side secure call to the haveIBeenPwnd password API. Further the datafile contains no passwords that meet the minimum password criteria. 2023-08-22 23:30:24 +10:00
Joel Biddle
1f60a3d73e fixed more error handling for password checks & translations 2023-08-22 22:42:02 +10:00
Joel Biddle
00089a6bba Added breached pwd error translations 2023-08-22 20:57:12 +10:00
Joel Biddle
026ea29847 further fixes to password check logic 2023-08-22 20:42:07 +10:00
Joel Biddle
1242d88acb Fixed breached pwd error messages 2023-08-22 20:20:54 +10:00
Joel Biddle
f47a119474 fixed breached pwd error messages 2023-08-22 20:20:13 +10:00
Joel Biddle
0b359cd797 Made breached pwd API comments clearer 2023-08-22 19:45:35 +10:00
Joel Biddle
c5ae402787 Added comments to explain breach passwords API 2023-08-22 18:14:03 +10:00
Joel Biddle
e288402ec4 Properly added pwndpasswords API to CSP 2023-08-22 17:58:10 +10:00
Joel Biddle
196beb8355 removed logs & added pwndpasswords.com api to CSP 2023-08-22 17:50:43 +10:00
Joel Biddle
d6222d5cee attempt to fix crypto.subtle issue 2023-08-22 17:33:35 +10:00
Joel Biddle
e855d4a0ba added types for crypto 2023-08-22 17:26:00 +10:00
Joel Biddle
20f34b4764 removed async in crypto.subtle 2023-08-22 17:14:18 +10:00
Joel Biddle
0eb21919fb Password breach check 2023-08-22 16:49:17 +10:00
Joel Biddle
fbeb210965 add to pwd length issue 2023-08-22 15:34:45 +10:00
Joel Biddle
0d1aa713ea added translations for error messges (used Google translate) 2023-08-22 14:57:02 +10:00
Ebezer Igbinoba
9a1b453c86 Feat: added tag color widgt and changed tag popover design 2023-08-22 05:12:23 +01:00
Joel Biddle
534d96ffb6 Set max password length (100 chars) to help prevent DDOS attack 2023-08-22 14:05:00 +10:00
Maidul Islam
5b342409e3 Merge pull request #815 from Infisical/snyk-fix-477e109149f5e5a943a435c5bf8814b7
[Snyk] Security upgrade winston-loki from 6.0.6 to 6.0.7
2023-08-21 16:02:02 -04:00
Maidul Islam
a9f54009b8 Merge pull request #848 from narindraditantyo/fix/rootless-frontend-image
fix: frontend image displaying some errors due to sed write permission
2023-08-21 15:54:29 -04:00
Maidul Islam
82947e183c Merge pull request #851 from sreehari2003/main
fix: form not submitting on keyboard enter
2023-08-21 15:53:15 -04:00
Maidul Islam
eb7ef2196a Merge pull request #872 from iamunnip/blogs
added blog link for setting up infisical in developement cluster
2023-08-21 14:09:18 -04:00
Maidul Islam
ad3801ce36 Merge pull request #882 from akhilmhdh/feat/integration-var-not-found
fix(integration): instead of throwing error console and return empty string on interpolation
2023-08-21 13:51:16 -04:00
Akhil Mohan
b7aac1a465 fix(integration): instead of throwing error console and return empty string on interpolation 2023-08-21 20:06:24 +05:30
Tuan Dang
e28ced8eed Provide default path for logging dashboard secrets event 2023-08-21 18:27:18 +07:00
Tuan Dang
4a95f936ea Correct enable blind-indexing web ui rendering condition 2023-08-21 17:27:32 +07:00
Tuan Dang
85a39c60bb Fix query condition on delete secret v3 2023-08-21 16:51:31 +07:00
Ebezer Igbinoba
66ea3ba172 feat: added custom design for tags 2023-08-20 10:02:40 +01:00
Maidul Islam
01d91c0dc7 update helm version 2023-08-19 17:19:42 -04:00
Maidul Islam
dedd27a781 remove unsed redis template 2023-08-19 17:19:07 -04:00
Maidul Islam
57a6d1fff6 fix syntax error in helm chart 2023-08-19 14:47:46 -04:00
Maidul Islam
554f0c79a4 update redis doc 2023-08-19 14:31:28 -04:00
Maidul Islam
2af88d4c99 Merge pull request #843 from Infisical/add-bull-queue
add bull queue
2023-08-19 14:13:34 -04:00
Maidul Islam
fc8b567352 fix syntax error in /api/status 2023-08-19 14:03:02 -04:00
Maidul Islam
ec234e198a Merge branch 'main' into add-bull-queue 2023-08-19 13:46:26 -04:00
Maidul Islam
6e1cc12e3a update redis banner text 2023-08-19 13:43:01 -04:00
Maidul Islam
1b4b7a967b fix docs typos 2023-08-19 13:42:33 -04:00
Unni P
e47d6b7f2f added blog link for setting up infisical in developement cluster 2023-08-19 08:59:58 +05:30
Maidul Islam
45a13d06b5 add redis why docs & update redis notice 2023-08-18 21:20:20 -04:00
vmatsiiako
4a48c088df Merge pull request #868 from daninge98/custom-environment-sorting
Adds user customizable environment ordering
2023-08-18 17:05:37 -07:00
Daniel Inge
2b65f65063 Rename things and fix bug in error checking 2023-08-18 17:33:59 -04:00
Maidul Islam
065e150847 update status api 2023-08-18 09:42:33 -04:00
Vladyslav Matsiiako
ab72eb1178 added scrollbar to modal 2023-08-17 14:03:56 -07:00
Maidul Islam
816099a8b4 Merge pull request #869 from Infisical/bring-back-file-vault
Bring back file vault
2023-08-17 15:28:37 -04:00
Maidul Islam
b5f672cc61 update vault docs 2023-08-17 15:20:17 -04:00
Maidul Islam
ddc7be18eb link to forked keyring and bring back vault command 2023-08-17 15:07:12 -04:00
Daniel Inge
c0ce92cf3d Formattting fix 2023-08-16 17:42:39 -04:00
Daniel Inge
0073fe459e Fix typo 2023-08-16 17:37:41 -04:00
Daniel Inge
a7f52a9298 Small formatting fixes 2023-08-16 17:36:07 -04:00
Daniel Inge
29c0d8ab57 Enable users to change the ordering of environments 2023-08-16 17:30:50 -04:00
Tuan Dang
d7b26cbf04 Fix Select placeholder in audit logs v2 2023-08-17 01:51:44 +07:00
Tuan Dang
767abe51ef Fix lint errors 2023-08-17 01:34:24 +07:00
Tuan Dang
5ac1816392 Correct SSO linking case and uncomment audit logs v2 2023-08-17 01:24:41 +07:00
vmatsiiako
c5b1e7298e Merge pull request #867 from daninge98/improve-tag-colors-and-sorting
Improve tag colors and sorting on dashboard page
2023-08-15 22:01:43 -07:00
Daniel Inge
3436e6be0e Small formatting changes 2023-08-15 18:46:17 -04:00
Daniel Inge
b000a78f74 Change tag color assignments and sorting 2023-08-15 18:39:15 -04:00
Killian
cb42db3de4 Normalize email when inviting memebers and logging in. 2023-08-15 15:57:27 +01:00
Vladyslav Matsiiako
11bb0d648f fixed capitalization 2023-08-14 18:36:44 -07:00
Vladyslav Matsiiako
90517258a2 added redis note 2023-08-14 18:30:40 -07:00
Maidul Islam
d78b37c632 add redis docs 2023-08-14 16:25:16 -04:00
Maidul Islam
4a6fc9e84f remove console.log and add redis to /status api 2023-08-14 16:24:43 -04:00
Maidul Islam
8030104c02 update helm read me with redis config details 2023-08-14 15:02:22 -04:00
BlackMagiq
3825269cbb Merge pull request #857 from Infisical/signup-secrets-fix
added a check for signup events
2023-08-14 11:22:16 +07:00
Tuan Dang
baa907dbb6 Update source to metadata.source 2023-08-14 11:09:22 +07:00
Vladyslav Matsiiako
83465dff2d added a check for signup events 2023-08-13 18:26:41 -07:00
BlackMagiq
67a8211cb0 Merge pull request #853 from Infisical/linking-sso
Add linking for existing users without SSO enabled logging in via SSO
2023-08-13 22:57:13 +07:00
Tuan Dang
bc108a82b6 Add SSO linking feature for existing users 2023-08-13 22:47:29 +07:00
Tuan Dang
05be5910d0 Update changelog 2023-08-13 17:18:18 +07:00
BlackMagiq
2341ec0e11 Merge pull request #829 from sheensantoscapadngan/feature/enable-users-to-select-multi-auth-methods
Feature: enable users to select multi auth methods (backward compatible)
2023-08-13 17:15:39 +07:00
sreehari jayaraj
9652d534b6 fix: moved handler to form submission 2023-08-13 14:00:30 +05:30
Sheen Capadngan
dd8f55804c finalized sso controller 2023-08-13 16:18:11 +08:00
Tuan Dang
95d25b114e Fix incorrect field in validateProviderAuthToken 2023-08-13 14:08:26 +07:00
Tuan Dang
c0f3aecad3 Fix lint issues 2023-08-13 11:12:07 +07:00
sreehari jayaraj
f650cd3925 fix: form not submitting on keyboard enter 2023-08-13 00:54:22 +05:30
Gregorius Agung Narindra Aditantyo
8a514e329f fix: frontend image displaying some errors due to sed write permission 2023-08-12 21:53:12 +07:00
Tuan Dang
dbd55441f2 Update login with multiple auth methods to toggle button and logic 2023-08-12 13:53:55 +07:00
Maidul Islam
01e613301a console.log queue errors 2023-08-11 19:47:15 -04:00
vmatsiiako
de7bd27b4b Update README.md 2023-08-11 14:54:34 -07:00
Maidul Islam
a4cdd14014 Merge pull request #846 from narindraditantyo/fix/rootless-backend-image
fix: backend image failed to start due to npm cache permission
2023-08-11 16:31:11 -04:00
Gregorius Agung Narindra Aditantyo
632c78f401 fix: backend image failed to start due to npm cache permission 2023-08-11 23:34:41 +07:00
Maidul Islam
051f4501e8 Merge pull request #837 from akhilmhdh/fix/supbase-del-res-secret
fix: supabase failed integration due to res secret deletion
2023-08-11 10:38:15 -04:00
Tuan Dang
69605a1a54 Fast forward 2023-08-11 12:46:30 +07:00
BlackMagiq
e47912edd7 Merge pull request #838 from Infisical/deprecation
Cleaning & deprecating parts of code
2023-08-11 12:10:19 +07:00
Tuan Dang
a4edf6bd0c Remove remaining SecurityClient auth calls in favor of hooks, keep RouteGuard 2023-08-11 11:27:33 +07:00
Maidul Islam
b11cd29943 close all queues 2023-08-10 19:13:09 -04:00
Maidul Islam
395b51c265 Merge pull request #844 from hahnbeelee/main
cursor-pointer for Explore button
2023-08-10 17:54:17 -04:00
Hahnbee Lee
27f56be466 cursor-pointer fir Explore button 2023-08-10 14:33:37 -07:00
Maidul Islam
dfe95ac773 add bull queue 2023-08-10 17:22:20 -04:00
Tuan Dang
2dba7847b6 Convert all SecurityClient API calls to hooks except auth 2023-08-10 17:19:23 +07:00
Tuan Dang
78802409bd Move all integration queries/mutations to hooks 2023-08-10 14:15:24 +07:00
Tuan Dang
9963724a6a Continue removing unused frontend components/logic, improve querying in select pages 2023-08-10 12:18:17 +07:00
Vladyslav Matsiiako
b49ef9efc9 minor frontend UX fixes 2023-08-09 12:03:00 -07:00
vmatsiiako
a31ffe9617 Update README.md 2023-08-09 10:12:10 -07:00
BlackMagiq
18beed7540 Merge pull request #839 from Infisical/permissions-audit-log
Add audit logs for workspace user role and read/write permission changes
2023-08-09 22:02:48 +07:00
Tuan Dang
0a538ac1a7 Add GitHub SSO to changelog 2023-08-09 22:02:19 +07:00
Tuan Dang
a75ad5ef26 Add logs for workspace user role and read/write permission changes 2023-08-09 21:54:56 +07:00
Tuan Dang
b47f61f1ad Delete more deprecated frontend calls 2023-08-09 17:55:57 +07:00
Tuan Dang
2a1665a2c3 Begin marking endpoints for deprecation, clean unused frontend code 2023-08-09 16:45:52 +07:00
Akhil Mohan
e993bd048e fix: supabase failed integration due to res secret deletion 2023-08-09 14:41:42 +05:30
Tuan Dang
11833ccf0f Note endpoints to deprecate 2023-08-09 11:32:57 +07:00
Maidul Islam
37d52432d0 Revert run as node backend due to slow build times 2023-08-08 14:11:06 -04:00
Maidul Islam
04b7e04d98 run full backend docker image as node user 2023-08-08 14:02:39 -04:00
Maidul Islam
57a3384f32 Merge pull request #834 from akhilmhdh/fix/copy-sec-not-populating
fix: secret path / with a new env causes secret list to be empty
2023-08-08 13:18:41 -04:00
Maidul Islam
c813c91aec Merge pull request #825 from akhilmhdh/feat/service-token-folder-api
feat: implemented service token support for folder and secret import api
2023-08-08 13:17:54 -04:00
Akhil Mohan
91947df5f6 feat: refactored getPathfromId to folder service 2023-08-08 22:33:59 +05:30
Akhil Mohan
8330890087 feat: implemented service token support for folder and secret import api 2023-08-08 22:20:36 +05:30
Tuan Dang
221e601173 Correct user agent function name in test 2023-08-08 22:57:38 +07:00
BlackMagiq
28c24fc8c1 Merge pull request #828 from Infisical/audit-log-revamp
Audit Log V2
2023-08-08 22:45:54 +07:00
Tuan Dang
a9389643b8 Log GET secrets v2 2023-08-08 22:42:13 +07:00
Tuan Dang
58854e6b81 Fix merge conflicts 2023-08-08 22:07:22 +07:00
Tuan Dang
7ae859e9ae Update secret imports audit log v2 2023-08-08 22:04:23 +07:00
Vladyslav Matsiiako
ff6e07bdcf minor style changes 2023-08-08 11:03:28 -04:00
Maidul Islam
fc9393b77f run backend docker commands as node instead of root 2023-08-08 09:48:27 -04:00
Tuan Dang
0cad823267 Add dashboard-specific secret and secret import audit logs, re-touch audit logs v2 UI 2023-08-08 19:03:24 +07:00
Akhil Mohan
97a0728f02 fix: secret path / with a new env causes secret list to be empty 2023-08-08 12:18:21 +05:30
Tuan Dang
6cb8cf53f8 Add date filter and pagination component to audit log v2 2023-08-08 12:52:34 +07:00
Tuan Dang
1ac607b42e Merge remote-tracking branch 'origin' into audit-log-revamp 2023-08-08 10:00:47 +07:00
BlackMagiq
ec21e35f8c Merge pull request #831 from akhilmhdh/feat/pagination-datepicker
Feat/pagination datepicker
2023-08-08 09:57:41 +07:00
Tuan Dang
2591161272 Add more audit log events 2023-08-08 09:50:49 +07:00
Akhil Mohan
be86e4176c feat(ui): added datepicker component 2023-08-07 16:22:15 +05:30
Akhil Mohan
2067c021ed feat(ui): added pagination component 2023-08-07 16:21:51 +05:30
Tuan Dang
648968c453 Run linter 2023-08-07 11:25:06 +07:00
Sheen Capadngan
dc3f2c78c1 resolved lint issue 2023-08-06 22:38:24 +08:00
Sheen Capadngan
b4dbdbabac used const 2023-08-06 22:33:53 +08:00
Sheen Capadngan
681255187f modified initialize org to check for auth providers 2023-08-06 22:30:02 +08:00
Sheen Capadngan
bde30049bc ensured backwards compatibility 2023-08-06 22:29:31 +08:00
Sheen Capadngan
0a140f5333 updated implementation of user update after sso change 2023-08-06 22:04:39 +08:00
Sheen Capadngan
3a9bf5409b finalization of create token logic 2023-08-06 21:46:20 +08:00
Sheen Capadngan
04fdccc45d modified backend controllers to support new auth providers 2023-08-06 19:45:27 +08:00
Sheen Capadngan
5604232aea added user controller and modified auth method page 2023-08-06 19:09:38 +08:00
Tuan Dang
373dfff8e0 Remove print statement 2023-08-05 17:06:49 +07:00
Tuan Dang
b9ce448bed Fix merge conflicts 2023-08-05 16:57:21 +07:00
Tuan Dang
142fcf0a01 Finish preliminary v2 audit logs 2023-08-05 16:55:06 +07:00
Maidul Islam
49bcd8839f move github scanning service to ee 2023-08-04 18:15:07 -04:00
Maidul Islam
d5f6e20c78 Merge pull request #822
fix: added dirty flag to set fn in dropzone paste secret
2023-08-04 17:49:19 -04:00
Maidul Islam
00030f2231 move secret scanning to ee 2023-08-04 17:42:29 -04:00
Maidul Islam
24d23e89d0 add exit code to run command 2023-08-04 12:10:46 -04:00
Maidul Islam
3fe592686a add clarity to CLI docs 2023-08-04 12:01:42 -04:00
Maidul Islam
9cba0970be Merge pull request #827 from Infisical/maidul98-patch-2
Update usage.mdx
2023-08-04 11:11:48 -04:00
Maidul Islam
8b50150ec8 Update usage.mdx 2023-08-04 11:11:17 -04:00
Maidul Islam
5af1eb508c disable trust IP 2023-08-04 10:49:05 -04:00
Akhil Mohan
9d57b1db87 fix: added dirty flag to set fn in dropzone paste secret 2023-08-04 11:46:23 +05:30
Maidul Islam
9a5329300c Merge pull request #817 from akhilmhdh/feat/import-sec-dashboard
feat: added copy secret feature in dashboard
2023-08-03 18:09:56 -04:00
Maidul Islam
b03c346985 nit: text update 2023-08-03 18:03:35 -04:00
Vladyslav Matsiiako
84efc3de46 pushed out soem changes 2023-08-03 13:30:22 -04:00
Akhil Mohan
2ff3818ecb feat: made changes as discussed with team on dropzone 2023-08-03 22:23:14 +05:30
Tuan Dang
6fbcbc4807 Add signup with GitHub option 2023-08-03 16:05:14 +07:00
BlackMagiq
9048988e2f Merge pull request #818 from JunedKhan101/feature-github-signin
initial-setup for github signin
2023-08-03 15:44:15 +07:00
Tuan Dang
98cfd72928 Merge remote-tracking branch 'origin' into feature-github-signin 2023-08-03 15:39:45 +07:00
Tuan Dang
2293abfc80 Revise and finish login with GitHub 2023-08-03 15:34:02 +07:00
Akhil Mohan
817a783ec2 feat: updated text and added select all in copy secrets for dashboard 2023-08-03 13:15:28 +05:30
BlackMagiq
9006212ab5 Merge pull request #819 from Infisical/view-licenses
Add tab to view enterprise license keys in usage and billing section
2023-08-03 11:59:44 +07:00
Tuan Dang
1627674c2a Merge remote-tracking branch 'origin' into view-licenses 2023-08-03 11:51:12 +07:00
Tuan Dang
bc65bf1238 Add section for users to view purchased enterprise license keys in organization usage and billing section 2023-08-03 11:48:10 +07:00
Vladyslav Matsiiako
3990b6dc49 fixed the autocapitalization ability 2023-08-02 20:01:06 -07:00
vmatsiiako
a3b8de2e84 Update mint.json 2023-08-02 18:37:59 -07:00
Maidul Islam
b5bffdbcac Merge pull request #813 from akhilmhdh/feat/sec-exp-ingtegration
Secret expansion and import in integrations
2023-08-02 19:16:03 -04:00
Maidul Islam
23e40e523a highlight infisical version in k8 docs 2023-08-02 17:41:45 -04:00
Maidul Islam
d1749deff0 enable checkIPAllowlist 2023-08-02 12:41:04 -04:00
Juned Khan
960aceed29 initial-setup for github signin 2023-08-02 21:28:35 +05:30
Maidul Islam
bd8397bda7 add status code and url to CallGetAccessibleEnvironments 2023-08-02 11:23:22 -04:00
Maidul Islam
9dac06744b delay cli update notification 2023-08-02 10:57:04 -04:00
Maidul Islam
bd80c2ccc3 swap out keyring package 2023-08-02 10:11:23 -04:00
Akhil Mohan
466dadc611 feat: added pull secret feature in dashboard with env json parsing and multiline parsing 2023-08-02 16:15:04 +05:30
Akhil Mohan
cc5ca30057 feat: updated multi line format on integrations sync secrets 2023-08-02 16:12:58 +05:30
Tuan Dang
62fa59619b Add community call link in README 2023-08-02 12:42:32 +07:00
Maidul Islam
7accaeffcf Revert "keyring swap, better error messages/warnings, delay upgrade notif"
This reverts commit 7f69a3b23f.
2023-08-01 22:55:19 -04:00
Maidul Islam
7f69a3b23f keyring swap, better error messages/warnings, delay upgrade notif 2023-08-01 21:12:13 -04:00
Maidul Islam
285a6d633a return instance of ServiceTokenData instead of object 2023-08-01 14:40:08 -04:00
Maidul Islam
12b71bcf67 Merge pull request #816 from jamesoyanna/fix-blog-404-issue
fix: Blog Section in Doc API Reference Redirects to 404
2023-08-01 13:33:33 -04:00
Maidul Islam
6c0be52ffa upgrade major version of mongoose from v6 to v7 2023-08-01 13:27:01 -04:00
Maidul Islam
9df51424a2 upgrade major version of mongoose from v6 to v7 2023-08-01 13:24:38 -04:00
snyk-bot
bb466dbe1c 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-PROTOBUFJS-5756498
2023-08-01 15:50:51 +00:00
jamesoyanna
531938a3f1 fix: Blog Section in Doc API Reference Redirects to 404 2023-08-01 16:28:32 +01:00
BlackMagiq
941a8699b5 Merge pull request #806 from atimapreandrew/teamcity-integration
Teamcity integration
2023-08-01 19:04:20 +07:00
Tuan Dang
6e42da9063 Optimize TeamCity integration 2023-08-01 18:59:27 +07:00
Akhil Mohan
b1981df8f0 chore: resolved merge conflict 2023-08-01 15:29:34 +05:30
Akhil Mohan
086652a89f fix: resolved infinite recursion cases 2023-08-01 15:24:18 +05:30
akhilmhdh
6574b6489f fix: added support for secret import and expansion in integrations 2023-08-01 15:24:18 +05:30
BlackMagiq
69903c0d5c Merge pull request #799 from afrieirham/fix/digital-ocean-sync
fix: digital ocean reset settings on sync
2023-08-01 15:24:57 +07:00
Tuan Dang
8ff33a4e63 Fix sentence in security mechanics 2023-08-01 14:46:50 +07:00
Maidul Islam
1d71864092 hide sign up with inviteOnlySignup=true 2023-07-31 23:54:35 -04:00
Tuan Dang
4b1a27b301 Update changelog 2023-08-01 10:11:22 +07:00
Tuan Dang
b78150e78d Updated membership logic for SAML auth 2023-07-31 17:36:42 +07:00
Andrew Atimapre
a0f08c73af Added images for TeamCity docs 2023-07-30 13:13:52 +01:00
BlackMagiq
59ebe0c22e Merge pull request #805 from Infisical/jumpcloud-saml
Add JumpCloud SAML Support
2023-07-30 14:36:10 +07:00
Tuan Dang
6729caeb75 Add JumpCloud SAML 2023-07-30 14:29:47 +07:00
Andrew Atimapre
3543a15c09 TeamCity integration 2023-07-30 01:57:39 +01:00
Andrew Atimapre
33e0f13eea Added TeamCity integration docs 2023-07-30 00:26:06 +01:00
Andrew Atimapre
e9cff4fe69 TeamCity integration 2023-07-30 00:00:24 +01:00
vmatsiiako
26867f7328 Update overview.mdx 2023-07-29 15:16:11 -07:00
BlackMagiq
233459d063 Merge pull request #804 from Infisical/jumpcloud-saml
Optimize SAML SSO configuration flow and add documentation for Azure AD SAML
2023-07-29 15:01:41 +07:00
Tuan Dang
ba6355e4d2 Fix lint errors 2023-07-29 14:58:13 +07:00
Tuan Dang
e961a30937 Optimize SAML SSO configuration flow, add docs for Azure AD SAML 2023-07-29 14:39:06 +07:00
Maidul Islam
53ff420304 Merge pull request #802 from akhilmhdh/feat/org-overview-loading
feat: added loading state for org overview page
2023-07-28 15:13:51 -04:00
Maidul Islam
196a613f16 Merge pull request #790 from subh-cs/subh-cs/better-logs-k8-operator
Better log for k8-operator
2023-07-28 15:11:40 -04:00
Tuan Dang
cc4b749ce8 Revise SAML flow, update Okta SAML docs 2023-07-29 01:57:07 +07:00
Maidul Islam
8cc5f2ef43 typo in cli usage.mdx 2023-07-28 13:26:35 -04:00
akhilmhdh
06bc02c392 feat: added loading state and show empty state only when loading for org overview page 2023-07-28 21:33:31 +05:30
Maidul Islam
3682c4d044 Merge pull request #800 from akhilmhdh/fix/style-overview-fixes
feat: fixed padding, added progress bar for routing, added sticky hea…
2023-07-28 09:51:33 -04:00
akhilmhdh
52892c26e5 feat: fixed padding, added progress bar for routing, added sticky header for overview 2023-07-28 16:55:22 +05:30
Afrie Irham
5ce67bf750 fix: send current app settings with env sync update 2023-07-28 18:00:46 +08:00
Tuan Dang
ed2cf68935 Merge remote-tracking branch 'origin' into jumpcloud-saml 2023-07-28 14:52:28 +07:00
Tuan Dang
386bc09d49 Update Okta SSO image convention 2023-07-28 14:52:07 +07:00
BlackMagiq
353c6e9166 Merge pull request #798 from Infisical/windmill-docs
Add docs for Windmill integration
2023-07-28 13:26:20 +07:00
Tuan Dang
1f69467207 Add docs for Windmill integration 2023-07-28 13:24:33 +07:00
Vladyslav Matsiiako
5ab218f1f8 fixed parsing .env with : 2023-07-27 19:40:39 -07:00
Vladyslav Matsiiako
e1b25aaa54 fixed the padding issue for the secret raw 2023-07-27 19:03:02 -07:00
Vladyslav Matsiiako
9193e7ef58 fix styling issues with secret rows 2023-07-27 15:50:42 -07:00
Vladyslav Matsiiako
3f998296fe ip table fix 2023-07-27 13:33:31 -07:00
Maidul Islam
6f7601f2c4 Merge pull request #793 from akhilmhdh/feat/new-overview-page
Feat/new overview page
2023-07-27 15:42:34 -04:00
Vladyslav Matsiiako
b7c7544baf minor style changes 2023-07-27 12:37:18 -07:00
BlackMagiq
4b7ae2477a Merge pull request #765 from sunilk4u/feat/windmill-integration
Feature: Windmill.dev cloud Integeration
2023-07-28 02:11:27 +07:00
Tuan Dang
e548883bba Fix lint errors, merge conflicts 2023-07-28 02:02:26 +07:00
Tuan Dang
a7ece1830e Revise Windmill integration 2023-07-28 01:30:28 +07:00
Tuan Dang
6502d232c9 Start Azure AD SAML docs 2023-07-27 23:48:53 +07:00
akhilmhdh
f31e8ddfe9 feat: added width for expandable table and secret missing count ui fix 2023-07-27 20:57:38 +05:30
akhilmhdh
7bbbdcc58b feat: implemented new overview page with improvement in dashboard 2023-07-27 16:36:34 +05:30
akhilmhdh
bca14dd5c4 feat: added new secret input component and updated toolbar key special prop to innerKey 2023-07-27 16:36:34 +05:30
akhilmhdh
b6b3c8a736 fix: resolved v2 secret update bug and object returning in import secret empty 2023-07-27 16:29:43 +05:30
Tuan Dang
d458bd7948 Merge branch 'feat/northflank-integration' 2023-07-27 15:18:28 +07:00
Tuan Dang
239989ceab Update contributors README 2023-07-27 15:17:15 +07:00
Tuan Dang
7ff13242c0 Add docs for Northflank 2023-07-27 15:16:11 +07:00
BlackMagiq
7db8555b65 Merge pull request #788 from ChukwunonsoFrank/feat/northflank-integration
Feature: Northflank integration
2023-07-27 15:15:36 +07:00
Tuan Dang
980a578bd5 Revise Northflank integration 2023-07-27 14:52:52 +07:00
Sunil Kumar
adb27bb729 fix: allow apps which have write access 2023-07-27 13:11:48 +05:30
BlackMagiq
d89d360880 Merge pull request #792 from Infisical/fix-ip-whitelisting
Update IP allowlist implementation
2023-07-27 11:47:56 +07:00
Tuan Dang
8ed5dbb26a Add default IPV6 CIDR for creating workspace 2023-07-27 11:23:57 +07:00
Tuan Dang
221a43e8a4 Update IP allowlist implementation 2023-07-27 11:18:36 +07:00
Subh
e8a2575f7e logging workspaceId, tokenName from k8-operator 2023-07-27 09:10:08 +05:30
Maidul Islam
41c1828324 roll forward: disable IP white listing 2023-07-26 20:50:53 -04:00
Vladyslav Matsiiako
c2c8cf90b7 Merge branch 'main' of https://github.com/Infisical/infisical 2023-07-26 14:03:47 -07:00
Vladyslav Matsiiako
00b4d6bd45 changed the icon 2023-07-26 14:03:37 -07:00
Maidul Islam
f5a6270d2a add workspace auth for multi env/glob request 2023-07-26 16:50:35 -04:00
Chukwunonso Frank
bc9d6253be change isDisabled criteria for Create Integration button 2023-07-26 21:19:02 +01:00
Chukwunonso Frank
a5b37c80ad chore: resolve merge conflicts 2023-07-26 20:39:51 +01:00
Sunil Kumar
7b1a4fa8e4 change regexp to accept deeper level paths 2023-07-27 00:48:17 +05:30
Sunil Kumar
7457f573e9 add dash and underscores for secret pattern test 2023-07-26 23:43:44 +05:30
Sunil Kumar
d67e96507a fix:unauthorized response for app name 2023-07-26 23:14:42 +05:30
Chukwunonso Frank
46545c1462 add secretGroup to integrationController.ts 2023-07-26 18:19:54 +01:00
BlackMagiq
8331cd4de8 Merge pull request #761 from atimapreandrew/terraform-cloud-integration
Terraform cloud integration
2023-07-26 23:16:51 +07:00
Tuan Dang
3447074eb5 Fix merge conflicts 2023-07-26 23:13:33 +07:00
Tuan Dang
5a708ee931 Optimize Terraform Cloud sync function 2023-07-26 23:10:38 +07:00
Tuan Dang
9913b2fb6c Initialize TrustedIP upon creating a new workspace 2023-07-26 22:20:51 +07:00
Tuan Dang
2c021f852f Update filter for trusted IPs backfill 2023-07-26 21:15:07 +07:00
Tuan Dang
8dbc894ce9 Replace insertMany operation with upsert for backfilling trusted ips 2023-07-26 20:45:58 +07:00
BlackMagiq
511904605f Merge pull request #786 from Infisical/debug-integrations
Fix PATCH IP whitelist behavior and breaking integrations due to incorrect project id in local storage
2023-07-26 17:55:24 +07:00
Tuan Dang
7ae6d1610f Fix IP whitelist PATCH endpoint, update localStorage project id to reflect navigated to project 2023-07-26 17:46:33 +07:00
Tuan Dang
7da6d72f13 Remove save call from backfilling trusted ips 2023-07-26 16:18:13 +07:00
Tuan Dang
ad33356994 Remove required comment for trusted IP schema 2023-07-26 15:29:43 +07:00
BlackMagiq
cfa2461479 Merge pull request #785 from Infisical/network-access
Add support for IP allowlisting / trusted IPs
2023-07-26 15:11:04 +07:00
Tuan Dang
bf08bfacb5 Fix lint errors 2023-07-26 15:06:18 +07:00
Tuan Dang
cf77820059 Merge remote-tracking branch 'origin' into network-access 2023-07-26 14:55:12 +07:00
Tuan Dang
1ca90f56b8 Add docs for IP allowlisting 2023-07-26 14:51:25 +07:00
Tuan Dang
5899d7aee9 Complete trusted IPs feature 2023-07-26 13:34:56 +07:00
Maidul Islam
b565194c43 create versions for brew releases 2023-07-25 15:39:29 -04:00
Maidul Islam
86e04577c9 print exec error messages as is 2023-07-25 14:17:31 -04:00
Andrew Atimapre
f4b3cafc5b Added Terraform Cloud integration docs 2023-07-25 16:51:53 +01:00
Andrew Atimapre
18aad7d520 Terraform Cloud integration 2023-07-25 15:25:11 +01:00
Vladyslav Matsiiako
54c79012db fix the org-members link 2023-07-25 07:01:27 -07:00
Maidul Islam
4b720bf940 Update kubernetes.mdx 2023-07-24 18:13:35 -04:00
Maidul Islam
993866bb8b Update secret-reference.mdx 2023-07-24 17:18:07 -04:00
Maidul Islam
8c39fa2438 add conditional imports to raw api 2023-07-24 15:01:31 -04:00
Maidul Islam
7bccfaefac Merge pull request #784 from akhilmhdh/fix/import-delete
fix: resolved secret import delete and include_import response control
2023-07-24 11:47:02 -04:00
akhilmhdh
e2b666345b fix: resolved secret import delete and include_import response control 2023-07-24 20:53:59 +05:30
Maidul Islam
90910819a3 Merge pull request #778 from afrieirham/docs/running-docs-locally
docs: add running infisical docs locally guide
2023-07-24 09:00:46 -04:00
Afrie Irham
8b070484dd docs: add running infisical docs locally 2023-07-24 20:36:42 +08:00
BlackMagiq
a764087c83 Merge pull request #782 from Infisical/improve-security-docs
Add section on service token best practices
2023-07-24 18:14:26 +07:00
Tuan Dang
27d5fa5aa0 Add section on service token best practices 2023-07-24 18:10:37 +07:00
Tuan Dang
2e7705999c Updated changelog and contributors in README 2023-07-24 12:56:02 +07:00
Vladyslav Matsiiako
428bf8e252 Merge branch 'main' of https://github.com/Infisical/infisical 2023-07-23 13:59:42 -07:00
Vladyslav Matsiiako
264740d84d style updates 2023-07-23 13:59:25 -07:00
Maidul Islam
723bcd4d83 Update react.mdx 2023-07-23 15:44:54 -04:00
Tuan Dang
9ed516ccb6 Uncomment Google SSO for signup 2023-07-24 02:35:51 +07:00
Tuan Dang
067ade94c8 Merge branch 'main' of https://github.com/Infisical/infisical 2023-07-24 01:54:09 +07:00
Tuan Dang
446edb6ed9 Add CLI support for SAML SSO 2023-07-24 01:53:56 +07:00
Maidul Islam
896529b7c6 auto scope raw secrets GET with service token 2023-07-23 12:31:03 -04:00
BlackMagiq
5c836d1c10 Merge pull request #779 from afrieirham/integration/digital-ocean-app-platform
Digital Ocean App Platform Integration
2023-07-23 23:01:35 +07:00
Tuan Dang
409d46aa10 Fix merge conflicts 2023-07-23 22:55:18 +07:00
Tuan Dang
682c63bc2a Fix DigitalOcean getApps case where there are no apps 2023-07-23 22:42:41 +07:00
BlackMagiq
1419371588 Merge pull request #776 from afrieirham/integration/cloud66
Cloud 66 integration
2023-07-23 22:19:23 +07:00
Tuan Dang
77fdb6307c Optimize Cloud66 integration sync function 2023-07-23 22:16:27 +07:00
Afrie Irham
c61bba2b6b docs: add digital ocean app platform integration guide 2023-07-23 22:39:08 +08:00
Afrie Irham
2dc0563042 view: fix integration name only show 3 words 2023-07-23 22:02:59 +08:00
Afrie Irham
b5fb2ef354 feat: DO app platform integration 2023-07-23 22:01:48 +08:00
Tuan Dang
dc01758946 Update SAML Okta docs screenshots 2023-07-23 16:59:08 +07:00
BlackMagiq
1f8683f59e Merge pull request #777 from Infisical/saml-docs
Add docs for Okta SAML 2.0 SSO
2023-07-23 16:49:47 +07:00
Tuan Dang
a5273cb86f Add docs for Okta SAML 2.0 SSO 2023-07-23 16:47:43 +07:00
Afrie Irham
d48b5157d4 docs: add cloud 66 integration guide 2023-07-23 17:39:29 +08:00
Afrie Irham
94a23bfa23 feat: add cloud 66 integration 2023-07-23 16:36:26 +08:00
Tuan Dang
fcdfa424bc Restrict changing user auth methods if SAML SSO is enforced 2023-07-23 15:19:17 +07:00
BlackMagiq
3fba1b3ff7 Merge pull request #774 from Infisical/saml-sso-edge-cases
Block inviting members to organization if SAML SSO is configured
2023-07-23 13:27:30 +07:00
Tuan Dang
953eed70b2 Add back attribution source for non-SAML SSO case 2023-07-23 13:24:12 +07:00
Tuan Dang
39ba795604 Block inviting members to organization if SAML SSO is configured 2023-07-23 13:05:37 +07:00
BlackMagiq
5b36227321 Merge pull request #773 from Infisical/debug-google-sso
Initialize organization bot upon creating organization
2023-07-23 12:07:45 +07:00
Tuan Dang
70d04be978 Initialize organization bot upon creating organization 2023-07-23 12:03:39 +07:00
Chukwunonso Frank
c2be6674b1 chore: resolve merge conflicts 2023-07-22 11:29:40 +01:00
BlackMagiq
565f234921 Merge pull request #772 from Infisical/switch-to-google-sso
Add user support for changing authentication methods
2023-07-22 12:38:22 +07:00
Tuan Dang
ab43e32982 Add user support for changing auth methods 2023-07-22 12:33:57 +07:00
Maidul Islam
be677fd6c2 disable token error 2023-07-21 18:41:32 -04:00
Maidul Islam
3d93c6a995 add sentry error to integ 2023-07-21 17:45:27 -04:00
Maidul Islam
edb201e11f comment out unused import 2023-07-21 17:33:46 -04:00
Maidul Islam
1807b3e029 add logs for integration and comment out google sso 2023-07-21 17:29:56 -04:00
Tuan Dang
c02c8e67d3 Merge branch 'main' of https://github.com/Infisical/infisical 2023-07-21 23:54:03 +07:00
Tuan Dang
d4c5be5f48 Update file casing 2023-07-21 23:53:50 +07:00
Tuan Dang
5f33c9a389 Update file casing 2023-07-21 23:53:16 +07:00
BlackMagiq
c9acb22261 Merge pull request #770 from Infisical/docs
Add/revise docs for Codefresh and Bitbucket integrations
2023-07-21 23:44:57 +07:00
Tuan Dang
33f0510995 Add docs for Codefresh integration, revise docs for Bitbucket integration 2023-07-21 23:41:04 +07:00
BlackMagiq
25b239a18b Merge pull request #755 from zwkee/integration/bitbucket
BitBucket Integration
2023-07-21 20:55:42 +07:00
Tuan Dang
504e0f6dc3 Fix lint issues backend 2023-07-21 20:52:35 +07:00
Tuan Dang
f450be3a00 Fix merge conflicts 2023-07-21 20:49:41 +07:00
Tuan Dang
d9f6c27e4d Update Bitbucket sync function 2023-07-21 20:16:39 +07:00
BlackMagiq
9cef35e9e6 Merge pull request #769 from Infisical/saml
Add Google SSO and SAML SSO (Okta)
2023-07-21 18:02:10 +07:00
Tuan Dang
2621ccdcf1 Add descriptions for SSO endpoints 2023-07-21 17:59:15 +07:00
Tuan Dang
75e90201c0 Lint and move redirectSSO into controller 2023-07-21 17:54:09 +07:00
Tuan Dang
fd3cf70e13 Add Google SSO 2023-07-21 17:48:36 +07:00
Tuan Dang
44108621b4 Run linter, fix import error 2023-07-21 15:01:28 +07:00
Tuan Dang
5ee65359bf Fix merge conflicts 2023-07-21 14:37:13 +07:00
Tuan Dang
241dceb845 Remove bodyparser and audit fix deps 2023-07-21 13:39:07 +07:00
Maidul Islam
af650ef4c7 patch env delete bug 2023-07-20 20:03:01 -04:00
Maidul Islam
817ddd228c Update overview.mdx 2023-07-20 19:15:58 -04:00
Maidul Islam
15d81233b4 update docs overvew 2023-07-20 18:25:54 -04:00
Maidul Islam
705b1833d0 update CLI usage and docs for pinning docker 2023-07-20 18:18:43 -04:00
Maidul Islam
beb8d2634a add docs to pin cli 2023-07-20 17:59:59 -04:00
Maidul Islam
fb3ceb4581 Revamp docker docs 2023-07-20 17:28:33 -04:00
Maidul Islam
2df33dc84f Merge pull request #764 from akhilmhdh/fix/include-optional
made include_imports optional in raw secrets fetch
2023-07-20 09:54:47 -04:00
Sunil Kumar
c62504d658 correct codefresh image file name 2023-07-20 19:21:04 +05:30
Sunil Kumar
ce08512ab5 Merge remote-tracking branch 'upstream/main' into feat/windmill-integration 2023-07-20 19:20:38 +05:30
Chukwunonso Frank
8abe7c7f99 add secretGroup attribute to model definition 2023-07-20 12:58:07 +01:00
akhilmhdh
043133444d fix: made include_imports optional in raw secrets fetch 2023-07-20 14:18:35 +05:30
Sunil Kumar
b3baaac5c8 map secret comments to windmill api description 2023-07-20 12:57:16 +05:30
Sunil Kumar
aa019e1501 add pattern match for windmill stored secrets 2023-07-20 02:12:36 +05:30
Sunil Kumar
0f8b505c78 change label for windmill workspace form 2023-07-20 01:45:16 +05:30
Sunil Kumar
5b7e23cdc5 add authorization of user for each app 2023-07-20 01:44:21 +05:30
BlackMagiq
df25657715 Merge pull request #760 from chisom5/feature-codefresh-integration
Codefresh integration
2023-07-20 00:14:27 +07:00
chisom okoye
79c2baba1a Merge branch 'Infisical:main' into feature-codefresh-integration 2023-07-19 17:39:45 +01:00
Maidul Islam
52a2a782f1 Merge pull request #762 from akhilmhdh/fix/sec-import-fail
fix: resolved empty secrets on fresh env and added empty states
2023-07-19 12:38:01 -04:00
Tuan Dang
eda095b55f Fix merge conflicts 2023-07-19 23:29:01 +07:00
akhilmhdh
93761f6487 fix: resolved empty secrets on fresh env and added empty states 2023-07-19 21:58:03 +05:30
Tuan Dang
c5438fbe6d Fix merge conflicts 2023-07-19 23:25:52 +07:00
Tuan Dang
e8fdaf571c Make sync function for Codefresh 2023-07-19 23:17:59 +07:00
Tuan Dang
846e2e037f Update 2023-07-19 22:23:48 +07:00
chisom okoye
a0a7ff8715 Codefresh integration
Worked on codefresh integration syncing secrets to infiscial
2023-07-19 16:22:25 +01:00
Sunil Kumar
ec1e842202 change windmill workspace label 2023-07-19 19:04:59 +05:30
Sunil Kumar
83d5291998 add interface for windmill request body 2023-07-19 15:00:42 +05:30
Sunil Kumar
638e011cc0 add windmill logo to integration variable 2023-07-19 14:47:37 +05:30
Sunil Kumar
d2d23a7aba add windmill logo 2023-07-19 14:47:15 +05:30
Sunil Kumar
a52c2f03bf add integration slug name mapping for windmill 2023-07-19 14:12:05 +05:30
Sunil Kumar Behera
51c12e0202 Merge branch 'Infisical:main' into feat/windmill-integration 2023-07-19 13:15:21 +05:30
Sunil Kumar
4db7b0c05e add function for windmill secret sync 2023-07-19 13:13:14 +05:30
Maidul Islam
284608762b update secret import docs 2023-07-19 00:57:35 -04:00
vmatsiiako
8960773150 Update overview.mdx 2023-07-18 21:51:18 -07:00
Maidul Islam
4684c9f8b1 Update secret-reference.mdx 2023-07-19 00:40:32 -04:00
Maidul Islam
abbf3e80f9 Update secret-reference.mdx 2023-07-19 00:31:45 -04:00
Maidul Islam
d272f580cf update k8 helm for import feature 2023-07-19 00:25:22 -04:00
Maidul Islam
da9cb70184 only send risk notif when risks are found 2023-07-19 00:05:19 -04:00
Maidul Islam
1f3f0375b9 add secret import to k8 operator 2023-07-18 23:59:03 -04:00
Vladyslav Matsiiako
8ad851d4b0 added the ability to change user name 2023-07-18 18:36:34 -07:00
Andrew Atimapre
edef22d28e Terraform Cloud integration 2023-07-18 23:14:41 +01:00
Maidul Islam
3b5bc151ba Merge pull request #758 from akhilmhdh/feat/secret-import
Implemented secret link/import feature
2023-07-18 16:58:46 -04:00
Maidul Islam
678cdd3308 Merge branch 'main' into feat/secret-import 2023-07-18 16:52:25 -04:00
Andrew Atimapre
76f43ab6b4 Terraform Cloud integration 2023-07-18 21:08:30 +01:00
Maidul Islam
33554f4057 patch bug when imports don't show with no secrets 2023-07-18 15:32:14 -04:00
Maidul Islam
c539d4d243 remove print 2023-07-18 15:31:31 -04:00
akhilmhdh
124e6dd998 feat(secret-import): added workspace validation for get imports and imported secret api 2023-07-18 19:40:35 +05:30
Vladyslav Matsiiako
cef29f5dd7 minor style update 2023-07-17 21:39:05 -07:00
Maidul Islam
95c914631a patch notify user on risk found 2023-07-17 21:52:24 -04:00
Maidul Islam
49ae61da08 remove border from risk selection 2023-07-17 21:49:58 -04:00
Maidul Islam
993abd0921 add secret scanning status to api 2023-07-17 21:28:47 -04:00
Maidul Islam
f37b497e48 Update overview.mdx 2023-07-17 21:11:27 -04:00
Maidul Islam
0d2e55a06f add telemetry for cloud secret scanning 2023-07-17 20:29:20 -04:00
Maidul Islam
040243d4f7 add telemetry for cloud secret scanning 2023-07-17 20:29:07 -04:00
Maidul Islam
c450b01763 update email for secret leak 2023-07-17 20:20:11 -04:00
Maidul Islam
4cd203c194 add ss-webhook to values file k8-infisical 2023-07-17 19:56:07 -04:00
Maidul Islam
178d444deb add web hook under api temporarily 2023-07-17 18:58:39 -04:00
Maidul Islam
139ca9022e Update build-staging-img.yml 2023-07-17 17:36:57 -04:00
Maidul Islam
34d3e80d17 Merge pull request #743 from Infisical/git-scanning-app
bring back secret engine for dev
2023-07-17 17:21:34 -04:00
Maidul Islam
deac5fe101 Merge branch 'main' into git-scanning-app 2023-07-17 17:20:04 -04:00
Maidul Islam
216f3a0d1b reload page after org link 2023-07-17 17:18:55 -04:00
Chukwunonso Frank
6ee7081640 add secret groups field functionality 2023-07-17 22:00:48 +01:00
Maidul Islam
43f4110c94 update risk status names 2023-07-17 16:46:15 -04:00
Maidul Islam
56d430afd6 update risk status and update email notifications 2023-07-17 16:41:33 -04:00
akhilmhdh
f681f0a98d fix(secret-import): resolved build failure in frontend 2023-07-18 00:29:42 +05:30
akhilmhdh
23cd6fd861 doc(secret-imports): updated docs for secret import 2023-07-17 23:10:42 +05:30
akhilmhdh
cf45c3dc8b feat(secret-import): updated cli to support secret import 2023-07-17 23:10:14 +05:30
akhilmhdh
45584e0c1a feat(secret-import): implemented ui for secret import 2023-07-17 23:08:57 +05:30
akhilmhdh
202900a7a3 feat(secret-import): implemented api for secret import 2023-07-17 23:08:42 +05:30
Maidul Islam
38b6a48bee Merge pull request #754 from JunedKhan101/docs-typo-fix
fixed typo
2023-07-17 10:49:46 -04:00
Sunil Kumar
04611d980b create windmill get all workspaces list function 2023-07-17 16:50:27 +05:30
Sunil Kumar
6125246794 add integration authorize redirect url 2023-07-17 16:35:11 +05:30
Sunil Kumar
52e26fc6fa create integration pages for windmill 2023-07-17 16:34:39 +05:30
Sunil Kumar
06bd98bf56 add windmill variables to model schema 2023-07-17 15:12:12 +05:30
Sunil Kumar
7c24e0181a add windmill variables to integration 2023-07-17 15:09:15 +05:30
Maidul Islam
53abce5780 remove secret engine folder 2023-07-16 16:51:01 -04:00
Maidul Islam
8c844fb188 move secret scanning to main container 2023-07-16 16:48:36 -04:00
Andrew Atimapre
ceeebc24fa Terraform Cloud integration 2023-07-16 21:12:35 +01:00
Kee, Zhen Wei
df7ad9e645 feat(integration): add integration with BitBucket 2023-07-16 22:04:51 +08:00
Juned Khan
a9135cdbcd fixed typo 2023-07-16 14:47:35 +05:30
Akhil Mohan
9b96daa185 Merge pull request #752 from afrieirham/feat/sort-integrations-alphabetically
feat: sort cloud and framework integrations alphabetically
2023-07-16 14:34:26 +05:30
Afrie Irham
9919d3ee6a feat: sort cloud and framework integrations alphabetically 2023-07-16 11:05:37 +08:00
Vladyslav Matsiiako
dfcd6b1efd changed docs structure 2023-07-14 19:14:36 -07:00
Vladyslav Matsiiako
07bc4c4a3a change docs structure 2023-07-14 19:11:39 -07:00
Vladyslav Matsiiako
d69465517f Added styling 2023-07-14 16:26:18 -07:00
Maidul Islam
6d807c0c74 Merge pull request #749 from RezaRahemtola/fix/cli-vault-cmd-last-line-break
fix(cli): Missing trailing linebreak in vault commands
2023-07-14 18:38:23 -04:00
Reza Rahemtola
868cc80210 fix(cli): Missing trailing linebreak in vault commands 2023-07-14 23:09:25 +02:00
Maidul Islam
3d4a616147 remove secret scanning from prod docker compose 2023-07-14 15:21:04 -04:00
vmatsiiako
bd3f9130e4 Merge pull request #747 from unkletayo/adetayoreadme-youtubelink-fix
docs(readme):update broken YouTube  page link
2023-07-14 09:19:51 -07:00
Adetayo Akinsanya
f607841acf Update README.md with the correct youtube link 2023-07-14 17:15:09 +01:00
Adetayo Akinsanya
55d813043d Update README.md
This PR fixes broken link to the YouTube page in the Readme file
2023-07-14 08:15:51 +01:00
Vladyslav Matsiiako
b2a3a3a0e6 added click-to-copy and changed the slack link 2023-07-13 19:09:00 -07:00
Maidul Islam
67d5f52aca extract correct params after git app install 2023-07-13 19:56:49 -04:00
Vladyslav Matsiiako
a34047521c styled cli redirect 2023-07-13 16:37:05 -07:00
Vladyslav Matsiiako
7ff806e8a6 fixed the signup orgId issue 2023-07-13 16:16:00 -07:00
Vladyslav Matsiiako
9763353d59 Fixed routing issues 2023-07-13 16:09:33 -07:00
Maidul Islam
4382935cb5 Merge pull request #733 from akhilmhdh/feat/webhooks
Feat/webhooks
2023-07-13 18:47:47 -04:00
Maidul Islam
7e3646ddcd add docs on how to pin k8 operator to avoid breaking changes 2023-07-13 17:53:59 -04:00
akhilmhdh
f7766fc182 fix: resolved just space in a secret value and not changing save state 2023-07-13 23:53:24 +05:30
akhilmhdh
3176370ef6 feat(webhook): removed console.log 2023-07-13 23:22:20 +05:30
akhilmhdh
9bed1682fc feat(webhooks): updated docs 2023-07-13 23:22:20 +05:30
akhilmhdh
daf2e2036e feat(webhook): implemented ui for webhooks 2023-07-13 23:22:20 +05:30
akhilmhdh
0f81c78639 feat(webhook): implemented api for webhooks 2023-07-13 23:21:18 +05:30
Vladyslav Matsiiako
8a19cfe0c6 removed secret scanning from the menu 2023-07-13 10:31:54 -07:00
Maidul Islam
a00fec9bca trigger standalone docker img too 2023-07-13 11:23:41 -04:00
BlackMagiq
209f224517 Merge pull request #745 from Infisical/docs-sdk
Remove individual SDK pages from docs
2023-07-13 17:10:26 +07:00
Tuan Dang
0b7f2b7d4b Remove individual SDK pages from docs in favor of each SDKs README on GitHub 2023-07-13 17:08:32 +07:00
BlackMagiq
eff15fc3d0 Merge pull request #744 from Infisical/usage-billing
Fix subscription context get organization from useOrganization
2023-07-13 17:07:42 +07:00
Tuan Dang
2614459772 Fix subscription context get organization from useOrganization 2023-07-13 17:01:53 +07:00
Vladyslav Matsiiako
4e926746cf fixing the pro trial bug 2023-07-12 15:46:42 -07:00
Maidul Islam
f022f6d3ee update secret engine port 2023-07-12 16:39:45 -04:00
Maidul Islam
1133ae4ae9 bring back secret engine for dev 2023-07-12 16:10:09 -04:00
Maidul Islam
edd5afa13b remove secret engine from main 2023-07-12 15:50:36 -04:00
vmatsiiako
442f572acc Merge branch 'infisical-radar-app' into main 2023-07-12 12:12:24 -07:00
Vladyslav Matsiiako
be58f3c429 removed the learning item from sidebar 2023-07-12 11:50:36 -07:00
vmatsiiako
3eea5d9322 Merge pull request #735 from Infisical/new-sidebars
fixing the bugs with sidebars
2023-07-12 11:23:26 -07:00
Vladyslav Matsiiako
e4e87163e8 removed org member section 2023-07-12 11:19:56 -07:00
Vladyslav Matsiiako
d3aeb729e0 fixing ui/ux bugs 2023-07-12 11:18:42 -07:00
Chukwunonso Frank
112d4ec9c0 refactor: modify Northflank integration sync logic 2023-07-12 12:25:44 +01:00
Maidul Islam
2e7c7cf1da fix typo in folder docs 2023-07-12 01:41:14 -04:00
Maidul Islam
5d39416532 replace cli quick start 2023-07-12 01:38:59 -04:00
Maidul Islam
af95adb589 Update usage.mdx 2023-07-12 01:31:09 -04:00
Maidul Islam
0fc4f96773 Merge pull request #736 from Infisical/revamp-docs
Revamp core docs
2023-07-12 01:29:10 -04:00
Maidul Islam
0a9adf33c8 revamp core docs 2023-07-12 01:23:28 -04:00
Vladyslav Matsiiako
f9110cedfa fixing the bug with switching orgs 2023-07-11 22:13:54 -07:00
vmatsiiako
88ec55fc49 Merge pull request #700 from Infisical/new-sidebars
new sidebars
2023-07-11 17:29:48 -07:00
Vladyslav Matsiiako
98b2a2a5c1 adding trial to the sidebar 2023-07-11 17:26:36 -07:00
vmatsiiako
27eeafbf36 Merge pull request #730 from Infisical/main
Catching up the branch
2023-07-11 16:19:39 -07:00
Vladyslav Matsiiako
0cf63028df fixing style and solving merge conflicts 2023-07-11 16:19:07 -07:00
vmatsiiako
0b52b3cf58 Update mint.json 2023-07-11 14:14:23 -07:00
vmatsiiako
e1764880a2 Update overview.mdx 2023-07-11 14:09:57 -07:00
vmatsiiako
d3a47ffcdd Update mint.json 2023-07-11 13:56:24 -07:00
vmatsiiako
9c1f88bb9c Update mint.json 2023-07-11 13:49:55 -07:00
Maidul Islam
ae2f3184e2 Merge pull request #711 from afrieirham/form-ux-enhancement
fix: enable users to press `Enter` in forms
2023-07-11 16:34:21 -04:00
BlackMagiq
3f1db47c30 Merge pull request #731 from Infisical/office-365-smtp
Add support for Office365 SMTP
2023-07-11 15:04:26 +07:00
Tuan Dang
3e3bbe298d Add support for Office365 SMTP 2023-07-11 14:50:41 +07:00
Vladyslav Matsiiako
46dc357651 final changes to sidebars 2023-07-11 00:04:14 -07:00
Maidul Islam
07d25cb673 extract version from tag 2023-07-10 23:26:14 -04:00
Maidul Islam
264f75ce8e correct gha for k8 operator 2023-07-10 23:20:45 -04:00
Maidul Islam
9713a19405 add semvar to k8 images 2023-07-10 23:14:10 -04:00
Andrew Atimapre
a3836b970a Terraform Cloud integration 2023-07-10 23:44:55 +01:00
Maidul Islam
ccfb8771f1 Merge pull request #728 from JunedKhan101/feature-723-remove-trailing-slash
Implemented feature to remove the trailing slash from the domain url
2023-07-10 10:26:53 -04:00
Chukwunonso Frank
5e2b31cb6c add window redirect for the Northflank integration 2023-07-10 12:57:16 +01:00
BlackMagiq
b36801652f Merge pull request #729 from Infisical/trial-revamp
Infisical Cloud Pro Free Trial Update
2023-07-10 15:13:28 +07:00
Tuan Dang
9e5b9cbdb5 Fix lint errors 2023-07-10 15:06:00 +07:00
Vladyslav Matsiiako
bdf4ebd1bc second iteration of the new sidebar 2023-07-09 23:58:27 -07:00
Tuan Dang
e91e7f96c2 Update free plan logic 2023-07-10 13:48:46 +07:00
Juned Khan
34fef4aaad Implemented feature to remove the trailing slash from the domain url 2023-07-10 12:16:51 +05:30
Maidul Islam
09330458e5 Merge pull request #721 from agoodman1999/main
add --path flag to docs for infisical secrets set
2023-07-10 00:09:09 -04:00
Maidul Islam
ed95b99ed1 Merge branch 'main' into main 2023-07-10 00:08:25 -04:00
Maidul Islam
dc1e1e8dcb Merge pull request #726 from RezaRahemtola/fix/docs
fix(docs): Wrong integration name and missing link
2023-07-10 00:05:47 -04:00
Maidul Islam
13a81c9222 add 401 error message for get secrets in cli 2023-07-09 23:25:35 -04:00
Maidul Islam
6354464859 update terraform docs with path and env 2023-07-09 22:40:00 -04:00
vmatsiiako
ec26404b94 Merge pull request #727 from Infisical/main
Catching up with main
2023-07-09 11:13:40 -07:00
Chukwunonso Frank
3c45941474 chore: resolve merge conflicts 2023-07-09 17:38:45 +01:00
Chukwunonso Frank
91e172fd79 add Northflank specific create.tsx file 2023-07-09 16:18:58 +01:00
Reza Rahemtola
5ef2508736 docs: Add missing pull request contribution link 2023-07-09 15:44:25 +02:00
Reza Rahemtola
93264fd2d0 docs: Fix wrong integration name 2023-07-09 15:40:59 +02:00
Afrie Irham
7020c7aeab fix: completing allow user to press Enter in forgot password flow 2023-07-09 15:08:25 +08:00
Maidul Islam
25b1673321 improve k8 operator docs 2023-07-08 21:48:06 -04:00
Maidul Islam
628bc711c2 update k8 docks for quick start 2023-07-08 21:12:05 -04:00
Maidul Islam
a3b4228685 add path to export command 2023-07-08 16:15:45 -04:00
Maidul Islam
374c8e4a1a Update ingress class values.yaml 2023-07-08 13:47:13 -04:00
Maidul Islam
5afcf2798f Update build-staging-img.yml 2023-07-08 13:32:35 -04:00
Maidul Islam
1657cf0a7e Update values.yaml 2023-07-08 13:16:10 -04:00
Maidul Islam
c9820d0071 Update values.yaml 2023-07-08 12:55:49 -04:00
Andrew Atimapre
3e975dc4f0 Terraform Cloud integration 2023-07-08 00:07:38 +01:00
Maidul Islam
b53c046eef Merge pull request #713 from akhilmhdh/feat/secret-reference
secret reference
2023-07-07 19:02:57 -04:00
Maidul Islam
fd10d7ed34 add docs for k8 secret refs 2023-07-07 18:59:23 -04:00
Maidul Islam
c5aae44249 add docs for k8 secret refs 2023-07-07 18:56:38 -04:00
Maidul Islam
83aa6127ec update k8 chart version 2023-07-07 15:56:47 -04:00
Maidul Islam
5a2299f758 update k8 operator crd for secret refs 2023-07-07 15:55:45 -04:00
Maidul Islam
57cdab0727 update k8 operator crd for secret refs 2023-07-07 15:55:22 -04:00
Maidul Islam
f82fa1b3b3 add secret reference support 2023-07-07 15:49:21 -04:00
Tuan Dang
e95eef2071 Merge branch 'main' of https://github.com/Infisical/infisical 2023-07-07 13:01:51 +07:00
Tuan Dang
53efdac0f0 Bring back catch TokenExpiredError in backend error-handling middleware 2023-07-07 13:01:38 +07:00
BlackMagiq
f5eafc39c5 Merge pull request #717 from atimapreandrew/add-laravel-forge-docs
Added docs for Laravel Forge Integration
2023-07-07 12:14:47 +07:00
Tuan Dang
0f72ccf82e Remove Laravel Forge from self-hosting docs, update image name 2023-07-07 12:13:47 +07:00
vmatsiiako
c191eb74fd Update README.md 2023-07-06 21:39:05 -07:00
agoodman1999
f9fca42c5b fix incorrect leading slash in example 2023-07-06 13:36:15 -04:00
agoodman1999
11a19eef07 add --path flag to docs for infisical secrets set 2023-07-06 13:20:48 -04:00
akhilmhdh
8a237af4ac feat(secret-ref): updated reference corner cases of trailing slashes 2023-07-06 22:15:10 +05:30
Andrew Atimapre
24413e1edd Added docs for Laravel Forge Integration 2023-07-06 15:43:43 +01:00
akhilmhdh
5aba0c60b8 feat(secret-ref): removed migration field unset op, refactored service token scope check to a utility fn 2023-07-06 20:01:46 +05:30
akhilmhdh
5599132efe fix(secret-ref): resolved service token unable to fetch secrets in cli 2023-07-06 18:58:48 +05:30
vmatsiiako
7f9e27e3d3 Update README.md 2023-07-05 15:41:38 -07:00
vmatsiiako
7d36360111 Updated AWS deploy image 2023-07-05 15:34:22 -07:00
vmatsiiako
d350297ce1 Deploy to AWS button updated 2023-07-05 15:28:17 -07:00
vmatsiiako
18d4e42d1f Update README.md 2023-07-05 15:19:54 -07:00
Maidul Islam
9faf5a3d5c add secret scanning to gamma values 2023-07-05 18:17:09 -04:00
Maidul Islam
da113612eb diable secret scan by default 2023-07-05 18:09:46 -04:00
Maidul Islam
e9e2eade89 update helm chart version 2023-07-05 17:56:30 -04:00
Maidul Islam
3cbc9c1b5c update helm chart to include git app 2023-07-05 17:54:29 -04:00
Maidul Islam
0772510e47 update gha for git app gamma deploy 2023-07-05 15:52:43 -04:00
Maidul Islam
f389aa07eb update docker file for prod build 2023-07-05 15:39:44 -04:00
Maidul Islam
27a110a93a build secret scanning 2023-07-05 15:22:29 -04:00
akhilmhdh
13eaa4e9a1 feat(secret-ref): updated doc 2023-07-05 23:00:17 +05:30
akhilmhdh
7ec7d05fb0 feat(secret-ref): implemented cli changes for secret reference 2023-07-05 23:00:17 +05:30
akhilmhdh
7fe4089bb0 feat(secret-ref): implemented ui for service token changes 2023-07-05 23:00:17 +05:30
akhilmhdh
0cee453202 feat(secret-ref): implemented backend changes for multi env and folder in service token 2023-07-05 23:00:17 +05:30
BlackMagiq
088d8097a9 Merge pull request #712 from atimapreandrew/laravel-forge-integration
Laravel forge integration
2023-07-05 23:43:43 +07:00
Tuan Dang
4e6fae03ff Patch sync Laravel Forge integration 2023-07-05 23:40:43 +07:00
Andrew Atimapre
732d0dfdca Added docs for Laravel Forge Integration 2023-07-05 13:45:10 +01:00
Afrie Irham
93e0232c21 fix: allow user to press Enter in forgot password page 2023-07-05 19:02:48 +08:00
Afrie Irham
37707c422a fix: allow user to press Enter in login page 2023-07-05 18:40:48 +08:00
Afrie Irham
2f1bd9ca61 fix: enable user to press Enter in signup flow 2023-07-05 18:32:03 +08:00
Tuan Dang
3d9ddbf9bc Merge branch 'main' of https://github.com/Infisical/infisical 2023-07-05 13:52:06 +07:00
Tuan Dang
7c9140dcec Update trial message 2023-07-05 13:51:50 +07:00
Maidul Islam
a63d179a0d add email notifications for risks 2023-07-04 22:06:29 -04:00
Maidul Islam
95dd8718bd Merge pull request #709 from raykeating/add-path-flag-to-infisical-run-docs
add --path flag to docs
2023-07-04 20:25:56 -04:00
Ray Keating
ff2c9e98c0 add --path flag to docs 2023-07-04 19:48:36 -04:00
Chukwunonso Frank
d9ab38c590 chore: resolve merge conflicts 2023-07-04 22:52:23 +01:00
Andrew Atimapre
23f4a350e7 Added docs for Laravel Forge Integration 2023-07-04 21:08:15 +01:00
Andrew Atimapre
696225d8d2 laravel forge integration 2023-07-04 20:01:49 +01:00
Andrew Atimapre
6c1ccc17b3 laravel forge integration 2023-07-04 19:28:42 +01:00
Andrew Atimapre
aa60f3a664 Merge branch 'main' of github.com:atimapreandrew/infisical 2023-07-04 17:49:08 +01:00
Maidul Islam
f01fb2830a patch Eslint GetToken issue 2023-07-04 11:11:05 -04:00
Maidul Islam
9f6aa6b13e add v1 secret scanning 2023-07-04 10:54:44 -04:00
BlackMagiq
b2ee15a4ff Merge pull request #708 from Infisical/free-trial
Initialize users on Infisical Cloud to Pro (Trial) Tier
2023-07-04 16:26:05 +07:00
Tuan Dang
42de0fbe73 Fix lint errors 2023-07-04 16:22:06 +07:00
Tuan Dang
553c986aa8 Update free trial indicator in usage and billing page 2023-07-04 16:01:20 +07:00
vmatsiiako
9a1e2260a0 Merge pull request #701 from Infisical/main
Update branch
2023-06-30 16:54:26 -07:00
Andrew Atimapre
98f7ce2585 Merge branch 'main' of github.com:atimapreandrew/infisical 2023-06-30 17:55:22 +01:00
BlackMagiq
c30ec8cb5f Merge pull request #697 from Infisical/revamp-project-settings
Standardize styling of Project Settings Page
2023-06-30 16:44:02 +07:00
Tuan Dang
104c752f9a Finish preliminary standardization of project settings page 2023-06-30 16:38:54 +07:00
Maidul Islam
b66bea5671 Merge pull request #692 from akhilmhdh/feat/multi-line-secrets
multi line support for secrets
2023-06-29 17:35:25 -04:00
Maidul Islam
f9313204a7 add docs for k8 re sync interval 2023-06-29 16:08:43 -04:00
Maidul Islam
cb5c371a4f add re-sync interval 2023-06-29 15:02:53 -04:00
BlackMagiq
a32df58f46 Merge pull request #695 from Infisical/check-rbac
Rewire RBAC paywall to new mechanism
2023-06-29 18:53:07 +07:00
Tuan Dang
e2658cc8dd Rewire RBAC paywall to new mechanism 2023-06-29 18:47:35 +07:00
BlackMagiq
1fbec20c6f Merge pull request #694 from Infisical/clean-org-settings
Clean Personal Settings and Organization Settings Pages
2023-06-29 18:19:24 +07:00
Tuan Dang
ddff8be53c Fix build error 2023-06-29 18:15:59 +07:00
Tuan Dang
114d488345 Fix merge conflicts 2023-06-29 17:53:33 +07:00
Tuan Dang
c4da5a6ead Fix merge conflicts 2023-06-29 17:49:01 +07:00
Tuan Dang
056f5a4555 Finish preliminary making user settings, org settings styling similar to usage and billing page 2023-06-29 17:47:23 +07:00
Vladyslav Matsiiako
dfc88d99f6 first draft new sidebar 2023-06-28 14:28:52 -07:00
Andrew Atimapre
033f41a7d5 Merge branch 'main' of github.com:atimapreandrew/infisical 2023-06-28 19:15:08 +01:00
akhilmhdh
5612a01039 fix(multi-line): resolved linting issues 2023-06-28 20:50:02 +05:30
akhilmhdh
f1d609cf40 fix: resolved secret version empty 2023-06-28 20:32:12 +05:30
akhilmhdh
0e9c71ae9f feat(multi-line): added support for multi-line in ui 2023-06-28 20:32:12 +05:30
Maidul Islam
d1af399489 Merge pull request #684 from akhilmhdh/feat/integrations-page-revamp
integrations page revamp
2023-06-27 17:50:49 -04:00
Maidul Islam
f445bac42f swap out for v3 secrets 2023-06-27 17:20:30 -04:00
Maidul Islam
798f091ff2 fix fetching secrets via service token 2023-06-27 15:00:03 -04:00
akhilmhdh
8381944bb2 feat(integrations-page): fixed id in delete modal 2023-06-27 23:56:43 +05:30
Tuan Dang
f9d0e0d971 Replace - with Unlimited in compare plans table 2023-06-27 22:00:13 +07:00
Tuan Dang
29d50f850b Correct current plan text in usage and billing 2023-06-27 19:01:31 +07:00
Tuan Dang
81c69d92b3 Restyle org name change section 2023-06-27 18:48:26 +07:00
BlackMagiq
5cd9f37fdf Merge pull request #687 from Infisical/paywalls
Add paywall for PIT and redirect paywall to contact sales in self-hosted
2023-06-27 17:49:42 +07:00
Tuan Dang
1cf65aca1b Remove print statement 2023-06-27 17:46:36 +07:00
Tuan Dang
470c429bd9 Merge remote-tracking branch 'origin' into paywalls 2023-06-27 17:46:18 +07:00
Tuan Dang
c8d081e818 Remove print statement 2023-06-27 17:45:20 +07:00
Tuan Dang
492c6a6f97 Fix lint errors 2023-06-27 17:30:37 +07:00
Tuan Dang
1dfd18e779 Add paywall for PIT and redirect paywall to contact sales in self-hosted 2023-06-27 17:19:33 +07:00
BlackMagiq
caed17152d Merge pull request #686 from Infisical/org-settings
Revamped organization usage and billing page for Infisical Cloud
2023-06-27 16:16:02 +07:00
Tuan Dang
825143f17c Adjust breadcrumb spacing 2023-06-27 16:12:18 +07:00
Tuan Dang
da144b4d02 Hide usage and billing from Navbar in self-hosted 2023-06-27 15:56:48 +07:00
Tuan Dang
f4c4545099 Merge remote-tracking branch 'origin' into org-settings 2023-06-27 15:39:51 +07:00
Tuan Dang
924a969307 Fix lint errors for revamped billing and usage page 2023-06-27 15:39:36 +07:00
Vladyslav Matsiiako
072f6c737c UI update to inetgrations 2023-06-26 18:08:00 -07:00
akhilmhdh
5f683dd389 feat(integrations-page): updated current integrations width and fixed id in delete modal 2023-06-26 14:31:13 +05:30
Tuan Dang
2526cbe6ca Add padding Checkly integration page 2023-06-26 12:39:29 +07:00
Vladyslav Matsiiako
6959fc52ac minor style updates 2023-06-25 21:49:28 -07:00
Andrew Atimapre
81bd684305 removed unnecessary variable declarations 2023-06-25 17:17:29 +01:00
BlackMagiq
68c8dad829 Merge pull request #682 from atimapreandrew/remove-unnecessary-backend-dependencies
removed await-to-js and builder-pattern dependencies from backend
2023-06-25 18:41:56 +07:00
Tuan Dang
ca3f7bac6c Remove catch error-handling in favor of error-handling middleware 2023-06-25 17:31:19 +07:00
Tuan Dang
a127d452bd Continue to make progress on usage and billing page revamp 2023-06-25 17:03:41 +07:00
akhilmhdh
7c77cc4ea4 fix(integrations-page): eslint fixes to the new upstream changes made 2023-06-24 23:44:52 +05:30
akhilmhdh
9c0e32a790 fix(integrations-page): added back cloudflare changes in main integrations page 2023-06-24 23:35:55 +05:30
akhilmhdh
611fae785a chore: updated to latested storybook v7 stable version 2023-06-24 23:31:37 +05:30
akhilmhdh
0ef4ac1cdc feat(integration-page): implemented new optimized integrations page 2023-06-24 23:31:37 +05:30
akhilmhdh
c04ea7e731 feat(integration-page): updated components and api hooks 2023-06-24 23:30:27 +05:30
Andrew Atimapre
9bdecaf02f removed await-to-js and builder-pattern dependencies from backend 2023-06-24 00:29:31 +01:00
Vladyslav Matsiiako
6b222bad01 youtube link change 2023-06-22 19:49:21 -07:00
Maidul Islam
079d68c042 remove dummy file content 2023-06-22 22:28:39 -04:00
Maidul Islam
4b800202fb git app with probot 2023-06-22 22:26:23 -04:00
Vladyslav Matsiiako
12d0916625 casting to date 2023-06-22 16:25:21 -07:00
Vladyslav Matsiiako
e0976d6bd6 added ? to getTime 2023-06-22 16:16:46 -07:00
Vladyslav Matsiiako
a31f364361 converted date to unix 2023-06-22 16:10:54 -07:00
Vladyslav Matsiiako
8efa17928c intercom date fix 2023-06-22 15:57:20 -07:00
Vladyslav Matsiiako
48bfdd500d date format intercom 2023-06-22 15:30:21 -07:00
Vladyslav Matsiiako
4621122cfb added created timestamp to intercom 2023-06-22 15:17:11 -07:00
Vladyslav Matsiiako
62fb048cce intercom debugging 2023-06-22 15:09:02 -07:00
Vladyslav Matsiiako
d4d0fe60b3 Merge branch 'main' of https://github.com/Infisical/infisical 2023-06-22 15:00:16 -07:00
Vladyslav Matsiiako
0a6e8e009b intercom update 2023-06-22 14:59:55 -07:00
Maidul Islam
9f319d7ce3 add dummy value for intercom 2023-06-22 17:17:38 -04:00
Vladyslav Matsiiako
7b3bd54386 intercom check 2023-06-22 13:29:26 -07:00
Tuan Dang
8d82e2d0fc Replace generic error with BadRequestError for missing refresh token in exchange 2023-06-22 18:08:23 +07:00
Tuan Dang
ffd4655e2f Add API Key auth mode support for v1/workspace 2023-06-22 17:53:09 +07:00
BlackMagiq
8f119fbdd3 Merge pull request #677 from Infisical/stripe-error
Remove all Stripe logic from codebase + any related issues
2023-06-22 17:24:11 +07:00
Tuan Dang
b22a179a17 Fix lint issues 2023-06-22 17:03:28 +07:00
Tuan Dang
1cbab58d29 Merge remote-tracking branch 'origin' into stripe-error 2023-06-22 16:38:46 +07:00
Tuan Dang
28943f3b6f Finish removing Stripe from codebase 2023-06-22 16:38:02 +07:00
Maidul Islam
b1f4e17aaf increase limit 2023-06-22 00:40:45 -04:00
Maidul Islam
afd0c6de08 remove unused import 2023-06-21 15:08:47 -04:00
Maidul Islam
cf114b0d3c Merge pull request #648 from quinton11/feat/cli-login-redirect
feat: cli login via browser
2023-06-21 14:47:47 -04:00
Maidul Islam
f785d62315 remove img from login by cli 2023-06-21 14:46:57 -04:00
Maidul Islam
7aeda9e245 remove service accounts from k8 docs 2023-06-21 12:45:56 -04:00
quinton11
8a5e655122 fix: frontend lint errors 2023-06-21 07:29:05 +00:00
quinton
9b447a4ab0 Merge branch 'main' into feat/cli-login-redirect 2023-06-21 06:47:57 +00:00
BlackMagiq
f3e84dc6eb Merge pull request #667 from Stijn-Kuijper/cloudflare-pages-integration
Cloudflare Pages integration
2023-06-21 13:09:38 +07:00
Tuan Dang
a18a86770e Add docs for Cloudflare Pages integration 2023-06-21 13:05:35 +07:00
Tuan Dang
6300f86cc4 Optimize and patch minor issues for Cloudflare Pages integration 2023-06-21 12:11:53 +07:00
Tuan Dang
df662b1058 Resolve merge conflicts 2023-06-21 11:44:07 +07:00
Maidul Islam
db019178b7 Merge pull request #661 from akhilmhdh/feat/folder-doc
doc(folders): updated docs about folders
2023-06-20 13:27:28 -04:00
BlackMagiq
dcec2dfcb0 Merge pull request #664 from khoa165/add-eslint
Add eslint rule and fix as many issues Add eslint rule and fix as many issues as possibleas possible
2023-06-21 00:03:26 +07:00
Stijn-Kuijper
e6ad153e83 feat: option to choose target environment 2023-06-20 13:43:22 +02:00
Khoa Le
9d33e4756b Add eslint rule and fix as many issues as possible 2023-06-19 23:42:04 -04:00
quinton11
c267aee20f feat: interactive login 2023-06-19 22:25:21 +00:00
akhilmhdh
381e40f9a3 doc(folders): updated docs about folders 2023-06-19 22:38:38 +05:30
Stijn-Kuijper
1760b319d3 cleanup 2023-06-19 16:00:53 +02:00
Stijn-Kuijper
59737f89c1 fix: cloudlfare pages sync request fix 2023-06-19 15:44:41 +02:00
Stijn-Kuijper
17097965d9 feat: cloudflare pages integration sync 2023-06-19 15:14:57 +02:00
Stijn-Kuijper
1a54bf34ef feat: fix getApps and create for cloudflare pages integration 2023-06-19 13:58:38 +02:00
quinton11
7e8ba077ae fix: terminal text alignment 2023-06-19 09:32:55 +00:00
Stijn-Kuijper
6ca010e2ba Merge branch 'Infisical:main' into cloudflare-pages-integration 2023-06-18 18:26:55 +02:00
BlackMagiq
e9eacc445d Merge pull request #650 from akhilmhdh/feat/integrations-page
Feat/integrations page
2023-06-17 10:06:30 +02:00
Tuan Dang
db12dafad2 Merge branch 'main' of https://github.com/Infisical/infisical 2023-06-17 10:35:49 +07:00
Tuan Dang
75acda0d7d Add option to attach accessId onto integration auth middleware 2023-06-17 10:35:42 +07:00
Maidul Islam
b98e276767 Merge pull request #658 from Infisical/cli-switch-v2-to-v3-secrets
cli: switch from v2 secrets to v3
2023-06-16 18:23:23 -04:00
Maidul Islam
149c58fa3e cli: switch from v2 secrets to v3 2023-06-16 17:49:25 -04:00
Maidul Islam
62d79b82f8 Merge pull request #642 from akhilmhdh/feat/folder-env-overview
Folder support in secret overview page
2023-06-16 13:19:16 -04:00
akhilmhdh
7f7e63236b fix: resolved dashboardpage latestKey undefined error 2023-06-16 20:45:31 +05:30
Maidul Islam
965a5cc113 update rate limits 2023-06-16 10:03:12 -04:00
quinton11
5a4a36a06a fix: minor change 2023-06-16 13:20:17 +00:00
quinton11
dd0fdea19f fix: included mfa login flow 2023-06-16 12:58:00 +00:00
Tuan Dang
af31549309 Update pairing-session link 2023-06-16 01:15:24 +01:00
BlackMagiq
072e5013fc Merge pull request #653 from pgaijin66/bugfix/docs/remove-duplicate-api-key-header
bugfix(docs): remove duplicate api key header from API reference docu…
2023-06-16 00:54:20 +01:00
Prabesh Thapa
43f2cf8dc3 bugfix(docs): remove duplicate api key header from API reference documentation 2023-06-15 16:49:50 -07:00
vmatsiiako
0aca308bbd Update README.md 2023-06-15 15:01:52 -07:00
Vladyslav Matsiiako
ff567892f9 added empty state for integrations and terraform 2023-06-15 14:58:40 -07:00
Vladyslav Matsiiako
15fc12627a minor style updates 2023-06-15 13:51:28 -07:00
akhilmhdh
a743c12c1b feat(folder-scoped-integrations): implemented ui for folders in integration page 2023-06-15 22:46:40 +05:30
akhilmhdh
2471418591 feat(folder-scoped-integration): implemented api changes for integrations to support folders 2023-06-15 22:46:39 +05:30
BlackMagiq
c77ebd4d0e Merge pull request #649 from Infisical/environment-paywall
Update implementation for environment limit paywall
2023-06-15 15:56:32 +01:00
Tuan Dang
ccaf9a9ffc Update implementation for environment limit paywall 2023-06-15 15:48:19 +01:00
Stijn-Kuijper
381806d84b feat: initial getApps for Cloudflare Pages 2023-06-15 09:46:09 +02:00
Vladyslav Matsiiako
391e37d49e fixed bugs with env and password reset 2023-06-14 21:27:37 -07:00
Maidul Islam
7088b3c9d8 patch refresh token cli 2023-06-14 17:32:01 -04:00
Maidul Islam
ccf0877b81 Revert "Revert "add refresh token to cli""
This reverts commit 6b0e0f70d2.
2023-06-14 17:32:01 -04:00
quinton11
9e9129dd02 feat: cli login via browser 2023-06-14 19:12:56 +00:00
Maidul Islam
0aa9390ece Merge pull request #647 from Budhathoki356/fix/typo
fix: minor typos in code
2023-06-14 14:51:44 -04:00
Maidul Islam
e47934a08a Merge branch 'main' into fix/typo 2023-06-14 14:47:22 -04:00
Eklal Budhathoki
04b7383bbe fix: minor typos in code 2023-06-15 00:17:00 +05:45
BlackMagiq
930b1e8d0c Merge pull request #645 from Infisical/environment-paywall
Update getPlan to consider the user's current workspace
2023-06-14 12:32:42 +01:00
Tuan Dang
82a026a426 Update refreshPlan to consider workspace 2023-06-14 12:28:01 +01:00
Tuan Dang
92647341a9 Update getPlan with workspace-specific consideration and add environmentLimit to returned plan 2023-06-14 11:52:48 +01:00
Maidul Islam
776cecc3ef create prod release action 2023-06-13 22:16:26 -04:00
Maidul Islam
a4fb2378bb wait for helm upgrade before mark complete 2023-06-13 22:06:53 -04:00
Maidul Islam
9742fdc770 rename docker image 2023-06-13 22:00:51 -04:00
Maidul Islam
786778fef6 isolate gamma environment 2023-06-13 21:56:15 -04:00
Maidul Islam
3f946180dd add terraform docs 2023-06-13 18:28:41 -04:00
akhilmhdh
b1b32a34c9 feat(folder-sec-overview): made folder cell fully select 2023-06-13 20:16:14 +05:30
Tuan Dang
3d70333f9c Update password-reset email response 2023-06-13 15:31:55 +01:00
akhilmhdh
a6cf7107b9 feat(folder-sec-overview): implemented folder based ui for sec overview 2023-06-13 19:26:33 +05:30
akhilmhdh
d590dd5db8 feat(folder-sec-overview): added folder path support in get secrets and get folders 2023-06-13 19:26:33 +05:30
Stijn-Kuijper
c64cf39b69 feat: cloudflare pages integration create page 2023-06-13 12:37:07 +02:00
Tuan Dang
f4404f66b8 Correct link to E2EE API usage example 2023-06-13 11:30:47 +01:00
BlackMagiq
9a62496d5c Merge pull request #641 from Infisical/improve-api-docs
Add REST API integration option to the introduction in docs
2023-06-13 11:26:53 +01:00
Tuan Dang
e24c1f38e0 Add REST API integration option in docs introduction 2023-06-13 11:23:13 +01:00
Stijn-Kuijper
dffcee52d7 feat: cloudflare integration auth page 2023-06-13 11:52:40 +02:00
Stijn-Kuijper
db28536ea8 feat: add clouflare pages button to integrations page 2023-06-13 11:12:12 +02:00
BlackMagiq
3ca9b7d6bf Merge pull request #640 from Infisical/improve-api-docs
Improve API docs for non-E2EE examples
2023-06-13 10:05:43 +01:00
Tuan Dang
37d2d580f4 Improve API docs for non-E2EE 2023-06-13 10:02:10 +01:00
Vladyslav Matsiiako
41dd2fda8a Changed the intercom to aprovider model 2023-06-12 21:42:29 -07:00
Vladyslav Matsiiako
22ca4f2e92 Fixed the typeerror issue 2023-06-12 20:56:19 -07:00
vmatsiiako
5882eb6f8a Merge pull request #639 from Infisical/intercom-tour
Switched intercom to AppLayout
2023-06-12 20:20:06 -07:00
Maidul Islam
c13d5e29f4 add intercom env replace during start up 2023-06-12 16:19:27 -07:00
Vladyslav Matsiiako
d99c54ca50 Switched intercom to layout 2023-06-12 15:38:12 -07:00
Tuan Dang
9dd0dac2f9 Patch frontend lint error 2023-06-12 18:07:15 +01:00
Tuan Dang
98efffafaa Patch subscription plan frontend validation 2023-06-12 17:47:32 +01:00
BlackMagiq
342ee50063 Merge pull request #638 from Infisical/non-e2ee-secrets
Add support for Encrypted Standard (ES) mode — i.e. read/write secrets in plaintext
2023-06-12 12:19:02 +01:00
Tuan Dang
553cf11ad2 Fix lint issue 2023-06-12 12:16:23 +01:00
Tuan Dang
4616cffecd Add support for read/write non-e2ee secrets 2023-06-12 12:04:28 +01:00
Vladyslav Matsiiako
39feb9a6ae Merge branch 'main' of https://github.com/Infisical/infisical 2023-06-11 19:24:38 -07:00
Vladyslav Matsiiako
82c1f8607d Added intercom 2023-06-11 19:23:30 -07:00
vmatsiiako
d4c3cbb53a Merge pull request #636 from mswider/self-hosted-env
Allow custom environments in self-hosted instances
2023-06-11 16:53:40 -07:00
mswider
1dea6749ba Allow custom environments in self-hosted instances 2023-06-11 18:19:01 -05:00
Tuan Dang
631eac803e Finish preliminary v3/secrets/raw endpoints 2023-06-11 12:11:25 +01:00
Tuan Dang
facabc683b Fix merge conflicts 2023-06-10 11:07:31 +01:00
BlackMagiq
4b99a9ea93 Merge pull request #633 from akhilmhdh/feat/folders-service-token
Folder scoped service token
2023-06-10 11:02:16 +01:00
akhilmhdh
445afb397c feat(folder-scoped-st): added batch,create secrets v2 secretpath support and service token 2023-06-10 12:10:43 +05:30
akhilmhdh
7d554f46d5 feat(folder-scoped-st): changed text css transformation in folders 2023-06-10 12:09:43 +05:30
Maidul Islam
bbef7d415c remove old commit 2023-06-09 18:41:10 -07:00
Maidul Islam
bb7b398fa7 throw unauthorized error instead of 500 for permission denied 2023-06-09 18:40:41 -07:00
Maidul Islam
570457c7c9 check path before service token create 2023-06-09 18:38:39 -07:00
Vladyslav Matsiiako
1b77b1d70b fixed the etxt issue 2023-06-09 17:02:41 -07:00
Vladyslav Matsiiako
0f697a91ab updated the workspace limit 2023-06-09 16:14:35 -07:00
Vladyslav Matsiiako
df6d23d1d3 fixed the ts error 2023-06-09 15:31:38 -07:00
Tuan Dang
0187d3012b Add non-e2ee option for getSecret, getSecrets, start createSecret 2023-06-09 21:20:12 +01:00
Vladyslav Matsiiako
4299a76fcd changed the default envs 2023-06-09 12:52:44 -07:00
Vladyslav Matsiiako
2bae6cf084 lots of frontend improvements 2023-06-09 12:50:17 -07:00
akhilmhdh
22beebc5d0 feat(folder-scoped-st): implemented frontend ui for folder scoped service token 2023-06-09 23:44:33 +05:30
akhilmhdh
6cb0a20675 feat(folder-scoped-st): implemented backend api for folder scoped service tokens 2023-06-09 23:44:33 +05:30
Tuan Dang
00fae0023a Add cluster URL image to docs for Vault integration 2023-06-09 15:57:47 +01:00
BlackMagiq
0377219a7a Merge pull request #632 from Infisical/vault-integration
Finish preliminary Vault integration, made docs for Vault and Checkly
2023-06-09 15:45:00 +01:00
Tuan Dang
00dfcfcf4e Finish preliminary Vault integration, made docs for Vault and Checkly 2023-06-09 15:36:37 +01:00
Vladyslav Matsiiako
f5441e9996 Merge branch 'main' of https://github.com/Infisical/infisical 2023-06-08 11:08:48 -07:00
Vladyslav Matsiiako
ee2fb33b50 changed the docs order 2023-06-08 11:08:27 -07:00
BlackMagiq
c51b194ba6 Merge pull request #629 from Infisical/optimize-checkly
Optimize Checkly integration
2023-06-08 11:21:28 +01:00
Tuan Dang
2920ba5195 Update Checkly envars only if changed 2023-06-08 11:18:23 +01:00
Tuan Dang
cd837b07aa Remove Sentry, part-try-catch from sync Checkly 2023-06-08 11:04:34 +01:00
BlackMagiq
a8e71e8170 Merge pull request #627 from Infisical/checkly-integration
Checkly integration
2023-06-08 10:56:19 +01:00
BlackMagiq
5fa96411d6 Merge branch 'main' into checkly-integration 2023-06-08 10:53:10 +01:00
Tuan Dang
329ab8ae61 Add +devices for verifyMfaToken user 2023-06-08 00:58:23 +01:00
Tuan Dang
3242d9b44e Fix change password button active state on no errors 2023-06-08 00:28:51 +01:00
Tuan Dang
8ce48fea43 Fix change password button active state on no errors 2023-06-08 00:27:59 +01:00
Maidul Islam
b011144258 reduce password forgot limit 2023-06-07 16:27:16 -07:00
Tuan Dang
674828e8e4 Copy data folder into backend build folder 2023-06-07 23:57:37 +01:00
Tuan Dang
c0563aff77 Bring back try-catch for initGlobalFeatureSet 2023-06-07 23:13:25 +01:00
BlackMagiq
7cec42a7fb Merge pull request #628 from Infisical/pentest-remediation
Fix issues/bugs
2023-06-07 22:52:08 +01:00
Tuan Dang
78493d9521 Fix lint errors 2023-06-07 22:47:47 +01:00
Vladyslav Matsiiako
49b3e8b538 comment fixes 2023-06-07 13:12:58 -07:00
Vladyslav Matsiiako
a3fca200fc comment fixes 2023-06-07 13:12:21 -07:00
Vladyslav Matsiiako
158eb584d2 integration with checkly done 2023-06-07 13:11:39 -07:00
Maidul Islam
e8bffb7217 Merge pull request #626 from akhilmhdh/fix/reload-submit
fix(ui): resolved reloading when form submission
2023-06-07 11:46:03 -07:00
akhilmhdh
604810ebd2 fix(ui): resolved reloading when form submission 2023-06-07 22:45:50 +05:30
Maidul Islam
d4108d1fab update email docs for self hosting 2023-06-07 10:13:43 -07:00
Tuan Dang
4d6ae0eef8 Merge remote-tracking branch 'origin' into pentest-remediation 2023-06-07 16:30:13 +01:00
BlackMagiq
8193490d7f Merge pull request #624 from Infisical/stabilize-server-try-catch
Bring back express-async-errors
2023-06-07 16:27:16 +01:00
Tuan Dang
0deba5e345 Bring back express-async-errors 2023-06-07 16:25:13 +01:00
Tuan Dang
a2055194c5 Fix merge conflicts 2023-06-07 13:12:54 +01:00
Tuan Dang
8c0d643a37 Fix merge conflicts 2023-06-07 12:58:24 +01:00
BlackMagiq
547a1fd142 Merge pull request #617 from Spelchure/removing-sentry-logs
feat: remove try-catch blocks for handling errors in middleware
2023-06-07 12:17:17 +01:00
Maidul Islam
04765ffb94 update email setup docs 2023-06-06 23:27:15 -07:00
Vladyslav Matsiiako
6b9aa200b5 login/signup styling fixes 2023-06-06 19:41:02 -07:00
Tuan Dang
5667e47b31 Add default rely on Cloudflare for IP addresses 2023-06-07 00:50:25 +01:00
Tuan Dang
a8ed187443 Add check for most common passwords 2023-06-07 00:06:35 +01:00
Tuan Dang
c5be497052 Strengthen password requirement 2023-06-06 23:06:44 +01:00
Maidul Islam
77d47e071b add folder id to versions in batch update 2023-06-06 13:31:08 -07:00
Maidul Islam
4bf2407d13 remove encryptionKey validation check 2023-06-06 09:43:11 -07:00
Tuan Dang
846f5c6680 Upgraded JWT invalidation/session logic to separate TokenVersion model. 2023-06-06 16:36:52 +01:00
BlackMagiq
6f1f07c9a5 Merge branch 'main' into removing-sentry-logs 2023-06-06 15:17:59 +01:00
Tuan Dang
aaca66e5a4 Patch support for ENCRYPTION_KEY and ROOT_ENCRYPTION_KEY in generateSecretBlindIndexHelper 2023-06-06 14:24:06 +01:00
Tuan Dang
b9dad5c3f0 Begin preliminary tokenVersion impl 2023-06-06 11:25:08 +01:00
Maidul Islam
3a79a855cb Merge pull request #622 from Infisical/folder-patch-v2
Patch backfill data
2023-06-05 23:14:14 -07:00
Maidul Islam
e28d0cbace bring back tags to secret version 2023-06-05 23:12:48 -07:00
Maidul Islam
c0fbe82ecb update populate number 2023-06-05 20:21:09 -07:00
Maidul Islam
b0e7304bff Patch backfill data 2023-06-05 20:19:15 -07:00
Tuan Dang
5a1b6acc93 Fix merge conflicts with auth changes 2023-06-05 21:27:01 +01:00
Tuan Dang
5f5ed5d0a9 Change export convention for helper functions 2023-06-05 21:00:23 +01:00
Spelchure
bfee0a6d30 feat: remove try-catch blocks for handling errors in middleware 2023-06-05 21:15:35 +03:00
Maidul Islam
08868681d8 Merge pull request #621 from akhilmhdh/fix/folder-breadcrumb
feat(folders): resolved auth issues and added the env dropdown change…
2023-06-05 09:51:59 -07:00
akhilmhdh
6dee858154 feat(folders): resolved auth issues and added the env dropdown change inside folders 2023-06-05 20:47:58 +05:30
Tuan Dang
0c18bd71c4 Implement preliminary pentest remediations 2023-06-05 00:44:10 +01:00
Maidul Islam
b9dfff1cd8 add migration complete logs 2023-06-04 16:37:57 -07:00
Maidul Islam
44b9533636 Merge pull request #609 from akhilmhdh/feat/folders
Feat/folders
2023-06-04 16:24:43 -07:00
Maidul Islam
599c8d94c9 Merge pull request #620 from Infisical/single-rate-limit-store
use mongo rate limit store
2023-06-04 13:45:56 -07:00
Maidul Islam
77788e1524 use mongo rate limit store 2023-06-04 13:43:57 -07:00
Maidul Islam
3df62a6e0a patch dup email bug for login 2023-06-04 11:07:52 -07:00
akhilmhdh
e74cc471db fix(folders): changed to secret path in controllers for get by path op 2023-06-04 13:26:20 +05:30
akhilmhdh
58d3f3945a feat(folders): removed old comments 2023-06-04 13:22:29 +05:30
akhilmhdh
29fa618bff feat(folders): changed / to root in breadcrumbs for folders 2023-06-04 13:18:05 +05:30
akhilmhdh
668b5a9cfd feat(folders): adopted new strategy for rollback on folders 2023-06-04 13:18:05 +05:30
akhilmhdh
6ce0f48b2c fix(folders): fixed algorithm missing in rollback versions and resolved env change reset folderid 2023-06-04 13:18:05 +05:30
Vladyslav Matsiiako
467e85b717 Minor style changes 2023-06-04 13:18:05 +05:30
akhilmhdh
579516bd38 feat(folders): implemented ui for folders in dashboard 2023-06-04 13:18:05 +05:30
akhilmhdh
deaa85cbe7 feat(folders): added support for snapshot by env and folder 2023-06-04 13:18:05 +05:30
Vladyslav Matsiiako
08a4404fed fixed the email issue 2023-06-03 13:58:53 -07:00
Maidul Islam
73aa01c568 prevent passport init when envs are undefined 2023-06-03 12:20:04 -07:00
vmatsiiako
b926601a29 Merge pull request #535 from sheensantoscapadngan/feature/google-signin-signup-integration
Feature/google signin signup integration
2023-06-02 23:44:45 -07:00
Maidul Islam
f619ee7297 revise self hosting order 2023-06-02 14:10:40 -07:00
Maidul Islam
bb825c3d68 add DO docs link 2023-06-02 14:06:04 -07:00
Maidul Islam
6bbd7f05a2 add digital ocean docs 2023-06-02 14:05:00 -07:00
Vladyslav Matsiiako
4865b69e6d updated the slack link 2023-06-01 13:54:02 -07:00
Vladyslav Matsiiako
6f3c7c0fbf fix ts issues 2023-05-31 11:29:08 -07:00
Vladyslav Matsiiako
be80b5124f Final style changes to login/signup 2023-05-31 11:25:37 -07:00
BlackMagiq
4232776637 Merge pull request #614 from Infisical/check-in-process
Update contributing docs to include expectations and procedures for submitting pull requests
2023-05-31 12:46:21 +03:00
Tuan Dang
2c12ede694 Add note for prioritization of first 3 PRs for contribution due to high volume of issues, PRs, and other initiatives in the pipeline 2023-05-31 12:44:30 +03:00
Tuan Dang
94141fedd6 Update contributing docs, add pull requests section 2023-05-31 12:25:08 +03:00
BlackMagiq
720ab446f9 Merge pull request #612 from Infisical/migration-script
Add migration script for server key re-encryption
2023-05-30 21:03:14 +03:00
Tuan Dang
1a1693dbbf Add encryption key validation to validation script 2023-05-30 20:46:20 +03:00
Tuan Dang
9440afa386 Remove re-encryption from Infisical, move to migration script 2023-05-30 20:30:58 +03:00
Maidul Islam
8b1ec1424d patch quote type in docs 2023-05-30 11:19:15 -04:00
Maidul Islam
bd56f3b64c update docker run command for self host 2023-05-30 11:14:22 -04:00
Sheen Capadngan
f20ea723b7 Merge branch 'main' into feature/google-signin-signup-integration 2023-05-30 20:46:20 +08:00
Maidul Islam
86f76ebe70 no default user for selfhosting docs 2023-05-30 08:39:43 -04:00
Maidul Islam
821385c2f3 Revert "add prod img publish ste p"
This reverts commit f7dbd41431.
2023-05-30 07:29:45 -04:00
Maidul Islam
03c65c8635 Revert "add dummy step"
This reverts commit 893c4777fe.
2023-05-30 07:29:31 -04:00
Maidul Islam
893c4777fe add dummy step 2023-05-29 18:49:14 -04:00
Maidul Islam
f7dbd41431 add prod img publish ste p 2023-05-29 18:46:04 -04:00
Maidul Islam
8d1f3e930a revert keychain name 2023-05-29 18:08:49 -04:00
Maidul Islam
f25715b3c4 update keychain name 2023-05-29 17:36:07 -04:00
Tuan Dang
37251ed607 Begin migration script for re-encryption 2023-05-29 23:46:16 +03:00
Maidul Islam
c078fb8bc1 allow user to create new keychain 2023-05-29 15:56:48 -04:00
Tuan Dang
2ae3c48b88 Merge branch 'main' of https://github.com/Infisical/infisical 2023-05-29 14:21:27 +03:00
Tuan Dang
ce28151952 Update posthog-js version 2023-05-29 14:21:16 +03:00
Sheen Capadngan
e6027b3c72 removed try catch from requireAuth middleware 2023-05-29 18:14:16 +08:00
Sheen Capadngan
7f4db518cc Merge branch 'main' into feature/google-signin-signup-integration 2023-05-29 18:00:43 +08:00
BlackMagiq
7562e7d667 Merge pull request #607 from Infisical/changelog
Add preliminary changelog to docs
2023-05-29 12:18:27 +03:00
Tuan Dang
5c8f33a2d8 Add preliminary changelog to docs 2023-05-29 12:15:47 +03:00
Vladyslav Matsiiako
d4f65e23c7 Merge branch 'feature/google-signin-signup-integration' of https://github.com/sheensantoscapadngan/infisical into feature/google-signin-signup-integration 2023-05-28 14:22:42 -07:00
Vladyslav Matsiiako
50609d06f5 Final style changes to signup 2023-05-28 14:22:37 -07:00
Vladyslav Matsiiako
3a5ad93450 Final style changes to signup 2023-05-28 14:22:17 -07:00
Tuan Dang
8493d51f5c Merge branch 'main' of https://github.com/Infisical/infisical 2023-05-28 22:23:51 +03:00
Tuan Dang
e90f63b375 Install and require express-async-errors earlier 2023-05-28 22:23:26 +03:00
Maidul Islam
af9ffdc51f delete pre commit (pre-commit.com) 2023-05-28 14:36:07 -04:00
Maidul Islam
3a76a82438 add dummy ENCRYPTION_KEY for testing backend docker img 2023-05-28 14:09:32 -04:00
Sheen Capadngan
8e972c704a resolved error handling issue with requireAuth middleware 2023-05-28 23:06:20 +08:00
Sheen Capadngan
b975115443 Merge branch 'main' into feature/google-signin-signup-integration 2023-05-28 22:12:02 +08:00
BlackMagiq
4a1821d537 Merge pull request #606 from Infisical/gitlab-integration
Add pagination to retrieve envars for GitLab integration
2023-05-28 16:51:29 +03:00
Tuan Dang
01b87aeebf Add pagination to retrieve envars for GitLab integration 2023-05-28 16:46:05 +03:00
Vladyslav Matsiiako
cea3b59053 Merge branch 'main' of https://github.com/Infisical/infisical 2023-05-27 19:12:47 -07:00
Vladyslav Matsiiako
a6f6711c9a posthog attribution adjustment 2023-05-27 19:12:32 -07:00
vmatsiiako
3d3b416da2 Merge pull request #602 from piyushchhabra/fix/project-list-scroll
fix(ui): fixed scroll on project list selection
2023-05-26 23:13:07 -07:00
Vladyslav Matsiiako
bfbe2f2dcf brought the button back down and removed side bar for other browsers 2023-05-26 23:08:57 -07:00
Maidul Islam
8e5db3ee2f Merge pull request #605 from Infisical/revert-601-add-refresh-token-cli
Revert "add refresh token to cli"
2023-05-26 16:56:13 -04:00
Maidul Islam
6b0e0f70d2 Revert "add refresh token to cli" 2023-05-26 16:56:02 -04:00
Maidul Islam
1fb9aad08a Revert "only re-store user creds when token expire"
This reverts commit df9efa65e7.
2023-05-26 16:55:29 -04:00
BlackMagiq
61a09d817b Merge pull request #604 from Infisical/revised-encryption-key
Update dummy variables in test
2023-05-26 17:31:59 +03:00
Tuan Dang
57b8ed4eef Merge remote-tracking branch 'origin' into revised-encryption-key 2023-05-26 17:29:54 +03:00
Tuan Dang
c3a1d03a9b Update test dummy variables 2023-05-26 17:29:23 +03:00
BlackMagiq
11afb6db51 Merge pull request #603 from Infisical/revised-encryption-key
Add encryption metadata and upgrade ENCRYPTION_KEY to ROOT_ENCRYPTION_KEY
2023-05-26 17:01:00 +03:00
Tuan Dang
200d9de740 Fix merge conflicts 2023-05-26 16:41:17 +03:00
vmatsiiako
17060b22d7 Update README.md 2023-05-25 21:24:07 -07:00
Tuan Dang
c730280eff Update FeatureSet interface to include used counts 2023-05-26 00:26:16 +03:00
Maidul Islam
c45120e6e9 add shorter env name for file vault 2023-05-25 13:27:20 -04:00
piyushchhabra
c96fbd3724 fix(ui): fixing scroll on project list selection 2023-05-25 19:44:06 +05:30
Tuan Dang
e1e2eb7c3b Add SecretBlindIndexData for development user initialization 2023-05-25 16:07:08 +03:00
Tuan Dang
7812061e66 Update isPaid telemetry accounting to be tier-based instead of via slug 2023-05-25 12:59:18 +03:00
Maidul Islam
ca41c65fe0 small helm doc changes 2023-05-24 23:46:34 -04:00
vmatsiiako
d8c15a366d Merge pull request #600 from piyushchhabra/fix/gui-tags-overflow
fix(ui): fixed tags overflow in delete card
2023-05-24 20:19:53 -07:00
Maidul Islam
df9efa65e7 only re-store user creds when token expire 2023-05-24 19:46:02 -04:00
Maidul Islam
1c5616e3b6 revise pre commit doc 2023-05-24 19:11:33 -04:00
Maidul Islam
27030138ec Merge pull request #601 from Infisical/add-refresh-token-cli
add refresh token to cli
2023-05-24 18:53:52 -04:00
Maidul Islam
c37ce4eaea add refresh token to cli 2023-05-24 18:51:42 -04:00
piyushchhabra
5aa367fe54 fix(ui): fixed tags overflow in card + port correction in README 2023-05-24 23:03:12 +05:30
Sheen Capadngan
fac4968193 moved oauth controller endpoints to auth 2023-05-24 23:44:30 +08:00
Maidul Islam
17647587f9 remove tests for time being 2023-05-24 10:48:11 -04:00
Maidul Islam
f3dc7fcf7b add timout to pull requests 2023-05-24 10:48:11 -04:00
Sheen Capadngan
93cf7cde2d fixed login issue after mfa 2023-05-24 21:33:24 +08:00
Sheen Capadngan
422d04d7d7 migrated to standard request 2023-05-24 18:50:59 +08:00
Sheen Capadngan
4c41d279e9 Merge branch 'main' into feature/google-signin-signup-integration 2023-05-24 18:39:18 +08:00
Tuan Dang
e65c6568e1 Modify convention for PostHog isPaid attr to be tier-based instead of slug 2023-05-24 10:26:06 +03:00
Maidul Islam
9d40a96633 Update README.md 2023-05-23 20:22:01 -04:00
Maidul Islam
859fe09ac6 Merge pull request #598 from Infisical/maidul98-patch-1
add pre commit install command to README.md
2023-05-23 20:20:57 -04:00
Maidul Islam
d0d6419d4d add pre commit install command to README.md 2023-05-23 20:20:10 -04:00
Maidul Islam
8b05ce11f7 add pre commit to husky 2023-05-23 20:15:39 -04:00
Maidul Islam
a7fb0786f9 improve pre commit docs 2023-05-23 19:45:10 -04:00
Maidul Islam
f2de1778cb catch case when hook path is default 2023-05-23 19:34:31 -04:00
Vladyslav Matsiiako
952cf47b9a Merge branch 'main' of https://github.com/Infisical/infisical 2023-05-23 15:41:43 -07:00
Vladyslav Matsiiako
1d17596af1 added boolean flag for the plan in posthog logging 2023-05-23 15:41:34 -07:00
Maidul Islam
01385687e0 make posthog failed calls level=debug 2023-05-23 18:16:13 -04:00
Maidul Islam
d2e3aa15b0 patch standalone docker image 2023-05-23 17:16:32 -04:00
Tuan Dang
96607153dc Modularize getOrganizationPlan function 2023-05-23 23:54:54 +03:00
Tuan Dang
a8502377c7 Add endpoint for updating organization plan 2023-05-23 23:14:20 +03:00
BlackMagiq
5aa99001cc Merge pull request #597 from Infisical/connect-to-license-server
Added add/remove/get organization payment methods and get cloud plans…
2023-05-23 22:39:35 +03:00
Tuan Dang
83dd35299c Added add/remove/get organization payment methods and get cloud plans from license server 2023-05-23 22:28:41 +03:00
Maidul Islam
b5b2f402ad add missing required envrs 2023-05-23 14:09:45 -04:00
Maidul Islam
ec34572087 patch invite only 2023-05-23 13:18:21 -04:00
BlackMagiq
7f7d120c2f Merge pull request #595 from Infisical/connect-to-license-server
Add support for fetching plan details from license server
2023-05-23 17:02:20 +03:00
Tuan Dang
899d46514c Add forwarding usedSeats and subscription quantity to license server on org member add/delete 2023-05-23 16:59:13 +03:00
Maidul Islam
658df21189 Add auto install pre commit 2023-05-23 00:09:00 -04:00
Sheen Capadngan
51914c6a2e resolved package-lock conflicts 2023-05-22 22:07:30 +08:00
Sheen Capadngan
ad37a14f2e Merge branch 'main' into feature/google-signin-signup-integration 2023-05-22 21:54:51 +08:00
Tuan Dang
8341faddc5 Add support for pulling plan details from license server with LICENSE_KEY, LICENSE_SERVER_KEY 2023-05-22 15:43:33 +03:00
Maidul Islam
8e3a23e6d8 fix prod node img for standalone 2023-05-22 08:18:50 -04:00
Sheen Capadngan
bc61de4a80 add provider auth secret to kubernetes and docker yaml 2023-05-20 23:15:36 +08:00
Maidul Islam
1c89474159 hello 2023-05-19 17:23:15 -04:00
Maidul Islam
2f765600b1 add pre-commit hook 2023-05-19 17:20:27 -04:00
Maidul Islam
d9057216b5 remove keyring access during telemetry 2023-05-19 16:10:59 -04:00
Maidul Islam
6aab90590f add version to cli run telemtry 2023-05-19 12:24:49 -04:00
Maidul Islam
f7466d4855 update cli telemetry 2023-05-19 12:20:37 -04:00
Maidul Islam
ea2565ed35 Merge pull request #591 from Infisical/cli-telemetry
Cli telemetry
2023-05-19 10:55:27 -04:00
Maidul Islam
4586656b85 add post hog api to go releaser and update cli telemetry 2023-05-19 10:49:57 -04:00
Maidul Islam
e4953398df add telemetry to cli 2023-05-19 00:16:26 -04:00
Maidul Islam
7722231656 Merge pull request #590 from Infisical/infisical-scan-docs
Infisical scan docs
2023-05-18 15:59:51 -04:00
Maidul Islam
845a476974 add secret scanning to README.md 2023-05-18 15:57:48 -04:00
Maidul Islam
fc19a17f4b update readme with scaning feature 2023-05-18 15:42:25 -04:00
Maidul Islam
0890b1912f Merge pull request #589 from Infisical/infisical-scan-docs
add docs for infisical scan
2023-05-18 15:20:26 -04:00
Maidul Islam
82ecc2d7dc add secret scanning to resources 2023-05-18 15:18:29 -04:00
Maidul Islam
460bdbb91c Merge pull request #587 from Infisical/snyk-upgrade-76cf9e766d00cfa629a2db56d3b5fc39
[Snyk] Upgrade posthog-js from 1.53.4 to 1.54.0
2023-05-18 14:57:16 -04:00
Maidul Islam
446a63a917 add docs for infisical scan 2023-05-18 14:55:39 -04:00
Maidul Islam
d67cb7b507 Merge pull request #588 from Infisical/add-gitleak
rebrand and small tweeks
2023-05-18 12:07:26 -04:00
Maidul Islam
353ff63298 rebrand and small tweeks 2023-05-18 12:04:17 -04:00
Sheen Capadngan
4367822777 re-added token caching and redirection 2023-05-18 23:04:55 +08:00
snyk-bot
9f40266f5c fix: upgrade posthog-js from 1.53.4 to 1.54.0
Snyk has created this PR to upgrade posthog-js from 1.53.4 to 1.54.0.

See this package in npm:
https://www.npmjs.com/package/posthog-js

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/53d4ecb6-6cc1-4918-aa73-bf9cae4ffd13?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-18 11:58:06 +00:00
Sheen Capadngan
ca4a9b9937 resolved MFA not appearing 2023-05-18 02:07:07 +08:00
Sheen Capadngan
ec8d62d106 show toast when oauth login error 2023-05-18 01:58:35 +08:00
Maidul Islam
8af8a1d3d5 Merge pull request #580 from Infisical/add-gitleak
add gitleak to cli
2023-05-17 13:20:40 -04:00
Maidul Islam
631423fbc8 Merge pull request #583 from Infisical/snyk-upgrade-32d764d8893bf7596281cd2751bb5f9b
[Snyk] Upgrade @aws-sdk/client-secrets-manager from 3.317.0 to 3.319.0
2023-05-17 13:11:54 -04:00
Maidul Islam
4383779377 Merge pull request #581 from Infisical/snyk-upgrade-efa6b99248f4e9459845f26b359fc5c8
[Snyk] Upgrade aws-sdk from 2.1362.0 to 2.1364.0
2023-05-17 13:11:37 -04:00
Maidul Islam
8249043826 add testing files and create create scan command 2023-05-17 13:08:00 -04:00
Sheen Capadngan
6ca3b8ba61 handled error cases for external auth login 2023-05-18 00:39:20 +08:00
Vladyslav Matsiiako
20294ee233 Fixed the const issue 2023-05-17 09:27:12 -07:00
Sheen Capadngan
4b2e91da74 added proper error handling for user creation 2023-05-18 00:12:28 +08:00
Sheen Capadngan
fac8affe78 added missing envs for documentation 2023-05-17 22:24:04 +08:00
Sheen Capadngan
1ccec486cc removed caching of providerAuthToken 2023-05-17 21:43:18 +08:00
BlackMagiq
c5a924e935 Merge pull request #585 from Infisical/gitlab-envs
Add support for custom environments in GitLab integration
2023-05-17 14:31:00 +03:00
Tuan Dang
429bfd27b2 Add support for custom environments in GitLab integration 2023-05-17 14:25:18 +03:00
snyk-bot
c99c873d78 fix: upgrade @aws-sdk/client-secrets-manager from 3.317.0 to 3.319.0
Snyk has created this PR to upgrade @aws-sdk/client-secrets-manager from 3.317.0 to 3.319.0.

See this package in npm:
https://www.npmjs.com/package/@aws-sdk/client-secrets-manager

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-16 19:34:58 +00:00
snyk-bot
092a6911ce fix: upgrade aws-sdk from 2.1362.0 to 2.1364.0
Snyk has created this PR to upgrade aws-sdk from 2.1362.0 to 2.1364.0.

See this package in npm:
https://www.npmjs.com/package/aws-sdk

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-16 19:34:50 +00:00
Vladyslav Matsiiako
a9b642e618 Merge branch 'main' of https://github.com/Infisical/infisical 2023-05-15 16:34:02 -07:00
Vladyslav Matsiiako
919ddf5de2 removed console log 2023-05-15 16:33:44 -07:00
Vladyslav Matsiiako
89a89af4e6 improving UX for the onboarding experience 2023-05-15 16:33:11 -07:00
Maidul Islam
b3e68cf3fb add gitleak to cli 2023-05-15 19:31:36 -04:00
Maidul Islam
960063e61a Merge pull request #574 from Infisical/snyk-upgrade-e333c5ab909cc9a88c7a6d9fc95a58ed
[Snyk] Upgrade @aws-sdk/client-secrets-manager from 3.312.0 to 3.317.0
2023-05-15 17:48:35 -04:00
Maidul Islam
abf4eaf6db Merge pull request #538 from Infisical/snyk-upgrade-64f35bb43ebf5a87403747b8d7956c34
[Snyk] Upgrade fs from 0.0.1-security to 0.0.2
2023-05-15 17:48:25 -04:00
Maidul Islam
739f97f5c9 Merge pull request #575 from Infisical/snyk-upgrade-6fd25092a72767ffb9954920488a4cd5
[Snyk] Upgrade @sentry/node from 7.47.0 to 7.49.0
2023-05-15 17:48:06 -04:00
Maidul Islam
faed5c1821 Merge pull request #576 from Infisical/snyk-upgrade-f1503bf1fac2c534c106f41288ce944d
[Snyk] Upgrade aws-sdk from 2.1360.0 to 2.1362.0
2023-05-15 17:47:54 -04:00
Maidul Islam
c95598aaa6 Merge pull request #578 from akhilmhdh/fix/compose-fail
fix: docker-compose failing due to missing frontend i18n file
2023-05-15 17:47:33 -04:00
akhilmhdh
e791684f4d fix: docker-compose failing due to missing frontend i18n file 2023-05-16 00:19:03 +05:30
Sheen Capadngan
6746f04f33 added self-hosting documentation for google 2023-05-15 23:39:19 +08:00
Vladyslav Matsiiako
d32c5fb869 update the dev stripe product id 2023-05-15 07:31:17 -07:00
Sheen Capadngan
dba19b4a1d Merge branch 'main' into feature/google-signin-signup-integration 2023-05-15 20:41:08 +08:00
Sheen Capadngan
884aed74a5 made last name optional 2023-05-15 20:39:45 +08:00
Vladyslav Matsiiako
abbf1918dc Added limits to the number of projects in an org 2023-05-14 18:25:27 -07:00
Sheen Capadngan
9dc7cc58a7 uncommented code 2023-05-15 00:41:27 +08:00
Maidul Islam
876d0119d3 Merge pull request #564 from parthvnp/feature/457
Add example in CLI usage docs to show how to utilize secrets in shell aliases
2023-05-13 11:23:27 -04:00
Maidul Islam
6d70dc437e update cli usage docs 2023-05-13 11:22:38 -04:00
Maidul Islam
174e22a2bc put aliases docs in Accordion 2023-05-13 11:17:17 -04:00
Sheen Capadngan
6f66b56e7c updated package-lock 2023-05-12 22:24:38 +08:00
Sheen Capadngan
be2bac41bb Merge branch 'main' into feature/google-signin-signup-integration 2023-05-12 22:22:51 +08:00
Vladyslav Matsiiako
f4815641d8 fixed the bug with smaller icon buttons 2023-05-11 18:11:04 -07:00
snyk-bot
5b95c255ec fix: upgrade aws-sdk from 2.1360.0 to 2.1362.0
Snyk has created this PR to upgrade aws-sdk from 2.1360.0 to 2.1362.0.

See this package in npm:
https://www.npmjs.com/package/aws-sdk

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-11 22:13:48 +00:00
snyk-bot
3123f6fc1f fix: upgrade @sentry/node from 7.47.0 to 7.49.0
Snyk has created this PR to upgrade @sentry/node from 7.47.0 to 7.49.0.

See this package in npm:
https://www.npmjs.com/package/@sentry/node

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-11 22:13:44 +00:00
snyk-bot
a913cd97a4 fix: upgrade @aws-sdk/client-secrets-manager from 3.312.0 to 3.317.0
Snyk has created this PR to upgrade @aws-sdk/client-secrets-manager from 3.312.0 to 3.317.0.

See this package in npm:
https://www.npmjs.com/package/@aws-sdk/client-secrets-manager

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-11 22:13:39 +00:00
Sheen Capadngan
0afa44a9f0 removed express-session types 2023-05-11 15:39:04 +08:00
Maidul Islam
781e0b24c8 add docs for spring boot maven 2023-05-10 21:08:38 -04:00
Vladyslav Matsiiako
5a99878d15 Final style edits to the login and signup flows 2023-05-10 16:12:57 -07:00
Vladyslav Matsiiako
0d3e7f3c0c Merge branch 'feature/google-signin-signup-integration' of https://github.com/sheensantoscapadngan/infisical into feature/google-signin-signup-integration 2023-05-10 12:55:19 -07:00
Vladyslav Matsiiako
967e520173 More designed changes to login flow 2023-05-10 12:55:08 -07:00
Sheen Capadngan
ccfe0b1eb9 reverted changes made to nginx config 2023-05-11 00:52:49 +08:00
Sheen Capadngan
0ef5779776 add providerAuthToken for MFA login 2023-05-11 00:47:16 +08:00
Sheen Capadngan
a194e90644 removed session references 2023-05-11 00:41:38 +08:00
Sheen Capadngan
addc849fa6 changed google-auth strategy and removed session use 2023-05-11 00:37:02 +08:00
Sheen Capadngan
074c0bdd77 utilized mongodb as persistent store for sessions 2023-05-10 23:01:44 +08:00
Maidul Islam
28de8cddd7 Merge pull request #567 from Infisical/snyk-upgrade-9b34558b947330a3bd25eec1f2f2e55c
[Snyk] Upgrade aws-sdk from 2.1358.0 to 2.1360.0
2023-05-10 10:31:42 -04:00
Maidul Islam
ed3e53f9a3 Merge pull request #568 from Infisical/snyk-upgrade-5eadfb75ba47539ba48a83549a83d185
[Snyk] Upgrade @godaddy/terminus from 4.11.2 to 4.12.0
2023-05-10 10:31:30 -04:00
Sheen Capadngan
7ee33e9393 resolved merge conflict issues and updated use of translations 2023-05-10 21:39:11 +08:00
Sheen Capadngan
32cef27e8e Merge branch 'main' into feature/google-sign 2023-05-10 21:11:42 +08:00
Vladyslav Matsiiako
1fce8cc769 More style changes to login 2023-05-09 23:24:37 -07:00
Vladyslav Matsiiako
4e7145dfe5 Style changes to login 2023-05-09 20:45:59 -07:00
Maidul Islam
9cb4d5abb7 improve docker compose and add standalone docs 2023-05-09 22:07:48 -04:00
vmatsiiako
efdd1e64c4 Merge pull request #537 from Infisical/snyk-upgrade-852b174d6fb41e4afff7bae352b8818d
[Snyk] Upgrade @fortawesome/react-fontawesome from 0.1.19 to 0.2.0
2023-05-09 17:52:12 -07:00
vmatsiiako
5b3be6063f Merge pull request #573 from akhilmhdh/feat/new-login
refactor(ui): changed frontend to normal i18n without SSR
2023-05-09 17:50:10 -07:00
Maidul Islam
12c399d4a9 fix typo in k8 docs 2023-05-09 17:34:20 -04:00
Maidul Islam
ecd17e1d6d refine k8 deploy docs 2023-05-09 17:32:57 -04:00
Maidul Islam
fb4c811414 update detailed kubernetes helm docs 2023-05-09 16:41:20 -04:00
akhilmhdh
3561c589b1 refactor(ui): changed frontend to normal i18n without SSR 2023-05-09 23:28:23 +05:30
Maidul Islam
420d71d923 add membership validate to folder get 2023-05-09 10:23:41 -04:00
snyk-bot
3db5c040c3 fix: upgrade @godaddy/terminus from 4.11.2 to 4.12.0
Snyk has created this PR to upgrade @godaddy/terminus from 4.11.2 to 4.12.0.

See this package in npm:
https://www.npmjs.com/package/@godaddy/terminus

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-09 08:42:48 +00:00
snyk-bot
b4f336a5bb fix: upgrade aws-sdk from 2.1358.0 to 2.1360.0
Snyk has created this PR to upgrade aws-sdk from 2.1358.0 to 2.1360.0.

See this package in npm:
https://www.npmjs.com/package/aws-sdk

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-09 08:42:43 +00:00
Maidul Islam
43e61c94f0 get folder by id 2023-05-08 21:01:26 -04:00
Maidul Islam
69fa4a80c5 update check for CLI update 2023-05-08 16:43:28 -04:00
Maidul Islam
cf9e8b8a6b patch login bug when override empty 2023-05-08 16:09:57 -04:00
Maidul Islam
c6d5498a42 add dangling prefix for aur 2023-05-08 10:59:24 -04:00
Parth Patel
7aa5ef844c Update CLI usage docs to showcase the ability to inject environment variables in shell aliases 2023-05-08 01:04:35 -04:00
Maidul Islam
ad7972e7e1 Merge pull request #552 from Infisical/snyk-upgrade-5957efd1bee99a5df1416be8165fe61a
[Snyk] Upgrade @aws-sdk/client-secrets-manager from 3.309.0 to 3.312.0
2023-05-07 19:13:46 -04:00
Maidul Islam
c6d8f24968 Merge pull request #562 from Infisical/snyk-upgrade-2f346d9e1a2c15f0c0929d23f00e36e5
[Snyk] Upgrade @sentry/tracing from 7.47.0 to 7.48.0
2023-05-07 19:13:36 -04:00
Maidul Islam
d8ff0bef0d add semantic-version gh action 2023-05-07 19:09:24 -04:00
Maidul Islam
29b96246b9 add back osx cross build 2023-05-07 17:00:12 -04:00
Maidul Islam
8503c9355b add completions for aurs 2023-05-07 16:55:42 -04:00
Maidul Islam
ddf0a272f6 back out of dir for archive file 2023-05-07 15:41:23 -04:00
Maidul Islam
e3980f8666 bring back completions and man page for cli 2023-05-07 15:27:19 -04:00
Vladyslav Matsiiako
d52534b185 Dashboard UI update 2023-05-07 12:24:40 -07:00
Sheen Capadngan
4c434555a4 finalized signup/signin ux regarding redirects 2023-05-07 20:54:30 +08:00
Tuan Dang
f011d61167 Merge remote-tracking branch 'origin' into revised-encryption-key 2023-05-06 22:22:03 +03:00
Tuan Dang
db07a033e1 Add filter query param to getApps for Netlify integration 2023-05-06 22:19:00 +03:00
Tuan Dang
87e047a152 Checkpoint finish preliminary support for ROOT_ENCRYPTION_KEY 2023-05-06 22:07:59 +03:00
Sheen Capadngan
ea86e59d4f resolved component alignment of signup 2023-05-06 19:26:42 +08:00
Sheen Capadngan
3e19e6fd99 finalized login and signup ui 2023-05-06 18:52:01 +08:00
snyk-bot
3c71bcaa8d fix: upgrade @sentry/tracing from 7.47.0 to 7.48.0
Snyk has created this PR to upgrade @sentry/tracing from 7.47.0 to 7.48.0.

See this package in npm:
https://www.npmjs.com/package/@sentry/tracing

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-06 01:50:17 +00:00
vmatsiiako
476d0be101 Merge pull request #560 from akhilmhdh/fix/token-cache-change
fix(ui): resolved token missing due to cache invalidation
2023-05-05 14:53:23 -07:00
Maidul Islam
2eff7b6128 set internal port for render 2023-05-05 16:26:03 -04:00
Maidul Islam
d8a781af1f remove health check 2023-05-05 16:06:28 -04:00
Maidul Islam
8b42f4f998 typo in doc 2023-05-05 15:50:19 -04:00
Maidul Islam
da127a3c0a update step 2 of fly.io 2023-05-05 15:48:03 -04:00
Maidul Islam
d4aa75a182 update self hosting docs layout 2023-05-05 15:42:41 -04:00
Maidul Islam
d097003e9b set sync=false for mongo db url render 2023-05-05 14:37:24 -04:00
Maidul Islam
b615a5084e update render IaC template 2023-05-05 14:31:11 -04:00
Maidul Islam
379f086828 add render IaC 2023-05-05 14:28:25 -04:00
akhilmhdh
f11a7d0f87 fix(ui): resolved token missing due to cache invalidation 2023-05-05 21:56:26 +05:30
Maidul Islam
f5aeb85c62 rename standalone docker image 2023-05-05 08:43:57 -04:00
Tuan Dang
3d3d7c9821 Merge remote-tracking branch 'origin' into revised-encryption-key 2023-05-05 10:27:44 +03:00
vmatsiiako
2966aa6eda Merge pull request #554 from akhilmhdh/feat/dashboard-v2
feat(ui): fixed lagging issues with new dashboard
2023-05-04 15:38:00 -07:00
Vladyslav Matsiiako
b1f2515731 fixed minor bugs and updated the design 2023-05-04 15:31:06 -07:00
Maidul Islam
c5094ec37d patch copy invite link 2023-05-04 18:27:09 -04:00
Maidul Islam
6c745f617d add org id to complete invite link 2023-05-04 17:50:36 -04:00
Tuan Dang
5eeda6272c Checkpoint adding crypto metadata 2023-05-04 20:35:06 +03:00
Sheen Capadngan
b734b51954 developed new ui for new login and signup page 2023-05-05 00:39:28 +08:00
akhilmhdh
82995fbd02 feat(ui): fixed lagging issues with new dashboard 2023-05-04 20:45:26 +05:30
snyk-bot
8d09a45454 fix: upgrade @aws-sdk/client-secrets-manager from 3.309.0 to 3.312.0
Snyk has created this PR to upgrade @aws-sdk/client-secrets-manager from 3.309.0 to 3.312.0.

See this package in npm:
https://www.npmjs.com/package/@aws-sdk/client-secrets-manager

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-04 00:03:35 +00:00
Vladyslav Matsiiako
38f578c4ae Fixed the issue with favicon 2023-05-03 16:06:50 -07:00
Maidul Islam
65b12eee5e update standlone gwf 2023-05-03 17:22:32 -04:00
Maidul Islam
9043db4727 add github workflow to release standalone app 2023-05-03 17:14:24 -04:00
Maidul Islam
0eceeb6aa9 create standalone infisical docker file 2023-05-03 16:57:19 -04:00
Maidul Islam
2d2bbbd0ad Update README.md 2023-05-03 15:51:15 -04:00
Maidul Islam
c9b4e11539 add note to ENCRYPTION_KEY to indicate non prod 2023-05-03 15:48:20 -04:00
Maidul Islam
fd4ea97e18 remove default smtp since Infisical no longer requires SMTP 2023-05-03 15:45:16 -04:00
Maidul Islam
49d2ecc460 switch install command to run prod docker compose 2023-05-03 15:41:11 -04:00
Sheen Capadngan
1172726e74 added signup v3 endpoints and developed initial new signup flow 2023-05-04 01:32:40 +08:00
Tuan Dang
c766686670 Fix merge conflicts for variable imports 2023-05-03 19:30:30 +03:00
BlackMagiq
ca31a70032 Merge pull request #550 from Infisical/gmail-smtp-support
Add support for Gmail SMTP + docs
2023-05-03 18:34:49 +03:00
Tuan Dang
3334338eaa Add Gmail SMTP option + docs 2023-05-03 18:28:20 +03:00
Tuan Dang
099cee7f39 Begin refactoring backfilling and preparation operations into setup and start adding encryption metadata to models 2023-05-03 14:21:42 +03:00
Sheen Capadngan
f703ee29e5 implemented comments 2023-05-03 18:58:32 +08:00
Maidul Islam
6d5e281811 add helm version requirement 2023-05-02 11:11:41 -04:00
Maidul Islam
87d36ac47a Merge pull request #547 from Infisical/snyk-upgrade-78c720000b2ea0a6b50d66fd8a2a84f9
[Snyk] Upgrade bigint-conversion from 2.3.0 to 2.4.0
2023-05-01 20:44:29 -04:00
Maidul Islam
b72e1198df Merge pull request #548 from Infisical/snyk-upgrade-965bd6eb4d7e75fef5c7e8cb5d4a3e5a
[Snyk] Upgrade mongoose from 6.10.4 to 6.10.5
2023-05-01 20:44:14 -04:00
Maidul Islam
837ea2ef40 add sem var to docker image workflow 2023-05-01 20:43:28 -04:00
Tuan Dang
b462ca3e89 Patch missing function invocation for GitLab envar 2023-05-01 22:38:01 +03:00
BlackMagiq
f639f682c9 Merge pull request #458 from Spelchure/removing-sentry-logs
Replace Sentry error handling logic
2023-05-01 22:35:11 +03:00
snyk-bot
365fcb3044 fix: upgrade mongoose from 6.10.4 to 6.10.5
Snyk has created this PR to upgrade mongoose from 6.10.4 to 6.10.5.

See this package in npm:
https://www.npmjs.com/package/mongoose

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-01 17:58:22 +00:00
snyk-bot
01d9695153 fix: upgrade bigint-conversion from 2.3.0 to 2.4.0
Snyk has created this PR to upgrade bigint-conversion from 2.3.0 to 2.4.0.

See this package in npm:
https://www.npmjs.com/package/bigint-conversion

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-05-01 17:58:17 +00:00
Spelchure
21eb1815c4 feat: remove try-catch blocks for handling errors in middleware 2023-05-01 17:14:39 +03:00
BlackMagiq
85f3ae95b6 Merge pull request #546 from Infisical/update-docs
Add local machine to deployment options
2023-05-01 16:04:11 +03:00
Tuan Dang
e888eed1bf Add local machine to deployment options 2023-05-01 16:02:46 +03:00
Maidul Islam
addac63700 fix broken link for start guide 2023-04-30 15:56:10 -04:00
snyk-bot
fd9387a25e fix: upgrade fs from 0.0.1-security to 0.0.2
Snyk has created this PR to upgrade fs from 0.0.1-security to 0.0.2.

See this package in npm:
https://www.npmjs.com/package/fs

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/53d4ecb6-6cc1-4918-aa73-bf9cae4ffd13?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-04-28 20:41:59 +00:00
snyk-bot
b17a40d83e fix: upgrade @fortawesome/react-fontawesome from 0.1.19 to 0.2.0
Snyk has created this PR to upgrade @fortawesome/react-fontawesome from 0.1.19 to 0.2.0.

See this package in npm:
https://www.npmjs.com/package/@fortawesome/react-fontawesome

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/53d4ecb6-6cc1-4918-aa73-bf9cae4ffd13?utm_source=github&utm_medium=referral&page=upgrade-pr
2023-04-28 20:41:56 +00:00
Sheen Capadngan
dfb84e9932 developed initial version of new login page 2023-04-27 23:10:27 +08:00
Sheen Capadngan
2dd1570200 updated use of environment variables to utilize await 2023-04-27 02:00:16 +08:00
Sheen Capadngan
69472514af Merge branch 'main' into feature/google-signin-signup-integration 2023-04-27 01:46:26 +08:00
Sheen Capadngan
f956170820 added auth v3 endpoints for login1 and login2 2023-04-27 01:38:06 +08:00
Sheen Capadngan
007e8c4442 initial setup for google signin signup integration 2023-04-25 23:47:46 +08:00
3075 changed files with 252571 additions and 108121 deletions

10
.dockerignore Normal file
View File

@@ -0,0 +1,10 @@
backend/node_modules
frontend/node_modules
backend/frontend-build
**/node_modules
**/.next
.dockerignore
.git
README.md
.dockerignore
**/Dockerfile

View File

@@ -1,20 +1,12 @@
# Keys
# Required key for platform encryption/decryption ops
# THIS IS A SAMPLE ENCRYPTION KEY AND SHOULD NEVER BE USED FOR PRODUCTION
ENCRYPTION_KEY=6c1fe4e407b8911c104518103505b218
# JWT
# Required secrets to sign JWT tokens
JWT_SIGNUP_SECRET=3679e04ca949f914c03332aaaeba805a
JWT_REFRESH_SECRET=5f2f3c8f0159068dc2bbb3a652a716ff
JWT_AUTH_SECRET=4be6ba5602e0fa0ac6ac05c3cd4d247f
JWT_SERVICE_SECRET=f32f716d70a42c5703f4656015e76200
# JWT lifetime
# Optional lifetimes for JWT tokens expressed in seconds or a string
# describing a time span (e.g. 60, "2 days", "10h", "7d")
JWT_AUTH_LIFETIME=
JWT_REFRESH_LIFETIME=
JWT_SIGNUP_LIFETIME=
# THIS IS A SAMPLE AUTH_SECRET KEY AND SHOULD NEVER BE USED FOR PRODUCTION
AUTH_SECRET=5lrMXKKWCVocS/uerPsl7V+TX/aaUaI7iDkgl3tSmLE=
# MongoDB
# Backend will connect to the MongoDB instance at connection string MONGO_URL which can either be a ref
@@ -22,6 +14,9 @@ JWT_SIGNUP_LIFETIME=
# Required
MONGO_URL=mongodb://root:example@mongo:27017/?authSource=admin
# Redis
REDIS_URL=redis://redis:6379
# Optional credentials for MongoDB container instance and Mongo-Express
MONGO_USERNAME=root
MONGO_PASSWORD=example
@@ -30,14 +25,12 @@ MONGO_PASSWORD=example
# Required
SITE_URL=http://localhost:8080
# Mail/SMTP
SMTP_HOST=
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_PORT=587
SMTP_SECURE=false
SMTP_FROM_ADDRESS=
SMTP_FROM_NAME=Infisical
# Mail/SMTP
SMTP_HOST=
SMTP_PORT=
SMTP_NAME=
SMTP_USERNAME=
SMTP_PASSWORD=
# Integration
# Optional only if integration is used
@@ -46,11 +39,13 @@ CLIENT_ID_VERCEL=
CLIENT_ID_NETLIFY=
CLIENT_ID_GITHUB=
CLIENT_ID_GITLAB=
CLIENT_ID_BITBUCKET=
CLIENT_SECRET_HEROKU=
CLIENT_SECRET_VERCEL=
CLIENT_SECRET_NETLIFY=
CLIENT_SECRET_GITHUB=
CLIENT_SECRET_GITLAB=
CLIENT_SECRET_BITBUCKET=
CLIENT_SLUG_VERCEL=
# Sentry (optional) for monitoring errors
@@ -60,10 +55,13 @@ SENTRY_DSN=
# Ignore - Not applicable for self-hosted version
POSTHOG_HOST=
POSTHOG_PROJECT_API_KEY=
STRIPE_SECRET_KEY=
STRIPE_PUBLISHABLE_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_PRODUCT_STARTER=
STRIPE_PRODUCT_TEAM=
STRIPE_PRODUCT_PRO=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
# SSO-specific variables
CLIENT_ID_GOOGLE_LOGIN=
CLIENT_SECRET_GOOGLE_LOGIN=
CLIENT_ID_GITHUB_LOGIN=
CLIENT_SECRET_GITHUB_LOGIN=
CLIENT_ID_GITLAB_LOGIN=
CLIENT_SECRET_GITLAB_LOGIN=

View File

@@ -8,7 +8,7 @@ assignees: ''
---
### Feature description
A clear and concise description of what the the feature should be.
A clear and concise description of what the feature should be.
### Why would it be useful?
Why would this feature be useful for Infisical users?

BIN
.github/images/Deploy to AWS.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
.github/images/deploy-aws-button.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
.github/images/deploy-to-aws.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
.github/images/do-k8-install-btn.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -6,13 +6,14 @@ services:
restart: unless-stopped
depends_on:
- mongo
image: infisical/backend:test
image: infisical/infisical:test
command: npm run start
environment:
- NODE_ENV=production
- MONGO_URL=mongodb://test:example@mongo:27017/?authSource=admin
- MONGO_USERNAME=test
- MONGO_PASSWORD=example
- ENCRYPTION_KEY=a984ecdf82ec779e55dbcc21303a900f
networks:
- infisical-test

38
.github/values.yaml vendored
View File

@@ -1,22 +1,3 @@
frontend:
enabled: true
name: frontend
podAnnotations: {}
deploymentAnnotations:
secrets.infisical.com/auto-reload: "true"
replicaCount: 2
image:
repository: infisical/frontend
tag: "latest"
pullPolicy: Always
kubeSecretRef: managed-secret-frontend
service:
annotations: {}
type: ClusterIP
nodePort: ""
frontendEnvironmentVariables: null
backend:
enabled: true
name: backend
@@ -25,7 +6,7 @@ backend:
secrets.infisical.com/auto-reload: "true"
replicaCount: 2
image:
repository: infisical/backend
repository: infisical/staging_infisical
tag: "latest"
pullPolicy: Always
kubeSecretRef: managed-backend-secret
@@ -33,12 +14,15 @@ backend:
annotations: {}
type: ClusterIP
nodePort: ""
resources:
limits:
memory: 300Mi
backendEnvironmentVariables: null
## Mongo DB persistence
mongodb:
enabled: true
enabled: false
persistence:
enabled: false
@@ -51,16 +35,10 @@ mongodbConnection:
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
# cert-manager.io/issuer: letsencrypt-nginx
# annotations:
# kubernetes.io/ingress.class: "nginx"
# cert-manager.io/issuer: letsencrypt-nginx
hostName: gamma.infisical.com ## <- Replace with your own domain
frontend:
path: /
pathType: Prefix
backend:
path: /api
pathType: Prefix
tls:
[]
# - secretName: letsencrypt-nginx

View File

@@ -0,0 +1,121 @@
name: Release production images (frontend, backend)
on:
push:
tags:
- "infisical/v*.*.*"
- "!infisical/v*.*.*-postgres"
jobs:
backend-image:
name: Build backend image
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
- name: 📦 Install dependencies to test all dependencies
run: npm ci --only-production
working-directory: backend
# - name: 🧪 Run tests
# run: npm run test:ci
# working-directory: backend
- 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 }}
load: true
context: backend
tags: infisical/infisical:test
- name: ⏻ Spawn backend container and dependencies
run: |
docker compose -f .github/resources/docker-compose.be-test.yml up --wait --quiet-pull
- name: 🧪 Test backend image
run: |
./.github/resources/healthcheck.sh infisical-backend-test
- name: ⏻ Shut down backend container and dependencies
run: |
docker compose -f .github/resources/docker-compose.be-test.yml down
- name: 🏗️ Build backend and push
uses: depot/build-push-action@v1
with:
project: 64mmf0n610
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
push: true
context: backend
tags: |
infisical/backend:${{ steps.commit.outputs.short }}
infisical/backend:latest
infisical/backend:${{ steps.extract_version.outputs.version }}
platforms: linux/amd64,linux/arm64
frontend-image:
name: Build frontend image
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
- 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 frontend and export to Docker
uses: depot/build-push-action@v1
with:
load: true
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
project: 64mmf0n610
context: frontend
tags: infisical/frontend:test
build-args: |
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
NEXT_INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
- name: ⏻ Spawn frontend container
run: |
docker run -d --rm --name infisical-frontend-test infisical/frontend:test
- name: 🧪 Test frontend image
run: |
./.github/resources/healthcheck.sh infisical-frontend-test
- name: ⏻ Shut down frontend container
run: |
docker stop infisical-frontend-test
- name: 🏗️ Build frontend and push
uses: depot/build-push-action@v1
with:
project: 64mmf0n610
push: true
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
context: frontend
tags: |
infisical/frontend:${{ steps.commit.outputs.short }}
infisical/frontend:latest
infisical/frontend:${{ steps.extract_version.outputs.version }}
platforms: linux/amd64,linux/arm64
build-args: |
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
NEXT_INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}

99
.github/workflows/build-staging-img.yml vendored Normal file
View File

@@ -0,0 +1,99 @@
name: Build, Publish and Deploy to Gamma
on: [workflow_dispatch]
jobs:
infisical-image:
name: Build backend image
runs-on: ubuntu-latest
steps:
- name: ☁️ Checkout source
uses: actions/checkout@v3
- name: 📦 Install dependencies to test all dependencies
run: npm ci --only-production
working-directory: backend
# - name: 🧪 Run tests
# run: npm run test:ci
# working-directory: backend
- 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 }}
load: true
context: .
file: Dockerfile.standalone-infisical
tags: infisical/infisical:test
- name: ⏻ Spawn backend container and dependencies
run: |
docker compose -f .github/resources/docker-compose.be-test.yml up --wait --quiet-pull
- name: 🧪 Test backend image
run: |
./.github/resources/healthcheck.sh infisical-backend-test
- name: ⏻ Shut down backend container and dependencies
run: |
docker compose -f .github/resources/docker-compose.be-test.yml down
- name: 🏗️ Build backend and push
uses: depot/build-push-action@v1
with:
project: 64mmf0n610
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
push: true
context: .
file: Dockerfile.standalone-infisical
tags: |
infisical/staging_infisical:${{ steps.commit.outputs.short }}
infisical/staging_infisical:latest
platforms: linux/amd64,linux/arm64
build-args: |
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
gamma-deployment:
name: Deploy to gamma
runs-on: ubuntu-latest
needs: [infisical-image]
steps:
- name: ☁️ Checkout source
uses: actions/checkout@v3
- name: Install Helm
uses: azure/setup-helm@v3
with:
version: v3.10.0
- name: Install infisical helm chart
run: |
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
- name: Install kubectl
uses: azure/setup-kubectl@v3
- name: Install doctl
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
- name: Save DigitalOcean kubeconfig with short-lived credentials
run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 k8s-1-25-4-do-0-nyc1-1670645170179
- name: switch to gamma namespace
run: kubectl config set-context --current --namespace=gamma
- name: test kubectl
run: kubectl get ingress
- name: Download helm values to file and upgrade gamma deploy
run: |
wget https://raw.githubusercontent.com/Infisical/infisical/main/.github/values.yaml
helm upgrade infisical infisical-helm-charts/infisical --values values.yaml --wait --install
if [[ $(helm status infisical) == *"FAILED"* ]]; then
echo "Helm upgrade failed"
exit 1
else
echo "Helm upgrade was successful"
fi

View File

@@ -13,6 +13,7 @@ jobs:
check-be-pr:
name: Check
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: ☁️ Checkout source
@@ -26,17 +27,17 @@ jobs:
- name: 📦 Install dependencies
run: npm ci --only-production
working-directory: backend
- name: 🧪 Run tests
run: npm run test:ci
working-directory: backend
- name: 📁 Upload test results
uses: actions/upload-artifact@v3
if: always()
with:
name: be-test-results
path: |
./backend/reports
./backend/coverage
# - name: 🧪 Run tests
# run: npm run test:ci
# working-directory: backend
# - name: 📁 Upload test results
# uses: actions/upload-artifact@v3
# if: always()
# with:
# name: be-test-results
# path: |
# ./backend/reports
# ./backend/coverage
- name: 🏗️ Run build
run: npm run build
working-directory: backend

View File

@@ -2,40 +2,35 @@ name: Check Frontend Pull Request
on:
pull_request:
types: [ opened, synchronize ]
types: [opened, synchronize]
paths:
- 'frontend/**'
- '!frontend/README.md'
- '!frontend/.*'
- 'frontend/.eslintrc.js'
- "frontend/**"
- "!frontend/README.md"
- "!frontend/.*"
- "frontend/.eslintrc.js"
jobs:
check-fe-pr:
name: Check
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
-
name: ☁️ Checkout source
- name: ☁️ Checkout source
uses: actions/checkout@v3
-
name: 🔧 Setup Node 16
- name: 🔧 Setup Node 16
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'
node-version: "16"
cache: "npm"
cache-dependency-path: frontend/package-lock.json
-
name: 📦 Install dependencies
- name: 📦 Install dependencies
run: npm ci --only-production --ignore-scripts
working-directory: frontend
# -
# name: 🧪 Run tests
# run: npm run test:ci
# working-directory: frontend
-
name: 🏗️ Run build
- name: 🏗️ Run build
run: npm run build
working-directory: frontend

View File

@@ -1,144 +0,0 @@
name: Build, Publish and Deploy to Gamma
on: [workflow_dispatch]
jobs:
backend-image:
name: Build backend image
runs-on: ubuntu-latest
steps:
- name: ☁️ Checkout source
uses: actions/checkout@v3
- name: 📦 Install dependencies to test all dependencies
run: npm ci --only-production
working-directory: backend
- name: 🧪 Run tests
run: npm run test:ci
working-directory: backend
- 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 }}
load: true
context: backend
tags: infisical/backend:test
- name: ⏻ Spawn backend container and dependencies
run: |
docker compose -f .github/resources/docker-compose.be-test.yml up --wait --quiet-pull
- name: 🧪 Test backend image
run: |
./.github/resources/healthcheck.sh infisical-backend-test
- name: ⏻ Shut down backend container and dependencies
run: |
docker compose -f .github/resources/docker-compose.be-test.yml down
- name: 🏗️ Build backend and push
uses: depot/build-push-action@v1
with:
project: 64mmf0n610
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
push: true
context: backend
tags: infisical/backend:${{ steps.commit.outputs.short }},
infisical/backend:latest
platforms: linux/amd64,linux/arm64
frontend-image:
name: Build frontend image
runs-on: ubuntu-latest
steps:
- name: ☁️ Checkout source
uses: actions/checkout@v3
- 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 frontend and export to Docker
uses: depot/build-push-action@v1
with:
load: true
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
project: 64mmf0n610
context: frontend
tags: infisical/frontend:test
build-args: |
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
- name: ⏻ Spawn frontend container
run: |
docker run -d --rm --name infisical-frontend-test infisical/frontend:test
- name: 🧪 Test frontend image
run: |
./.github/resources/healthcheck.sh infisical-frontend-test
- name: ⏻ Shut down frontend container
run: |
docker stop infisical-frontend-test
- name: 🏗️ Build frontend and push
uses: depot/build-push-action@v1
with:
project: 64mmf0n610
push: true
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
context: frontend
tags: infisical/frontend:${{ steps.commit.outputs.short }},
infisical/frontend:latest
platforms: linux/amd64,linux/arm64
build-args: |
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
gamma-deployment:
name: Deploy to gamma
runs-on: ubuntu-latest
needs: [frontend-image, backend-image]
steps:
- name: ☁️ Checkout source
uses: actions/checkout@v3
- name: Install Helm
uses: azure/setup-helm@v3
with:
version: v3.10.0
- name: Install infisical helm chart
run: |
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
- name: Install kubectl
uses: azure/setup-kubectl@v3
- name: Install doctl
uses: digitalocean/action-doctl@v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
- name: Save DigitalOcean kubeconfig with short-lived credentials
run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 k8s-1-25-4-do-0-nyc1-1670645170179
- name: switch to gamma namespace
run: kubectl config set-context --current --namespace=gamma
- name: test kubectl
run: kubectl get ingress
- name: Download helm values to file and upgrade gamma deploy
run: |
wget https://raw.githubusercontent.com/Infisical/infisical/main/.github/values.yaml
helm upgrade infisical infisical-helm-charts/infisical --values values.yaml --recreate-pods
if [[ $(helm status infisical) == *"FAILED"* ]]; then
echo "Helm upgrade failed"
exit 1
else
echo "Helm upgrade was successful"
fi

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

@@ -0,0 +1,79 @@
name: Release standalone docker image
on:
push:
tags:
- "infisical/v*.*.*"
- "!infisical/v*.*.*-postgres"
jobs:
infisical-standalone:
name: Build infisical standalone image
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
- uses: paulhatch/semantic-version@v5.0.2
id: version
with:
# The prefix to use to identify tags
tag_prefix: "infisical-standalone/v"
# A string which, if present in a git commit, indicates that a change represents a
# major (breaking) change, supports regular expressions wrapped with '/'
major_pattern: "(MAJOR)"
# Same as above except indicating a minor change, supports regular expressions wrapped with '/'
minor_pattern: "(MINOR)"
# A string to determine the format of the version output
version_format: "${major}.${minor}.${patch}-prerelease${increment}"
# Optional path to check for changes. If any changes are detected in the path the
# 'changed' output will true. Enter multiple paths separated by spaces.
change_path: "backend,frontend"
# Prevents pre-v1.0.0 version from automatically incrementing the major version.
# If enabled, when the major version is 0, major releases will be treated as minor and minor as patch. Note that the version_type output is unchanged.
enable_prerelease_mode: true
# - name: 🧪 Run tests
# run: npm run test:ci
# 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
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

@@ -46,6 +46,7 @@ jobs:
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GO_RELEASER_GITHUB_TOKEN }}
POSTHOG_API_KEY_FOR_CLI: ${{ secrets.POSTHOG_API_KEY_FOR_CLI }}
FURY_TOKEN: ${{ secrets.FURYPUSHTOKEN }}
AUR_KEY: ${{ secrets.AUR_KEY }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

View File

@@ -1,10 +1,16 @@
name: Release Docker image for K8 operator
on: [workflow_dispatch]
name: Release Docker image for K8 operator
on:
push:
tags:
- "infisical-k8-operator/v*.*.*"
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Extract version from tag
id: extract_version
run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical-k8-operator/}"
- uses: actions/checkout@v2
- name: 🔧 Set up QEMU
@@ -26,4 +32,6 @@ jobs:
context: k8-operator
push: true
platforms: linux/amd64,linux/arm64
tags: infisical/kubernetes-operator:latest
tags: |
infisical/kubernetes-operator:latest
infisical/kubernetes-operator:${{ steps.extract_version.outputs.version }}

9
.gitignore vendored
View File

@@ -1,7 +1,9 @@
# backend
node_modules
.env
.env.test
.env.dev
.env.gamma
.env.prod
.env.infisical
@@ -32,7 +34,7 @@ reports
junit.xml
# next.js
/.next/
.next/
/out/
# production
@@ -56,3 +58,8 @@ yarn-error.log*
# Infisical init
.infisical.json
# Editor specific
.vscode/*
frontend-build

View File

@@ -18,7 +18,9 @@ monorepo:
builds:
- id: darwin-build
binary: infisical
ldflags: -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }}
ldflags:
- -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }}
- -X github.com/Infisical/infisical-merge/packages/telemetry.POSTHOG_API_KEY_FOR_CLI={{ .Env.POSTHOG_API_KEY_FOR_CLI }}
flags:
- -trimpath
env:
@@ -36,7 +38,9 @@ builds:
env:
- CGO_ENABLED=0
binary: infisical
ldflags: -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }}
ldflags:
- -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }}
- -X github.com/Infisical/infisical-merge/packages/telemetry.POSTHOG_API_KEY_FOR_CLI={{ .Env.POSTHOG_API_KEY_FOR_CLI }}
flags:
- -trimpath
goos:
@@ -65,10 +69,10 @@ archives:
- goos: windows
format: zip
files:
- README*
- LICENSE*
- manpages/*
- completions/*
- ../README*
- ../LICENSE*
- ../manpages/*
- ../completions/*
release:
replace_existing_draft: true
@@ -98,12 +102,28 @@ brews:
folder: Formula
homepage: "https://infisical.com"
description: "The official Infisical CLI"
# install: |-
# bin.install "infisical"
# bash_completion.install "completions/infisical.bash" => "infisical"
# zsh_completion.install "completions/infisical.zsh" => "_infisical"
# fish_completion.install "completions/infisical.fish"
# man1.install "manpages/infisical.1.gz"
install: |-
bin.install "infisical"
bash_completion.install "completions/infisical.bash" => "infisical"
zsh_completion.install "completions/infisical.zsh" => "_infisical"
fish_completion.install "completions/infisical.fish"
man1.install "manpages/infisical.1.gz"
- name: "infisical@{{.Version}}"
tap:
owner: Infisical
name: homebrew-get-cli
commit_author:
name: "Infisical"
email: ai@infisical.com
folder: Formula
homepage: "https://infisical.com"
description: "The official Infisical CLI"
install: |-
bin.install "infisical"
bash_completion.install "completions/infisical.bash" => "infisical"
zsh_completion.install "completions/infisical.zsh" => "_infisical"
fish_completion.install "completions/infisical.fish"
man1.install "manpages/infisical.1.gz"
nfpms:
- id: infisical
@@ -121,15 +141,15 @@ nfpms:
- apk
- archlinux
bindir: /usr/bin
# contents:
# - src: ./completions/infisical.bash
# dst: /etc/bash_completion.d/infisical
# - src: ./completions/infisical.fish
# dst: /usr/share/fish/vendor_completions.d/infisical.fish
# - src: ./completions/infisical.zsh
# dst: /usr/share/zsh/site-functions/_infisical
# - src: ./manpages/infisical.1.gz
# dst: /usr/share/man/man1/infisical.1.gz
contents:
- src: ./completions/infisical.bash
dst: /etc/bash_completion.d/infisical
- src: ./completions/infisical.fish
dst: /usr/share/fish/vendor_completions.d/infisical.fish
- src: ./completions/infisical.zsh
dst: /usr/share/zsh/site-functions/_infisical
- src: ./manpages/infisical.1.gz
dst: /usr/share/man/man1/infisical.1.gz
scoop:
bucket:
@@ -156,13 +176,24 @@ aurs:
install -Dm755 "./infisical" "${pkgdir}/usr/bin/infisical"
# license
install -Dm644 "./LICENSE" "${pkgdir}/usr/share/licenses/infisical/LICENSE"
# completions
mkdir -p "${pkgdir}/usr/share/bash-completion/completions/"
mkdir -p "${pkgdir}/usr/share/zsh/site-functions/"
mkdir -p "${pkgdir}/usr/share/fish/vendor_completions.d/"
install -Dm644 "./completions/infisical.bash" "${pkgdir}/usr/share/bash-completion/completions/infisical"
install -Dm644 "./completions/infisical.zsh" "${pkgdir}/usr/share/zsh/site-functions/_infisical"
install -Dm644 "./completions/infisical.fish" "${pkgdir}/usr/share/fish/vendor_completions.d/infisical.fish"
# 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

@@ -1,5 +1,6 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
infisical scan git-changes --staged -v

1
.infisicalignore Normal file
View File

@@ -0,0 +1 @@
.github/resources/docker-compose.be-test.yml:generic-api-key:16

View File

@@ -0,0 +1,130 @@
ARG POSTHOG_HOST=https://app.posthog.com
ARG POSTHOG_API_KEY=posthog-api-key
ARG INTERCOM_ID=intercom-id
FROM node:20-alpine AS base
FROM base AS frontend-dependencies
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY frontend/package.json frontend/package-lock.json frontend/next.config.js ./
# Install dependencies
RUN npm ci --only-production --ignore-scripts
# Rebuild the source code only when needed
FROM base AS frontend-builder
WORKDIR /app
# Copy dependencies
COPY --from=frontend-dependencies /app/node_modules ./node_modules
# Copy all files
COPY /frontend .
ENV NODE_ENV production
ENV NEXT_PUBLIC_ENV production
ARG POSTHOG_HOST
ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST
ARG POSTHOG_API_KEY
ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY
ARG INTERCOM_ID
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
ARG INFISICAL_PLATFORM_VERSION
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
# Build
RUN npm run build
# Production image
FROM base AS frontend-runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 non-root-user
RUN mkdir -p /app/.next/cache/images && chown non-root-user:nodejs /app/.next/cache/images
VOLUME /app/.next/cache/images
COPY --chown=non-root-user:nodejs --chmod=555 frontend/scripts ./scripts
COPY --from=frontend-builder /app/public ./public
RUN chown non-root-user:nodejs ./public/data
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/standalone ./
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/static ./.next/static
USER non-root-user
ENV NEXT_TELEMETRY_DISABLED 1
##
## BACKEND
##
FROM base AS backend-build
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 non-root-user
WORKDIR /app
COPY backend/package*.json ./
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
FROM base AS backend-runner
WORKDIR /app
COPY backend/package*.json ./
RUN npm ci --only-production
COPY --from=backend-build /app .
RUN mkdir frontend-build
# Production stage
FROM base AS production
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 non-root-user
## set pre baked keys
ARG POSTHOG_API_KEY
ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY
ARG INTERCOM_ID=intercom-id
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
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
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

115
README.md

File diff suppressed because one or more lines are too long

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

41
backend-mongo/.eslintrc Normal file
View File

@@ -0,0 +1,41 @@
{
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"unused-imports"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"no-empty-function": "off",
"@typescript-eslint/no-empty-function": "off",
"no-console": 2,
"quotes": [
"error",
"double",
{
"avoidEscape": true
}
],
"comma-dangle": [
"error",
"only-multiline"
],
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"@typescript-eslint/no-extra-semi": "off", // added to be able to push
"unused-imports/no-unused-vars": [
"warn",
{
"vars": "all",
"varsIgnorePattern": "^_",
"args": "after-used",
"argsIgnorePattern": "^_"
}
],
"sort-imports": 1
}
}

View File

@@ -0,0 +1,7 @@
{
"singleQuote": false,
"printWidth": 100,
"trailingComma": "none",
"tabWidth": 2,
"semi": true
}

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

@@ -14,7 +14,7 @@ declare global {
JWT_SIGNUP_LIFETIME: string;
JWT_SIGNUP_SECRET: string;
MONGO_URL: string;
NODE_ENV: 'development' | 'staging' | 'testing' | 'production';
NODE_ENV: "development" | "staging" | "testing" | "production";
VERBOSE_ERROR_OUTPUT: string;
LOKI_HOST: string;
CLIENT_ID_HEROKU: string;
@@ -39,12 +39,6 @@ declare global {
SMTP_PASSWORD: string;
SMTP_FROM_ADDRESS: string;
SMTP_FROM_NAME: string;
STRIPE_PRODUCT_STARTER: string;
STRIPE_PRODUCT_TEAM: string;
STRIPE_PRODUCT_PRO: string;
STRIPE_PUBLISHABLE_KEY: string;
STRIPE_SECRET_KEY: string;
STRIPE_WEBHOOK_SECRET: string;
TELEMETRY_ENABLED: string;
LICENSE_KEY: string;
}

View File

Before

Width:  |  Height:  |  Size: 493 KiB

After

Width:  |  Height:  |  Size: 493 KiB

View File

@@ -0,0 +1,9 @@
export default {
preset: "ts-jest",
testEnvironment: "node",
collectCoverageFrom: ["src/*.{js,ts}", "!**/node_modules/**"],
modulePaths: ["<rootDir>/src"],
testMatch: ["<rootDir>/tests/**/*.test.ts"],
setupFiles: ["<rootDir>/test-resources/env-vars.js"],
setupFilesAfterEnv: ["<rootDir>/tests/setupTests.ts"],
};

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}"
}
}

8047
backend-mongo/spec.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
import ora from "ora";
import nodemailer from "nodemailer";
import { getSmtpHost, getSmtpPort } from "./config";
import { logger } from "./utils/logging";
import mongoose from "mongoose";
import { redisClient } from "./services/RedisService";
type BootstrapOpt = {
transporter: nodemailer.Transporter;
};
export const bootstrap = async ({ transporter }: BootstrapOpt) => {
const spinner = ora().start();
spinner.info("Checking configurations...");
spinner.info("Testing smtp connection");
await transporter
.verify()
.then(async () => {
spinner.succeed("SMTP successfully connected");
})
.catch(async (err) => {
spinner.fail(`SMTP - Failed to connect to ${await getSmtpHost()}:${await getSmtpPort()}`);
logger.error(err);
});
spinner.info("Testing mongodb connection");
if (mongoose.connection.readyState !== mongoose.ConnectionStates.connected) {
spinner.fail("Mongo DB - Failed to connect");
} else {
spinner.succeed("Mongodb successfully connected");
}
spinner.info("Testing redis connection");
const redisPing = await redisClient?.ping();
if (!redisPing) {
spinner.fail("Redis - Failed to connect");
} else {
spinner.succeed("Redis successfully connected");
}
spinner.stop();
};

View File

@@ -0,0 +1,176 @@
import { GITLAB_URL } from "../variables";
import InfisicalClient from "infisical-node";
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;
return secretValue === "" ? undefined : secretValue;
};
export const getRootEncryptionKey = async () => {
const secretValue = (await client.getSecret("ROOT_ENCRYPTION_KEY")).secretValue;
return secretValue === "" ? undefined : secretValue;
};
export const getInviteOnlySignup = async () =>
(await client.getSecret("INVITE_ONLY_SIGNUP")).secretValue === "true";
export const getSaltRounds = async () =>
parseInt((await client.getSecret("SALT_ROUNDS")).secretValue) || 10;
export const getAuthSecret = async () =>
(await client.getSecret("JWT_AUTH_SECRET")).secretValue ??
(await client.getSecret("AUTH_SECRET")).secretValue;
export const getJwtAuthLifetime = async () =>
(await client.getSecret("JWT_AUTH_LIFETIME")).secretValue || "10d";
export const getJwtMfaLifetime = async () =>
(await client.getSecret("JWT_MFA_LIFETIME")).secretValue || "5m";
export const getJwtRefreshLifetime = async () =>
(await client.getSecret("JWT_REFRESH_LIFETIME")).secretValue || "90d";
export const getJwtServiceSecret = async () =>
(await client.getSecret("JWT_SERVICE_SECRET")).secretValue; // TODO: deprecate (related to ST V1)
export const getJwtSignupLifetime = async () =>
(await client.getSecret("JWT_SIGNUP_LIFETIME")).secretValue || "15m";
export const getJwtProviderAuthLifetime = async () =>
(await client.getSecret("JWT_PROVIDER_AUTH_LIFETIME")).secretValue || "15m";
export const getMongoURL = async () => (await client.getSecret("MONGO_URL")).secretValue;
export const getNodeEnv = async () =>
(await client.getSecret("NODE_ENV")).secretValue || "production";
export const getVerboseErrorOutput = async () =>
(await client.getSecret("VERBOSE_ERROR_OUTPUT")).secretValue === "true" && true;
export const getLokiHost = async () => (await client.getSecret("LOKI_HOST")).secretValue;
export const getClientIdAzure = async () => (await client.getSecret("CLIENT_ID_AZURE")).secretValue;
export const getClientIdHeroku = async () =>
(await client.getSecret("CLIENT_ID_HEROKU")).secretValue;
export const getClientIdVercel = async () =>
(await client.getSecret("CLIENT_ID_VERCEL")).secretValue;
export const getClientIdNetlify = async () =>
(await client.getSecret("CLIENT_ID_NETLIFY")).secretValue;
export const getClientIdGitHub = async () =>
(await client.getSecret("CLIENT_ID_GITHUB")).secretValue;
export const getClientIdGitLab = async () =>
(await client.getSecret("CLIENT_ID_GITLAB")).secretValue;
export const getClientIdBitBucket = async () =>
(await client.getSecret("CLIENT_ID_BITBUCKET")).secretValue;
export const getClientIdGCPSecretManager = async () =>
(await client.getSecret("CLIENT_ID_GCP_SECRET_MANAGER")).secretValue;
export const getClientSecretAzure = async () =>
(await client.getSecret("CLIENT_SECRET_AZURE")).secretValue;
export const getClientSecretHeroku = async () =>
(await client.getSecret("CLIENT_SECRET_HEROKU")).secretValue;
export const getClientSecretVercel = async () =>
(await client.getSecret("CLIENT_SECRET_VERCEL")).secretValue;
export const getClientSecretNetlify = async () =>
(await client.getSecret("CLIENT_SECRET_NETLIFY")).secretValue;
export const getClientSecretGitHub = async () =>
(await client.getSecret("CLIENT_SECRET_GITHUB")).secretValue;
export const getClientSecretGitLab = async () =>
(await client.getSecret("CLIENT_SECRET_GITLAB")).secretValue;
export const getClientSecretBitBucket = async () =>
(await client.getSecret("CLIENT_SECRET_BITBUCKET")).secretValue;
export const getClientSecretGCPSecretManager = async () =>
(await client.getSecret("CLIENT_SECRET_GCP_SECRET_MANAGER")).secretValue;
export const getClientSlugVercel = async () =>
(await client.getSecret("CLIENT_SLUG_VERCEL")).secretValue;
export const getClientIdGoogleLogin = async () =>
(await client.getSecret("CLIENT_ID_GOOGLE_LOGIN")).secretValue;
export const getClientSecretGoogleLogin = async () =>
(await client.getSecret("CLIENT_SECRET_GOOGLE_LOGIN")).secretValue;
export const getClientIdGitHubLogin = async () =>
(await client.getSecret("CLIENT_ID_GITHUB_LOGIN")).secretValue;
export const getClientSecretGitHubLogin = async () =>
(await client.getSecret("CLIENT_SECRET_GITHUB_LOGIN")).secretValue;
export const getClientIdGitLabLogin = async () =>
(await client.getSecret("CLIENT_ID_GITLAB_LOGIN")).secretValue;
export const getClientSecretGitLabLogin = async () =>
(await client.getSecret("CLIENT_SECRET_GITLAB_LOGIN")).secretValue;
export const getUrlGitLabLogin = async () =>
(await client.getSecret("URL_GITLAB_LOGIN")).secretValue || GITLAB_URL;
export const getAwsCloudWatchLog = async () => {
const logGroupName =
(await client.getSecret("AWS_CLOUDWATCH_LOG_GROUP_NAME")).secretValue || "infisical-log-stream";
const region = (await client.getSecret("AWS_CLOUDWATCH_LOG_REGION")).secretValue;
const accessKeyId = (await client.getSecret("AWS_CLOUDWATCH_LOG_ACCESS_KEY_ID")).secretValue;
const accessKeySecret = (await client.getSecret("AWS_CLOUDWATCH_LOG_ACCESS_KEY_SECRET"))
.secretValue;
const interval = parseInt(
(await client.getSecret("AWS_CLOUDWATCH_LOG_INTERVAL")).secretValue || 1000,
10
);
if (!region || !accessKeyId || !accessKeySecret) return;
return { logGroupName, region, accessKeySecret, accessKeyId, interval };
};
export const getPostHogHost = async () =>
(await client.getSecret("POSTHOG_HOST")).secretValue || "https://app.posthog.com";
export const getPostHogProjectApiKey = async () =>
(await client.getSecret("POSTHOG_PROJECT_API_KEY")).secretValue ||
"phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE";
export const getSentryDSN = async () => (await client.getSecret("SENTRY_DSN")).secretValue;
export const getSiteURL = async () => (await client.getSecret("SITE_URL")).secretValue;
export const getSmtpHost = async () => (await client.getSecret("SMTP_HOST")).secretValue;
export const getSmtpSecure = async () =>
(await client.getSecret("SMTP_SECURE")).secretValue === "true" || false;
export const getSmtpPort = async () =>
parseInt((await client.getSecret("SMTP_PORT")).secretValue) || 587;
export const getSmtpUsername = async () => (await client.getSecret("SMTP_USERNAME")).secretValue;
export const getSmtpPassword = async () => (await client.getSecret("SMTP_PASSWORD")).secretValue;
export const getSmtpFromAddress = async () =>
(await client.getSecret("SMTP_FROM_ADDRESS")).secretValue;
export const getSmtpFromName = async () =>
(await client.getSecret("SMTP_FROM_NAME")).secretValue || "Infisical";
export const getSecretScanningWebhookProxy = async () =>
(await client.getSecret("SECRET_SCANNING_WEBHOOK_PROXY")).secretValue;
export const getSecretScanningWebhookSecret = async () =>
(await client.getSecret("SECRET_SCANNING_WEBHOOK_SECRET")).secretValue;
export const getSecretScanningGitAppId = async () =>
(await client.getSecret("SECRET_SCANNING_GIT_APP_ID")).secretValue;
export const getSecretScanningPrivateKey = async () =>
(await client.getSecret("SECRET_SCANNING_PRIVATE_KEY")).secretValue;
export const getRedisUrl = async () => (await client.getSecret("REDIS_URL")).secretValue;
export const getIsInfisicalCloud = async () =>
(await client.getSecret("INFISICAL_CLOUD")).secretValue === "true";
export const getLicenseKey = async () => {
const secretValue = (await client.getSecret("LICENSE_KEY")).secretValue;
return secretValue === "" ? undefined : secretValue;
};
export const getLicenseServerKey = async () => {
const secretValue = (await client.getSecret("LICENSE_SERVER_KEY")).secretValue;
return secretValue === "" ? undefined : secretValue;
};
export const getLicenseServerUrl = async () =>
(await client.getSecret("LICENSE_SERVER_URL")).secretValue || "https://portal.infisical.com";
export const getTelemetryEnabled = async () =>
(await client.getSecret("TELEMETRY_ENABLED")).secretValue !== "false" && true;
export const getLoopsApiKey = async () => (await client.getSecret("LOOPS_API_KEY")).secretValue;
export const getSmtpConfigured = async () =>
(await client.getSecret("SMTP_HOST")).secretValue == "" ||
(await client.getSecret("SMTP_HOST")).secretValue == undefined
? false
: true;
export const getHttpsEnabled = async () => {
if ((await getNodeEnv()) != "production") {
// no https for anything other than prod
return false;
}
if (
(await client.getSecret("HTTPS_ENABLED")).secretValue == undefined ||
(await client.getSecret("HTTPS_ENABLED")).secretValue == ""
) {
// default when no value present
return true;
}
return (await client.getSecret("HTTPS_ENABLED")).secretValue === "true" && true;
};

View File

@@ -0,0 +1,124 @@
import axios from "axios";
import axiosRetry from "axios-retry";
import {
getLicenseKeyAuthToken,
getLicenseServerKeyAuthToken,
setLicenseKeyAuthToken,
setLicenseServerKeyAuthToken,
} from "./storage";
import {
getLicenseKey,
getLicenseServerKey,
getLicenseServerUrl,
} from "./index";
// should have JWT to interact with the license server
export const licenseServerKeyRequest = axios.create();
export const licenseKeyRequest = axios.create();
export const standardRequest = axios.create();
// add retry functionality to the axios instance
axiosRetry(standardRequest, {
retries: 3,
retryDelay: axiosRetry.exponentialDelay, // exponential back-off delay between retries
retryCondition: (error) => {
// only retry if the error is a network error or a 5xx server error
return axiosRetry.isNetworkError(error) || axiosRetry.isRetryableError(error);
},
});
export const refreshLicenseServerKeyToken = async () => {
const licenseServerKey = await getLicenseServerKey();
const licenseServerUrl = await getLicenseServerUrl();
const { data: { token } } = await standardRequest.post(
`${licenseServerUrl}/api/auth/v1/license-server-login`, {},
{
headers: {
"X-API-KEY": licenseServerKey,
},
}
);
setLicenseServerKeyAuthToken(token);
return token;
}
export const refreshLicenseKeyToken = async () => {
const licenseKey = await getLicenseKey();
const licenseServerUrl = await getLicenseServerUrl();
const { data: { token } } = await standardRequest.post(
`${licenseServerUrl}/api/auth/v1/license-login`, {},
{
headers: {
"X-API-KEY": licenseKey,
},
}
);
setLicenseKeyAuthToken(token);
return token;
}
licenseServerKeyRequest.interceptors.request.use((config) => {
const token = getLicenseServerKeyAuthToken();
if (token && config.headers) {
// eslint-disable-next-line no-param-reassign
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, (err) => {
return Promise.reject(err);
});
licenseServerKeyRequest.interceptors.response.use((response) => {
return response
}, async function (err) {
const originalRequest = err.config;
if (err.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
// refresh
const token = await refreshLicenseServerKeyToken();
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
return licenseServerKeyRequest(originalRequest);
}
return Promise.reject(err);
});
licenseKeyRequest.interceptors.request.use((config) => {
const token = getLicenseKeyAuthToken();
if (token && config.headers) {
// eslint-disable-next-line no-param-reassign
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, (err) => {
return Promise.reject(err);
});
licenseKeyRequest.interceptors.response.use((response) => {
return response
}, async function (err) {
const originalRequest = err.config;
if (err.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
// refresh
const token = await refreshLicenseKeyToken();
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
return licenseKeyRequest(originalRequest);
}
return Promise.reject(err);
});

View File

@@ -0,0 +1,24 @@
import { IServerConfig, ServerConfig } from "../models/serverConfig";
let serverConfig: IServerConfig;
export const serverConfigInit = async () => {
const cfg = await ServerConfig.findOne({}).lean();
if (!cfg) {
const cfg = new ServerConfig();
await cfg.save();
serverConfig = cfg.toObject();
} else {
serverConfig = cfg;
}
return serverConfig;
};
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.toObject();
return serverConfig;
};

View File

@@ -0,0 +1,30 @@
const MemoryLicenseServerKeyTokenStorage = () => {
let authToken: string;
return {
setToken: (token: string) => {
authToken = token;
},
getToken: () => authToken,
};
};
const MemoryLicenseKeyTokenStorage = () => {
let authToken: string;
return {
setToken: (token: string) => {
authToken = token;
},
getToken: () => authToken,
};
};
const licenseServerTokenStorage = MemoryLicenseServerKeyTokenStorage();
const licenseTokenStorage = MemoryLicenseKeyTokenStorage();
export const getLicenseServerKeyAuthToken = licenseServerTokenStorage.getToken;
export const setLicenseServerKeyAuthToken = licenseServerTokenStorage.setToken;
export const getLicenseKeyAuthToken = licenseTokenStorage.getToken;
export const setLicenseKeyAuthToken = licenseTokenStorage.setToken;

View File

@@ -0,0 +1,101 @@
import { Request, Response } from "express";
import { getHttpsEnabled, getIsMigrationMode } from "../../config";
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
import { validateRequest } from "../../helpers/validation";
import { User } from "../../models";
import { TelemetryService } from "../../services";
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
import * as reqValidator from "../../validation/admin";
export const getServerConfigInfo = async (_req: Request, res: Response) => {
const config = getServerConfig();
const isMigrationModeOn = await getIsMigrationMode();
return res.send({ config: { ...config, isMigrationModeOn } });
};
export const updateServerConfig = async (req: Request, res: Response) => {
const {
body: { allowSignUp }
} = await validateRequest(reqValidator.UpdateServerConfigV1, req);
const config = await setServerConfig({ allowSignUp });
return res.send({ config });
};
export const adminSignUp = async (req: Request, res: Response) => {
const cfg = getServerConfig();
if (cfg.initialized) throw UnauthorizedRequestError({ message: "Admin has been created" });
const {
body: {
email,
publicKey,
salt,
lastName,
verifier,
firstName,
protectedKey,
protectedKeyIV,
protectedKeyTag,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag
}
} = await validateRequest(reqValidator.SignupV1, req);
let user = await User.findOne({ email });
if (user) throw BadRequestError({ message: "User already exist" });
user = new User({
email,
firstName,
lastName,
encryptionVersion: 2,
protectedKey,
protectedKeyIV,
protectedKeyTag,
publicKey,
encryptedPrivateKey,
iv: encryptedPrivateKeyIV,
tag: encryptedPrivateKeyTag,
salt,
verifier,
superAdmin: true
});
await user.save();
await initializeDefaultOrg({ organizationName: "Admin Org", user });
await setServerConfig({ initialized: true });
// issue tokens
const tokens = await issueAuthTokens({
userId: user._id,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
const token = tokens.token;
const postHogClient = await TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
event: "admin initialization",
properties: {
email: user.email,
lastName,
firstName
}
});
}
// store (refresh) token in httpOnly cookie
res.cookie("jid", tokens.refreshToken, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: await getHttpsEnabled()
});
return res.status(200).send({
message: "Successfully set up admin account",
user,
token
});
};

View File

@@ -0,0 +1,277 @@
import { Request, Response } from "express";
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 { clearTokens, createToken, issueAuthTokens } from "../../helpers/auth";
import { checkUserDevice } from "../../helpers/user";
import { AuthTokenType } from "../../variables";
import {
BadRequestError,
UnauthorizedRequestError
} from "../../utils/errors";
import {
getAuthSecret,
getHttpsEnabled,
getJwtAuthLifetime,
} from "../../config";
import { ActorType } from "../../ee/models";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/auth";
declare module "jsonwebtoken" {
export interface AuthnJwtPayload extends jwt.JwtPayload {
authTokenType: AuthTokenType;
}
export interface UserIDJwtPayload extends jwt.JwtPayload {
userId: string;
refreshVersion?: number;
}
export interface IdentityAccessTokenJwtPayload extends jwt.JwtPayload {
_id: string;
clientSecretId: string;
identityAccessTokenId: string;
authTokenType: string;
}
}
/**
* Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol
* @param req
* @param res
* @returns
*/
export const login1 = async (req: Request, res: Response) => {
const {
body: { email, clientPublicKey }
} = await validateRequest(reqValidator.Login1V1, req);
const user = await User.findOne({
email
}).select("+salt +verifier");
if (!user) throw new Error("Failed to find user");
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier
},
async () => {
// generate server-side public key
const serverPublicKey = server.getPublicKey();
await LoginSRPDetail.findOneAndReplace(
{ email: email },
{
email: email,
clientPublicKey: clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt)
},
{ upsert: true, returnNewDocument: false }
);
return res.status(200).send({
serverPublicKey,
salt: user.salt
});
}
);
};
/**
* Log in user step 2: complete step 2 of SRP protocol and return token and their (encrypted)
* private key
* @param req
* @param res
* @returns
*/
export const login2 = async (req: Request, res: Response) => {
const {
body: { email, clientProof }
} = await validateRequest(reqValidator.Login2V1, req);
const user = await User.findOne({
email
}).select("+salt +verifier +publicKey +encryptedPrivateKey +iv +tag");
if (!user) throw new Error("Failed to find user");
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: email });
if (!loginSRPDetailFromDB) {
return BadRequestError(
Error(
"It looks like some details from the first login are not found. Please try login one again"
)
);
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier,
b: loginSRPDetailFromDB.serverBInt
},
async () => {
server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey);
// compare server and client shared keys
if (server.checkClientProof(clientProof)) {
// issue tokens
await checkUserDevice({
user,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
const tokens = await issueAuthTokens({
userId: user._id,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
// store (refresh) token in httpOnly cookie
res.cookie("jid", tokens.refreshToken, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: await getHttpsEnabled()
});
// return (access) token in response
return res.status(200).send({
token: tokens.token,
publicKey: user.publicKey,
encryptedPrivateKey: user.encryptedPrivateKey,
iv: user.iv,
tag: user.tag
});
}
return res.status(400).send({
message: "Failed to authenticate. Try again?"
});
}
);
};
/**
* Log out user
* @param req
* @param res
* @returns
*/
export const logout = async (req: Request, res: Response) => {
if (req.authData.actor.type === ActorType.USER && req.authData.tokenVersionId) {
await clearTokens(req.authData.tokenVersionId);
}
// clear httpOnly cookie
res.cookie("jid", "", {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: (await getHttpsEnabled()) as boolean
});
return res.status(200).send({
message: "Successfully logged out."
});
};
export const revokeAllSessions = async (req: Request, res: Response) => {
await TokenVersion.updateMany(
{
user: req.user._id
},
{
$inc: {
refreshVersion: 1,
accessVersion: 1
}
}
);
return res.status(200).send({
message: "Successfully revoked all sessions."
});
};
/**
* Return user is authenticated
* @param req
* @param res
* @returns
*/
export const checkAuth = async (req: Request, res: Response) => {
return res.status(200).send({
message: "Authenticated"
});
};
/**
* Return new JWT access token by first validating the refresh token
* @param req
* @param res
* @returns
*/
export const getNewToken = async (req: Request, res: Response) => {
const refreshToken = req.cookies.jid;
if (!refreshToken)
throw BadRequestError({
message: "Failed to find refresh token in request cookies"
});
const decodedToken = <jwt.UserIDJwtPayload>jwt.verify(refreshToken, await getAuthSecret());
if (decodedToken.authTokenType !== AuthTokenType.REFRESH_TOKEN) throw UnauthorizedRequestError();
const user = await User.findOne({
_id: decodedToken.userId
}).select("+publicKey +refreshVersion +accessVersion");
if (!user) throw new Error("Failed to authenticate unfound user");
if (!user?.publicKey) throw new Error("Failed to authenticate not fully set up account");
const tokenVersion = await TokenVersion.findById(decodedToken.tokenVersionId);
if (!tokenVersion)
throw UnauthorizedRequestError({
message: "Failed to validate refresh token"
});
if (decodedToken.refreshVersion !== tokenVersion.refreshVersion)
throw BadRequestError({
message: "Failed to validate refresh token"
});
const token = createToken({
payload: {
authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: decodedToken.userId,
tokenVersionId: tokenVersion._id.toString(),
accessVersion: tokenVersion.refreshVersion
},
expiresIn: await getJwtAuthLifetime(),
secret: await getAuthSecret()
});
return res.status(200).send({
token
});
};
export const handleAuthProviderCallback = (req: Request, res: Response) => {
res.redirect(`/login/provider/success?token=${encodeURIComponent(req.providerAuthToken)}`);
};

View File

@@ -0,0 +1,135 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { Bot, BotKey } from "../../models";
import { createBot } from "../../helpers/bot";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/bot";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
import { BadRequestError } from "../../utils/errors";
interface BotKey {
encryptedKey: string;
nonce: string;
}
/**
* Return bot for workspace with id [workspaceId]. If a workspace bot doesn't exist,
* then create and return a new bot.
* @param req
* @param res
* @returns
*/
export const getBotByWorkspaceId = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetBotByWorkspaceIdV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Integrations
);
let bot = await Bot.findOne({
workspace: workspaceId
});
if (!bot) {
// case: bot doesn't exist for workspace with id [workspaceId]
// -> create a new bot and return it
bot = await createBot({
name: "Infisical Bot",
workspaceId: new Types.ObjectId(workspaceId)
});
}
return res.status(200).send({
bot
});
};
/**
* Return bot with id [req.bot._id] with active state set to [isActive].
* @param req
* @param res
* @returns
*/
export const setBotActiveState = async (req: Request, res: Response) => {
const {
body: { botKey, isActive },
params: { botId }
} = await validateRequest(reqValidator.SetBotActiveStateV1, req);
const bot = await Bot.findById(botId);
if (!bot) {
throw BadRequestError({ message: "Bot not found" });
}
const userId = req.user._id;
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: bot.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Integrations
);
if (isActive) {
// bot state set to active -> share workspace key with bot
if (!botKey?.encryptedKey || !botKey?.nonce) {
return res.status(400).send({
message: "Failed to set bot state to active - missing bot key"
});
}
await BotKey.findOneAndUpdate(
{
workspace: bot.workspace
},
{
encryptedKey: botKey.encryptedKey,
nonce: botKey.nonce,
sender: userId,
bot: bot._id,
workspace: bot.workspace
},
{
upsert: true,
new: true
}
);
} else {
// case: bot state set to inactive -> delete bot's workspace key
await BotKey.deleteOne({
bot: bot._id
});
}
const updatedBot = await Bot.findOneAndUpdate(
{
_id: bot._id
},
{
isActive
},
{
new: true
}
);
if (!updatedBot) throw new Error("Failed to update bot active state");
return res.status(200).send({
bot
});
};

View File

@@ -0,0 +1,43 @@
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";
import * as keyController from "./keyController";
import * as membershipController from "./membershipController";
import * as membershipOrgController from "./membershipOrgController";
import * as organizationController from "./organizationController";
import * as passwordController from "./passwordController";
import * as secretController from "./secretController";
import * as serviceTokenController from "./serviceTokenController";
import * as signupController from "./signupController";
import * as userActionController from "./userActionController";
import * as userController from "./userController";
import * as workspaceController from "./workspaceController";
import * as secretScanningController from "./secretScanningController";
import * as webhookController from "./webhookController";
import * as secretImpsController from "./secretImpsController";
import * as adminController from "./adminController";
export {
authController,
universalAuthController,
botController,
integrationAuthController,
integrationController,
keyController,
membershipController,
membershipOrgController,
organizationController,
passwordController,
secretController,
serviceTokenController,
signupController,
userActionController,
userController,
workspaceController,
secretScanningController,
webhookController,
secretImpsController,
adminController
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,322 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { Folder, IWorkspace, Integration, IntegrationAuth } from "../../models";
import { EventService } from "../../services";
import { eventStartIntegration } from "../../events";
import { getFolderByPath } from "../../services/FolderService";
import { BadRequestError } from "../../utils/errors";
import { EEAuditLogService } from "../../ee/services";
import { EventType } from "../../ee/models";
import { syncSecretsToActiveIntegrationsQueue } from "../../queues/integrations/syncSecretsToThirdPartyServices";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/integration";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
/**
* Create/initialize an (empty) integration for integration authorization
* @param req
* @param res
* @returns
*/
export const createIntegration = async (req: Request, res: Response) => {
const {
body: {
isActive,
sourceEnvironment,
secretPath,
app,
path,
appId,
owner,
region,
scope,
targetService,
targetServiceId,
integrationAuthId,
targetEnvironment,
targetEnvironmentId,
metadata
}
} = await validateRequest(reqValidator.CreateIntegrationV1, req);
const integrationAuth = await IntegrationAuth.findById(integrationAuthId)
.populate<{ workspace: IWorkspace }>("workspace")
.select(
"+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt"
);
if (!integrationAuth) throw BadRequestError({ message: "Integration auth not found" });
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: integrationAuth.workspace._id
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.Integrations
);
const folders = await Folder.findOne({
workspace: integrationAuth.workspace._id,
environment: sourceEnvironment
});
if (folders) {
const folder = getFolderByPath(folders.nodes, secretPath);
if (!folder) {
throw BadRequestError({
message: "Folder path doesn't exist"
});
}
}
// TODO: validate [sourceEnvironment] and [targetEnvironment]
// initialize new integration after saving integration access token
const integration = await new Integration({
workspace: integrationAuth.workspace._id,
environment: sourceEnvironment,
isActive,
app,
appId,
targetEnvironment,
targetEnvironmentId,
targetService,
targetServiceId,
owner,
path,
region,
scope,
secretPath,
integration: integrationAuth.integration,
integrationAuth: new Types.ObjectId(integrationAuthId),
metadata
}).save();
if (integration) {
// trigger event - push secrets
EventService.handleEvent({
event: eventStartIntegration({
workspaceId: integration.workspace,
environment: sourceEnvironment
})
});
}
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_INTEGRATION,
metadata: {
integrationId: integration._id.toString(),
integration: integration.integration,
environment: integration.environment,
secretPath,
url: integration.url,
app: integration.app,
appId: integration.appId,
targetEnvironment: integration.targetEnvironment,
targetEnvironmentId: integration.targetEnvironmentId,
targetService: integration.targetService,
targetServiceId: integration.targetServiceId,
path: integration.path,
region: integration.region
}
},
{
workspaceId: integration.workspace
}
);
return res.status(200).send({
integration
});
};
/**
* Change environment or name of integration with id [integrationId]
* @param req
* @param res
* @returns
*/
export const updateIntegration = async (req: Request, res: Response) => {
// TODO: add integration-specific validation to ensure that each
// integration has the correct fields populated in [Integration]
const {
body: {
environment,
isActive,
app,
appId,
targetEnvironment,
owner, // github-specific integration param
secretPath
},
params: { integrationId }
} = await validateRequest(reqValidator.UpdateIntegrationV1, req);
const integration = await Integration.findById(integrationId);
if (!integration) throw BadRequestError({ message: "Integration not found" });
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: integration.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Integrations
);
const folders = await Folder.findOne({
workspace: integration.workspace,
environment
});
if (folders) {
const folder = getFolderByPath(folders.nodes, secretPath);
if (!folder) {
throw BadRequestError({
message: "Path for service token does not exist"
});
}
}
const updatedIntegration = await Integration.findOneAndUpdate(
{
_id: integration._id
},
{
environment,
isActive,
app,
appId,
targetEnvironment,
owner,
secretPath
},
{
new: true
}
);
if (updatedIntegration) {
// trigger event - push secrets
EventService.handleEvent({
event: eventStartIntegration({
workspaceId: updatedIntegration.workspace,
environment
})
});
}
return res.status(200).send({
integration: updatedIntegration
});
};
/**
* Delete integration with id [integrationId]
* @param req
* @param res
* @returns
*/
export const deleteIntegration = async (req: Request, res: Response) => {
const {
params: { integrationId }
} = await validateRequest(reqValidator.DeleteIntegrationV1, req);
const integration = await Integration.findById(integrationId);
if (!integration) throw BadRequestError({ message: "Integration not found" });
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: integration.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Integrations
);
const deletedIntegration = await Integration.findOneAndDelete({
_id: integrationId
});
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,
{
type: EventType.DELETE_INTEGRATION,
metadata: {
integrationId: integration._id.toString(),
integration: integration.integration,
environment: integration.environment,
secretPath: integration.secretPath,
url: integration.url,
app: integration.app,
appId: integration.appId,
targetEnvironment: integration.targetEnvironment,
targetEnvironmentId: integration.targetEnvironmentId,
targetService: integration.targetService,
targetServiceId: integration.targetServiceId,
path: integration.path,
region: integration.region
}
},
{
workspaceId: integration.workspace
}
);
return res.status(200).send({
integration
});
};
// Will trigger sync for all integrations within the given env and workspace id
export const manualSync = async (req: Request, res: Response) => {
const {
body: { workspaceId, environment }
} = await validateRequest(reqValidator.ManualSyncV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Integrations
);
syncSecretsToActiveIntegrationsQueue({
workspaceId,
environment
});
res.status(200).send();
};

View File

@@ -0,0 +1,101 @@
import { Types } from "mongoose";
import { Request, Response } from "express";
import { Key } from "../../models";
import { findMembership } from "../../helpers/membership";
import { EventType } from "../../ee/models";
import { EEAuditLogService } from "../../ee/services";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/key";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
/**
* Add (encrypted) copy of workspace key for workspace with id [workspaceId] for user with
* id [key.userId]
* @param req
* @param res
* @returns
*/
export const uploadKey = async (req: Request, res: Response) => {
const {
params: { workspaceId },
body: { key }
} = await validateRequest(reqValidator.UploadKeyV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Member
);
// validate membership of receiver
const receiverMembership = await findMembership({
user: key.userId,
workspace: workspaceId
});
if (!receiverMembership) {
throw new Error("Failed receiver membership validation for workspace");
}
await new Key({
encryptedKey: key.encryptedKey,
nonce: key.nonce,
sender: req.user._id,
receiver: key.userId,
workspace: workspaceId
}).save();
return res.status(200).send({
message: "Successfully uploaded key to workspace"
});
};
/**
* Return latest (encrypted) copy of workspace key for user
* @param req
* @param res
* @returns
*/
export const getLatestKey = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetLatestKeyV1, req);
// get latest key
const latestKey = await Key.find({
workspace: workspaceId,
receiver: req.user._id
})
.sort({ createdAt: -1 })
.limit(1)
.populate("sender", "+publicKey");
const resObj: any = {};
if (latestKey.length > 0) {
resObj["latestKey"] = latestKey[0];
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.GET_WORKSPACE_KEY,
metadata: {
keyId: latestKey[0]._id.toString()
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
}
return res.status(200).send(resObj);
};

View File

@@ -0,0 +1,286 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { IUser, Key, Membership, MembershipOrg, User, Workspace } from "../../models";
import { EventType, Role } from "../../ee/models";
import { deleteMembership as deleteMember, findMembership } from "../../helpers/membership";
import { sendMail } from "../../helpers/nodemailer";
import { ACCEPTED, ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../../variables";
import { getSiteURL } from "../../config";
import { EEAuditLogService, EELicenseService } from "../../ee/services";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/membership";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
import { BadRequestError } from "../../utils/errors";
import { InviteUserToWorkspaceV1 } from "../../validation/workspace";
/**
* Check that user is a member of workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const validateMembership = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.ValidateMembershipV1, req);
// validate membership
const membership = await findMembership({
user: req.user._id,
workspace: workspaceId
});
if (!membership) {
throw new Error("Failed to validate membership");
}
return res.status(200).send({
message: "Workspace membership confirmed"
});
};
/**
* Delete membership with id [membershipId]
* @param req
* @param res
* @returns
*/
export const deleteMembership = async (req: Request, res: Response) => {
const {
params: { membershipId }
} = await validateRequest(reqValidator.DeleteMembershipV1, req);
// check if membership to delete exists
const membershipToDelete = await Membership.findOne({
_id: membershipId
}).populate<{ user: IUser }>("user");
if (!membershipToDelete) {
throw new Error("Failed to delete workspace membership that doesn't exist");
}
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: membershipToDelete.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Member
);
// delete workspace membership
const deletedMembership = await deleteMember({
membershipId: membershipToDelete._id.toString()
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.REMOVE_WORKSPACE_MEMBER,
metadata: {
userId: membershipToDelete.user._id.toString(),
email: membershipToDelete.user.email
}
},
{
workspaceId: membershipToDelete.workspace
}
);
return res.status(200).send({
deletedMembership
});
};
/**
* Change and return workspace membership role
* @param req
* @param res
* @returns
*/
export const changeMembershipRole = async (req: Request, res: Response) => {
const {
body: { role },
params: { membershipId }
} = await validateRequest(reqValidator.ChangeMembershipRoleV1, req);
// validate target membership
const membershipToChangeRole = await Membership.findById(membershipId).populate<{ user: IUser }>(
"user"
);
if (!membershipToChangeRole) {
throw new Error("Failed to find membership to change role");
}
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: membershipToChangeRole.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Member
);
const isCustomRole = ![ADMIN, MEMBER, VIEWER, NO_ACCESS].includes(role);
if (isCustomRole) {
const wsRole = await Role.findOne({
slug: role,
isOrgRole: false,
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
});
return res.status(200).send({
membership
});
}
const membership = await Membership.findByIdAndUpdate(
membershipId,
{
$set: {
role
},
$unset: {
customRole: 1
}
},
{
new: true
}
);
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.UPDATE_USER_WORKSPACE_ROLE,
metadata: {
userId: membershipToChangeRole.user._id.toString(),
email: membershipToChangeRole.user.email,
oldRole: membershipToChangeRole.role,
newRole: role
}
},
{
workspaceId: membershipToChangeRole.workspace
}
);
return res.status(200).send({
membership
});
};
/**
* Add user with email [email] to workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const inviteUserToWorkspace = async (req: Request, res: Response) => {
const {
params: { workspaceId },
body: { email }
} = await validateRequest(InviteUserToWorkspaceV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.Member
);
const invitee = await User.findOne({
email
}).select("+publicKey");
if (!invitee || !invitee?.publicKey) throw new Error("Failed to validate invitee");
// validate invitee's workspace membership - ensure member isn't
// already a member of the workspace
const inviteeMembership = await Membership.findOne({
user: invitee._id,
workspace: workspaceId
}).populate<{ user: IUser }>("user");
if (inviteeMembership) throw new Error("Failed to add existing member of workspace");
const workspace = await Workspace.findById(workspaceId);
if (!workspace) throw new Error("Failed to find workspace");
// validate invitee's organization membership - ensure that only
// (accepted) organization members can be added to the workspace
const membershipOrg = await MembershipOrg.findOne({
user: invitee._id,
organization: workspace.organization,
status: ACCEPTED
});
if (!membershipOrg) throw new Error("Failed to validate invitee's organization membership");
// get latest key
const latestKey = await Key.findOne({
workspace: workspaceId,
receiver: req.user._id
})
.sort({ createdAt: -1 })
.populate("sender", "+publicKey");
// create new workspace membership
await new Membership({
user: invitee._id,
workspace: workspaceId,
role: MEMBER
}).save();
await sendMail({
template: "workspaceInvitation.handlebars",
subjectLine: "Infisical workspace invitation",
recipients: [invitee.email],
substitutions: {
inviterFirstName: req.user.firstName,
inviterEmail: req.user.email,
workspaceName: workspace.name,
callback_url: (await getSiteURL()) + "/login"
}
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.ADD_WORKSPACE_MEMBER,
metadata: {
userId: invitee._id.toString(),
email: invitee.email
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.status(200).send({
invitee,
latestKey
});
};

View File

@@ -0,0 +1,292 @@
import { Types } from "mongoose";
import { Request, Response } from "express";
import { MembershipOrg, Organization, User } from "../../models";
import { SSOConfig } from "../../ee/models";
import { deleteMembershipOrg as deleteMemberFromOrg } from "../../helpers/membershipOrg";
import { createToken } from "../../helpers/auth";
import { updateSubscriptionOrgQuantity } from "../../helpers/organization";
import { sendMail } from "../../helpers/nodemailer";
import { TokenService } from "../../services";
import { EELicenseService } from "../../ee/services";
import { ACCEPTED, AuthTokenType, INVITED, MEMBER, TOKEN_EMAIL_ORG_INVITATION } from "../../variables";
import * as reqValidator from "../../validation/membershipOrg";
import {
getAuthSecret,
getJwtSignupLifetime,
getSiteURL,
getSmtpConfigured
} from "../../config";
import { validateUserEmail } from "../../validation";
import { validateRequest } from "../../helpers/validation";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { ForbiddenError } from "@casl/ability";
/**
* Delete organization membership with id [membershipOrgId] from organization
* @param req
* @param res
* @returns
*/
export const deleteMembershipOrg = async (req: Request, _res: Response) => {
const {
params: { membershipOrgId }
} = await validateRequest(reqValidator.DelOrgMembershipv1, req);
// check if organization membership to delete exists
const membershipOrgToDelete = await MembershipOrg.findOne({
_id: membershipOrgId
}).populate("user");
if (!membershipOrgToDelete) {
throw new Error("Failed to delete organization membership that doesn't exist");
}
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: membershipOrgToDelete.organization
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Member
);
// delete organization membership
await deleteMemberFromOrg({
membershipOrgId: membershipOrgToDelete._id.toString()
});
await updateSubscriptionOrgQuantity({
organizationId: membershipOrgToDelete.organization.toString()
});
return membershipOrgToDelete;
};
/**
* Change and return organization membership role
* @param req
* @param res
* @returns
*/
export const changeMembershipOrgRole = async (req: Request, res: Response) => {
// change role for (target) organization membership with id
// [membershipOrgId]
let membershipToChangeRole;
return res.status(200).send({
membershipOrg: membershipToChangeRole
});
};
/**
* Organization invitation step 1: Send email invitation to user with email [email]
* for organization with id [organizationId] containing magic link
* @param req
* @param res
* @returns
*/
export const inviteUserToOrganization = async (req: Request, res: Response) => {
let inviteeMembershipOrg, completeInviteLink;
const {
body: { inviteeEmail, organizationId }
} = await validateRequest(reqValidator.InviteUserToOrgv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Member
);
const host = req.headers.host;
const siteUrl = `${req.protocol}://${host}`;
const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId));
const ssoConfig = await SSOConfig.findOne({
organization: new Types.ObjectId(organizationId)
});
if (ssoConfig && ssoConfig.isActive) {
// case: SAML SSO is enabled for the organization
return res.status(400).send({
message: "Failed to invite member due to SAML SSO configured for organization"
});
}
if (plan.memberLimit !== null) {
// case: limit imposed on number of members allowed
if (plan.membersUsed >= plan.memberLimit) {
// case: number of members used exceeds the number of members allowed
return res.status(400).send({
message:
"Failed to invite member due to member limit reached. Upgrade plan to invite more members."
});
}
}
const invitee = await User.findOne({
email: inviteeEmail
}).select("+publicKey");
if (invitee) {
// case: invitee is an existing user
inviteeMembershipOrg = await MembershipOrg.findOne({
user: invitee._id,
organization: organizationId
});
if (inviteeMembershipOrg && inviteeMembershipOrg.status === ACCEPTED) {
throw new Error("Failed to invite an existing member of the organization");
}
if (!inviteeMembershipOrg) {
await new MembershipOrg({
user: invitee,
inviteEmail: inviteeEmail,
organization: organizationId,
role: MEMBER,
status: INVITED
}).save();
}
} else {
// check if invitee has been invited before
inviteeMembershipOrg = await MembershipOrg.findOne({
inviteEmail: inviteeEmail,
organization: organizationId
});
if (!inviteeMembershipOrg) {
// case: invitee has never been invited before
// validate that email is not disposable
validateUserEmail(inviteeEmail);
await new MembershipOrg({
inviteEmail: inviteeEmail,
organization: organizationId,
role: MEMBER,
status: INVITED
}).save();
}
}
const organization = await Organization.findOne({ _id: organizationId });
if (organization) {
const token = await TokenService.createToken({
type: TOKEN_EMAIL_ORG_INVITATION,
email: inviteeEmail,
organizationId: organization._id
});
await sendMail({
template: "organizationInvitation.handlebars",
subjectLine: "Infisical organization invitation",
recipients: [inviteeEmail],
substitutions: {
inviterFirstName: req.user.firstName,
inviterEmail: req.user.email,
organizationName: organization.name,
email: inviteeEmail,
organizationId: organization._id.toString(),
token,
callback_url: (await getSiteURL()) + "/signupinvite"
}
});
if (!(await getSmtpConfigured())) {
completeInviteLink = `${
siteUrl + "/signupinvite"
}?token=${token}&to=${inviteeEmail}&organization_id=${organization._id}`;
}
}
await updateSubscriptionOrgQuantity({ organizationId });
return res.status(200).send({
message: `Sent an invite link to ${req.body.inviteeEmail}`,
completeInviteLink
});
};
/**
* Organization invitation step 2: Verify that code [code] was sent to email [email] as part of
* magic link and issue a temporary signup token for user to complete setting up their account
* @param req
* @param res
* @returns
*/
export const verifyUserToOrganization = async (req: Request, res: Response) => {
let user;
const {
body: { organizationId, email, code }
} = await validateRequest(reqValidator.VerifyUserToOrgv1, req);
user = await User.findOne({ email }).select("+publicKey");
const membershipOrg = await MembershipOrg.findOne({
inviteEmail: email,
status: INVITED,
organization: new Types.ObjectId(organizationId)
});
if (!membershipOrg) throw new Error("Failed to find any invitations for email");
await TokenService.validateToken({
type: TOKEN_EMAIL_ORG_INVITATION,
email,
organizationId: membershipOrg.organization,
token: code
});
if (user && user?.publicKey) {
// case: user has already completed account
// membership can be approved and redirected to login/dashboard
membershipOrg.status = ACCEPTED;
await membershipOrg.save();
await updateSubscriptionOrgQuantity({
organizationId
});
return res.status(200).send({
message: "Successfully verified email",
user
});
}
if (!user) {
// initialize user account
user = await new User({
email
}).save();
}
// generate temporary signup token
const token = createToken({
payload: {
authTokenType: AuthTokenType.SIGNUP_TOKEN,
userId: user._id.toString()
},
expiresIn: await getJwtSignupLifetime(),
secret: await getAuthSecret()
});
return res.status(200).send({
message: "Successfully verified email",
user,
token
});
};

View File

@@ -0,0 +1,387 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import {
IncidentContactOrg,
Membership,
MembershipOrg,
Organization,
Workspace
} from "../../models";
import { getLicenseServerUrl, getSiteURL } from "../../config";
import { licenseServerKeyRequest } from "../../config/request";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/organization";
import { ACCEPTED } from "../../variables";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { OrganizationNotFoundError } from "../../utils/errors";
import { ForbiddenError } from "@casl/ability";
export const getOrganizations = async (req: Request, res: Response) => {
const organizations = (
await MembershipOrg.find({
user: req.user._id,
status: ACCEPTED
}).populate("organization")
).map((m) => m.organization);
return res.status(200).send({
organizations
});
};
/**
* Return organization with id [organizationId]
* @param req
* @param res
* @returns
*/
export const getOrganization = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgv1, req);
// ensure user has membership
await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
})
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
return res.status(200).send({
organization
});
};
/**
* Return organization memberships for organization with id [organizationId]
* @param req
* @param res
* @returns
*/
export const getOrganizationMembers = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgMembersv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Member
);
const users = await MembershipOrg.find({
organization: organizationId
}).populate("user", "+publicKey");
return res.status(200).send({
users
});
};
/**
* Return workspaces that user is part of in organization with id [organizationId]
* @param req
* @param res
* @returns
*/
export const getOrganizationWorkspaces = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgWorkspacesv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
})
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Workspace
);
const workspacesSet = new Set(
(
await Workspace.find(
{
organization: organizationId
},
"_id"
)
).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);
return res.status(200).send({
workspaces
});
};
/**
* Change name of organization with id [organizationId] to [name]
* @param req
* @param res
* @returns
*/
export const changeOrganizationName = async (req: Request, res: Response) => {
const {
params: { organizationId },
body: { name }
} = await validateRequest(reqValidator.ChangeOrgNamev1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Settings
);
const organization = await Organization.findOneAndUpdate(
{
_id: organizationId
},
{
name
},
{
new: true
}
);
return res.status(200).send({
message: "Successfully changed organization name",
organization
});
};
/**
* Return incident contacts of organization with id [organizationId]
* @param req
* @param res
* @returns
*/
export const getOrganizationIncidentContacts = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgIncidentContactv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.IncidentAccount
);
const incidentContactsOrg = await IncidentContactOrg.find({
organization: organizationId
});
return res.status(200).send({
incidentContactsOrg
});
};
/**
* Add and return new incident contact with email [email] for organization with id [organizationId]
* @param req
* @param res
* @returns
*/
export const addOrganizationIncidentContact = async (req: Request, res: Response) => {
const {
params: { organizationId },
body: { email }
} = await validateRequest(reqValidator.CreateOrgIncideContact, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.IncidentAccount
);
const incidentContactOrg = await IncidentContactOrg.findOneAndUpdate(
{ email, organization: organizationId },
{ email, organization: organizationId },
{ upsert: true, new: true }
);
return res.status(200).send({
incidentContactOrg
});
};
/**
* Delete incident contact with email [email] for organization with id [organizationId]
* @param req
* @param res
* @returns
*/
export const deleteOrganizationIncidentContact = async (req: Request, res: Response) => {
const {
params: { organizationId },
body: { email }
} = await validateRequest(reqValidator.DelOrgIncideContact, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.IncidentAccount
);
const incidentContactOrg = await IncidentContactOrg.findOneAndDelete({
email,
organization: organizationId
});
return res.status(200).send({
message: "Successfully deleted organization incident contact",
incidentContactOrg
});
};
/**
* Redirect user to billing portal or add card page depending on
* if there is a card on file
* @param req
* @param res
* @returns
*/
export const createOrganizationPortalSession = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlanBillingInfov1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const {
data: { pmtMethods }
} = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/payment-methods`
);
if (pmtMethods.length < 1) {
// case: organization has no payment method on file
// -> redirect to add payment method portal
const {
data: { url }
} = await licenseServerKeyRequest.post(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/payment-methods`,
{
success_url: (await getSiteURL()) + "/dashboard",
cancel_url: (await getSiteURL()) + "/dashboard"
}
);
return res.status(200).send({ url });
} else {
// case: organization has payment method on file
// -> redirect to billing portal
const {
data: { url }
} = await licenseServerKeyRequest.post(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/billing-portal`,
{
return_url: (await getSiteURL()) + "/dashboard"
}
);
return res.status(200).send({ url });
}
};
/**
* Given a org id, return the projects each member of the org belongs to
* @param req
* @param res
* @returns
*/
export const getOrganizationMembersAndTheirWorkspaces = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgMembersv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Member
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Workspace
);
const workspacesSet = (
await Workspace.find(
{
organization: organizationId
},
"_id"
)
).map((w) => w._id.toString());
const memberships = await Membership.find({
workspace: { $in: workspacesSet }
}).populate("workspace");
const userToWorkspaceIds: any = {};
memberships.forEach((membership) => {
const user = membership.user.toString();
if (userToWorkspaceIds[user]) {
userToWorkspaceIds[user].push(membership.workspace);
} else {
userToWorkspaceIds[user] = [membership.workspace];
}
});
return res.json(userToWorkspaceIds);
};

View File

@@ -0,0 +1,370 @@
import { Request, Response } from "express";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const jsrp = require("jsrp");
import * as bigintConversion from "bigint-conversion";
import { BackupPrivateKey, LoginSRPDetail, User } from "../../models";
import { clearTokens, createToken, sendMail } from "../../helpers";
import { TokenService } from "../../services";
import { AuthTokenType, TOKEN_EMAIL_PASSWORD_RESET } from "../../variables";
import { BadRequestError } from "../../utils/errors";
import {
getAuthSecret,
getHttpsEnabled,
getJwtSignupLifetime,
getSiteURL
} from "../../config";
import { ActorType } from "../../ee/models";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/auth";
/**
* Password reset step 1: Send email verification link to email [email]
* for account recovery.
* @param req
* @param res
* @returns
*/
export const emailPasswordReset = async (req: Request, res: Response) => {
const {
body: { email }
} = await validateRequest(reqValidator.EmailPasswordResetV1, req);
const user = await User.findOne({ email }).select("+publicKey");
if (!user || !user?.publicKey) {
// case: user has already completed account
return res.status(200).send({
message: "If an account exists with this email, a password reset link has been sent"
});
}
const token = await TokenService.createToken({
type: TOKEN_EMAIL_PASSWORD_RESET,
email
});
await sendMail({
template: "passwordReset.handlebars",
subjectLine: "Infisical password reset",
recipients: [email],
substitutions: {
email,
token,
callback_url: (await getSiteURL()) + "/password-reset"
}
});
return res.status(200).send({
message: "If an account exists with this email, a password reset link has been sent"
});
};
/**
* Password reset step 2: Verify email verification link sent to email [email]
* @param req
* @param res
* @returns
*/
export const emailPasswordResetVerify = async (req: Request, res: Response) => {
const {
body: { email, code }
} = await validateRequest(reqValidator.EmailPasswordResetVerifyV1, req);
const user = await User.findOne({ email }).select("+publicKey");
if (!user || !user?.publicKey) {
// case: user doesn't exist with email [email] or
// hasn't even completed their account
return res.status(403).send({
error: "Failed email verification for password reset"
});
}
await TokenService.validateToken({
type: TOKEN_EMAIL_PASSWORD_RESET,
email,
token: code
});
// generate temporary password-reset token
const token = createToken({
payload: {
authTokenType: AuthTokenType.SIGNUP_TOKEN,
userId: user._id.toString()
},
expiresIn: await getJwtSignupLifetime(),
secret: await getAuthSecret()
});
return res.status(200).send({
message: "Successfully verified email",
user,
token
});
};
/**
* Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol
* @param req
* @param res
* @returns
*/
export const srp1 = async (req: Request, res: Response) => {
// return salt, serverPublicKey as part of first step of SRP protocol
const {
body: { clientPublicKey }
} = await validateRequest(reqValidator.Srp1V1, req);
const user = await User.findOne({
email: req.user.email
}).select("+salt +verifier");
if (!user) throw new Error("Failed to find user");
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier
},
async () => {
// generate server-side public key
const serverPublicKey = server.getPublicKey();
await LoginSRPDetail.findOneAndReplace(
{ email: req.user.email },
{
email: req.user.email,
clientPublicKey: clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt)
},
{ upsert: true, returnNewDocument: false }
);
return res.status(200).send({
serverPublicKey,
salt: user.salt
});
}
);
};
/**
* Change account SRP authentication information for user
* Requires verifying [clientProof] as part of step 2 of SRP protocol
* as initiated in POST /srp1
* @param req
* @param res
* @returns
*/
export const changePassword = async (req: Request, res: Response) => {
const {
body: {
clientProof,
protectedKey,
protectedKeyIV,
protectedKeyTag,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt,
verifier
}
} = await validateRequest(reqValidator.ChangePasswordV1, req);
const user = await User.findOne({
email: req.user.email
}).select("+salt +verifier");
if (!user) throw new Error("Failed to find user");
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email });
if (!loginSRPDetailFromDB) {
return BadRequestError(
Error(
"It looks like some details from the first login are not found. Please try login one again"
)
);
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier,
b: loginSRPDetailFromDB.serverBInt
},
async () => {
server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey);
// compare server and client shared keys
if (server.checkClientProof(clientProof)) {
// change password
await User.findByIdAndUpdate(
req.user._id.toString(),
{
encryptionVersion: 2,
protectedKey,
protectedKeyIV,
protectedKeyTag,
encryptedPrivateKey,
iv: encryptedPrivateKeyIV,
tag: encryptedPrivateKeyTag,
salt,
verifier
},
{
new: true
}
);
if (req.authData.actor.type === ActorType.USER && req.authData.tokenVersionId) {
await clearTokens(req.authData.tokenVersionId);
}
// clear httpOnly cookie
res.cookie("jid", "", {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: (await getHttpsEnabled()) as boolean
});
return res.status(200).send({
message: "Successfully changed password"
});
}
return res.status(400).send({
error: "Failed to change password. Try again?"
});
}
);
};
/**
* Create or change backup private key for user
* @param req
* @param res
* @returns
*/
export const createBackupPrivateKey = async (req: Request, res: Response) => {
// create/change backup private key
// requires verifying [clientProof] as part of second step of SRP protocol
// as initiated in /srp1
const {
body: { clientProof, encryptedPrivateKey, salt, verifier, iv, tag }
} = await validateRequest(reqValidator.CreateBackupPrivateKeyV1, req);
const user = await User.findOne({
email: req.user.email
}).select("+salt +verifier");
if (!user) throw new Error("Failed to find user");
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email });
if (!loginSRPDetailFromDB) {
return BadRequestError(
Error(
"It looks like some details from the first login are not found. Please try login one again"
)
);
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier,
b: loginSRPDetailFromDB.serverBInt
},
async () => {
server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey);
// compare server and client shared keys
if (server.checkClientProof(clientProof)) {
// create new or replace backup private key
const backupPrivateKey = await BackupPrivateKey.findOneAndUpdate(
{ user: req.user._id },
{
user: req.user._id,
encryptedPrivateKey,
iv,
tag,
salt,
verifier
},
{ upsert: true, new: true }
).select("+user, encryptedPrivateKey");
// issue tokens
return res.status(200).send({
message: "Successfully updated backup private key",
backupPrivateKey
});
}
return res.status(400).send({
message: "Failed to update backup private key"
});
}
);
};
/**
* Return backup private key for user
* @param req
* @param res
* @returns
*/
export const getBackupPrivateKey = async (req: Request, res: Response) => {
const backupPrivateKey = await BackupPrivateKey.findOne({
user: req.user._id
}).select("+encryptedPrivateKey +iv +tag");
if (!backupPrivateKey) throw new Error("Failed to find backup private key");
return res.status(200).send({
backupPrivateKey
});
};
export const resetPassword = async (req: Request, res: Response) => {
const {
body: {
encryptedPrivateKey,
protectedKeyTag,
protectedKey,
protectedKeyIV,
salt,
verifier,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag
}
} = await validateRequest(reqValidator.ResetPasswordV1, req);
await User.findByIdAndUpdate(
req.user._id.toString(),
{
encryptionVersion: 2,
protectedKey,
protectedKeyIV,
protectedKeyTag,
encryptedPrivateKey,
iv: encryptedPrivateKeyIV,
tag: encryptedPrivateKeyTag,
salt,
verifier
},
{
new: true
}
);
return res.status(200).send({
message: "Successfully reset password"
});
};

View File

@@ -0,0 +1,209 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { Key } from "../../models";
import {
pullSecrets as pull,
v1PushSecrets as push,
reformatPullSecrets
} from "../../helpers/secret";
import { pushKeys } from "../../helpers/key";
import { eventPushSecrets } from "../../events";
import { EventService } from "../../services";
import { TelemetryService } from "../../services";
interface PushSecret {
ciphertextKey: string;
ivKey: string;
tagKey: string;
hashKey: string;
ciphertextValue: string;
ivValue: string;
tagValue: string;
hashValue: string;
ciphertextComment: string;
ivComment: string;
tagComment: string;
hashComment: string;
type: "shared" | "personal";
}
/**
* Upload (encrypted) secrets to workspace with id [workspaceId]
* for environment [environment]
* @param req
* @param res
* @returns
*/
export const pushSecrets = async (req: Request, res: Response) => {
// upload (encrypted) secrets to workspace with id [workspaceId]
const postHogClient = await TelemetryService.getPostHogClient();
let { secrets }: { secrets: PushSecret[] } = 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: PushSecret) => s.ciphertextKey !== "" && s.ciphertextValue !== "");
await push({
userId: req.user._id,
workspaceId,
environment,
secrets
});
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] and (encrypted) workspace key
* @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;
// 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: req.user._id.toString(),
workspaceId,
environment,
channel: channel ? channel : "cli",
ipAddress: req.realIP
});
const key = await Key.findOne({
workspace: workspaceId,
receiver: req.user._id
})
.sort({ createdAt: -1 })
.populate("sender", "+publicKey");
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,
key
});
};
/**
* Return (encrypted) secrets for workspace with id [workspaceId]
* for environment [environment] and (encrypted) workspace key
* via service token
* @param req
* @param res
* @returns
*/
export const pullSecretsServiceToken = async (req: Request, res: Response) => {
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;
// validate environment
const workspaceEnvs = req.membership.workspace.environments;
if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) {
throw new Error("Failed to validate environment");
}
const secrets = await pull({
userId: req.serviceToken.user._id.toString(),
workspaceId,
environment,
channel: "cli",
ipAddress: req.realIP
});
const key = {
encryptedKey: req.serviceToken.encryptedKey,
nonce: req.serviceToken.nonce,
sender: {
publicKey: req.serviceToken.publicKey
},
receiver: req.serviceToken.user,
workspace: req.serviceToken.workspace
};
if (postHogClient) {
// capture secrets pulled event in production
postHogClient.capture({
distinctId: req.serviceToken.user.email,
event: "secrets pulled",
properties: {
numberOfSecrets: secrets.length,
environment,
workspaceId,
channel: channel ? channel : "cli"
}
});
}
return res.status(200).send({
secrets: reformatPullSecrets({ secrets }),
key
});
};

View File

@@ -0,0 +1,734 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { isValidScope } from "../../helpers";
import { Folder, IServiceTokenData, SecretImport, ServiceTokenData } from "../../models";
import { getAllImportedSecrets } from "../../services/SecretImportService";
import { getFolderByPath, getFolderWithPathFromId } from "../../services/FolderService";
import {
BadRequestError,
ResourceNotFoundError,
UnauthorizedRequestError
} from "../../utils/errors";
import { EEAuditLogService } from "../../ee/services";
import { EventType } from "../../ee/models";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/secretImports";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError, subject } from "@casl/ability";
export const createSecretImp = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Create secret import'
#swagger.description = 'Create secret import'
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"workspaceId": {
"type": "string",
"description": "ID of workspace where to create secret import",
"example": "someWorkspaceId"
},
"environment": {
"type": "string",
"description": "Slug of environment where to create secret import",
"example": "dev"
},
"directory": {
"type": "string",
"description": "Path where to create secret import like / or /foo/bar. Default is /",
"example": "/foo/bar"
},
"secretImport": {
"type": "object",
"properties": {
"environment": {
"type": "string",
"description": "Slug of environment to import from",
"example": "development"
},
"secretPath": {
"type": "string",
"description": "Path where to import from like / or /foo/bar.",
"example": "/user/oauth"
}
}
}
},
"required": ["workspaceId", "environment", "directory", "secretImport"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "successfully created secret import"
}
},
"description": "Confirmation of secret import creation"
}
}
}
}
#swagger.responses[400] = {
description: "Bad Request. For example, 'Secret import already exist'"
}
#swagger.responses[401] = {
description: "Unauthorized request. For example, 'Folder Permission Denied'"
}
#swagger.responses[404] = {
description: "Resource Not Found. For example, 'Failed to find folder'"
}
*/
const {
body: { workspaceId, environment, directory, secretImport }
} = await validateRequest(reqValidator.CreateSecretImportV1, req);
if (req.authData.authPayload instanceof ServiceTokenData) {
// root check
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
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({
workspace: workspaceId,
environment
}).lean();
if (!folders && directory !== "/")
throw ResourceNotFoundError({ message: "Failed to find folder" });
let folderId = "root";
if (folders) {
const folder = getFolderByPath(folders.nodes, directory);
if (!folder) throw BadRequestError({ message: "Folder not found" });
folderId = folder.id;
}
const importSecDoc = await SecretImport.findOne({
workspace: workspaceId,
environment,
folderId
});
if (!importSecDoc) {
const doc = new SecretImport({
workspace: workspaceId,
environment,
folderId,
imports: [{ environment: secretImport.environment, secretPath: secretImport.secretPath }]
});
await doc.save();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_SECRET_IMPORT,
metadata: {
secretImportId: doc._id.toString(),
folderId: doc.folderId.toString(),
importFromEnvironment: secretImport.environment,
importFromSecretPath: secretImport.secretPath,
importToEnvironment: environment,
importToSecretPath: directory
}
},
{
workspaceId: doc.workspace
}
);
return res.status(200).json({ message: "successfully created secret import" });
}
const doesImportExist = importSecDoc.imports.find(
(el) => el.environment === secretImport.environment && el.secretPath === secretImport.secretPath
);
if (doesImportExist) {
throw BadRequestError({ message: "Secret import already exist" });
}
importSecDoc.imports.push({
environment: secretImport.environment,
secretPath: secretImport.secretPath
});
await importSecDoc.save();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_SECRET_IMPORT,
metadata: {
secretImportId: importSecDoc._id.toString(),
folderId: importSecDoc.folderId.toString(),
importFromEnvironment: secretImport.environment,
importFromSecretPath: secretImport.secretPath,
importToEnvironment: environment,
importToSecretPath: directory
}
},
{
workspaceId: importSecDoc.workspace
}
);
return res.status(200).json({ message: "successfully created secret import" });
};
// to keep the ordering, you must pass all the imports in here not the only updated one
// this is because the order decide which import gets overriden
/**
* Update secret import
* @param req
* @param res
* @returns
*/
export const updateSecretImport = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Update secret import'
#swagger.description = 'Update secret import'
#swagger.parameters['id'] = {
in: 'path',
description: 'ID of secret import to update',
required: true,
type: 'string',
example: 'import12345'
}
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"secretImports": {
"type": "array",
"description": "List of secret imports to update to",
"items": {
"type": "object",
"properties": {
"environment": {
"type": "string",
"description": "Slug of environment to import from",
"example": "dev"
},
"secretPath": {
"type": "string",
"description": "Path where to import secrets from like / or /foo/bar",
"example": "/foo/bar"
}
},
"required": ["environment", "secretPath"]
}
}
},
"required": ["secretImports"]
}
}
}
}
#swagger.responses[200] = {
description: 'Successfully updated the secret import',
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "successfully updated secret import"
}
}
}
}
}
}
#swagger.responses[400] = {
description: 'Bad Request - Import not found',
}
#swagger.responses[403] = {
description: 'Forbidden access due to insufficient permissions',
}
#swagger.responses[401] = {
description: 'Unauthorized access due to invalid token or scope',
}
*/
const {
body: { secretImports },
params: { id }
} = await validateRequest(reqValidator.UpdateSecretImportV1, req);
const importSecDoc = await SecretImport.findById(id);
if (!importSecDoc) {
throw BadRequestError({ message: "Import not found" });
}
// check for service token validity
const folders = await Folder.findOne({
workspace: importSecDoc.workspace,
environment: importSecDoc.environment
}).lean();
let secretPath = "/";
if (folders) {
const { folderPath } = getFolderWithPathFromId(folders.nodes, importSecDoc.folderId);
secretPath = folderPath;
}
if (req.authData.authPayload instanceof ServiceTokenData) {
// token permission check
const isValidScopeAccess = isValidScope(
req.authData.authPayload,
importSecDoc.environment,
secretPath
);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
// non token entry check
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, {
environment: importSecDoc.environment,
secretPath
})
);
secretImports.forEach(({ environment, secretPath }) => {
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
);
})
}
const orderBefore = importSecDoc.imports;
importSecDoc.imports = secretImports;
await importSecDoc.save();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.UPDATE_SECRET_IMPORT,
metadata: {
importToEnvironment: importSecDoc.environment,
importToSecretPath: secretPath,
secretImportId: importSecDoc._id.toString(),
folderId: importSecDoc.folderId.toString(),
orderBefore,
orderAfter: secretImports
}
},
{
workspaceId: importSecDoc.workspace
}
);
return res.status(200).json({ message: "successfully updated secret import" });
};
/**
* Delete secret import
* @param req
* @param res
* @returns
*/
export const deleteSecretImport = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Delete secret import'
#swagger.description = 'Delete secret import'
#swagger.parameters['id'] = {
in: 'path',
description: 'ID of parent secret import document from which to delete secret import',
required: true,
type: 'string',
example: '12345abcde'
}
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"secretImportEnv": {
"type": "string",
"description": "Slug of environment of import to delete",
"example": "someWorkspaceId"
},
"secretImportPath": {
"type": "string",
"description": "Path like / or /foo/bar of import to delete",
"example": "production"
}
},
"required": ["id", "secretImportEnv", "secretImportPath"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"example": "successfully delete secret import"
}
},
"description": "Confirmation of secret import deletion"
}
}
}
}
*/
const {
params: { id },
body: { secretImportEnv, secretImportPath }
} = await validateRequest(reqValidator.DeleteSecretImportV1, req);
const importSecDoc = await SecretImport.findById(id);
if (!importSecDoc) {
throw BadRequestError({ message: "Import not found" });
}
// check for service token validity
const folders = await Folder.findOne({
workspace: importSecDoc.workspace,
environment: importSecDoc.environment
}).lean();
let secretPath = "/";
if (folders) {
const { folderPath } = getFolderWithPathFromId(folders.nodes, importSecDoc.folderId);
secretPath = folderPath;
}
if (req.authData.authPayload instanceof ServiceTokenData) {
const isValidScopeAccess = isValidScope(
req.authData.authPayload,
importSecDoc.environment,
secretPath
);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, {
environment: importSecDoc.environment,
secretPath
})
);
}
importSecDoc.imports = importSecDoc.imports.filter(
({ environment, secretPath }) =>
!(environment === secretImportEnv && secretPath === secretImportPath)
);
await importSecDoc.save();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.DELETE_SECRET_IMPORT,
metadata: {
secretImportId: importSecDoc._id.toString(),
folderId: importSecDoc.folderId.toString(),
importFromEnvironment: secretImportEnv,
importFromSecretPath: secretImportPath,
importToEnvironment: importSecDoc.environment,
importToSecretPath: secretPath
}
},
{
workspaceId: importSecDoc.workspace
}
);
return res.status(200).json({ message: "successfully delete secret import" });
};
/**
* Get secret imports
* @param req
* @param res
* @returns
*/
export const getSecretImports = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Get secret imports'
#swagger.description = 'Get secret imports'
#swagger.parameters['workspaceId'] = {
in: 'query',
description: 'ID of workspace where to get secret imports from',
required: true,
type: 'string',
example: 'workspace12345'
}
#swagger.parameters['environment'] = {
in: 'query',
description: 'Slug of environment where to get secret imports from',
required: true,
type: 'string',
example: 'production'
}
#swagger.parameters['directory'] = {
in: 'query',
description: 'Path where to get secret imports from like / or /foo/bar. Default is /',
required: false,
type: 'string',
example: 'folder12345'
}
#swagger.responses[200] = {
description: 'Successfully retrieved secret import',
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"secretImport": {
$ref: '#/definitions/SecretImport'
}
}
}
}
}
}
#swagger.responses[403] = {
description: 'Forbidden access due to insufficient permissions',
}
#swagger.responses[401] = {
description: 'Unauthorized access due to invalid token or scope',
}
*/
const {
query: { workspaceId, environment, directory }
} = await validateRequest(reqValidator.GetSecretImportsV1, req);
if (req.authData.authPayload instanceof ServiceTokenData) {
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
environment,
secretPath: directory
})
);
}
const folders = await Folder.findOne({
workspace: workspaceId,
environment
}).lean();
if (!folders && directory !== "/") throw BadRequestError({ message: "Folder not found" });
let folderId = "root";
if (folders) {
const folder = getFolderByPath(folders.nodes, directory);
if (!folder) throw BadRequestError({ message: "Folder not found" });
folderId = folder.id;
}
const importSecDoc = await SecretImport.findOne({
workspace: workspaceId,
environment,
folderId
});
if (!importSecDoc) {
return res.status(200).json({ secretImport: {} });
}
return res.status(200).json({ secretImport: importSecDoc });
};
/**
* Get all secret imports
* @param req
* @param res
* @returns
*/
export const getAllSecretsFromImport = async (req: Request, res: Response) => {
const {
query: { workspaceId, environment, directory }
} = await validateRequest(reqValidator.GetAllSecretsFromImportV1, req);
if (req.authData.authPayload instanceof ServiceTokenData) {
// check for service token validity
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
environment,
secretPath: directory
})
);
}
const folders = await Folder.findOne({
workspace: workspaceId,
environment
}).lean();
if (!folders && directory !== "/") throw BadRequestError({ message: "Folder not found" });
let folderId = "root";
if (folders) {
const folder = getFolderByPath(folders.nodes, directory);
if (!folder) throw BadRequestError({ message: "Folder not found" });
folderId = folder.id;
}
const importSecDoc = await SecretImport.findOne({
workspace: workspaceId,
environment,
folderId
});
if (!importSecDoc) {
return res.status(200).json({ secrets: [] });
}
let secretPath = "/";
if (folders) {
const { folderPath } = getFolderWithPathFromId(folders.nodes, importSecDoc.folderId);
secretPath = folderPath;
}
let permissionCheckFn: (env: string, secPath: string) => boolean; // used to pass as callback function to import secret
if (req.authData.authPayload instanceof ServiceTokenData) {
// check for service token validity
const isValidScopeAccess = isValidScope(
req.authData.authPayload,
importSecDoc.environment,
secretPath
);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
permissionCheckFn = (env: string, secPath: string) =>
isValidScope(req.authData.authPayload as IServiceTokenData, env, secPath);
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: importSecDoc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
environment: importSecDoc.environment,
secretPath
})
);
permissionCheckFn = (env: string, secPath: string) =>
permission.can(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, {
environment: env,
secretPath: secPath
})
);
}
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.GET_SECRET_IMPORTS,
metadata: {
environment,
secretImportId: importSecDoc._id.toString(),
folderId,
numberOfImports: importSecDoc.imports.length
}
},
{
workspaceId: importSecDoc.workspace
}
);
const secrets = await getAllImportedSecrets(
workspaceId,
environment,
folderId,
permissionCheckFn
);
return res.status(200).json({ secrets });
};

View File

@@ -0,0 +1,193 @@
import { Request, Response } from "express";
import {
GitAppInstallationSession,
GitAppOrganizationInstallation,
GitRisks
} from "../../ee/models";
import crypto from "crypto";
import { Types } from "mongoose";
import { OrganizationNotFoundError, UnauthorizedRequestError } from "../../utils/errors";
import { scanGithubFullRepoForSecretLeaks } from "../../queues/secret-scanning/githubScanFullRepository";
import { getSecretScanningGitAppId, getSecretScanningPrivateKey } from "../../config";
import {
STATUS_RESOLVED_FALSE_POSITIVE,
STATUS_RESOLVED_NOT_REVOKED,
STATUS_RESOLVED_REVOKED
} from "../../ee/models/gitRisks";
import { ProbotOctokit } from "probot";
import { Organization } from "../../models";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/secretScanning";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { ForbiddenError } from "@casl/ability";
export const createInstallationSession = async (req: Request, res: Response) => {
const sessionId = crypto.randomBytes(16).toString("hex");
const {
params: { organizationId }
} = await validateRequest(reqValidator.CreateInstalLSessionv1, req);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.SecretScanning
);
await GitAppInstallationSession.findByIdAndUpdate(
organization,
{
organization: organization.id,
sessionId: sessionId,
user: new Types.ObjectId(req.user._id)
},
{ upsert: true }
).lean();
res.send({
sessionId: sessionId
});
};
export const linkInstallationToOrganization = async (req: Request, res: Response) => {
const {
body: { sessionId, installationId }
} = await validateRequest(reqValidator.LinkInstallationToOrgv1, req);
const installationSession = await GitAppInstallationSession.findOneAndDelete({
sessionId: sessionId
});
if (!installationSession) {
throw UnauthorizedRequestError();
}
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: installationSession.organization
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.SecretScanning
);
const installationLink = await GitAppOrganizationInstallation.findOneAndUpdate(
{
organizationId: installationSession.organization
},
{
installationId: installationId,
organizationId: installationSession.organization,
user: installationSession.user
},
{
upsert: true
}
).lean();
const octokit = new ProbotOctokit({
auth: {
appId: await getSecretScanningGitAppId(),
privateKey: await getSecretScanningPrivateKey(),
installationId: installationId.toString()
}
});
const {
data: { repositories }
} = await octokit.apps.listReposAccessibleToInstallation();
for (const repository of repositories) {
scanGithubFullRepoForSecretLeaks({
organizationId: installationSession.organization.toString(),
installationId,
repository: { id: repository.id, fullName: repository.full_name }
});
}
res.json(installationLink);
};
export const getCurrentOrganizationInstallationStatus = async (req: Request, res: Response) => {
const { organizationId } = req.params;
try {
const appInstallation = await GitAppOrganizationInstallation.findOne({
organizationId: organizationId
}).lean();
if (!appInstallation) {
res.json({
appInstallationComplete: false
});
}
res.json({
appInstallationComplete: true
});
} catch {
res.json({
appInstallationComplete: false
});
}
};
export const getRisksForOrganization = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgRisksv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.SecretScanning
);
const risks = await GitRisks.find({ organization: organizationId })
.sort({ createdAt: -1 })
.lean();
res.json({
risks: risks
});
};
export const updateRisksStatus = async (req: Request, res: Response) => {
const {
params: { organizationId, riskId },
body: { status }
} = await validateRequest(reqValidator.UpdateRiskStatusv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.SecretScanning
);
const isRiskResolved =
status == STATUS_RESOLVED_FALSE_POSITIVE ||
status == STATUS_RESOLVED_REVOKED ||
status == STATUS_RESOLVED_NOT_REVOKED
? true
: false;
const risk = await GitRisks.findByIdAndUpdate(riskId, {
status: status,
isResolved: isRiskResolved
}).lean();
res.json(risk);
};

View File

@@ -0,0 +1,680 @@
import { ForbiddenError, subject } from "@casl/ability";
import { Request, Response } from "express";
import { Types } from "mongoose";
import { EventType, FolderVersion } from "../../ee/models";
import { EEAuditLogService, EESecretService } from "../../ee/services";
import { isValidScope } from "../../helpers/secrets";
import { validateRequest } from "../../helpers/validation";
import { Secret, ServiceTokenData } from "../../models";
import { Folder } from "../../models/folder";
import {
appendFolder,
getAllFolderIds,
getFolderByPath,
getFolderWithPathFromId,
validateFolderName
} from "../../services/FolderService";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
import * as reqValidator from "../../validation/folders";
const ERR_FOLDER_NOT_FOUND = BadRequestError({ message: "The folder doesn't exist" });
// verify workspace id/environment
export const createFolder = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Create folder'
#swagger.description = 'Create folder'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"workspaceId": {
"type": "string",
"description": "ID of the workspace where to create folder",
"example": "someWorkspaceId"
},
"environment": {
"type": "string",
"description": "Slug of environment where to create folder",
"example": "production"
},
"folderName": {
"type": "string",
"description": "Name of folder to create",
"example": "my_folder"
},
"directory": {
"type": "string",
"description": "Path where to create folder like / or /foo/bar. Default is /",
"example": "/foo/bar"
}
},
"required": ["workspaceId", "environment", "folderName"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"folder": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "ID of folder",
"example": "someFolderId"
},
"name": {
"type": "string",
"description": "Name of folder",
"example": "my_folder"
},
"version": {
"type": "number",
"description": "Version of folder",
"example": 1
}
},
"description": "Details of created folder"
}
}
}
}
}
}
#swagger.responses[400] = {
description: "Bad Request. For example, 'Folder name cannot contain spaces. Only underscore and dashes'"
}
#swagger.responses[401] = {
description: "Unauthorized request. For example, 'Folder Permission Denied'"
}
*/
const {
body: { workspaceId, environment, folderName, directory }
} = await validateRequest(reqValidator.CreateFolderV1, req);
if (!validateFolderName(folderName)) {
throw BadRequestError({
message: "Folder name cannot contain spaces. Only underscore and dashes"
});
}
if (req.authData.authPayload instanceof ServiceTokenData) {
// token check
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
// user check
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
);
}
const folders = await Folder.findOne({
workspace: workspaceId,
environment
}).lean();
// space has no folders initialized
if (!folders) {
const folder = new Folder({
workspace: workspaceId,
environment,
nodes: {
id: "root",
name: "root",
version: 1,
children: []
}
});
const { parent, child } = appendFolder(folder.nodes, { folderName, directory });
await folder.save();
const folderVersion = new FolderVersion({
workspace: workspaceId,
environment,
nodes: parent
});
await folderVersion.save();
await EESecretService.takeSecretSnapshot({
workspaceId: new Types.ObjectId(workspaceId),
environment
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_FOLDER,
metadata: {
environment,
folderId: child.id,
folderName,
folderPath: directory
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.json({ folder: { id: child.id, name: folderName } });
}
const { parent, child, hasCreated } = appendFolder(folders.nodes, { folderName, directory });
if (!hasCreated) return res.json({ folder: child });
await Folder.findByIdAndUpdate(folders._id, folders);
const folderVersion = new FolderVersion({
workspace: workspaceId,
environment,
nodes: parent
});
await folderVersion.save();
await EESecretService.takeSecretSnapshot({
workspaceId: new Types.ObjectId(workspaceId),
environment,
folderId: child.id
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_FOLDER,
metadata: {
environment,
folderId: child.id,
folderName,
folderPath: directory
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.json({ folder: child });
};
/**
* Update folder with id [folderId]
* @param req
* @param res
* @returns
*/
export const updateFolderById = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Update folder'
#swagger.description = 'Update folder'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['folderName'] = {
"description": "Name of folder to update",
"required": true,
"type": "string"
}
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"workspaceId": {
"type": "string",
"description": "ID of workspace where to update folder",
"example": "someWorkspaceId"
},
"environment": {
"type": "string",
"description": "Slug of environment where to update folder",
"example": "production"
},
"name": {
"type": "string",
"description": "Name of folder to update to",
"example": "updated_folder_name"
},
"directory": {
"type": "string",
"description": "Path where to update folder like / or /foo/bar. Default is /",
"example": "/foo/bar"
}
},
"required": ["workspaceId", "environment", "name"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Success message",
"example": "Successfully updated folder"
},
"folder": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of updated folder",
"example": "updated_folder_name"
},
"id": {
"type": "string",
"description": "ID of created folder",
"example": "abc123"
}
},
"description": "Details of the updated folder"
}
}
}
}
}
}
#swagger.responses[400] = {
description: "Bad Request. Reasons can include 'The folder doesn't exist' or 'Folder name cannot contain spaces. Only underscore and dashes'"
}
#swagger.responses[401] = {
description: "Unauthorized request. For example, 'Folder Permission Denied'"
}
*/
const {
body: { workspaceId, environment, name, directory },
params: { folderName }
} = await validateRequest(reqValidator.UpdateFolderV1, req);
if (!validateFolderName(name)) {
throw BadRequestError({
message: "Folder name cannot contain spaces. Only underscore and dashes"
});
}
if (req.authData.authPayload instanceof ServiceTokenData) {
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
);
}
const folders = await Folder.findOne({ workspace: workspaceId, environment });
if (!folders) {
throw BadRequestError({ message: "The folder doesn't exist" });
}
const parentFolder = getFolderByPath(folders.nodes, directory);
if (!parentFolder) {
throw BadRequestError({ message: "The folder doesn't exist" });
}
const folder = parentFolder.children.find(({ name }) => name === folderName);
if (!folder) throw ERR_FOLDER_NOT_FOUND;
const oldFolderName = folder.name;
parentFolder.version += 1;
folder.name = name;
await Folder.findByIdAndUpdate(folders._id, folders);
const folderVersion = new FolderVersion({
workspace: workspaceId,
environment,
nodes: parentFolder
});
await folderVersion.save();
await EESecretService.takeSecretSnapshot({
workspaceId: new Types.ObjectId(workspaceId),
environment,
folderId: parentFolder.id
});
const { folderPath } = getFolderWithPathFromId(folders.nodes, folder.id);
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.UPDATE_FOLDER,
metadata: {
environment,
folderId: folder.id,
oldFolderName,
newFolderName: name,
folderPath
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.json({
message: "Successfully updated folder",
folder: { name: folder.name, id: folder.id }
});
};
/**
* Delete folder with id [folderId]
* @param req
* @param res
* @returns
*/
export const deleteFolder = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Delete folder'
#swagger.description = 'Delete folder'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['folderName'] = {
"description": "Name of folder to delete",
"required": true,
"type": "string",
"in": "path"
}
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"workspaceId": {
"type": "string",
"description": "ID of the workspace where to delete folder",
"example": "someWorkspaceId"
},
"environment": {
"type": "string",
"description": "Slug of environment where to delete folder",
"example": "production"
},
"directory": {
"type": "string",
"description": "Path where to delete folder like / or /foo/bar. Default is /",
"example": "/foo/bar"
}
},
"required": ["workspaceId", "environment"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Success message",
"example": "successfully deleted folders"
},
"folders": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "ID of deleted folder",
"example": "abc123"
},
"name": {
"type": "string",
"description": "Name of deleted folder",
"example": "someFolderName"
}
}
},
"description": "List of IDs and names of deleted folders"
}
}
}
}
}
}
#swagger.responses[400] = {
description: "Bad Request. Reasons can include 'The folder doesn't exist'"
}
#swagger.responses[401] = {
description: "Unauthorized request. For example, 'Folder Permission Denied'"
}
*/
const {
params: { folderName },
body: { environment, workspaceId, directory }
} = await validateRequest(reqValidator.DeleteFolderV1, req);
if (req.authData.authPayload instanceof ServiceTokenData) {
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
// check that user is a member of the workspace
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
);
}
const folders = await Folder.findOne({ workspace: workspaceId, environment });
if (!folders) throw ERR_FOLDER_NOT_FOUND;
const parentFolder = getFolderByPath(folders.nodes, directory);
if (!parentFolder) throw ERR_FOLDER_NOT_FOUND;
const index = parentFolder.children.findIndex(({ name }) => name === folderName);
if (index === -1) throw ERR_FOLDER_NOT_FOUND;
const deletedFolder = parentFolder.children.splice(index, 1)[0];
parentFolder.version += 1;
const delFolderIds = getAllFolderIds(deletedFolder);
await Folder.findByIdAndUpdate(folders._id, folders);
const folderVersion = new FolderVersion({
workspace: workspaceId,
environment,
nodes: parentFolder
});
await folderVersion.save();
if (delFolderIds.length) {
await Secret.deleteMany({
folder: { $in: delFolderIds.map(({ id }) => id) },
workspace: workspaceId,
environment
});
}
await EESecretService.takeSecretSnapshot({
workspaceId: new Types.ObjectId(workspaceId),
environment,
folderId: parentFolder.id
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.DELETE_FOLDER,
metadata: {
environment,
folderId: deletedFolder.id,
folderName: deletedFolder.name,
folderPath: directory
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.send({ message: "successfully deleted folders", folders: delFolderIds });
};
/**
* Get folders for workspace with id [workspaceId] and environment [environment]
* considering directory/path [directory]
* @param req
* @param res
* @returns
*/
export const getFolders = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Get folders'
#swagger.description = 'Get folders'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of the workspace where to get folders from",
"required": true,
"type": "string",
"in": "query"
}
#swagger.parameters['environment'] = {
"description": "Slug of environment where to get folders from",
"required": true,
"type": "string",
"in": "query"
}
#swagger.parameters['directory'] = {
"description": "Path where to get fodlers from like / or /foo/bar. Default is /",
"required": false,
"type": "string",
"in": "query"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"folders": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "someFolderId"
},
"name": {
"type": "string",
"example": "someFolderName"
}
}
},
"description": "List of folders"
}
}
}
}
}
}
#swagger.responses[400] = {
description: "Bad Request. For instance, 'The folder doesn't exist'"
}
#swagger.responses[401] = {
description: "Unauthorized request. For example, 'Folder Permission Denied'"
}
*/
const {
query: { workspaceId, environment, directory }
} = await validateRequest(reqValidator.GetFoldersV1, req);
if (req.authData.authPayload instanceof ServiceTokenData) {
const isValidScopeAccess = isValidScope(req.authData.authPayload, environment, directory);
if (!isValidScopeAccess) {
throw UnauthorizedRequestError({ message: "Folder Permission Denied" });
}
} else {
// check that user is a member of the workspace
await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
}
const folders = await Folder.findOne({ workspace: workspaceId, environment });
if (!folders) {
return res.send({ folders: [], dir: [] });
}
const folder = getFolderByPath(folders.nodes, directory);
return res.send({
folders: folder?.children?.map(({ id, name }) => ({ id, name })) || []
});
};

View File

@@ -0,0 +1,75 @@
import { Request, Response } from "express";
import { ServiceToken } from "../../models";
import { createToken } from "../../helpers/auth";
import { getJwtServiceSecret } from "../../config";
/**
* Return service token on request
* @param req
* @param res
* @returns
*/
export const getServiceToken = async (req: Request, res: Response) => {
return res.status(200).send({
serviceToken: req.serviceToken,
});
};
/**
* Create and return a new service token
* @param req
* @param res
* @returns
*/
export const createServiceToken = async (req: Request, res: Response) => {
let token;
try {
const {
name,
workspaceId,
environment,
expiresIn,
publicKey,
encryptedKey,
nonce,
} = req.body;
// validate environment
const workspaceEnvs = req.membership.workspace.environments;
if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) {
throw new Error("Failed to validate environment");
}
// compute access token expiration date
const expiresAt = new Date();
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
const serviceToken = await new ServiceToken({
name,
user: req.user._id,
workspace: workspaceId,
environment,
expiresAt,
publicKey,
encryptedKey,
nonce,
}).save();
token = createToken({
payload: {
serviceTokenId: serviceToken._id.toString(),
workspaceId,
},
expiresIn: expiresIn,
secret: await getJwtServiceSecret(),
});
} catch (err) {
return res.status(400).send({
message: "Failed to create service token",
});
}
return res.status(200).send({
token,
});
};

View File

@@ -0,0 +1,99 @@
import { Request, Response } from "express";
import { AuthMethod, User } from "../../models";
import { checkEmailVerification, sendEmailVerification } from "../../helpers/signup";
import { createToken } from "../../helpers/auth";
import {
getAuthSecret,
getJwtSignupLifetime,
getSmtpConfigured
} from "../../config";
import { validateUserEmail } from "../../validation";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/auth";
import { AuthTokenType } from "../../variables";
/**
* Signup step 1: Initialize account for user under email [email] and send a verification code
* to that email
* @param req
* @param res
* @returns
*/
export const beginEmailSignup = async (req: Request, res: Response) => {
const {
body: { email }
} = await validateRequest(reqValidator.BeginEmailSignUpV1, req);
// validate that email is not disposable
validateUserEmail(email);
const user = await User.findOne({ email }).select("+publicKey");
if (user && user?.publicKey) {
// case: user has already completed account
return res.status(403).send({
error: "Failed to send email verification code for complete account"
});
}
// send send verification email
await sendEmailVerification({ email });
return res.status(200).send({
message: `Sent an email verification code to ${email}`
});
};
/**
* Signup step 2: Verify that code [code] was sent to email [email] and issue
* a temporary signup token for user to complete setting up their account
* @param req
* @param res
* @returns
*/
export const verifyEmailSignup = async (req: Request, res: Response) => {
let user;
const {
body: { email, code }
} = await validateRequest(reqValidator.VerifyEmailSignUpV1, req);
// initialize user account
user = await User.findOne({ email }).select("+publicKey");
if (user && user?.publicKey) {
// case: user has already completed account
return res.status(403).send({
error: "Failed email verification for complete user"
});
}
// verify email
if (await getSmtpConfigured()) {
await checkEmailVerification({
email,
code
});
}
if (!user) {
user = await new User({
email,
authMethods: [AuthMethod.EMAIL]
}).save();
}
// generate temporary signup token
const token = createToken({
payload: {
authTokenType: AuthTokenType.SIGNUP_TOKEN,
userId: user._id.toString()
},
expiresIn: await getJwtSignupLifetime(),
secret: await getAuthSecret()
});
return res.status(200).send({
message: "Successfuly verified email",
user,
token
});
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
import { Request, Response } from "express";
import { validateRequest } from "../../helpers/validation";
import { UserAction } from "../../models";
import * as reqValidator from "../../validation/action";
/**
* Add user action [action]
* @param req
* @param res
* @returns
*/
export const addUserAction = async (req: Request, res: Response) => {
// add/record new action [action] for user with id [req.user._id]
const {
body: { action }
} = await validateRequest(reqValidator.AddUserActionV1, req);
const userAction = await UserAction.findOneAndUpdate(
{
user: req.user._id,
action
},
{ user: req.user._id, action },
{
new: true,
upsert: true
}
);
return res.status(200).send({
message: "Successfully recorded user action",
userAction
});
};
/**
* Return user action [action] for user
* @param req
* @param res
* @returns
*/
export const getUserAction = async (req: Request, res: Response) => {
// get user action [action] for user with id [req.user._id]
const {
query: { action }
} = await validateRequest(reqValidator.GetUserActionV1, req);
const userAction = await UserAction.findOne({
user: req.user._id,
action
});
return res.status(200).send({
userAction
});
};

View File

@@ -0,0 +1,13 @@
import { Request, Response } from "express";
/**
* Return user on request
* @param req
* @param res
* @returns
*/
export const getUser = async (req: Request, res: Response) => {
return res.status(200).send({
user: req.user,
});
};

View File

@@ -0,0 +1,268 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { client, getEncryptionKey, getRootEncryptionKey } from "../../config";
import { Webhook } from "../../models";
import { getWebhookPayload, triggerWebhookRequest } from "../../services/WebhookService";
import { BadRequestError, ResourceNotFoundError } from "../../utils/errors";
import { EEAuditLogService } from "../../ee/services";
import { EventType } from "../../ee/models";
import {
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_BASE64,
ENCODING_SCHEME_UTF8
} from "../../variables";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/webhooks";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto";
export const createWebhook = async (req: Request, res: Response) => {
const {
body: { webhookUrl, webhookSecretKey, environment, workspaceId, secretPath }
} = await validateRequest(reqValidator.CreateWebhookV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.Webhooks
);
const webhook = new Webhook({
workspace: workspaceId,
environment,
secretPath,
url: webhookUrl
});
if (webhookSecretKey) {
const encryptionKey = await getEncryptionKey();
const rootEncryptionKey = await getRootEncryptionKey();
if (rootEncryptionKey) {
const { ciphertext, iv, tag } = client.encryptSymmetric(webhookSecretKey, rootEncryptionKey);
webhook.iv = iv;
webhook.tag = tag;
webhook.encryptedSecretKey = ciphertext;
webhook.algorithm = ALGORITHM_AES_256_GCM;
webhook.keyEncoding = ENCODING_SCHEME_BASE64;
} else if (encryptionKey) {
const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({
plaintext: webhookSecretKey,
key: encryptionKey
});
webhook.iv = iv;
webhook.tag = tag;
webhook.encryptedSecretKey = ciphertext;
webhook.algorithm = ALGORITHM_AES_256_GCM;
webhook.keyEncoding = ENCODING_SCHEME_UTF8;
}
}
await webhook.save();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_WEBHOOK,
metadata: {
webhookId: webhook._id.toString(),
environment,
secretPath,
webhookUrl,
isDisabled: false
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.status(200).send({
webhook,
message: "successfully created webhook"
});
};
export const updateWebhook = async (req: Request, res: Response) => {
const {
body: { isDisabled },
params: { webhookId }
} = await validateRequest(reqValidator.UpdateWebhookV1, req);
const webhook = await Webhook.findById(webhookId);
if (!webhook) {
throw BadRequestError({ message: "Webhook not found!!" });
}
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: webhook.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Webhooks
);
if (typeof isDisabled !== undefined) {
webhook.isDisabled = isDisabled;
}
await webhook.save();
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.UPDATE_WEBHOOK_STATUS,
metadata: {
webhookId: webhook._id.toString(),
environment: webhook.environment,
secretPath: webhook.secretPath,
webhookUrl: webhook.url,
isDisabled
}
},
{
workspaceId: webhook.workspace
}
);
return res.status(200).send({
webhook,
message: "successfully updated webhook"
});
};
export const deleteWebhook = async (req: Request, res: Response) => {
const {
params: { webhookId }
} = await validateRequest(reqValidator.DeleteWebhookV1, req);
let webhook = await Webhook.findById(webhookId);
if (!webhook) {
throw ResourceNotFoundError({ message: "Webhook not found!!" });
}
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: webhook.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Webhooks
);
webhook = await Webhook.findByIdAndDelete(webhookId);
if (!webhook) {
throw ResourceNotFoundError({ message: "Webhook not found!!" });
}
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.DELETE_WEBHOOK,
metadata: {
webhookId: webhook._id.toString(),
environment: webhook.environment,
secretPath: webhook.secretPath,
webhookUrl: webhook.url,
isDisabled: webhook.isDisabled
}
},
{
workspaceId: webhook.workspace
}
);
return res.status(200).send({
message: "successfully removed webhook"
});
};
export const testWebhook = async (req: Request, res: Response) => {
const {
params: { webhookId }
} = await validateRequest(reqValidator.TestWebhookV1, req);
const webhook = await Webhook.findById(webhookId);
if (!webhook) {
throw BadRequestError({ message: "Webhook not found!!" });
}
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: webhook.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Webhooks
);
try {
await triggerWebhookRequest(
webhook,
getWebhookPayload(
"test",
webhook.workspace.toString(),
webhook.environment,
webhook.secretPath
)
);
await Webhook.findByIdAndUpdate(webhookId, {
lastStatus: "success",
lastRunErrorMessage: null
});
} catch (err) {
await Webhook.findByIdAndUpdate(webhookId, {
lastStatus: "failed",
lastRunErrorMessage: (err as Error).message
});
return res.status(400).send({
message: "Failed to receive response",
error: (err as Error).message
});
}
return res.status(200).send({
message: "Successfully received response"
});
};
export const listWebhooks = async (req: Request, res: Response) => {
const {
query: { environment, workspaceId, secretPath }
} = await validateRequest(reqValidator.ListWebhooksV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Webhooks
);
const optionalFilters: Record<string, string> = {};
if (environment) optionalFilters.environment = environment as string;
if (secretPath) optionalFilters.secretPath = secretPath as string;
const webhooks = await Webhook.find({
workspace: new Types.ObjectId(workspaceId as string),
...optionalFilters
});
return res.status(200).send({
webhooks
});
};

View File

@@ -0,0 +1,359 @@
import { Types } from "mongoose";
import { Request, Response } from "express";
import {
IUser,
Integration,
IntegrationAuth,
Membership,
Organization,
ServiceToken,
Workspace
} from "../../models";
import { createWorkspace as create, deleteWorkspace as deleteWork } from "../../helpers/workspace";
import { EELicenseService } from "../../ee/services";
import { addMemberships } from "../../helpers/membership";
import { ADMIN } from "../../variables";
import { OrganizationNotFoundError } from "../../utils/errors";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { ForbiddenError } from "@casl/ability";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
/**
* Return public keys of members of workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const getWorkspacePublicKeys = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspacePublicKeysV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Member
);
const publicKeys = (
await Membership.find({
workspace: workspaceId
}).populate<{ user: IUser }>("user", "publicKey")
).map((member) => {
return {
publicKey: member.user.publicKey,
userId: member.user._id
};
});
return res.status(200).send({
publicKeys
});
};
/**
* Return memberships for workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const getWorkspaceMemberships = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceMembershipsV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Member
);
const users = await Membership.find({
workspace: workspaceId
}).populate("user", "+publicKey");
return res.status(200).send({
users
});
};
/**
* Return workspaces that user is part of
* @param req
* @param res
* @returns
*/
export const getWorkspaces = async (req: Request, res: Response) => {
const workspaces = (
await Membership.find({
user: req.user._id
}).populate("workspace")
).map((m) => m.workspace);
return res.status(200).send({
workspaces
});
};
/**
* Return workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const getWorkspace = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceV1, req);
const workspace = await Workspace.findOne({
_id: workspaceId
});
return res.status(200).send({
workspace
});
};
/**
* Create new workspace named [workspaceName] under organization with id
* [organizationId] and add user as admin
* @param req
* @param res
* @returns
*/
export const createWorkspace = async (req: Request, res: Response) => {
const {
body: { organizationId, workspaceName }
} = await validateRequest(reqValidator.CreateWorkspaceV1, req);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Workspace
);
const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId));
if (plan.workspaceLimit !== null) {
// case: limit imposed on number of workspaces allowed
if (plan.workspacesUsed >= plan.workspaceLimit) {
// case: number of workspaces used exceeds the number of workspaces allowed
return res.status(400).send({
message:
"Failed to create workspace due to plan limit reached. Upgrade plan to add more workspaces."
});
}
}
if (workspaceName.length < 1) {
throw new Error("Workspace names must be at least 1-character long");
}
// create workspace and add user as member
const workspace = await create({
name: workspaceName,
organizationId: new Types.ObjectId(organizationId)
});
await addMemberships({
userIds: [req.user._id],
workspaceId: workspace._id.toString(),
roles: [ADMIN]
});
return res.status(200).send({
workspace
});
};
/**
* Delete workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const deleteWorkspace = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.DeleteWorkspaceV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Workspace
);
// delete workspace
const workspace = await deleteWork({
workspaceId: new Types.ObjectId(workspaceId)
});
return res.status(200).send({
workspace
});
};
/**
* Change name of workspace with id [workspaceId] to [name]
* @param req
* @param res
* @returns
*/
export const changeWorkspaceName = async (req: Request, res: Response) => {
const {
params: { workspaceId },
body: { name }
} = await validateRequest(reqValidator.ChangeWorkspaceNameV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Workspace
);
const workspace = await Workspace.findOneAndUpdate(
{
_id: workspaceId
},
{
name
},
{
new: true
}
);
return res.status(200).send({
message: "Successfully changed workspace name",
workspace
});
};
/**
* Return integrations for workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const getWorkspaceIntegrations = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceIntegrationsV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Integrations
);
const integrations = await Integration.find({
workspace: workspaceId
});
return res.status(200).send({
integrations
});
};
/**
* Return (integration) authorizations for workspace with id [workspaceId]
* @param req
* @param res
* @returns
*/
export const getWorkspaceIntegrationAuthorizations = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceIntegrationAuthorizationsV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Integrations
);
const authorizations = await IntegrationAuth.find({
workspace: workspaceId
});
return res.status(200).send({
authorizations
});
};
/**
* Return service service tokens for workspace [workspaceId] belonging to user
* @param req
* @param res
* @returns
*/
export const getWorkspaceServiceTokens = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceServiceTokensV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.ServiceTokens
);
// ?? FIX.
const serviceTokens = await ServiceToken.find({
user: req.user._id,
workspace: workspaceId
});
return res.status(200).send({
serviceTokens
});
};

View File

@@ -0,0 +1,315 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { Request, Response } from "express";
import jwt from "jsonwebtoken";
import * as bigintConversion from "bigint-conversion";
const jsrp = require("jsrp");
import { LoginSRPDetail, User } from "../../models";
import { createToken, issueAuthTokens } from "../../helpers/auth";
import { checkUserDevice } from "../../helpers/user";
import { sendMail } from "../../helpers/nodemailer";
import { TokenService } from "../../services";
import { BadRequestError, InternalServerError } from "../../utils/errors";
import { AuthTokenType, TOKEN_EMAIL_MFA } from "../../variables";
import { getAuthSecret, getHttpsEnabled, getJwtMfaLifetime } from "../../config";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/auth";
declare module "jsonwebtoken" {
export interface UserIDJwtPayload extends jwt.JwtPayload {
userId: string;
}
}
/**
* Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol
* @param req
* @param res
* @returns
*/
export const login1 = async (req: Request, res: Response) => {
const { email, clientPublicKey }: { email: string; clientPublicKey: string } = req.body;
const user = await User.findOne({
email
}).select("+salt +verifier");
if (!user) throw new Error("Failed to find user");
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier
},
async () => {
// generate server-side public key
const serverPublicKey = server.getPublicKey();
await LoginSRPDetail.findOneAndReplace(
{ email: email },
{
email: email,
clientPublicKey: clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt)
},
{ upsert: true, returnNewDocument: false }
);
return res.status(200).send({
serverPublicKey,
salt: user.salt
});
}
);
};
/**
* Log in user step 2: complete step 2 of SRP protocol and return token and their (encrypted)
* private key
* @param req
* @param res
* @returns
*/
export const login2 = async (req: Request, res: Response) => {
if (!req.headers["user-agent"])
throw InternalServerError({ message: "User-Agent header is required" });
const { email, clientProof } = req.body;
const user = await User.findOne({
email
}).select(
"+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices"
);
if (!user) throw new Error("Failed to find user");
const loginSRPDetail = await LoginSRPDetail.findOneAndDelete({ email: email });
if (!loginSRPDetail) {
return BadRequestError(Error("Failed to find login details for SRP"));
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier,
b: loginSRPDetail.serverBInt
},
async () => {
server.setClientPublicKey(loginSRPDetail.clientPublicKey);
// compare server and client shared keys
if (server.checkClientProof(clientProof)) {
if (user.isMfaEnabled) {
// case: user has MFA enabled
// generate temporary MFA token
const token = createToken({
payload: {
authTokenType: AuthTokenType.MFA_TOKEN,
userId: user._id.toString()
},
expiresIn: await getJwtMfaLifetime(),
secret: await getAuthSecret()
});
const code = await TokenService.createToken({
type: TOKEN_EMAIL_MFA,
email
});
// send MFA code [code] to [email]
await sendMail({
template: "emailMfa.handlebars",
subjectLine: "Infisical MFA code",
recipients: [email],
substitutions: {
code
}
});
return res.status(200).send({
mfaEnabled: true,
token
});
}
await checkUserDevice({
user,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
// issue tokens
const tokens = await issueAuthTokens({
userId: user._id,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
// store (refresh) token in httpOnly cookie
res.cookie("jid", tokens.refreshToken, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: await getHttpsEnabled()
});
// case: user does not have MFA enabled
// return (access) token in response
interface ResponseData {
mfaEnabled: boolean;
encryptionVersion: any;
protectedKey?: string;
protectedKeyIV?: string;
protectedKeyTag?: string;
token: string;
publicKey?: string;
encryptedPrivateKey?: string;
iv?: string;
tag?: string;
}
const response: ResponseData = {
mfaEnabled: false,
encryptionVersion: user.encryptionVersion,
token: tokens.token,
publicKey: user.publicKey,
encryptedPrivateKey: user.encryptedPrivateKey,
iv: user.iv,
tag: user.tag
};
if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) {
response.protectedKey = user.protectedKey;
response.protectedKeyIV = user.protectedKeyIV;
response.protectedKeyTag = user.protectedKeyTag;
}
return res.status(200).send(response);
}
return res.status(400).send({
message: "Failed to authenticate. Try again?"
});
}
);
};
/**
* Send MFA token to email [email]
* @param req
* @param res
*/
export const sendMfaToken = async (req: Request, res: Response) => {
const code = await TokenService.createToken({
type: TOKEN_EMAIL_MFA,
email: req.user.email
});
// send MFA code [code] to [email]
await sendMail({
template: "emailMfa.handlebars",
subjectLine: "Infisical MFA code",
recipients: [req.user.email],
substitutions: {
code
}
});
return res.status(200).send({
message: "Successfully sent new MFA code"
});
};
/**
* Verify MFA token [mfaToken] and issue JWT and refresh tokens if the
* MFA token [mfaToken] is valid
* @param req
* @param res
*/
export const verifyMfaToken = async (req: Request, res: Response) => {
const {
body: { mfaToken }
} = await validateRequest(reqValidator.VerifyMfaTokenV2, req);
await TokenService.validateToken({
type: TOKEN_EMAIL_MFA,
email: req.user.email,
token: mfaToken
});
const user = await User.findOne({
email: req.user.email
}).select(
"+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices"
);
if (!user) throw new Error("Failed to find user");
await LoginSRPDetail.deleteOne({ userId: user.id });
await checkUserDevice({
user,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
// issue tokens
const tokens = await issueAuthTokens({
userId: user._id,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
// store (refresh) token in httpOnly cookie
res.cookie("jid", tokens.refreshToken, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: await getHttpsEnabled()
});
interface VerifyMfaTokenRes {
encryptionVersion: number;
protectedKey?: string;
protectedKeyIV?: string;
protectedKeyTag?: string;
token: string;
publicKey: string;
encryptedPrivateKey: string;
iv: string;
tag: string;
}
interface VerifyMfaTokenRes {
encryptionVersion: number;
protectedKey?: string;
protectedKeyIV?: string;
protectedKeyTag?: string;
token: string;
publicKey: string;
encryptedPrivateKey: string;
iv: string;
tag: string;
}
const resObj: VerifyMfaTokenRes = {
encryptionVersion: user.encryptionVersion,
token: tokens.token,
publicKey: user.publicKey as string,
encryptedPrivateKey: user.encryptedPrivateKey as string,
iv: user.iv as string,
tag: user.tag as string
};
if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) {
resObj.protectedKey = user.protectedKey;
resObj.protectedKeyIV = user.protectedKeyIV;
resObj.protectedKeyTag = user.protectedKeyTag;
}
return res.status(200).send(resObj);
};

View File

@@ -0,0 +1,604 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import {
Folder,
Integration,
Membership,
Secret,
ServiceToken,
ServiceTokenData,
Workspace
} from "../../models";
import { EventType, SecretVersion } from "../../ee/models";
import { EEAuditLogService, EELicenseService } from "../../ee/services";
import { BadRequestError, WorkspaceNotFoundError } from "../../utils/errors";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/environments";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
import { SecretImport } from "../../models";
import { Webhook } from "../../models";
/**
* Create new workspace environment named [environmentName]
* with slug [environmentSlug] under workspace with id
* @param req
* @param res
* @returns
*/
export const createWorkspaceEnvironment = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Create environment'
#swagger.description = 'Create environment'
#swagger.security = [{
"apiKeyAuth": [],
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of workspace where to create environment",
"required": true,
"type": "string",
"in": "path"
}
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"environmentName": {
"type": "string",
"description": "Name of the environment to create",
"example": "development"
},
"environmentSlug": {
"type": "string",
"description": "Slug of environment to create",
"example": "dev-environment"
}
},
"required": ["environmentName", "environmentSlug"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Sucess message",
"example": "Successfully created environment"
},
"workspace": {
"type": "string",
"description": "ID of workspace where environment was created",
"example": "abc123"
},
"environment": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of created environment",
"example": "Staging"
},
"slug": {
"type": "string",
"description": "Slug of created environment",
"example": "staging"
}
}
}
},
"description": "Details of the created environment"
}
}
}
}
*/
const {
params: { workspaceId },
body: { environmentName, environmentSlug }
} = await validateRequest(reqValidator.CreateWorkspaceEnvironmentV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.Environments
);
const workspace = await Workspace.findById(workspaceId).exec();
if (!workspace) throw WorkspaceNotFoundError();
const plan = await EELicenseService.getPlan(workspace.organization);
if (plan.environmentLimit !== null) {
// case: limit imposed on number of environments allowed
if (workspace.environments.length >= plan.environmentLimit) {
// case: number of environments used exceeds the number of environments allowed
return res.status(400).send({
message:
"Failed to create environment due to environment limit reached. Upgrade plan to create more environments."
});
}
}
if (
!workspace ||
workspace?.environments.find(
({ name, slug }) => slug === environmentSlug || environmentName === name
)
) {
throw new Error("Failed to create workspace environment");
}
workspace?.environments.push({
name: environmentName,
slug: environmentSlug.toLowerCase()
});
await workspace.save();
await EELicenseService.refreshPlan(workspace.organization, new Types.ObjectId(workspaceId));
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_ENVIRONMENT,
metadata: {
name: environmentName,
slug: environmentSlug
}
},
{
workspaceId: workspace._id
}
);
return res.status(200).send({
message: "Successfully created new environment",
workspace: workspaceId,
environment: {
name: environmentName,
slug: environmentSlug
}
});
};
/**
* Swaps the ordering of two environments in the database. This is purely for aesthetic purposes.
* @param req
* @param res
* @returns
*/
export const reorderWorkspaceEnvironments = async (req: Request, res: Response) => {
const {
params: { workspaceId },
body: { environmentName, environmentSlug, otherEnvironmentSlug, otherEnvironmentName }
} = await validateRequest(reqValidator.ReorderWorkspaceEnvironmentsV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Environments
);
// atomic update the env to avoid conflict
const workspace = await Workspace.findById(workspaceId).exec();
if (!workspace) {
throw BadRequestError({ message: "Couldn't load workspace" });
}
const environmentIndex = workspace.environments.findIndex(
(env) => env.name === environmentName && env.slug === environmentSlug
);
const otherEnvironmentIndex = workspace.environments.findIndex(
(env) => env.name === otherEnvironmentName && env.slug === otherEnvironmentSlug
);
if (environmentIndex === -1 || otherEnvironmentIndex === -1) {
throw BadRequestError({ message: "environment or otherEnvironment couldn't be found" });
}
// swap the order of the environments
[workspace.environments[environmentIndex], workspace.environments[otherEnvironmentIndex]] = [
workspace.environments[otherEnvironmentIndex],
workspace.environments[environmentIndex]
];
await workspace.save();
return res.status(200).send({
message: "Successfully reordered environments",
workspace: workspaceId
});
};
/**
* Rename workspace environment with new name and slug of a workspace with [workspaceId]
* Old slug [oldEnvironmentSlug] must be provided
* @param req
* @param res
* @returns
*/
export const renameWorkspaceEnvironment = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Update environment'
#swagger.description = 'Update environment'
#swagger.security = [{
"apiKeyAuth": [],
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of workspace where to update environment",
"required": true,
"type": "string",
"in": "path"
}
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"environmentName": {
"type": "string",
"description": "Name of environment to update to",
"example": "Staging-Renamed"
},
"environmentSlug": {
"type": "string",
"description": "Slug of environment to update to",
"example": "staging-renamed"
},
"oldEnvironmentSlug": {
"type": "string",
"description": "Current slug of environment",
"example": "staging-old"
}
},
"required": ["environmentName", "environmentSlug", "oldEnvironmentSlug"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Success message",
"example": "Successfully update environment"
},
"workspace": {
"type": "string",
"description": "ID of workspace where environment was updated",
"example": "abc123"
},
"environment": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of updated environment",
"example": "Staging-Renamed"
},
"slug": {
"type": "string",
"description": "Slug of updated environment",
"example": "staging-renamed"
}
}
}
},
"description": "Details of the renamed environment"
}
}
}
}
*/
const {
params: { workspaceId },
body: { environmentName, environmentSlug, oldEnvironmentSlug }
} = await validateRequest(reqValidator.UpdateWorkspaceEnvironmentV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Environments
);
// user should pass both new slug and env name
if (!environmentSlug || !environmentName) {
throw new Error("Invalid environment given.");
}
// atomic update the env to avoid conflict
const workspace = await Workspace.findById(workspaceId).exec();
if (!workspace) {
throw new Error("Failed to create workspace environment");
}
const isEnvExist = workspace.environments.some(
({ name, slug }) =>
slug !== oldEnvironmentSlug && (name === environmentName || slug === environmentSlug)
);
if (isEnvExist) {
throw new Error("Invalid environment given");
}
const envIndex = workspace?.environments.findIndex(({ slug }) => slug === oldEnvironmentSlug);
if (envIndex === -1) {
throw new Error("Invalid environment given");
}
const oldEnvironment = workspace.environments[envIndex];
workspace.environments[envIndex].name = environmentName;
workspace.environments[envIndex].slug = environmentSlug.toLowerCase();
await workspace.save();
await Secret.updateMany(
{ workspace: workspaceId, environment: oldEnvironmentSlug },
{ environment: environmentSlug }
);
await SecretVersion.updateMany(
{ workspace: workspaceId, environment: oldEnvironmentSlug },
{ environment: environmentSlug }
);
await ServiceToken.updateMany(
{ workspace: workspaceId, environment: oldEnvironmentSlug },
{ environment: environmentSlug }
);
await ServiceTokenData.updateMany(
{
workspace: workspaceId,
"scopes.environment": oldEnvironmentSlug
},
{ $set: { "scopes.$[element].environment": environmentSlug } },
{ arrayFilters: [{ "element.environment": oldEnvironmentSlug }] }
);
await Integration.updateMany(
{ workspace: workspaceId, environment: oldEnvironmentSlug },
{ environment: environmentSlug }
);
await Folder.updateMany(
{ workspace: workspaceId, environment: oldEnvironmentSlug },
{ environment: environmentSlug }
);
await SecretImport.updateMany(
{ workspace: workspaceId, environment: oldEnvironmentSlug },
{ environment: environmentSlug }
);
await SecretImport.updateMany(
{ workspace: workspaceId, "imports.environment": oldEnvironmentSlug },
{ $set: { "imports.$[element].environment": environmentSlug } },
{ arrayFilters: [{ "element.environment": oldEnvironmentSlug }] },
);
await Webhook.updateMany(
{ workspace: workspaceId, environment: oldEnvironmentSlug },
{ environment: environmentSlug }
);
await Membership.updateMany(
{
workspace: workspaceId,
"deniedPermissions.environmentSlug": oldEnvironmentSlug
},
{ $set: { "deniedPermissions.$[element].environmentSlug": environmentSlug } },
{ arrayFilters: [{ "element.environmentSlug": oldEnvironmentSlug }] }
);
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.UPDATE_ENVIRONMENT,
metadata: {
oldName: oldEnvironment.name,
newName: environmentName,
oldSlug: oldEnvironment.slug,
newSlug: environmentSlug.toLowerCase()
}
},
{
workspaceId: workspace._id
}
);
return res.status(200).send({
message: "Successfully update environment",
workspace: workspaceId,
environment: {
name: environmentName,
slug: environmentSlug
}
});
};
/**
* Delete workspace environment by [environmentSlug] of workspace [workspaceId] and do the clean up
* @param req
* @param res
* @returns
*/
export const deleteWorkspaceEnvironment = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Delete environment'
#swagger.description = 'Delete environment'
#swagger.security = [{
"apiKeyAuth": []
}]
#swagger.parameters['workspaceId'] = {
"description": "ID of workspace where to delete environment",
"required": true,
"type": "string",
"in": "path"
}
#swagger.requestBody = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"environmentSlug": {
"type": "string",
"description": "Slug of environment to delete",
"example": "dev"
}
},
"required": ["environmentSlug"]
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Success message",
"example": "Successfully deleted environment"
},
"workspace": {
"type": "string",
"description": "ID of workspace where environment was deleted",
"example": "abc123"
},
"environment": {
"type": "string",
"description": "Slug of deleted environment",
"example": "dev"
}
},
"description": "Response after deleting an environment from a workspace"
}
}
}
}
*/
const {
params: { workspaceId },
body: { environmentSlug }
} = await validateRequest(reqValidator.DeleteWorkspaceEnvironmentV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Environments
);
// atomic update the env to avoid conflict
const workspace = await Workspace.findById(workspaceId).exec();
if (!workspace) {
throw new Error("Failed to create workspace environment");
}
const envIndex = workspace?.environments.findIndex(({ slug }) => slug === environmentSlug);
if (envIndex === -1) {
throw new Error("Invalid environment given");
}
const oldEnvironment = workspace.environments[envIndex];
workspace.environments.splice(envIndex, 1);
await workspace.save();
// clean up
await Secret.deleteMany({
workspace: workspaceId,
environment: environmentSlug
});
await SecretVersion.deleteMany({
workspace: workspaceId,
environment: environmentSlug
});
// await ServiceToken.deleteMany({
// workspace: workspaceId,
// environment: environmentSlug,
// });
const result = await ServiceTokenData.updateMany(
{ workspace: workspaceId },
{ $pull: { scopes: { environment: environmentSlug } } }
);
if (result.modifiedCount > 0) {
await ServiceTokenData.deleteMany({ workspace: workspaceId, scopes: { $size: 0 } });
}
await Integration.deleteMany({
workspace: workspaceId,
environment: environmentSlug
});
await Membership.updateMany(
{ workspace: workspaceId },
{ $pull: { deniedPermissions: { environmentSlug: environmentSlug } } }
);
await EELicenseService.refreshPlan(workspace.organization, new Types.ObjectId(workspaceId));
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.DELETE_ENVIRONMENT,
metadata: {
name: oldEnvironment.name,
slug: oldEnvironment.slug
}
},
{
workspaceId: workspace._id
}
);
return res.status(200).send({
message: "Successfully deleted environment",
workspace: workspaceId,
environment: environmentSlug
});
};

View File

@@ -0,0 +1,25 @@
import * as authController from "./authController";
import * as signupController from "./signupController";
import * as usersController from "./usersController";
import * as organizationsController from "./organizationsController";
import * as workspaceController from "./workspaceController";
import * as serviceTokenDataController from "./serviceTokenDataController";
import * as secretController from "./secretController";
import * as secretsController from "./secretsController";
import * as environmentController from "./environmentController";
import * as tagController from "./tagController";
import * as membershipController from "./membershipController";
export {
authController,
signupController,
usersController,
organizationsController,
workspaceController,
serviceTokenDataController,
secretController,
secretsController,
environmentController,
tagController,
membershipController
};

View File

@@ -0,0 +1,107 @@
import { ForbiddenError } from "@casl/ability";
import { Request, Response } from "express";
import { Types } from "mongoose";
import { getSiteURL } from "../../config";
import { EventType } from "../../ee/models";
import { EEAuditLogService } from "../../ee/services";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { sendMail } from "../../helpers";
import { validateRequest } from "../../helpers/validation";
import { IUser, Key, Membership, MembershipOrg, Workspace } from "../../models";
import { BadRequestError } from "../../utils/errors";
import * as reqValidator from "../../validation/membership";
import { ACCEPTED, MEMBER } from "../../variables";
export const addUserToWorkspace = async (req: Request, res: Response) => {
const {
params: { workspaceId },
body: { members }
} = await validateRequest(reqValidator.AddUserToWorkspaceV2, req);
// check workspace
const workspace = await Workspace.findById(workspaceId);
if (!workspace) throw new Error("Failed to find workspace");
// check permission
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.Member
);
// validate members are part of the organization
const orgMembers = await MembershipOrg.find({
status: ACCEPTED,
_id: { $in: members.map(({ orgMembershipId }) => orgMembershipId) },
organization: workspace.organization
})
.populate<{ user: IUser }>("user")
.select({ _id: 1, user: 1 })
.lean();
if (orgMembers.length !== members.length)
throw BadRequestError({ message: "Org member not found" });
const existingMember = await Membership.find({
workspace: workspaceId,
user: { $in: orgMembers.map(({ user }) => user) }
});
if (existingMember?.length)
throw BadRequestError({ message: "Some users are already part of workspace" });
await Membership.insertMany(
orgMembers.map(({ user }) => ({ user: user._id, workspace: workspaceId, role: MEMBER }))
);
const encKeyGroupedByOrgMemberId = members.reduce<Record<string, (typeof members)[number]>>(
(prev, curr) => ({ ...prev, [curr.orgMembershipId]: curr }),
{}
);
await Key.insertMany(
orgMembers.map(({ user, _id: id }) => ({
encryptedKey: encKeyGroupedByOrgMemberId[id.toString()].workspaceEncryptedKey,
nonce: encKeyGroupedByOrgMemberId[id.toString()].workspaceEncryptedNonce,
sender: req.user._id,
receiver: user._id,
workspace: workspaceId
}))
);
await sendMail({
template: "workspaceInvitation.handlebars",
subjectLine: "Infisical workspace invitation",
recipients: orgMembers.map(({ user }) => user.email),
substitutions: {
inviterFirstName: req.user.firstName,
inviterEmail: req.user.email,
workspaceName: workspace.name,
callback_url: (await getSiteURL()) + "/login"
}
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.ADD_BATCH_WORKSPACE_MEMBER,
metadata: orgMembers.map(({ user }) => ({
userId: user._id.toString(),
email: user.email
}))
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.status(200).send({
success: true,
data: orgMembers
});
};

View File

@@ -0,0 +1,505 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import {
IWorkspace,
Identity,
IdentityMembership,
IdentityMembershipOrg,
Membership,
MembershipOrg,
User,
Workspace
} from "../../models";
import { Role } from "../../ee/models";
import { deleteMembershipOrg } from "../../helpers/membershipOrg";
import {
createOrganization as create,
deleteOrganization,
updateSubscriptionOrgQuantity
} from "../../helpers/organization";
import { addMembershipsOrg } from "../../helpers/membershipOrg";
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,
getAuthDataOrgPermissions
} from "../../ee/services/RoleService";
import { EELicenseService } from "../../ee/services";
import { ForbiddenError } from "@casl/ability";
/**
* Return memberships for organization with id [organizationId]
* @param req
* @param res
*/
export const getOrganizationMemberships = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return organization user memberships'
#swagger.description = 'Return organization user memberships'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
"description": "ID of organization",
"required": true,
"type": "string"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"memberships": {
"type": "array",
"items": {
$ref: "#/components/schemas/MembershipOrg"
},
"description": "Memberships of organization"
}
}
}
}
}
}
*/
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgMembersv2, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Member
);
const memberships = await MembershipOrg.find({
organization: organizationId
}).populate("user", "+publicKey");
return res.status(200).send({
memberships
});
};
/**
* Update role of membership with id [membershipId] to role [role]
* @param req
* @param res
*/
export const updateOrganizationMembership = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Update organization user membership'
#swagger.description = 'Update organization user membership'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
"description": "ID of organization",
"required": true,
"type": "string"
}
#swagger.parameters['membershipId'] = {
"description": "ID of organization membership to update",
"required": true,
"type": "string"
}
#swagger.requestBody = {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"role": {
"type": "string",
"description": "Role of organization membership - either owner, admin, or member",
}
}
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"membership": {
$ref: "#/components/schemas/MembershipOrg",
"description": "Updated organization membership"
}
}
}
}
}
}
*/
const {
params: { organizationId, membershipId },
body: { role }
} = await validateRequest(reqValidator.UpdateOrgMemberv2, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Member
);
const isCustomRole = ![ADMIN, MEMBER, NO_ACCESS].includes(role);
if (isCustomRole) {
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,
customRole: orgRole
});
return res.status(200).send({
membership
});
}
const membership = await MembershipOrg.findByIdAndUpdate(
membershipId,
{
$set: {
role
},
$unset: {
customRole: 1
}
},
{
new: true
}
);
return res.status(200).send({
membership
});
};
/**
* Delete organization membership with id [membershipId]
* @param req
* @param res
* @returns
*/
export const deleteOrganizationMembership = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Delete organization user membership'
#swagger.description = 'Delete organization user membership'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
"description": "ID of organization",
"required": true,
"type": "string"
}
#swagger.parameters['membershipId'] = {
"description": "ID of organization membership to delete",
"required": true,
"type": "string"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"membership": {
$ref: "#/components/schemas/MembershipOrg",
"description": "Deleted organization membership"
}
}
}
}
}
}
*/
const {
params: { organizationId, membershipId }
} = await validateRequest(reqValidator.DeleteOrgMemberv2, req);
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
);
// delete organization membership
const membership = await deleteMembershipOrg({
membershipOrgId: membershipId
});
await updateSubscriptionOrgQuantity({
organizationId: membership.organization.toString()
});
return res.status(200).send({
membership
});
};
/**
* Return workspaces for organization with id [organizationId] that user has
* access to
* @param req
* @param res
*/
export const getOrganizationWorkspaces = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return projects in organization that user is part of'
#swagger.description = 'Return projects in organization that user is part of'
#swagger.security = [{
"apiKeyAuth": [],
"bearerAuth": []
}]
#swagger.parameters['organizationId'] = {
"description": "ID of organization",
"required": true,
"type": "string"
}
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"workspaces": {
"type": "array",
"items": {
$ref: "#/components/schemas/Project"
},
"description": "Projects of organization"
}
}
}
}
}
}
*/
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgWorkspacesv2, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Workspace
);
const workspacesSet = new Set(
(
await Workspace.find(
{
organization: organizationId
},
"_id"
)
).map((w) => w._id.toString())
);
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
});
};
/**
* Create new organization named [organizationName]
* and add user as owner
* @param req
* @param res
* @returns
*/
export const createOrganization = async (req: Request, res: Response) => {
const {
body: { name }
} = await validateRequest(reqValidator.CreateOrgv2, req);
// create organization and add user as member
const organization = await create({
email: req.user.email,
name
});
await addMembershipsOrg({
userIds: [req.user._id.toString()],
organizationId: organization._id.toString(),
roles: [ADMIN],
statuses: [ACCEPTED]
});
return res.status(200).send({
organization
});
};
/**
* Delete organization with id [organizationId]
* @param req
* @param res
*/
export const deleteOrganizationById = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.DeleteOrgv2, req);
const membershipOrg = await MembershipOrg.findOne({
user: req.user._id,
organization: new Types.ObjectId(organizationId),
role: ADMIN
});
if (!membershipOrg) throw UnauthorizedRequestError();
const organization = await deleteOrganization({
organizationId: new Types.ObjectId(organizationId)
});
return res.status(200).send({
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

@@ -0,0 +1,419 @@
import { Request, Response } from "express";
import mongoose, { Types } from "mongoose";
import {
CreateSecretRequestBody,
ModifySecretRequestBody,
SanitizedSecretForCreate,
SanitizedSecretModify
} from "../../types/secret";
const { ValidationError } = mongoose.Error;
import {
ValidationError as RouteValidationError,
UnauthorizedRequestError
} from "../../utils/errors";
import {
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_UTF8,
SECRET_PERSONAL,
SECRET_SHARED
} from "../../variables";
import { TelemetryService } from "../../services";
import { Secret, User } from "../../models";
import { AccountNotFoundError } from "../../utils/errors";
/**
* Create secret for workspace with id [workspaceId] and environment [environment]
* @param req
* @param res
*/
export const createSecret = async (req: Request, res: Response) => {
const postHogClient = await TelemetryService.getPostHogClient();
const secretToCreate: CreateSecretRequestBody = req.body.secret;
const { workspaceId, environment } = req.params;
const sanitizedSecret: SanitizedSecretForCreate = {
secretKeyCiphertext: secretToCreate.secretKeyCiphertext,
secretKeyIV: secretToCreate.secretKeyIV,
secretKeyTag: secretToCreate.secretKeyTag,
secretKeyHash: secretToCreate.secretKeyHash,
secretValueCiphertext: secretToCreate.secretValueCiphertext,
secretValueIV: secretToCreate.secretValueIV,
secretValueTag: secretToCreate.secretValueTag,
secretValueHash: secretToCreate.secretValueHash,
secretCommentCiphertext: secretToCreate.secretCommentCiphertext,
secretCommentIV: secretToCreate.secretCommentIV,
secretCommentTag: secretToCreate.secretCommentTag,
secretCommentHash: secretToCreate.secretCommentHash,
workspace: new Types.ObjectId(workspaceId),
environment,
type: secretToCreate.type,
user: new Types.ObjectId(req.user._id),
algorithm: ALGORITHM_AES_256_GCM,
keyEncoding: ENCODING_SCHEME_UTF8
};
const secret = await new Secret(sanitizedSecret).save();
if (postHogClient) {
postHogClient.capture({
event: "secrets added",
distinctId: req.user.email,
properties: {
numberOfSecrets: 1,
workspaceId,
environment,
channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli",
userAgent: req.headers?.["user-agent"]
}
});
}
res.status(200).send({
secret
});
};
/**
* Create many secrets for workspace with id [workspaceId] and environment [environment]
* @param req
* @param res
*/
export const createSecrets = async (req: Request, res: Response) => {
const postHogClient = await TelemetryService.getPostHogClient();
const secretsToCreate: CreateSecretRequestBody[] = req.body.secrets;
const { workspaceId, environment } = req.params;
const sanitizedSecretesToCreate: SanitizedSecretForCreate[] = [];
secretsToCreate.forEach((rawSecret) => {
const safeUpdateFields: SanitizedSecretForCreate = {
secretKeyCiphertext: rawSecret.secretKeyCiphertext,
secretKeyIV: rawSecret.secretKeyIV,
secretKeyTag: rawSecret.secretKeyTag,
secretKeyHash: rawSecret.secretKeyHash,
secretValueCiphertext: rawSecret.secretValueCiphertext,
secretValueIV: rawSecret.secretValueIV,
secretValueTag: rawSecret.secretValueTag,
secretValueHash: rawSecret.secretValueHash,
secretCommentCiphertext: rawSecret.secretCommentCiphertext,
secretCommentIV: rawSecret.secretCommentIV,
secretCommentTag: rawSecret.secretCommentTag,
secretCommentHash: rawSecret.secretCommentHash,
workspace: new Types.ObjectId(workspaceId),
environment,
type: rawSecret.type,
user: new Types.ObjectId(req.user._id),
algorithm: ALGORITHM_AES_256_GCM,
keyEncoding: ENCODING_SCHEME_UTF8
};
sanitizedSecretesToCreate.push(safeUpdateFields);
});
const secrets = await Secret.insertMany(sanitizedSecretesToCreate);
if (postHogClient) {
postHogClient.capture({
event: "secrets added",
distinctId: req.user.email,
properties: {
numberOfSecrets: (secretsToCreate ?? []).length,
workspaceId,
environment,
channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli",
userAgent: req.headers?.["user-agent"]
}
});
}
res.status(200).send({
secrets
});
};
/**
* Delete secrets in workspace with id [workspaceId] and environment [environment]
* @param req
* @param res
*/
export const deleteSecrets = async (req: Request, res: Response) => {
const postHogClient = await TelemetryService.getPostHogClient();
const { workspaceId, environmentName } = req.params;
const secretIdsToDelete: string[] = req.body.secretIds;
const secretIdsUserCanDelete = await Secret.find({ workspace: workspaceId, environment: environmentName }, { _id: 1 });
const secretsUserCanDeleteSet: Set<string> = new Set(
secretIdsUserCanDelete.map((objectId) => objectId._id.toString())
);
// Filter out IDs that user can delete and then map them to delete operations
const deleteOperationsToPerform = secretIdsToDelete
.filter(secretIdToDelete => {
if (!secretsUserCanDeleteSet.has(secretIdToDelete)) {
throw RouteValidationError({
message: "You cannot delete secrets that you do not have access to"
});
}
return true;
})
.map(secretIdToDelete => ({
deleteOne: { filter: { _id: new Types.ObjectId(secretIdToDelete) } }
}));
const numSecretsDeleted = deleteOperationsToPerform.length;
await Secret.bulkWrite(deleteOperationsToPerform);
if (postHogClient) {
postHogClient.capture({
event: "secrets deleted",
distinctId: req.user.email,
properties: {
numberOfSecrets: numSecretsDeleted,
environment: environmentName,
workspaceId,
channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli",
userAgent: req.headers?.["user-agent"]
}
});
}
res.status(200).send();
};
/**
* Delete secret with id [secretId]
* @param req
* @param res
*/
export const deleteSecret = async (req: Request, res: Response) => {
const postHogClient = await TelemetryService.getPostHogClient();
await Secret.findByIdAndDelete(req._secret._id);
if (postHogClient) {
postHogClient.capture({
event: "secrets deleted",
distinctId: req.user.email,
properties: {
numberOfSecrets: 1,
workspaceId: req._secret.workspace.toString(),
environment: req._secret.environment,
channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli",
userAgent: req.headers?.["user-agent"]
}
});
}
res.status(200).send({
secret: req._secret
});
};
/**
* Update secrets for workspace with id [workspaceId] and environment [environment]
* @param req
* @param res
* @returns
*/
export const updateSecrets = async (req: Request, res: Response) => {
const postHogClient = await TelemetryService.getPostHogClient();
const { workspaceId, environmentName } = req.params;
const secretsModificationsRequested: ModifySecretRequestBody[] = req.body.secrets;
const secretIdsUserCanModify = await Secret.find({ workspace: workspaceId, environment: environmentName }, { _id: 1 });
const secretsUserCanModifySet: Set<string> = new Set(
secretIdsUserCanModify.map((objectId) => objectId._id.toString())
);
const updateOperationsToPerform: any = [];
secretsModificationsRequested.forEach((userModifiedSecret) => {
if (secretsUserCanModifySet.has(userModifiedSecret._id.toString())) {
const sanitizedSecret: SanitizedSecretModify = {
secretKeyCiphertext: userModifiedSecret.secretKeyCiphertext,
secretKeyIV: userModifiedSecret.secretKeyIV,
secretKeyTag: userModifiedSecret.secretKeyTag,
secretKeyHash: userModifiedSecret.secretKeyHash,
secretValueCiphertext: userModifiedSecret.secretValueCiphertext,
secretValueIV: userModifiedSecret.secretValueIV,
secretValueTag: userModifiedSecret.secretValueTag,
secretValueHash: userModifiedSecret.secretValueHash,
secretCommentCiphertext: userModifiedSecret.secretCommentCiphertext,
secretCommentIV: userModifiedSecret.secretCommentIV,
secretCommentTag: userModifiedSecret.secretCommentTag,
secretCommentHash: userModifiedSecret.secretCommentHash
};
const updateOperation = {
updateOne: {
filter: { _id: userModifiedSecret._id, workspace: workspaceId },
update: { $inc: { version: 1 }, $set: sanitizedSecret }
}
};
updateOperationsToPerform.push(updateOperation);
} else {
throw UnauthorizedRequestError({
message: "You do not have permission to modify one or more of the requested secrets"
});
}
});
await Secret.bulkWrite(updateOperationsToPerform);
if (postHogClient) {
postHogClient.capture({
event: "secrets modified",
distinctId: req.user.email,
properties: {
numberOfSecrets: (secretsModificationsRequested ?? []).length,
environment: environmentName,
workspaceId,
channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli",
userAgent: req.headers?.["user-agent"]
}
});
}
return res.status(200).send();
};
/**
* Update a secret within workspace with id [workspaceId] and environment [environment]
* @param req
* @param res
* @returns
*/
export const updateSecret = async (req: Request, res: Response) => {
const postHogClient = await TelemetryService.getPostHogClient();
const { workspaceId, environmentName } = req.params;
const secretModificationsRequested: ModifySecretRequestBody = req.body.secret;
await Secret.findOne({ workspace: workspaceId, environment: environmentName }, { _id: 1 });
const sanitizedSecret: SanitizedSecretModify = {
secretKeyCiphertext: secretModificationsRequested.secretKeyCiphertext,
secretKeyIV: secretModificationsRequested.secretKeyIV,
secretKeyTag: secretModificationsRequested.secretKeyTag,
secretKeyHash: secretModificationsRequested.secretKeyHash,
secretValueCiphertext: secretModificationsRequested.secretValueCiphertext,
secretValueIV: secretModificationsRequested.secretValueIV,
secretValueTag: secretModificationsRequested.secretValueTag,
secretValueHash: secretModificationsRequested.secretValueHash,
secretCommentCiphertext: secretModificationsRequested.secretCommentCiphertext,
secretCommentIV: secretModificationsRequested.secretCommentIV,
secretCommentTag: secretModificationsRequested.secretCommentTag,
secretCommentHash: secretModificationsRequested.secretCommentHash
};
const singleModificationUpdate = await Secret.updateOne(
{ _id: secretModificationsRequested._id, workspace: workspaceId },
{ $inc: { version: 1 }, $set: sanitizedSecret }
)
.catch((error) => {
if (error instanceof ValidationError) {
throw RouteValidationError({
message: "Unable to apply modifications, please try again",
stack: error.stack
});
}
throw error;
});
if (postHogClient) {
postHogClient.capture({
event: "secrets modified",
distinctId: req.user.email,
properties: {
numberOfSecrets: 1,
environment: environmentName,
workspaceId,
channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli",
userAgent: req.headers?.["user-agent"]
}
});
}
return res.status(200).send(singleModificationUpdate);
};
/**
* Return secrets for workspace with id [workspaceId], environment [environment] and user
* with id [req.user._id]
* @param req
* @param res
* @returns
*/
export const getSecrets = async (req: Request, res: Response) => {
const postHogClient = await TelemetryService.getPostHogClient();
const { environment } = req.query;
const { workspaceId } = req.params;
let userId: Types.ObjectId | undefined = undefined; // used for getting personal secrets for user
let userEmail: string | undefined = undefined; // used for posthog
if (req.user) {
userId = req.user._id;
userEmail = req.user.email;
}
if (req.serviceTokenData) {
userId = req.serviceTokenData.user;
const user = await User.findById(req.serviceTokenData.user, "email");
if (!user) throw AccountNotFoundError();
userEmail = user.email;
}
const secrets = await Secret.find({
workspace: workspaceId,
environment,
$or: [{ user: userId }, { user: { $exists: false } }],
type: { $in: [SECRET_SHARED, SECRET_PERSONAL] }
})
.catch((err) => {
throw RouteValidationError({
message: "Failed to get secrets, please try again",
stack: err.stack
});
})
if (postHogClient) {
postHogClient.capture({
event: "secrets pulled",
distinctId: userEmail,
properties: {
numberOfSecrets: (secrets ?? []).length,
environment,
workspaceId,
channel: req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") ? "web" : "cli",
userAgent: req.headers?.["user-agent"]
}
});
}
return res.json(secrets);
};
/**
* Return secret with id [secretId]
* @param req
* @param res
* @returns
*/
export const getSecret = async (req: Request, res: Response) => {
// if (postHogClient) {
// postHogClient.capture({
// event: 'secrets pulled',
// distinctId: req.user.email,
// properties: {
// numberOfSecrets: 1,
// workspaceId: req._secret.workspace.toString(),
// environment: req._secret.environment,
// channel: req.headers?.['user-agent']?.toLowerCase().includes('mozilla') ? 'web' : 'cli',
// userAgent: req.headers?.['user-agent']
// }
// });
// }
return res.status(200).send({
secret: req._secret
});
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,201 @@
import { Request, Response } from "express";
import crypto from "crypto";
import bcrypt from "bcrypt";
import { ServiceTokenData } from "../../models";
import { getSaltRounds } from "../../config";
import { BadRequestError } from "../../utils/errors";
import { ActorType, EventType } from "../../ee/models";
import { EEAuditLogService } from "../../ee/services";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/serviceTokenData";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import { ForbiddenError, subject } from "@casl/ability";
import { Types } from "mongoose";
/**
* Return service token data associated with service token on request
* @param req
* @param res
* @returns
*/
export const getServiceTokenData = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return Infisical Token data'
#swagger.description = 'Return Infisical Token data'
#swagger.security = [{
"bearerAuth": []
}]
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"serviceTokenData": {
"type": "object",
$ref: "#/components/schemas/ServiceTokenData",
"description": "Details of service token"
}
}
}
}
}
}
*/
if (!(req.authData.authPayload instanceof ServiceTokenData))
throw BadRequestError({
message: "Failed accepted client validation for service token data"
});
const serviceTokenData = await ServiceTokenData.findById(req.authData.authPayload._id)
.select("+encryptedKey +iv +tag")
.populate("user")
.lean();
return res.status(200).json(serviceTokenData);
};
/**
* Create new service token data for workspace with id [workspaceId] and
* environment [environment].
* @param req
* @param res
* @returns
*/
export const createServiceTokenData = async (req: Request, res: Response) => {
let serviceTokenData;
const {
body: { workspaceId, permissions, tag, encryptedKey, scopes, name, expiresIn, iv }
} = await validateRequest(reqValidator.CreateServiceTokenV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
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());
let expiresAt;
if (expiresIn) {
expiresAt = new Date();
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
}
let user;
if (req.authData.actor.type === ActorType.USER) {
user = req.authData.authPayload._id;
}
serviceTokenData = await new ServiceTokenData({
name,
workspace: workspaceId,
user,
scopes,
lastUsed: new Date(),
expiresAt,
secretHash,
encryptedKey,
iv,
tag,
permissions
}).save();
// return service token data without sensitive data
serviceTokenData = await ServiceTokenData.findById(serviceTokenData._id);
if (!serviceTokenData) throw new Error("Failed to find service token data");
const serviceToken = `st.${serviceTokenData._id.toString()}.${secret}`;
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.CREATE_SERVICE_TOKEN,
metadata: {
name,
scopes
}
},
{
workspaceId: new Types.ObjectId(workspaceId)
}
);
return res.status(200).send({
serviceToken,
serviceTokenData
});
};
/**
* Delete service token data with id [serviceTokenDataId].
* @param req
* @param res
* @returns
*/
export const deleteServiceTokenData = async (req: Request, res: Response) => {
const {
params: { serviceTokenDataId }
} = await validateRequest(reqValidator.DeleteServiceTokenV2, req);
let serviceTokenData = await ServiceTokenData.findById(serviceTokenDataId);
if (!serviceTokenData) throw BadRequestError({ message: "Service token not found" });
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: serviceTokenData.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.ServiceTokens
);
serviceTokenData = await ServiceTokenData.findByIdAndDelete(serviceTokenDataId);
if (!serviceTokenData)
return res.status(200).send({
message: "Failed to delete service token"
});
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.DELETE_SERVICE_TOKEN,
metadata: {
name: serviceTokenData.name,
scopes: serviceTokenData?.scopes
}
},
{
workspaceId: serviceTokenData.workspace
}
);
return res.status(200).send({
serviceTokenData
});
};

View File

@@ -0,0 +1,262 @@
import { Request, Response } from "express";
import { MembershipOrg, User } from "../../models";
import { completeAccount } from "../../helpers/user";
import {
initializeDefaultOrg,
} from "../../helpers/signup";
import { issueAuthTokens } from "../../helpers/auth";
import { ACCEPTED, INVITED } from "../../variables";
import { standardRequest } from "../../config/request";
import { getHttpsEnabled, getLoopsApiKey } from "../../config";
import { updateSubscriptionOrgQuantity } from "../../helpers/organization";
/**
* Complete setting up user by adding their personal and auth information as part of the
* signup flow
* @param req
* @param res
* @returns
*/
export const completeAccountSignup = async (req: Request, res: Response) => {
let user;
const {
email,
firstName,
lastName,
protectedKey,
protectedKeyIV,
protectedKeyTag,
publicKey,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt,
verifier,
organizationName,
}: {
email: string;
firstName: string;
lastName: string;
protectedKey: string;
protectedKeyIV: string;
protectedKeyTag: string;
publicKey: string;
encryptedPrivateKey: string;
encryptedPrivateKeyIV: string;
encryptedPrivateKeyTag: string;
salt: string;
verifier: string;
organizationName: string;
} = req.body;
// get user
user = await User.findOne({ email });
if (!user || (user && user?.publicKey)) {
// case 1: user doesn't exist.
// case 2: user has already completed account
return res.status(403).send({
error: "Failed to complete account for complete user",
});
}
// complete setting up user's account
user = await completeAccount({
userId: user._id.toString(),
firstName,
lastName,
encryptionVersion: 2,
protectedKey,
protectedKeyIV,
protectedKeyTag,
publicKey,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt,
verifier,
});
if (!user)
throw new Error("Failed to complete account for non-existent user"); // ensure user is non-null
// initialize default organization and workspace
await initializeDefaultOrg({
organizationName,
user,
});
// update organization membership statuses that are
// invited to completed with user attached
const membershipsToUpdate = await MembershipOrg.find({
inviteEmail: email,
status: INVITED,
});
membershipsToUpdate.forEach(async (membership) => {
await updateSubscriptionOrgQuantity({
organizationId: membership.organization.toString(),
});
});
// update organization membership statuses that are
// invited to completed with user attached
await MembershipOrg.updateMany(
{
inviteEmail: email,
status: INVITED,
},
{
user,
status: ACCEPTED,
}
);
// issue tokens
const tokens = await issueAuthTokens({
userId: user._id,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? "",
});
const token = tokens.token;
// sending a welcome email to new users
if (await getLoopsApiKey()) {
await standardRequest.post("https://app.loops.so/api/v1/events/send", {
"email": email,
"eventName": "Sign Up",
"firstName": firstName,
"lastName": lastName,
}, {
headers: {
"Accept": "application/json",
"Authorization": "Bearer " + (await getLoopsApiKey()),
},
});
}
// store (refresh) token in httpOnly cookie
res.cookie("jid", tokens.refreshToken, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: await getHttpsEnabled(),
});
return res.status(200).send({
message: "Successfully set up account",
user,
token,
});
};
/**
* Complete setting up user by adding their personal and auth information as part of the
* invite flow
* @param req
* @param res
* @returns
*/
export const completeAccountInvite = async (req: Request, res: Response) => {
let user;
const {
email,
firstName,
lastName,
protectedKey,
protectedKeyIV,
protectedKeyTag,
publicKey,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt,
verifier,
} = req.body;
// get user
user = await User.findOne({ email });
if (!user || (user && user?.publicKey)) {
// case 1: user doesn't exist.
// case 2: user has already completed account
return res.status(403).send({
error: "Failed to complete account for complete user",
});
}
const membershipOrg = await MembershipOrg.findOne({
inviteEmail: email,
status: INVITED,
});
if (!membershipOrg) throw new Error("Failed to find invitations for email");
// complete setting up user's account
user = await completeAccount({
userId: user._id.toString(),
firstName,
lastName,
encryptionVersion: 2,
protectedKey,
protectedKeyIV,
protectedKeyTag,
publicKey,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt,
verifier,
});
if (!user)
throw new Error("Failed to complete account for non-existent user");
// update organization membership statuses that are
// invited to completed with user attached
const membershipsToUpdate = await MembershipOrg.find({
inviteEmail: email,
status: INVITED,
});
membershipsToUpdate.forEach(async (membership) => {
await updateSubscriptionOrgQuantity({
organizationId: membership.organization.toString(),
});
});
await MembershipOrg.updateMany(
{
inviteEmail: email,
status: INVITED,
},
{
user,
status: ACCEPTED,
}
);
// issue tokens
const tokens = await issueAuthTokens({
userId: user._id,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? "",
});
const token = tokens.token;
// store (refresh) token in httpOnly cookie
res.cookie("jid", tokens.refreshToken, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: await getHttpsEnabled(),
});
return res.status(200).send({
message: "Successfully set up account",
user,
token,
});
};

View File

@@ -0,0 +1,92 @@
import { ForbiddenError } from "@casl/ability";
import { Request, Response } from "express";
import { Types } from "mongoose";
import { Secret, Tag } from "../../models";
import { BadRequestError } from "../../utils/errors";
import { validateRequest } from "../../helpers/validation";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../ee/services/ProjectRoleService";
import * as reqValidator from "../../validation/tags";
export const createWorkspaceTag = async (req: Request, res: Response) => {
const {
body: { name, slug },
params: { workspaceId }
} = await validateRequest(reqValidator.CreateWorkspaceTagsV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.Tags
);
const tagToCreate = {
name,
workspace: new Types.ObjectId(workspaceId),
slug,
user: new Types.ObjectId(req.user._id)
};
const createdTag = await new Tag(tagToCreate).save();
res.json(createdTag);
};
export const deleteWorkspaceTag = async (req: Request, res: Response) => {
const {
params: { tagId }
} = await validateRequest(reqValidator.DeleteWorkspaceTagsV2, req);
const tagFromDB = await Tag.findById(tagId);
if (!tagFromDB) {
throw BadRequestError();
}
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: tagFromDB.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Tags
);
const result = await Tag.findByIdAndDelete(tagId);
// remove the tag from secrets
await Secret.updateMany({ tags: { $in: [tagId] } }, { $pull: { tags: tagId } });
res.json(result);
};
export const getWorkspaceTags = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceTagsV2, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Tags
);
const workspaceTags = await Tag.find({
workspace: new Types.ObjectId(workspaceId)
});
return res.json({
workspaceTags
});
};

View File

@@ -0,0 +1,314 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import crypto from "crypto";
import bcrypt from "bcrypt";
import { APIKeyData, AuthMethod, MembershipOrg, TokenVersion, User } from "../../models";
import { getSaltRounds } from "../../config";
import { validateRequest } from "../../helpers/validation";
import { deleteUser } from "../../helpers/user";
import * as reqValidator from "../../validation";
/**
* Update the current user's MFA-enabled status [isMfaEnabled].
* Note: Infisical currently only supports email-based 2FA only; this will expand to
* include SMS and authenticator app modes of authentication in the future.
* @param req
* @param res
* @returns
*/
export const updateMyMfaEnabled = async (req: Request, res: Response) => {
const {
body: { isMfaEnabled }
} = await validateRequest(reqValidator.UpdateMyMfaEnabledV2, req);
req.user.isMfaEnabled = isMfaEnabled;
if (isMfaEnabled) {
// TODO: adapt this route/controller
// to work for different forms of MFA
req.user.mfaMethods = ["email"];
} else {
req.user.mfaMethods = [];
}
await req.user.save();
const user = req.user;
return res.status(200).send({
user
});
};
/**
* Update name of the current user to [firstName, lastName].
* @param req
* @param res
* @returns
*/
export const updateName = async (req: Request, res: Response) => {
const {
body: { lastName, firstName }
} = await validateRequest(reqValidator.UpdateNameV2, req);
const user = await User.findByIdAndUpdate(
req.user._id.toString(),
{
firstName,
lastName: lastName ?? ""
},
{
new: true
}
);
return res.status(200).send({
user
});
};
/**
* Update auth method of the current user to [authMethods]
* @param req
* @param res
* @returns
*/
export const updateAuthMethods = async (req: Request, res: Response) => {
const {
body: { authMethods }
} = await validateRequest(reqValidator.UpdateAuthMethodsV2, req);
const hasSamlEnabled = req.user.authMethods.some((authMethod: AuthMethod) =>
[AuthMethod.OKTA_SAML, AuthMethod.AZURE_SAML, AuthMethod.JUMPCLOUD_SAML].includes(authMethod)
);
if (hasSamlEnabled) {
return res.status(400).send({
message: "Failed to update user authentication method because SAML SSO is enforced"
});
}
const user = await User.findByIdAndUpdate(
req.user._id.toString(),
{
authMethods
},
{
new: true
}
);
return res.status(200).send({
user
});
};
/**
* Return organizations that the current user is part of.
* @param req
* @param res
*/
export const getMyOrganizations = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return organizations that current user is part of'
#swagger.description = 'Return organizations that current user is part of'
#swagger.security = [{
"apiKeyAuth": []
}]
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"organizations": {
"type": "array",
"items": {
$ref: "#/components/schemas/Organization"
},
"description": "Organizations that user is part of"
}
}
}
}
}
}
*/
const organizations = (
await MembershipOrg.find({
user: req.user._id
}).populate("organization")
).map((m) => m.organization);
return res.status(200).send({
organizations
});
};
/**
* Return API keys belonging to current user.
* @param req
* @param res
* @returns
*/
export const getMyAPIKeys = async (req: Request, res: Response) => {
const apiKeyData = await APIKeyData.find({
user: req.user._id
});
return res.status(200).send(apiKeyData);
};
/**
* Create new API key for current user.
* @param req
* @param res
* @returns
*/
export const createAPIKey = async (req: Request, res: Response) => {
const {
body: { name, expiresIn }
} = await validateRequest(reqValidator.CreateApiKeyV2, req);
const secret = crypto.randomBytes(16).toString("hex");
const secretHash = await bcrypt.hash(secret, await getSaltRounds());
const expiresAt = new Date();
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
let apiKeyData = await new APIKeyData({
name,
lastUsed: new Date(),
expiresAt,
user: req.user._id,
secretHash
}).save();
// return api key data without sensitive data
apiKeyData = (await APIKeyData.findById(apiKeyData._id)) as any;
if (!apiKeyData) throw new Error("Failed to find API key data");
const apiKey = `ak.${apiKeyData._id.toString()}.${secret}`;
return res.status(200).send({
apiKey,
apiKeyData
});
};
/**
* Delete API key with id [apiKeyDataId] belonging to current user
* @param req
* @param res
*/
export const deleteAPIKey = async (req: Request, res: Response) => {
const {
params: { apiKeyDataId }
} = await validateRequest(reqValidator.DeleteApiKeyV2, req);
const apiKeyData = await APIKeyData.findOneAndDelete({
_id: new Types.ObjectId(apiKeyDataId),
user: req.user._id
});
return res.status(200).send({
apiKeyData
});
};
/**
* Return active sessions (TokenVersion) belonging to user
* @param req
* @param res
* @returns
*/
export const getMySessions = async (req: Request, res: Response) => {
const tokenVersions = await TokenVersion.find({
user: req.user._id
});
return res.status(200).send(tokenVersions);
};
/**
* Revoke all active sessions belong to user
* @param req
* @param res
* @returns
*/
export const deleteMySessions = async (req: Request, res: Response) => {
await TokenVersion.updateMany(
{
user: req.user._id
},
{
$inc: {
refreshVersion: 1,
accessVersion: 1
}
}
);
return res.status(200).send({
message: "Successfully revoked all sessions"
});
};
/**
* Return the current user.
* @param req
* @param res
* @returns
*/
export const getMe = async (req: Request, res: Response) => {
/*
#swagger.summary = "Retrieve the current user on the request"
#swagger.description = "Retrieve the current user on the request"
#swagger.security = [{
"apiKeyAuth": []
}]
#swagger.responses[200] = {
content: {
"application/json": {
"schema": {
"type": "object",
"properties": {
"user": {
"type": "object",
$ref: "#/components/schemas/CurrentUser",
"description": "Current user on request"
}
}
}
}
}
}
*/
const user = await User.findById(req.user._id).select(
"+salt +publicKey +encryptedPrivateKey +iv +tag +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag"
);
return res.status(200).send({
user
});
};
/**
* Delete the current user.
* @param req
* @param res
*/
export const deleteMe = async (req: Request, res: Response) => {
const user = await deleteUser({
userId: req.user._id
});
return res.status(200).send({
user
});
}

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

@@ -0,0 +1,224 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { Request, Response } from "express";
import jwt from "jsonwebtoken";
import * as bigintConversion from "bigint-conversion";
const jsrp = require("jsrp");
import { LoginSRPDetail, User } from "../../models";
import { createToken, issueAuthTokens, validateProviderAuthToken } from "../../helpers/auth";
import { checkUserDevice } from "../../helpers/user";
import { sendMail } from "../../helpers/nodemailer";
import { TokenService } from "../../services";
import { BadRequestError, InternalServerError } from "../../utils/errors";
import { AuthTokenType, TOKEN_EMAIL_MFA } from "../../variables";
import { getAuthSecret, getHttpsEnabled, getJwtMfaLifetime } from "../../config";
import { AuthMethod } from "../../models/user";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/auth";
declare module "jsonwebtoken" {
export interface ProviderAuthJwtPayload extends jwt.JwtPayload {
userId: string;
email: string;
authProvider: AuthMethod;
isUserCompleted: boolean;
}
}
/**
* Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol
* @param req
* @param res
* @returns
*/
export const login1 = async (req: Request, res: Response) => {
const {
body: { email, clientPublicKey, providerAuthToken }
} = await validateRequest(reqValidator.Login1V3, req);
const user = await User.findOne({
email
}).select("+salt +verifier");
if (!user) throw new Error("Failed to find user");
if (!user.authMethods.includes(AuthMethod.EMAIL)) {
await validateProviderAuthToken({
email,
providerAuthToken
});
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier
},
async () => {
// generate server-side public key
const serverPublicKey = server.getPublicKey();
await LoginSRPDetail.findOneAndReplace(
{
email: email
},
{
email,
userId: user.id,
clientPublicKey: clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt)
},
{ upsert: true, returnNewDocument: false }
);
return res.status(200).send({
serverPublicKey,
salt: user.salt
});
}
);
};
/**
* Log in user step 2: complete step 2 of SRP protocol and return token and their (encrypted)
* private key
* @param req
* @param res
* @returns
*/
export const login2 = async (req: Request, res: Response) => {
if (!req.headers["user-agent"])
throw InternalServerError({ message: "User-Agent header is required" });
const {
body: { email, providerAuthToken, clientProof }
} = await validateRequest(reqValidator.Login2V3, req);
const user = await User.findOne({
email
}).select(
"+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices"
);
if (!user) throw new Error("Failed to find user");
if (!user.authMethods.includes(AuthMethod.EMAIL)) {
await validateProviderAuthToken({
email,
providerAuthToken
});
}
const loginSRPDetail = await LoginSRPDetail.findOneAndDelete({ email: email });
if (!loginSRPDetail) {
return BadRequestError(Error("Failed to find login details for SRP"));
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier,
b: loginSRPDetail.serverBInt
},
async () => {
server.setClientPublicKey(loginSRPDetail.clientPublicKey);
// compare server and client shared keys
if (server.checkClientProof(clientProof)) {
if (user.isMfaEnabled) {
// case: user has MFA enabled
// generate temporary MFA token
const token = createToken({
payload: {
authTokenType: AuthTokenType.MFA_TOKEN,
userId: user._id.toString()
},
expiresIn: await getJwtMfaLifetime(),
secret: await getAuthSecret()
});
const code = await TokenService.createToken({
type: TOKEN_EMAIL_MFA,
email
});
// send MFA code [code] to [email]
await sendMail({
template: "emailMfa.handlebars",
subjectLine: "Infisical MFA code",
recipients: [user.email],
substitutions: {
code
}
});
return res.status(200).send({
mfaEnabled: true,
token
});
}
await checkUserDevice({
user,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
// issue tokens
const tokens = await issueAuthTokens({
userId: user._id,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
// store (refresh) token in httpOnly cookie
res.cookie("jid", tokens.refreshToken, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: await getHttpsEnabled()
});
// case: user does not have MFA enablgged
// return (access) token in response
interface ResponseData {
mfaEnabled: boolean;
encryptionVersion: any;
protectedKey?: string;
protectedKeyIV?: string;
protectedKeyTag?: string;
token: string;
publicKey?: string;
encryptedPrivateKey?: string;
iv?: string;
tag?: string;
}
const response: ResponseData = {
mfaEnabled: false,
encryptionVersion: user.encryptionVersion,
token: tokens.token,
publicKey: user.publicKey,
encryptedPrivateKey: user.encryptedPrivateKey,
iv: user.iv,
tag: user.tag
};
if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) {
response.protectedKey = user.protectedKey;
response.protectedKeyIV = user.protectedKeyIV;
response.protectedKeyTag = user.protectedKeyTag;
}
return res.status(200).send(response);
}
return res.status(400).send({
message: "Failed to authenticate. Try again?"
});
}
);
};

View File

@@ -0,0 +1,13 @@
import * as usersController from "./usersController";
import * as secretsController from "./secretsController";
import * as workspacesController from "./workspacesController";
import * as authController from "./authController";
import * as signupController from "./signupController";
export {
usersController,
authController,
secretsController,
signupController,
workspacesController
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,193 @@
import jwt from "jsonwebtoken";
import { Request, Response } from "express";
import * as Sentry from "@sentry/node";
import { MembershipOrg, User } from "../../models";
import { completeAccount } from "../../helpers/user";
import { initializeDefaultOrg } from "../../helpers/signup";
import { issueAuthTokens, validateProviderAuthToken } from "../../helpers/auth";
import { ACCEPTED, AuthTokenType, INVITED } from "../../variables";
import { standardRequest } from "../../config/request";
import { getAuthSecret, getHttpsEnabled, getLoopsApiKey } from "../../config";
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
import { TelemetryService } from "../../services";
import { AuthMethod } from "../../models";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/auth";
/**
* Complete setting up user by adding their personal and auth information as part of the
* signup flow
* @param req
* @param res
* @returns
*/
export const completeAccountSignup = async (req: Request, res: Response) => {
let user, token;
try {
const {
body: {
email,
publicKey,
salt,
lastName,
verifier,
firstName,
protectedKey,
protectedKeyIV,
protectedKeyTag,
organizationName,
providerAuthToken,
attributionSource,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag
}
} = await validateRequest(reqValidator.CompletedAccountSignupV3, req);
user = await User.findOne({ email });
if (!user || (user && user?.publicKey)) {
// case 1: user doesn't exist.
// case 2: user has already completed account
return res.status(403).send({
error: "Failed to complete account for complete user"
});
}
if (providerAuthToken) {
await validateProviderAuthToken({
email,
providerAuthToken
});
} else {
const [AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE] = <[string, string]>(
req.headers["authorization"]?.split(" ", 2)
) ?? [null, null];
if (AUTH_TOKEN_TYPE === null) {
throw BadRequestError({ message: "Missing Authorization Header in the request header." });
}
if (AUTH_TOKEN_TYPE.toLowerCase() !== "bearer") {
throw BadRequestError({
message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.`
});
}
if (AUTH_TOKEN_VALUE === null) {
throw BadRequestError({
message: "Missing Authorization Body in the request header"
});
}
const decodedToken = <jwt.UserIDJwtPayload>(
jwt.verify(AUTH_TOKEN_VALUE, await getAuthSecret())
);
if (decodedToken.authTokenType !== AuthTokenType.SIGNUP_TOKEN) throw UnauthorizedRequestError();
if (decodedToken.userId !== user.id) throw UnauthorizedRequestError();
}
// complete setting up user's account
user = await completeAccount({
userId: user._id.toString(),
firstName,
lastName,
encryptionVersion: 2,
protectedKey,
protectedKeyIV,
protectedKeyTag,
publicKey,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt,
verifier
});
if (!user) throw new Error("Failed to complete account for non-existent user"); // ensure user is non-null
const hasSamlEnabled = user.authMethods.some((authMethod: AuthMethod) =>
[AuthMethod.OKTA_SAML, AuthMethod.AZURE_SAML, AuthMethod.JUMPCLOUD_SAML].includes(authMethod)
);
if (!hasSamlEnabled) {
// TODO: modify this part
// initialize default organization and workspace
await initializeDefaultOrg({
organizationName,
user
});
}
// update organization membership statuses that are
// invited to completed with user attached
await MembershipOrg.updateMany(
{
inviteEmail: email,
status: INVITED
},
{
user,
status: ACCEPTED
}
);
// issue tokens
const tokens = await issueAuthTokens({
userId: user._id,
ip: req.realIP,
userAgent: req.headers["user-agent"] ?? ""
});
token = tokens.token;
// sending a welcome email to new users
if (await getLoopsApiKey()) {
await standardRequest.post(
"https://app.loops.so/api/v1/events/send",
{
email: email,
eventName: "Sign Up",
firstName: firstName,
lastName: lastName
},
{
headers: {
Accept: "application/json",
Authorization: "Bearer " + (await getLoopsApiKey())
}
}
);
}
// store (refresh) token in httpOnly cookie
res.cookie("jid", tokens.refreshToken, {
httpOnly: true,
path: "/",
sameSite: "strict",
secure: await getHttpsEnabled()
});
const postHogClient = await TelemetryService.getPostHogClient();
if (postHogClient) {
postHogClient.capture({
event: "User Signed Up",
distinctId: email,
properties: {
email,
...(attributionSource ? { attributionSource } : {})
}
});
}
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
return res.status(400).send({
message: "Failed to complete account setup"
});
}
return res.status(200).send({
message: "Successfully set up account",
user,
token
});
};

View File

@@ -0,0 +1,18 @@
import { Request, Response } from "express";
import { APIKeyDataV2 } from "../../models";
/**
* Return API keys belonging to current user.
* @param req
* @param res
* @returns
*/
export const getMyAPIKeys = async (req: Request, res: Response) => {
const apiKeyData = await APIKeyDataV2.find({
user: req.user._id
});
return res.status(200).send({
apiKeyData
});
}

View File

@@ -0,0 +1,142 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { validateRequest } from "../../helpers/validation";
import { Membership, Secret, User } from "../../models";
import { SecretService } from "../../services";
import { getAuthDataProjectPermissions } from "../../ee/services/ProjectRoleService";
import { UnauthorizedRequestError } from "../../utils/errors";
import * as reqValidator from "../../validation/workspace";
/**
* Return whether or not all secrets in workspace with id [workspaceId]
* are blind-indexed
* @param req
* @param res
* @returns
*/
export const getWorkspaceBlindIndexStatus = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceBlinkIndexStatusV3, req);
await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
if (req.authData.authPayload instanceof User) {
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: new Types.ObjectId(workspaceId)
});
if (!membership) throw UnauthorizedRequestError();
if (membership.role !== "admin")
throw UnauthorizedRequestError({ message: "User must be an admin" });
}
const secretsWithoutBlindIndex = await Secret.countDocuments({
workspace: new Types.ObjectId(workspaceId),
secretBlindIndex: {
$exists: false
}
});
return res.status(200).send(secretsWithoutBlindIndex === 0);
};
/**
* Get all secrets for workspace with id [workspaceId]
*/
export const getWorkspaceSecrets = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.GetWorkspaceSecretsV3, req);
await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
if (req.authData.authPayload instanceof User) {
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: new Types.ObjectId(workspaceId)
});
if (!membership) throw UnauthorizedRequestError();
if (membership.role !== "admin")
throw UnauthorizedRequestError({ message: "User must be an admin" });
}
const secrets = await Secret.find({
workspace: new Types.ObjectId(workspaceId)
});
return res.status(200).send({
secrets
});
};
/**
* Update blind indices for secrets in workspace with id [workspaceId]
* @param req
* @param res
*/
export const nameWorkspaceSecrets = async (req: Request, res: Response) => {
const {
params: { workspaceId },
body: { secretsToUpdate }
} = await validateRequest(reqValidator.NameWorkspaceSecretsV3, req);
await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
if (req.authData.authPayload instanceof User) {
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: new Types.ObjectId(workspaceId)
});
if (!membership) throw UnauthorizedRequestError();
if (membership.role !== "admin")
throw UnauthorizedRequestError({ message: "User must be an admin" });
}
// get secret blind index salt
const salt = await SecretService.getSecretBlindIndexSalt({
workspaceId: new Types.ObjectId(workspaceId)
});
// update secret blind indices
const operations = await Promise.all(
secretsToUpdate.map(async (secretToUpdate) => {
const secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt({
secretName: secretToUpdate.secretName,
salt
});
return {
updateOne: {
filter: {
_id: new Types.ObjectId(secretToUpdate._id)
},
update: {
secretBlindIndex
}
}
};
})
);
await Secret.bulkWrite(operations);
return res.status(200).send({
message: "Successfully named workspace secrets"
});
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
import { Request, Response } from "express";
import { EELicenseService } from "../../services";
import { getLicenseServerUrl } from "../../../config";
import { licenseServerKeyRequest } from "../../../config/request";
import { validateRequest } from "../../../helpers/validation";
import * as reqValidator from "../../../validation/cloudProducts";
/**
* Return available cloud product information.
* Note: Nicely formatted to easily construct a table from
* @param req
* @param res
* @returns
*/
export const getCloudProducts = async (req: Request, res: Response) => {
const {
query: { "billing-cycle": billingCycle }
} = await validateRequest(reqValidator.GetCloudProductsV1, req);
if (EELicenseService.instanceType === "cloud") {
const { data } = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}`
);
return res.status(200).send(data);
}
return res.status(200).send({
head: [],
rows: []
});
};

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

@@ -0,0 +1,31 @@
import * as identitiesController from "./identitiesController";
import * as secretController from "./secretController";
import * as secretSnapshotController from "./secretSnapshotController";
import * as organizationsController from "./organizationsController";
import * as ssoController from "./ssoController";
import * as usersController from "./usersController";
import * as workspaceController from "./workspaceController";
import * as membershipController from "./membershipController";
import * as cloudProductsController from "./cloudProductsController";
import * as roleController from "./roleController";
import * as secretApprovalPolicyController from "./secretApprovalPolicyController";
import * as secretApprovalRequestController from "./secretApprovalRequestsController";
import * as secretRotationProviderController from "./secretRotationProviderController";
import * as secretRotationController from "./secretRotationController";
export {
identitiesController,
secretController,
secretSnapshotController,
organizationsController,
ssoController,
usersController,
workspaceController,
membershipController,
cloudProductsController,
roleController,
secretApprovalPolicyController,
secretApprovalRequestController,
secretRotationProviderController,
secretRotationController
};

View File

@@ -0,0 +1,86 @@
import { Request, Response } from "express";
import { IUser, Membership, Workspace } from "../../../models";
import { EventType } from "../../../ee/models";
import { IMembershipPermission } from "../../../models/membership";
import { BadRequestError, UnauthorizedRequestError } from "../../../utils/errors";
import { ADMIN, MEMBER } from "../../../variables/organization";
import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from "../../../variables";
import _ from "lodash";
import { EEAuditLogService } from "../../services";
export const denyMembershipPermissions = async (req: Request, res: Response) => {
const { membershipId } = req.params;
const { permissions } = req.body;
const sanitizedMembershipPermissions: IMembershipPermission[] = permissions.map((permission: IMembershipPermission) => {
if (!permission.ability || !permission.environmentSlug || ![PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS].includes(permission.ability)) {
throw BadRequestError({ message: "One or more required fields are missing from the request or have incorrect type" })
}
return {
environmentSlug: permission.environmentSlug,
ability: permission.ability
}
})
const sanitizedMembershipPermissionsUnique = _.uniqWith(sanitizedMembershipPermissions, _.isEqual)
const membershipToModify = await Membership.findById(membershipId)
if (!membershipToModify) {
throw BadRequestError({ message: "Unable to locate resource" })
}
// check if the user making the request is a admin of this project
if (![ADMIN, MEMBER].includes(membershipToModify.role)) {
throw UnauthorizedRequestError()
}
// check if the requested slugs are indeed a part of this related workspace
const relatedWorkspace = await Workspace.findById(membershipToModify.workspace)
if (!relatedWorkspace) {
throw BadRequestError({ message: "Something went wrong when locating the related workspace" })
}
const uniqueEnvironmentSlugs = new Set(_.uniq(_.map(relatedWorkspace.environments, "slug")));
sanitizedMembershipPermissionsUnique.forEach(permission => {
if (!uniqueEnvironmentSlugs.has(permission.environmentSlug)) {
throw BadRequestError({ message: "Unknown environment slug reference" })
}
})
// update the permissions
const updatedMembershipWithPermissions = await Membership.findByIdAndUpdate(
{ _id: membershipToModify._id },
{ $set: { deniedPermissions: sanitizedMembershipPermissionsUnique } },
{ new: true }
).populate<{ user: IUser }>("user");
if (!updatedMembershipWithPermissions) {
throw BadRequestError({ message: "The resource has been removed before it can be modified" })
}
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS,
metadata: {
userId: updatedMembershipWithPermissions.user._id.toString(),
email: updatedMembershipWithPermissions.user.email,
deniedPermissions: updatedMembershipWithPermissions.deniedPermissions.map(({
environmentSlug,
ability
}) => ({
environmentSlug,
ability
}))
}
},
{
workspaceId: updatedMembershipWithPermissions.workspace
}
);
res.send({
permissionsDenied: updatedMembershipWithPermissions.deniedPermissions,
})
}

View File

@@ -0,0 +1,550 @@
import { Types } from "mongoose";
import { Request, Response } from "express";
import { getLicenseServerUrl } from "../../../config";
import { licenseServerKeyRequest } from "../../../config/request";
import { EELicenseService } from "../../services";
import { validateRequest } from "../../../helpers/validation";
import * as reqValidator from "../../../validation/organization";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getAuthDataOrgPermissions,
} from "../../services/RoleService";
import { ForbiddenError } from "@casl/ability";
import { Organization } from "../../../models";
import { OrganizationNotFoundError } from "../../../utils/errors";
export const getOrganizationPlansTable = async (req: Request, res: Response) => {
const {
query: { billingCycle },
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlansTablev1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const { data } = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}`
);
return res.status(200).send(data);
};
/**
* Return the organization current plan's feature set
*/
export const getOrganizationPlan = async (req: Request, res: Response) => {
const {
query: { workspaceId },
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlanv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const plan = await EELicenseService.getPlan(
new Types.ObjectId(organizationId),
new Types.ObjectId(workspaceId)
);
return res.status(200).send({
plan
});
};
/**
* Return checkout url for pro trial
* @param req
* @param res
* @returns
*/
export const startOrganizationTrial = async (req: Request, res: Response) => {
const {
params: { organizationId },
body: { success_url }
} = await validateRequest(reqValidator.StartOrgTrailv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const {
data: { url }
} = await licenseServerKeyRequest.post(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/session/trial`,
{
success_url
}
);
EELicenseService.delPlan(new Types.ObjectId(organizationId));
return res.status(200).send({
url
});
};
/**
* Return the organization's current plan's billing info
* @param req
* @param res
* @returns
*/
export const getOrganizationPlanBillingInfo = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlanBillingInfov1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { data } = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/cloud-plan/billing`
);
return res.status(200).send(data);
};
/**
* Return the organization's current plan's feature table
* @param req
* @param res
* @returns
*/
export const getOrganizationPlanTable = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPlanTablev1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { data } = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/cloud-plan/table`
);
return res.status(200).send(data);
};
export const getOrganizationBillingDetails = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgBillingDetailsv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { data } = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details`
);
return res.status(200).send(data);
};
export const updateOrganizationBillingDetails = async (req: Request, res: Response) => {
const {
params: { organizationId },
body: { name, email }
} = await validateRequest(reqValidator.UpdateOrgBillingDetailsv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { data } = await licenseServerKeyRequest.patch(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details`,
{
...(name ? { name } : {}),
...(email ? { email } : {})
}
);
return res.status(200).send(data);
};
/**
* Return the organization's payment methods on file
*/
export const getOrganizationPmtMethods = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgPmtMethodsv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const {
data: { pmtMethods }
} = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/payment-methods`
);
return res.status(200).send(pmtMethods);
};
/**
* Return URL to add payment method for organization
*/
export const addOrganizationPmtMethod = async (req: Request, res: Response) => {
const {
params: { organizationId },
body: { success_url, cancel_url }
} = await validateRequest(reqValidator.CreateOrgPmtMethodv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const {
data: { url }
} = await licenseServerKeyRequest.post(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/payment-methods`,
{
success_url,
cancel_url
}
);
return res.status(200).send({
url
});
};
/**
* Delete payment method with id [pmtMethodId] for organization
* @param req
* @param res
* @returns
*/
export const deleteOrganizationPmtMethod = async (req: Request, res: Response) => {
const {
params: { organizationId, pmtMethodId }
} = await validateRequest(reqValidator.DelOrgPmtMethodv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { data } = await licenseServerKeyRequest.delete(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/payment-methods/${pmtMethodId}`
);
return res.status(200).send(data);
};
/**
* Return the organization's tax ids on file
*/
export const getOrganizationTaxIds = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgTaxIdsv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const {
data: { tax_ids }
} = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/tax-ids`
);
return res.status(200).send(tax_ids);
};
/**
* Add tax id to organization
*/
export const addOrganizationTaxId = async (req: Request, res: Response) => {
const {
params: { organizationId },
body: { type, value }
} = await validateRequest(reqValidator.CreateOrgTaxId, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { data } = await licenseServerKeyRequest.post(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/tax-ids`,
{
type,
value
}
);
return res.status(200).send(data);
};
/**
* Delete tax id with id [taxId] from organization tax ids on file
* @param req
* @param res
* @returns
*/
export const deleteOrganizationTaxId = async (req: Request, res: Response) => {
const {
params: { organizationId, taxId }
} = await validateRequest(reqValidator.DelOrgTaxIdv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const { data } = await licenseServerKeyRequest.delete(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/billing-details/tax-ids/${taxId}`
);
return res.status(200).send(data);
};
/**
* Return organization's invoices on file
* @param req
* @param res
* @returns
*/
export const getOrganizationInvoices = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgInvoicesv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const {
data: { invoices }
} = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/invoices`
);
return res.status(200).send(invoices);
};
/**
* Return organization's licenses on file
* @param req
* @param res
* @returns
*/
export const getOrganizationLicenses = async (req: Request, res: Response) => {
const {
params: { organizationId }
} = await validateRequest(reqValidator.GetOrgLicencesv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
const organization = await Organization.findById(organizationId);
if (!organization) {
throw OrganizationNotFoundError({
message: "Failed to find organization"
});
}
const {
data: { licenses }
} = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${
organization.customerId
}/licenses`
);
return res.status(200).send(licenses);
};

View File

@@ -0,0 +1,290 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { Membership, User } from "../../../models";
import {
CreateRoleSchema,
DeleteRoleSchema,
GetRoleSchema,
GetUserPermission,
GetUserProjectPermission,
UpdateRoleSchema
} from "../../validation/role";
import {
ProjectPermissionActions,
ProjectPermissionSub,
adminProjectPermissions,
getAuthDataProjectPermissions,
memberProjectPermissions,
noAccessProjectPermissions,
viewerProjectPermission
} from "../../services/ProjectRoleService";
import {
OrgPermissionActions,
OrgPermissionSubjects,
adminPermissions,
getAuthDataOrgPermissions,
getUserOrgPermissions,
memberPermissions,
noAccessPermissions
} from "../../services/RoleService";
import { BadRequestError } from "../../../utils/errors";
import { Role } from "../../models";
import { validateRequest } from "../../../helpers/validation";
import { packRules } from "@casl/ability/extra";
export const createRole = async (req: Request, res: Response) => {
const {
body: { workspaceId, name, description, slug, permissions, orgId }
} = await validateRequest(CreateRoleSchema, req);
const isOrgRole = !workspaceId; // if workspaceid is provided then its a workspace rule
if (isOrgRole) {
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." });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
if (permission.cannot(ProjectPermissionActions.Create, ProjectPermissionSub.Role)) {
throw BadRequestError({ message: "User doesn't have the permission." });
}
}
const existingRole = await Role.findOne({ organization: orgId, workspace: workspaceId, slug });
if (existingRole) {
throw BadRequestError({ message: "Role already exist" });
}
const role = new Role({
organization: orgId,
workspace: workspaceId,
isOrgRole,
name,
slug,
permissions,
description
});
await role.save();
res.status(200).json({
message: "Successfully created role",
data: {
role
}
});
};
export const updateRole = async (req: Request, res: Response) => {
const {
params: { id },
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 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." });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
if (permission.cannot(ProjectPermissionActions.Edit, ProjectPermissionSub.Role)) {
throw BadRequestError({ message: "User doesn't have the workspace permission." });
}
}
if (slug) {
const existingRole = await Role.findOne({
organization: orgId,
slug,
isOrgRole,
workspace: workspaceId
});
if (existingRole && existingRole.id !== id) {
throw BadRequestError({ message: "Role already exist" });
}
}
const role = await Role.findByIdAndUpdate(
id,
{ name, description, slug, permissions },
{ returnDocument: "after" }
);
if (!role) {
throw BadRequestError({ message: "Role not found" });
}
res.status(200).json({
message: "Successfully updated role",
data: {
role
}
});
};
export const deleteRole = async (req: Request, res: Response) => {
const {
params: { id }
} = await validateRequest(DeleteRoleSchema, req);
const role = await Role.findById(id);
if (!role) {
throw BadRequestError({ message: "Role not found" });
}
const isOrgRole = !role.workspace;
if (isOrgRole) {
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." });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: role.workspace
});
if (permission.cannot(ProjectPermissionActions.Delete, ProjectPermissionSub.Role)) {
throw BadRequestError({ message: "User doesn't have the workspace permission." });
}
}
await Role.findByIdAndDelete(role.id);
res.status(200).json({
message: "Successfully deleted role",
data: {
role
}
});
};
export const getRoles = async (req: Request, res: Response) => {
const {
query: { workspaceId, orgId }
} = await validateRequest(GetRoleSchema, req);
const isOrgRole = !workspaceId;
if (isOrgRole) {
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." });
}
} else {
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
if (permission.cannot(ProjectPermissionActions.Read, ProjectPermissionSub.Role)) {
throw BadRequestError({ message: "User doesn't have the workspace permission." });
}
}
const customRoles = await Role.find({ organization: orgId, isOrgRole, workspace: workspaceId });
// as this is shared between org and workspace switch the rule set based on it
const roles = [
{
_id: "admin",
name: "Admin",
slug: "admin",
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",
slug: "member",
description: "Non-administrative role in an organization",
permissions: isOrgRole ? memberPermissions.rules : memberProjectPermissions.rules
},
// viewer role only for project level
...(isOrgRole
? []
: [
{
_id: "viewer",
name: "Viewer",
slug: "viewer",
description: "Non-administrative role in an organization",
permissions: viewerProjectPermission.rules
}
]),
...customRoles
];
res.status(200).json({
message: "Successfully fetched role list",
data: {
roles
}
});
};
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({
data: {
permissions: packRules(permission.rules),
membership
}
});
};
export const getUserWorkspacePermissions = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(GetUserProjectPermission, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
let membership;
if (req.authData.authPayload instanceof User) {
membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: new Types.ObjectId(workspaceId)
})
}
res.status(200).json({
data: {
permissions: packRules(permission.rules),
membership
}
});
};

View File

@@ -0,0 +1,143 @@
import { Types } from "mongoose";
import { ForbiddenError, subject } from "@casl/ability";
import { Request, Response } from "express";
import { nanoid } from "nanoid";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../services/ProjectRoleService";
import { validateRequest } from "../../../helpers/validation";
import { SecretApprovalPolicy } from "../../models/secretApprovalPolicy";
import { getSecretPolicyOfBoard } from "../../services/SecretApprovalService";
import { BadRequestError } from "../../../utils/errors";
import * as reqValidator from "../../validation/secretApproval";
const ERR_SECRET_APPROVAL_NOT_FOUND = BadRequestError({ message: "secret approval not found" });
export const createSecretApprovalPolicy = async (req: Request, res: Response) => {
const {
body: { approvals, secretPath, approvers, environment, workspaceId, name }
} = await validateRequest(reqValidator.CreateSecretApprovalRule, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.SecretApproval
);
const secretApproval = new SecretApprovalPolicy({
workspace: workspaceId,
name: name ?? `${environment}-${nanoid(3)}`,
secretPath,
environment,
approvals,
approvers
});
await secretApproval.save();
return res.send({
approval: secretApproval
});
};
export const updateSecretApprovalPolicy = async (req: Request, res: Response) => {
const {
body: { approvals, approvers, secretPath, name },
params: { id }
} = await validateRequest(reqValidator.UpdateSecretApprovalRule, req);
const secretApproval = await SecretApprovalPolicy.findById(id);
if (!secretApproval) throw ERR_SECRET_APPROVAL_NOT_FOUND;
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: secretApproval.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.SecretApproval
);
const updatedDoc = await SecretApprovalPolicy.findByIdAndUpdate(id, {
approvals,
approvers,
name: (name || secretApproval?.name) ?? `${secretApproval.environment}-${nanoid(3)}`,
...(secretPath === null ? { $unset: { secretPath: 1 } } : { secretPath })
});
return res.send({
approval: updatedDoc
});
};
export const deleteSecretApprovalPolicy = async (req: Request, res: Response) => {
const {
params: { id }
} = await validateRequest(reqValidator.DeleteSecretApprovalRule, req);
const secretApproval = await SecretApprovalPolicy.findById(id);
if (!secretApproval) throw ERR_SECRET_APPROVAL_NOT_FOUND;
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: secretApproval.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.SecretApproval
);
const deletedDoc = await SecretApprovalPolicy.findByIdAndDelete(id);
return res.send({
approval: deletedDoc
});
};
export const getSecretApprovalPolicy = async (req: Request, res: Response) => {
const {
query: { workspaceId }
} = await validateRequest(reqValidator.GetSecretApprovalRuleList, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretApproval
);
const doc = await SecretApprovalPolicy.find({ workspace: workspaceId });
return res.send({
approvals: doc
});
};
export const getSecretApprovalPolicyOfBoard = async (req: Request, res: Response) => {
const {
query: { workspaceId, environment, secretPath }
} = await validateRequest(reqValidator.GetSecretApprovalPolicyOfABoard, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { secretPath, environment })
);
const secretApprovalPolicy = await getSecretPolicyOfBoard(workspaceId, environment, secretPath);
return res.send({ policy: secretApprovalPolicy });
};

View File

@@ -0,0 +1,366 @@
import { Request, Response } from "express";
import { validateRequest } from "../../../helpers/validation";
import { Folder, Membership, User } from "../../../models";
import { ApprovalStatus, SecretApprovalRequest } from "../../models/secretApprovalRequest";
import * as reqValidator from "../../validation/secretApprovalRequest";
import { getFolderWithPathFromId } from "../../../services/FolderService";
import { BadRequestError, UnauthorizedRequestError } from "../../../utils/errors";
import { ISecretApprovalPolicy, SecretApprovalPolicy } from "../../models/secretApprovalPolicy";
import { performSecretApprovalRequestMerge } from "../../services/SecretApprovalService";
import { Types } from "mongoose";
import { EEAuditLogService } from "../../services";
import { EventType } from "../../models";
export const getSecretApprovalRequestCount = async (req: Request, res: Response) => {
const {
query: { workspaceId }
} = 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([
{
$match: {
workspace: new Types.ObjectId(workspaceId)
}
},
{
$lookup: {
from: SecretApprovalPolicy.collection.name,
localField: "policy",
foreignField: "_id",
as: "policy"
}
},
{ $unwind: "$policy" },
...(membership.role !== "admin"
? [
{
$match: {
$or: [
{ committer: new Types.ObjectId(membership.id) },
{ "policy.approvers": new Types.ObjectId(membership.id) }
]
}
}
]
: []),
{
$group: {
_id: "$status",
count: { $sum: 1 }
}
}
]);
const openRequests = approvalRequestCount.find(({ _id }) => _id === "open");
const closedRequests = approvalRequestCount.find(({ _id }) => _id === "close");
return res.send({
approvals: { open: openRequests?.count || 0, closed: closedRequests?.count || 0 }
});
};
export const getSecretApprovalRequests = async (req: Request, res: Response) => {
const {
query: { status, committer, workspaceId, environment, limit, offset }
} = 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 = {
workspace: new Types.ObjectId(workspaceId),
environment,
committer: committer ? new Types.ObjectId(committer) : undefined,
status
};
// to strip of undefined in query we use es6 spread to ignore those fields
Object.entries(query).forEach(
([key, value]) => value === undefined && delete query[key as keyof typeof query]
);
const approvalRequests = await SecretApprovalRequest.aggregate([
{
$match: query
},
{ $sort: { createdAt: -1 } },
{
$lookup: {
from: SecretApprovalPolicy.collection.name,
localField: "policy",
foreignField: "_id",
as: "policy"
}
},
{ $unwind: "$policy" },
...(membership.role !== "admin"
? [
{
$match: {
$or: [
{ committer: new Types.ObjectId(membership.id) },
{ "policy.approvers": new Types.ObjectId(membership.id) }
]
}
}
]
: []),
{ $skip: offset },
{ $limit: limit }
]);
if (!approvalRequests.length) return res.send({ approvals: [] });
const unqiueEnvs = environment ?? {
$in: [...new Set(approvalRequests.map(({ environment }) => environment))]
};
const approvalRootFolders = await Folder.find({
workspace: workspaceId,
environment: unqiueEnvs
}).lean();
const formatedApprovals = approvalRequests.map((el) => {
let secretPath = "/";
const folders = approvalRootFolders.find(({ environment }) => environment === el.environment);
if (folders) {
secretPath = getFolderWithPathFromId(folders?.nodes, el.folderId)?.folderPath || "/";
}
return { ...el, secretPath };
});
return res.send({
approvals: formatedApprovals
});
};
export const getSecretApprovalRequestDetails = async (req: Request, res: Response) => {
const {
params: { id }
} = await validateRequest(reqValidator.getSecretApprovalRequestDetails, req);
const secretApprovalRequest = await SecretApprovalRequest.findById(id)
.populate<{ policy: ISecretApprovalPolicy }>("policy")
.populate({
path: "commits.secretVersion",
populate: {
path: "tags"
}
})
.populate("commits.secret", "version")
.populate("commits.newVersion.tags")
.lean();
if (!secretApprovalRequest)
throw BadRequestError({ message: "Secret approval request not found" });
if (!(req.authData.authPayload instanceof User)) return;
const membership = await Membership.findOne({
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.equals(membership.id) &&
!secretApprovalRequest.policy.approvers.find(
(approverId) => approverId.toString() === membership._id.toString()
)
) {
throw UnauthorizedRequestError({ message: "User has no access" });
}
let secretPath = "/";
const approvalRootFolders = await Folder.findOne({
workspace: secretApprovalRequest.workspace,
environment: secretApprovalRequest.environment
}).lean();
if (approvalRootFolders) {
secretPath =
getFolderWithPathFromId(approvalRootFolders?.nodes, secretApprovalRequest.folderId)
?.folderPath || "/";
}
return res.send({
approval: { ...secretApprovalRequest, secretPath }
});
};
export const updateSecretApprovalReviewStatus = async (req: Request, res: Response) => {
const {
body: { status },
params: { id }
} = await validateRequest(reqValidator.updateSecretApprovalReviewStatus, req);
const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{
policy: ISecretApprovalPolicy;
}>("policy");
if (!secretApprovalRequest)
throw BadRequestError({ message: "Secret approval request not found" });
if (!(req.authData.authPayload instanceof User)) return;
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (
membership.role !== "admin" &&
secretApprovalRequest.committer !== membership.id &&
!secretApprovalRequest.policy.approvers.find((approverId) => approverId.equals(membership.id))
) {
throw UnauthorizedRequestError({ message: "User has no access" });
}
const reviewerPos = secretApprovalRequest.reviewers.findIndex(
({ member }) => member.toString() === membership._id.toString()
);
if (reviewerPos !== -1) {
secretApprovalRequest.reviewers[reviewerPos].status = status;
} else {
secretApprovalRequest.reviewers.push({ member: membership._id, status });
}
await secretApprovalRequest.save();
return res.send({ status });
};
export const mergeSecretApprovalRequest = async (req: Request, res: Response) => {
const {
params: { id }
} = await validateRequest(reqValidator.mergeSecretApprovalRequest, req);
const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{
policy: ISecretApprovalPolicy;
}>("policy");
if (!secretApprovalRequest)
throw BadRequestError({ message: "Secret approval request not found" });
if (!(req.authData.authPayload instanceof User)) return;
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (
membership.role !== "admin" &&
secretApprovalRequest.committer !== membership.id &&
!secretApprovalRequest.policy.approvers.find((approverId) => approverId.equals(membership.id))
) {
throw UnauthorizedRequestError({ message: "User has no access" });
}
const reviewers = secretApprovalRequest.reviewers.reduce<Record<string, ApprovalStatus>>(
(prev, curr) => ({ ...prev, [curr.member.toString()]: curr.status }),
{}
);
const hasMinApproval =
secretApprovalRequest.policy.approvals <=
secretApprovalRequest.policy.approvers.filter(
(approverId) => reviewers[approverId.toString()] === ApprovalStatus.APPROVED
).length;
if (!hasMinApproval) throw BadRequestError({ message: "Doesn't have minimum approvals needed" });
const approval = await performSecretApprovalRequestMerge(
id,
req.authData,
membership._id.toString()
);
return res.send({ approval });
};
export const updateSecretApprovalRequestStatus = async (req: Request, res: Response) => {
const {
body: { status },
params: { id }
} = await validateRequest(reqValidator.updateSecretApprovalRequestStatus, req);
const secretApprovalRequest = await SecretApprovalRequest.findById(id).populate<{
policy: ISecretApprovalPolicy;
}>("policy");
if (!secretApprovalRequest)
throw BadRequestError({ message: "Secret approval request not found" });
if (!(req.authData.authPayload instanceof User)) return;
const membership = await Membership.findOne({
user: req.authData.authPayload._id,
workspace: secretApprovalRequest.workspace
});
if (!membership) throw UnauthorizedRequestError();
if (
membership.role !== "admin" &&
secretApprovalRequest.committer !== membership.id &&
!secretApprovalRequest.policy.approvers.find((approverId) => approverId.equals(membership._id))
) {
throw UnauthorizedRequestError({ message: "User has no access" });
}
if (secretApprovalRequest.hasMerged)
throw BadRequestError({ message: "Approval request has been merged" });
if (secretApprovalRequest.status === "close" && status === "close")
throw BadRequestError({ message: "Approval request is already closed" });
if (secretApprovalRequest.status === "open" && status === "open")
throw BadRequestError({ message: "Approval request is already open" });
const updatedRequest = await SecretApprovalRequest.findByIdAndUpdate(
id,
{ status, statusChangeBy: membership._id },
{ new: true }
);
if (status === "close") {
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.SECRET_APPROVAL_CLOSED,
metadata: {
closedBy: membership._id.toString(),
secretApprovalRequestId: id,
secretApprovalRequestSlug: secretApprovalRequest.slug
}
},
{
workspaceId: secretApprovalRequest.workspace
}
);
} else {
await EEAuditLogService.createAuditLog(
req.authData,
{
type: EventType.SECRET_APPROVAL_REOPENED,
metadata: {
reopenedBy: membership._id.toString(),
secretApprovalRequestId: id,
secretApprovalRequestSlug: secretApprovalRequest.slug
}
},
{
workspaceId: secretApprovalRequest.workspace
}
);
}
return res.send({ approval: updatedRequest });
};

View File

@@ -0,0 +1,269 @@
import { ForbiddenError, subject } from "@casl/ability";
import { Request, Response } from "express";
import { validateRequest } from "../../../helpers/validation";
import { Folder, Secret } from "../../../models";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../services/ProjectRoleService";
import { BadRequestError } from "../../../utils/errors";
import * as reqValidator from "../../../validation";
import { SecretVersion } from "../../models";
import { EESecretService } from "../../services";
import { getFolderWithPathFromId } from "../../../services/FolderService";
/**
* Return secret versions for secret with id [secretId]
* @param req
* @param res
*/
export const getSecretVersions = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Return secret versions'
#swagger.description = 'Return secret versions'
#swagger.security = [{
"apiKeyAuth": []
}]
#swagger.parameters['secretId'] = {
"description": "ID of secret",
"required": true,
"type": "string"
}
#swagger.parameters['offset'] = {
"description": "Number of versions to skip",
"required": false,
"type": "string"
}
#swagger.parameters['limit'] = {
"description": "Maximum number of versions to return",
"required": false,
"type": "string"
}
#swagger.responses[200] = {
content: {
"application/json": {
schema: {
"type": "object",
"properties": {
"secretVersions": {
"type": "array",
"items": {
$ref: "#/components/schemas/SecretVersion"
},
"description": "Secret versions"
}
}
}
}
}
}
*/
const {
params: { secretId },
query: { offset, limit }
} = await validateRequest(reqValidator.GetSecretVersionsV1, req);
const secret = await Secret.findById(secretId);
if (!secret) {
throw BadRequestError({ message: "Failed to find secret" });
}
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: secret.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRollback
);
const secretVersions = await SecretVersion.find({
secret: secretId
})
.sort({ createdAt: -1 })
.skip(offset)
.limit(limit);
return res.status(200).send({
secretVersions
});
};
/**
* Roll back secret with id [secretId] to version [version]
* @param req
* @param res
* @returns
*/
export const rollbackSecretVersion = async (req: Request, res: Response) => {
/*
#swagger.summary = 'Roll back secret to a version.'
#swagger.description = 'Roll back secret to a version.'
#swagger.security = [{
"apiKeyAuth": []
}]
#swagger.parameters['secretId'] = {
"description": "ID of secret",
"required": true,
"type": "string"
}
#swagger.requestBody = {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"version": {
"type": "integer",
"description": "Version of secret to roll back to"
}
}
}
}
}
}
#swagger.responses[200] = {
content: {
"application/json": {
schema: {
"type": "object",
"properties": {
"secret": {
"type": "object",
$ref: "#/components/schemas/Secret",
"description": "Secret rolled back to"
}
}
}
}
}
}
*/
const {
params: { secretId },
body: { version }
} = await validateRequest(reqValidator.RollbackSecretVersionV1, req);
const toBeUpdatedSec = await Secret.findById(secretId);
if (!toBeUpdatedSec) {
throw BadRequestError({ message: "Failed to find secret" });
}
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: toBeUpdatedSec.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.SecretRollback
);
// validate secret version
const oldSecretVersion = await SecretVersion.findOne({
secret: secretId,
version
}).select("+secretBlindIndex");
if (!oldSecretVersion) throw new Error("Failed to find secret version");
const {
workspace,
type,
user,
environment,
secretBlindIndex,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
algorithm,
folder,
keyEncoding
} = oldSecretVersion;
let secretPath = "/";
const folders = await Folder.findOne({ workspace, environment });
if (folders)
secretPath = getFolderWithPathFromId(folders.nodes, folder || "root")?.folderPath || "/";
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment: toBeUpdatedSec.environment, secretPath })
);
// update secret
const secret = await Secret.findByIdAndUpdate(
secretId,
{
$inc: {
version: 1
},
workspace,
type,
user,
environment,
...(secretBlindIndex ? { secretBlindIndex } : {}),
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
folderId: folder,
algorithm,
keyEncoding
},
{
new: true
}
);
if (!secret) throw new Error("Failed to find and update secret");
// add new secret version
await new SecretVersion({
secret: secretId,
version: secret.version,
workspace,
type,
user,
environment,
isDeleted: false,
...(secretBlindIndex ? { secretBlindIndex } : {}),
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
folder,
algorithm,
keyEncoding
}).save();
// take secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId: secret.workspace,
environment,
folderId: folder
});
return res.status(200).send({
secret
});
};

View File

@@ -0,0 +1,110 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { validateRequest } from "../../../helpers/validation";
import * as reqValidator from "../../validation/secretRotation";
import * as secretRotationService from "../../secretRotation/service";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
export const createSecretRotation = async (req: Request, res: Response) => {
const {
body: {
provider,
customProvider,
interval,
outputs,
secretPath,
environment,
workspaceId,
inputs
}
} = await validateRequest(reqValidator.createSecretRotationV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.SecretRotation
);
const secretRotation = await secretRotationService.createSecretRotation({
workspaceId,
inputs,
environment,
secretPath,
outputs,
interval,
customProvider,
provider
});
return res.send({ secretRotation });
};
export const restartSecretRotations = async (req: Request, res: Response) => {
const {
body: { id }
} = await validateRequest(reqValidator.restartSecretRotationV1, req);
const doc = await secretRotationService.getSecretRotationById({ id });
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: doc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.SecretRotation
);
const secretRotation = await secretRotationService.restartSecretRotation({ id });
return res.send({ secretRotation });
};
export const deleteSecretRotations = async (req: Request, res: Response) => {
const {
params: { id }
} = await validateRequest(reqValidator.removeSecretRotationV1, req);
const doc = await secretRotationService.getSecretRotationById({ id });
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: doc.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.SecretRotation
);
const secretRotations = await secretRotationService.deleteSecretRotation({ id });
return res.send({ secretRotations });
};
export const getSecretRotations = async (req: Request, res: Response) => {
const {
query: { workspaceId }
} = await validateRequest(reqValidator.getSecretRotationV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRotation
);
const secretRotations = await secretRotationService.getSecretRotationOfWorkspace(workspaceId);
return res.send({ secretRotations });
};

View File

@@ -0,0 +1,33 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { validateRequest } from "../../../helpers/validation";
import * as reqValidator from "../../validation/secretRotationProvider";
import * as secretRotationProviderService from "../../secretRotation/service";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../services/ProjectRoleService";
import { ForbiddenError } from "@casl/ability";
export const getProviderTemplates = async (req: Request, res: Response) => {
const {
params: { workspaceId }
} = await validateRequest(reqValidator.getSecretRotationProvidersV1, req);
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: new Types.ObjectId(workspaceId)
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRotation
);
const rotationProviderList = await secretRotationProviderService.getProviderTemplate({
workspaceId
});
return res.send(rotationProviderList);
};

View File

@@ -0,0 +1,62 @@
import { ForbiddenError } from "@casl/ability";
import { Request, Response } from "express";
import { validateRequest } from "../../../helpers/validation";
import {
ProjectPermissionActions,
ProjectPermissionSub,
getAuthDataProjectPermissions
} from "../../services/ProjectRoleService";
import * as reqValidator from "../../../validation/secretSnapshot";
import { ISecretVersion, SecretSnapshot, TFolderRootVersionSchema } from "../../models";
/**
* Return secret snapshot with id [secretSnapshotId]
* @param req
* @param res
* @returns
*/
export const getSecretSnapshot = async (req: Request, res: Response) => {
const {
params: { secretSnapshotId }
} = await validateRequest(reqValidator.GetSecretSnapshotV1, req);
const secretSnapshot = await SecretSnapshot.findById(secretSnapshotId)
.lean()
.populate<{ secretVersions: ISecretVersion[] }>({
path: "secretVersions",
populate: {
path: "tags",
model: "Tag"
}
})
.populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion");
if (!secretSnapshot) throw new Error("Failed to find secret snapshot");
const { permission } = await getAuthDataProjectPermissions({
authData: req.authData,
workspaceId: secretSnapshot.workspace
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRollback
);
const folderId = secretSnapshot.folderId;
// to show only the folder required secrets
secretSnapshot.secretVersions = secretSnapshot.secretVersions.filter(
({ folder }) => folder === folderId
);
secretSnapshot.folderVersion = secretSnapshot?.folderVersion?.nodes?.children?.map(
({ id, name }) => ({
id,
name
})
) as any;
return res.status(200).send({
secretSnapshot
});
};

View File

@@ -0,0 +1,268 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { BotOrgService } from "../../../services";
import { SSOConfig } from "../../models";
import { AuthMethod, MembershipOrg, User } from "../../../models";
import { getSSOConfigHelper } from "../../helpers/organizations";
import { client } from "../../../config";
import { ResourceNotFoundError } from "../../../utils/errors";
import { getSiteURL } from "../../../config";
import { EELicenseService } from "../../services";
import * as reqValidator from "../../../validation/sso";
import { validateRequest } from "../../../helpers/validation";
import {
OrgPermissionActions,
OrgPermissionSubjects,
getAuthDataOrgPermissions
} from "../../services/RoleService";
import { ForbiddenError } from "@casl/ability";
/**
* Redirect user to appropriate SSO endpoint after successful authentication
* to finish inputting their master key for logging in or signing up
* @param req
* @param res
* @returns
*/
export const redirectSSO = async (req: Request, res: Response) => {
if (req.isUserCompleted) {
return res.redirect(
`${await getSiteURL()}/login/sso?token=${encodeURIComponent(req.providerAuthToken)}`
);
}
return res.redirect(
`${await getSiteURL()}/signup/sso?token=${encodeURIComponent(req.providerAuthToken)}`
);
};
/**
* Return organization SAML SSO configuration
* @param req
* @param res
* @returns
*/
export const getSSOConfig = async (req: Request, res: Response) => {
const {
query: { organizationId }
} = await validateRequest(reqValidator.GetSsoConfigv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Sso
);
const data = await getSSOConfigHelper({
organizationId: new Types.ObjectId(organizationId)
});
return res.status(200).send(data);
};
/**
* Update organization SAML SSO configuration
* @param req
* @param res
* @returns
*/
export const updateSSOConfig = async (req: Request, res: Response) => {
const {
body: { organizationId, authProvider, isActive, entryPoint, issuer, cert }
} = await validateRequest(reqValidator.UpdateSsoConfigv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Sso
);
const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId));
if (!plan.samlSSO)
return res.status(400).send({
message:
"Failed to update SAML SSO configuration due to plan restriction. Upgrade plan to update SSO configuration."
});
interface PatchUpdate {
authProvider?: string;
isActive?: boolean;
encryptedEntryPoint?: string;
entryPointIV?: string;
entryPointTag?: string;
encryptedIssuer?: string;
issuerIV?: string;
issuerTag?: string;
encryptedCert?: string;
certIV?: string;
certTag?: string;
}
const update: PatchUpdate = {};
if (authProvider) {
update.authProvider = authProvider;
}
if (isActive !== undefined) {
update.isActive = isActive;
}
const key = await BotOrgService.getSymmetricKey(new Types.ObjectId(organizationId));
if (entryPoint) {
const {
ciphertext: encryptedEntryPoint,
iv: entryPointIV,
tag: entryPointTag
} = client.encryptSymmetric(entryPoint, key);
update.encryptedEntryPoint = encryptedEntryPoint;
update.entryPointIV = entryPointIV;
update.entryPointTag = entryPointTag;
}
if (issuer) {
const {
ciphertext: encryptedIssuer,
iv: issuerIV,
tag: issuerTag
} = client.encryptSymmetric(issuer, key);
update.encryptedIssuer = encryptedIssuer;
update.issuerIV = issuerIV;
update.issuerTag = issuerTag;
}
if (cert) {
const {
ciphertext: encryptedCert,
iv: certIV,
tag: certTag
} = client.encryptSymmetric(cert, key);
update.encryptedCert = encryptedCert;
update.certIV = certIV;
update.certTag = certTag;
}
const ssoConfig = await SSOConfig.findOneAndUpdate(
{
organization: new Types.ObjectId(organizationId)
},
update,
{
new: true
}
);
if (!ssoConfig)
throw ResourceNotFoundError({
message: "Failed to find SSO config to update"
});
if (update.isActive !== undefined) {
const membershipOrgs = await MembershipOrg.find({
organization: new Types.ObjectId(organizationId)
}).select("user");
if (update.isActive) {
await User.updateMany(
{
_id: {
$in: membershipOrgs.map((membershipOrg) => membershipOrg.user)
}
},
{
authMethods: [ssoConfig.authProvider]
}
);
} else {
await User.updateMany(
{
_id: {
$in: membershipOrgs.map((membershipOrg) => membershipOrg.user)
}
},
{
authMethods: [AuthMethod.EMAIL]
}
);
}
}
return res.status(200).send(ssoConfig);
};
/**
* Create organization SAML SSO configuration
* @param req
* @param res
* @returns
*/
export const createSSOConfig = async (req: Request, res: Response) => {
const {
body: { organizationId, authProvider, isActive, entryPoint, issuer, cert }
} = await validateRequest(reqValidator.CreateSsoConfigv1, req);
const { permission } = await getAuthDataOrgPermissions({
authData: req.authData,
organizationId: new Types.ObjectId(organizationId)
});
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Sso
);
const plan = await EELicenseService.getPlan(new Types.ObjectId(organizationId));
if (!plan.samlSSO)
return res.status(400).send({
message:
"Failed to create SAML SSO configuration due to plan restriction. Upgrade plan to add SSO configuration."
});
const key = await BotOrgService.getSymmetricKey(new Types.ObjectId(organizationId));
const {
ciphertext: encryptedEntryPoint,
iv: entryPointIV,
tag: entryPointTag
} = client.encryptSymmetric(entryPoint, key);
const {
ciphertext: encryptedIssuer,
iv: issuerIV,
tag: issuerTag
} = client.encryptSymmetric(issuer, key);
const {
ciphertext: encryptedCert,
iv: certIV,
tag: certTag
} = client.encryptSymmetric(cert, key);
const ssoConfig = await new SSOConfig({
organization: new Types.ObjectId(organizationId),
authProvider,
isActive,
encryptedEntryPoint,
entryPointIV,
entryPointTag,
encryptedIssuer,
issuerIV,
issuerTag,
encryptedCert,
certIV,
certTag
}).save();
return res.status(200).send(ssoConfig);
};

View File

@@ -0,0 +1,13 @@
import { Request, Response } from "express";
/**
* Return the ip address of the current user
* @param req
* @param res
* @returns
*/
export const getMyIp = (req: Request, res: Response) => {
return res.status(200).send({
ip: req.authData.ipAddress
});
}

File diff suppressed because it is too large Load Diff

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