1
0
mirror of https://github.com/Infisical/infisical.git synced 2025-03-24 21:44:53 +00:00

Compare commits

..

68 Commits

Author SHA1 Message Date
2142f5736c Merge pull request from Infisical/snyk-upgrade-adb30694539efb19ffe3e73890bb6b8e
[Snyk] Upgrade aws-sdk from 2.1545.0 to 2.1549.0
2024-02-23 13:39:50 -05:00
ce764d70ad Merge branch 'main' into snyk-upgrade-adb30694539efb19ffe3e73890bb6b8e 2024-02-23 13:39:43 -05:00
c2d0ddb2fc Merge pull request from Infisical/snyk-upgrade-d2de299aecc7f7e0bc3f4806027b63db
[Snyk] Upgrade @aws-sdk/client-secrets-manager from 3.502.0 to 3.504.0
2024-02-23 13:38:39 -05:00
7ba9588509 Merge pull request from Infisical/snyk-upgrade-321e83ad66200d3a9986ba215332d07e
[Snyk] Upgrade axios from 1.6.4 to 1.6.7
2024-02-23 13:38:24 -05:00
cddb09e031 Merge pull request from Infisical/snyk-upgrade-ef9af10ff1fb4ccb502ef71e8db6e32a
[Snyk] Upgrade dotenv from 16.3.1 to 16.4.1
2024-02-23 13:38:13 -05:00
046dc83638 Merge pull request from Infisical/snyk-upgrade-79bce0f7942398d32958cc208d2bf3d9
[Snyk] Upgrade @fastify/cors from 8.4.1 to 8.5.0
2024-02-23 13:38:00 -05:00
320074ef6c fix: upgrade @fastify/cors from 8.4.1 to 8.5.0
Snyk has created this PR to upgrade @fastify/cors from 8.4.1 to 8.5.0.

See this package in npm:
https://www.npmjs.com/package/@fastify/cors

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
2024-02-23 17:54:12 +00:00
e780ee6573 fix: upgrade dotenv from 16.3.1 to 16.4.1
Snyk has created this PR to upgrade dotenv from 16.3.1 to 16.4.1.

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

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
2024-02-23 17:54:08 +00:00
a5a881c382 fix: upgrade axios from 1.6.4 to 1.6.7
Snyk has created this PR to upgrade axios from 1.6.4 to 1.6.7.

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

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
2024-02-23 17:54:04 +00:00
200d4a5af6 fix: upgrade @aws-sdk/client-secrets-manager from 3.502.0 to 3.504.0
Snyk has created this PR to upgrade @aws-sdk/client-secrets-manager from 3.502.0 to 3.504.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
2024-02-23 17:54:00 +00:00
07318ec54b fix: upgrade aws-sdk from 2.1545.0 to 2.1549.0
Snyk has created this PR to upgrade aws-sdk from 2.1545.0 to 2.1549.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
2024-02-23 17:53:57 +00:00
92d237a714 Merge pull request from Infisical/snyk-fix-619f8d103918c8185c0381a3771a208f
[Snyk] Security upgrade sanitize-html from 2.11.0 to 2.12.1
2024-02-23 09:49:03 -05:00
6ef988fa86 Merge pull request from akhilmhdh/feat/telemetry-new-fields
feat(telemetry): added new telemetry events
2024-02-23 09:48:42 -05:00
70822d0d98 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-SANITIZEHTML-6256334
2024-02-23 11:28:36 +00:00
e91499b301 feat(telemetry): updated telemetry distinct id to use service token from secrets one 2024-02-23 13:22:53 +05:30
92acb4d943 feat(telemetry): fixed typo in filename lib/telemetry and capitalized new posthog event names 2024-02-23 13:19:16 +05:30
76daa20d69 feat(telemetry): added telemetry events for creation of integration,project,machine identity and user invitation to org 2024-02-23 13:19:16 +05:30
a231813f01 Merge pull request from Nithishvb/fix-uppercase-member-search 2024-02-23 01:02:01 -05:00
3eb2bdb191 Merge pull request from Infisical/daniel/show-upgrade-to-everyone
(style): Show upgrade alert to all users
2024-02-22 22:31:05 -05:00
cadf6e1157 Update UpgradeOverlay.tsx 2024-02-23 01:13:26 +01:00
ceb7fafc06 Update UpgradeProjectAlert.tsx 2024-02-23 01:12:22 +01:00
3063bb9982 Update UpgradeProjectAlert.tsx 2024-02-23 01:12:02 +01:00
3d82a43615 Merge pull request from Infisical/daniel/ghost-users-fixes
(Fix): Project upgrade
2024-02-22 17:20:44 -05:00
028541a18a Update project-membership-service.ts 2024-02-22 23:18:32 +01:00
66a631ff46 Update SecretOverviewPage.tsx 2024-02-22 23:16:21 +01:00
28adb8f0ac Re-add upgrade popup 2024-02-22 23:12:41 +01:00
5c988c2cd5 Docs 2024-02-22 23:07:07 +01:00
acf8a54abb Fix service tokens not working after upgrade 2024-02-22 23:06:55 +01:00
387094aa27 Allow deleting project members even on V1 projects 2024-02-22 23:06:24 +01:00
4251e95c15 Merge pull request from Salman2301/fix-typo-doc-port
docs(sdk): fix typo PORT
2024-02-22 16:26:23 -05:00
f4386c2d93 Merge pull request from akhilmhdh/fix/service-token-email-telemetry
fix(telemetry): added back email for telemetry when using service token
2024-02-22 16:23:00 -05:00
ff4b943854 fix admin signup phrasing 2024-02-22 16:04:12 -05:00
879a5ecfac Merge pull request from Salman2301/feat-admin-signup
Add admin invite only signup field
2024-02-22 15:39:06 -05:00
a831a7d848 small typos and update migration timestamp 2024-02-22 15:35:09 -05:00
3138784d1a Merge branch 'main' into feat-admin-signup 2024-02-22 15:13:28 -05:00
0b258e3918 make clear service token with null creator 2024-02-22 15:06:00 -05:00
d0545a01b9 Merge pull request from Infisical/snyk-upgrade-12de5d06bf0c091610dcb9c1c21ef687
[Snyk] Upgrade mysql2 from 3.6.5 to 3.9.1
2024-02-22 14:46:59 -05:00
d71398344f Merge pull request from Infisical/snyk-upgrade-28f9cfd389af9a9d16a7b1f08b87f2b4
[Snyk] Upgrade bullmq from 5.1.1 to 5.1.6
2024-02-22 14:46:46 -05:00
25e3cc047b Merge pull request from Infisical/snyk-upgrade-69ae80b8287feeb813ee50b31af31ab0
[Snyk] Upgrade zod-to-json-schema from 3.22.0 to 3.22.4
2024-02-22 14:46:36 -05:00
17149de567 Merge pull request from Infisical/snyk-upgrade-a58302f2598bcda51b89dcf7293bd0ad
[Snyk] Upgrade @fastify/swagger from 8.12.0 to 8.14.0
2024-02-22 14:46:23 -05:00
cca2fb7ff5 Merge pull request from Infisical/snyk-upgrade-d48144dd89e80fb18b02fe45b4dfd7c8
[Snyk] Upgrade fastify from 4.24.3 to 4.26.0
2024-02-22 14:46:12 -05:00
f1f2d62993 fix: access member returns empty results when search using upper case letters. 2024-02-22 22:32:58 +05:30
be49de5f34 fix(telemetry): added back email for telemetry when using service token 2024-02-22 17:09:33 +05:30
acfa89ba8b fix typo 2024-02-22 05:01:50 -05:00
389ec85554 Merge pull request from akhilmhdh/ci/frontend-ts-check
chore: added type and lint check for frontend ci/cd
2024-02-22 04:54:23 -05:00
2a6b0efe22 Merge pull request from Infisical/update-self-host-config-docker-compose
Update self host config docker compose
2024-02-22 04:45:59 -05:00
74d9a76f75 update self config/docker guide 2024-02-22 04:42:39 -05:00
9c67d43ebe remove upgrade popup 2024-02-22 03:27:41 -05:00
d8f3531b50 chore: added type and lint check for frontend 2024-02-22 13:28:07 +05:30
57be73c17e fix: upgrade fastify from 4.24.3 to 4.26.0
Snyk has created this PR to upgrade fastify from 4.24.3 to 4.26.0.

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

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
2024-02-22 07:47:03 +00:00
a10129e750 fix: upgrade @fastify/swagger from 8.12.0 to 8.14.0
Snyk has created this PR to upgrade @fastify/swagger from 8.12.0 to 8.14.0.

See this package in npm:
https://www.npmjs.com/package/@fastify/swagger

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
2024-02-22 07:46:59 +00:00
adc10cf675 fix: upgrade zod-to-json-schema from 3.22.0 to 3.22.4
Snyk has created this PR to upgrade zod-to-json-schema from 3.22.0 to 3.22.4.

See this package in npm:
https://www.npmjs.com/package/zod-to-json-schema

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
2024-02-22 07:46:55 +00:00
49f7780e52 fix: upgrade bullmq from 5.1.1 to 5.1.6
Snyk has created this PR to upgrade bullmq from 5.1.1 to 5.1.6.

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

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
2024-02-22 07:46:52 +00:00
26482c6b0a fix: upgrade mysql2 from 3.6.5 to 3.9.1
Snyk has created this PR to upgrade mysql2 from 3.6.5 to 3.9.1.

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

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
2024-02-22 07:46:48 +00:00
fed022ed09 feat: removed unused inviteSignup flag 2024-02-22 13:09:51 +05:30
64fbe4161c docs(sdk): fix typo PORT 2024-02-22 12:27:04 +05:30
45772f0108 add envs 2024-02-22 01:27:02 -05:00
d9888f9dd1 envars update + docker standalone 2024-02-22 00:13:21 -05:00
97d2a15d3e feat: updated admin dashboard to use zod and ts enum 2024-02-16 13:41:18 +05:30
a1cc118514 Merge remote-tracking branch 'origin/main' into feat-admin-signup 2024-02-14 23:46:25 +05:30
ee69bccb6e Update disabled sign up routes 2024-02-14 14:18:44 +05:30
0ff3ddb0c8 Update generate schema run 2024-02-14 07:52:46 +05:30
0fb87ab05f Update move to react hook form, rename allowedSignUpDomain 2024-02-12 04:09:46 +05:30
2ef8781378 Update support multiple domain and error handling 2024-02-11 10:55:36 +05:30
3f96f0a8fb Fix dropdown not working on page transition 2024-02-11 00:40:17 +05:30
da377f6fda Update error handling and refactor 2024-02-10 23:00:16 +05:30
5cf1ec2400 Add restrict signup based on domain 2024-02-10 10:44:39 +05:30
6c1489a87b Add admin invite only signup field 2024-02-10 03:26:56 +05:30
56 changed files with 1289 additions and 1042 deletions

@ -1,4 +1,4 @@
name: Check Frontend Pull Request
name: Check Frontend Type and Lint check
on:
pull_request:
@ -10,8 +10,8 @@ on:
- "frontend/.eslintrc.js"
jobs:
check-fe-pr:
name: Check
check-fe-ts-lint:
name: Check Frontend Type and Lint check
runs-on: ubuntu-latest
timeout-minutes: 15
@ -25,12 +25,11 @@ jobs:
cache: "npm"
cache-dependency-path: frontend/package-lock.json
- name: 📦 Install dependencies
run: npm ci --only-production --ignore-scripts
run: npm install
working-directory: frontend
# -
# name: 🧪 Run tests
# run: npm run test:ci
# working-directory: frontend
- name: 🏗️ Run build
run: npm run build
- name: 🏗️ Run Type check
run: npm run type:check
working-directory: frontend
- name: 🏗️ Run Link check
run: npm run lint:fix
working-directory: frontend

@ -9,17 +9,17 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@aws-sdk/client-secrets-manager": "^3.502.0",
"@aws-sdk/client-secrets-manager": "^3.504.0",
"@casl/ability": "^6.5.0",
"@fastify/cookie": "^9.2.0",
"@fastify/cors": "^8.4.1",
"@fastify/cors": "^8.5.0",
"@fastify/etag": "^5.1.0",
"@fastify/formbody": "^7.4.0",
"@fastify/helmet": "^11.1.1",
"@fastify/passport": "^2.4.0",
"@fastify/rate-limit": "^9.0.0",
"@fastify/session": "^10.7.0",
"@fastify/swagger": "^8.12.0",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^2.1.0",
"@node-saml/passport-saml": "^4.0.4",
"@octokit/rest": "^20.0.2",
@ -29,13 +29,13 @@
"@ucast/mongo2js": "^1.3.4",
"ajv": "^8.12.0",
"argon2": "^0.31.2",
"aws-sdk": "^2.1545.0",
"axios": "^1.6.4",
"aws-sdk": "^2.1549.0",
"axios": "^1.6.7",
"axios-retry": "^4.0.0",
"bcrypt": "^5.1.1",
"bullmq": "^5.1.1",
"dotenv": "^16.3.1",
"fastify": "^4.24.3",
"bullmq": "^5.1.6",
"dotenv": "^16.4.1",
"fastify": "^4.26.0",
"fastify-plugin": "^4.5.1",
"handlebars": "^4.7.8",
"ioredis": "^5.3.2",
@ -45,7 +45,7 @@
"knex": "^3.0.1",
"libsodium-wrappers": "^0.7.13",
"lodash.isequal": "^4.5.0",
"mysql2": "^3.6.5",
"mysql2": "^3.9.1",
"nanoid": "^5.0.4",
"node-cache": "^5.1.2",
"nodemailer": "^6.9.9",
@ -63,7 +63,7 @@
"tweetnacl-util": "^0.15.1",
"uuid": "^9.0.1",
"zod": "^3.22.4",
"zod-to-json-schema": "^3.22.0"
"zod-to-json-schema": "^3.22.4"
},
"devDependencies": {
"@types/bcrypt": "^5.0.2",
@ -661,15 +661,15 @@
}
},
"node_modules/@aws-sdk/client-secrets-manager": {
"version": "3.502.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.502.0.tgz",
"integrity": "sha512-ICU084A/EbYMqca6NVFqeMtHh+KCdn0H7UjARUy5ur1yOlXXvxqAJGtKZDYFjuEO08F30zbv7+4HCOy6yjOJ0Q==",
"version": "3.504.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.504.0.tgz",
"integrity": "sha512-JPwsYfQMjs5t74JmA4r1AjpiOG/LEw74d4a8vEdSy3pe2lhl/sSsxSdQtbI30wlJJramngtLNZjxn2+BGDphbg==",
"dependencies": {
"@aws-crypto/sha256-browser": "3.0.0",
"@aws-crypto/sha256-js": "3.0.0",
"@aws-sdk/client-sts": "3.502.0",
"@aws-sdk/client-sts": "3.504.0",
"@aws-sdk/core": "3.496.0",
"@aws-sdk/credential-provider-node": "3.502.0",
"@aws-sdk/credential-provider-node": "3.504.0",
"@aws-sdk/middleware-host-header": "3.502.0",
"@aws-sdk/middleware-logger": "3.502.0",
"@aws-sdk/middleware-recursion-detection": "3.502.0",
@ -767,13 +767,13 @@
}
},
"node_modules/@aws-sdk/client-sso-oidc": {
"version": "3.502.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.502.0.tgz",
"integrity": "sha512-Yc9tZqTOMWtdgpkrdjKShgWb9oKNsFQrItfoiN1xWDllaFFRPi2KTiZiR0AbSTrNasJy13d210DOxrIdte+kWQ==",
"version": "3.504.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.504.0.tgz",
"integrity": "sha512-ODA33/nm2srhV08EW0KZAP577UgV0qjyr7Xp2yEo8MXWL4ZqQZprk1c+QKBhjr4Djesrm0VPmSD/np0mtYP68A==",
"dependencies": {
"@aws-crypto/sha256-browser": "3.0.0",
"@aws-crypto/sha256-js": "3.0.0",
"@aws-sdk/client-sts": "3.502.0",
"@aws-sdk/client-sts": "3.504.0",
"@aws-sdk/core": "3.496.0",
"@aws-sdk/middleware-host-header": "3.502.0",
"@aws-sdk/middleware-logger": "3.502.0",
@ -815,13 +815,13 @@
"node": ">=14.0.0"
},
"peerDependencies": {
"@aws-sdk/credential-provider-node": "*"
"@aws-sdk/credential-provider-node": "^3.504.0"
}
},
"node_modules/@aws-sdk/client-sts": {
"version": "3.502.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.502.0.tgz",
"integrity": "sha512-0q08gsvn6nuRqjK+i/e30PT/t7vvYwmGJS0PhJikZWv5yRDNSUxSYG0uDwKSbLDzmc2UX5+mLeyjPHlL4hbGlA==",
"version": "3.504.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.504.0.tgz",
"integrity": "sha512-IESs8FkL7B/uY+ml4wgoRkrr6xYo4PizcNw6JX17eveq1gRBCPKeGMjE6HTDOcIYZZ8rqz/UeuH3JD4UhrMOnA==",
"dependencies": {
"@aws-crypto/sha256-browser": "3.0.0",
"@aws-crypto/sha256-js": "3.0.0",
@ -867,7 +867,7 @@
"node": ">=14.0.0"
},
"peerDependencies": {
"@aws-sdk/credential-provider-node": "*"
"@aws-sdk/credential-provider-node": "^3.504.0"
}
},
"node_modules/@aws-sdk/core": {
@ -900,16 +900,35 @@
"node": ">=14.0.0"
}
},
"node_modules/@aws-sdk/credential-provider-ini": {
"version": "3.502.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.502.0.tgz",
"integrity": "sha512-1wB/escbspUY6uRDEMp9AMMyypUSyuQ0AMO1yQNtXviV8cPf+CuRbqP/UVnimHO1RuX0n5BmjDVVjUIEU6kuGA==",
"node_modules/@aws-sdk/credential-provider-http": {
"version": "3.503.1",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.503.1.tgz",
"integrity": "sha512-rTdlFFGoPPFMF2YjtlfRuSgKI+XsF49u7d98255hySwhsbwd3Xp+utTTPquxP+CwDxMHbDlI7NxDzFiFdsoZug==",
"dependencies": {
"@aws-sdk/client-sts": "3.502.0",
"@aws-sdk/types": "3.502.0",
"@smithy/fetch-http-handler": "^2.4.1",
"@smithy/node-http-handler": "^2.3.1",
"@smithy/property-provider": "^2.1.1",
"@smithy/protocol-http": "^3.1.1",
"@smithy/smithy-client": "^2.3.1",
"@smithy/types": "^2.9.1",
"@smithy/util-stream": "^2.1.1",
"tslib": "^2.5.0"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@aws-sdk/credential-provider-ini": {
"version": "3.504.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.504.0.tgz",
"integrity": "sha512-ODICLXfr8xTUd3wweprH32Ge41yuBa+u3j0JUcLdTUO1N9ldczSMdo8zOPlP0z4doqD3xbnqMkjNQWgN/Q+5oQ==",
"dependencies": {
"@aws-sdk/client-sts": "3.504.0",
"@aws-sdk/credential-provider-env": "3.502.0",
"@aws-sdk/credential-provider-process": "3.502.0",
"@aws-sdk/credential-provider-sso": "3.502.0",
"@aws-sdk/credential-provider-web-identity": "3.502.0",
"@aws-sdk/credential-provider-sso": "3.504.0",
"@aws-sdk/credential-provider-web-identity": "3.504.0",
"@aws-sdk/types": "3.502.0",
"@smithy/credential-provider-imds": "^2.2.1",
"@smithy/property-provider": "^2.1.1",
@ -922,15 +941,16 @@
}
},
"node_modules/@aws-sdk/credential-provider-node": {
"version": "3.502.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.502.0.tgz",
"integrity": "sha512-qg71UpYeFrjhu5hD+vdRqZ+EYFB11BeszsbfEJGaHhOMHmmTHNBaDAexW+bUnJSXcJL0a8vniCvca+rElbcAHQ==",
"version": "3.504.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.504.0.tgz",
"integrity": "sha512-6+V5hIh+tILmUjf2ZQWQINR3atxQVgH/bFrGdSR/sHSp/tEgw3m0xWL3IRslWU1e4/GtXrfg1iYnMknXy68Ikw==",
"dependencies": {
"@aws-sdk/credential-provider-env": "3.502.0",
"@aws-sdk/credential-provider-ini": "3.502.0",
"@aws-sdk/credential-provider-http": "3.503.1",
"@aws-sdk/credential-provider-ini": "3.504.0",
"@aws-sdk/credential-provider-process": "3.502.0",
"@aws-sdk/credential-provider-sso": "3.502.0",
"@aws-sdk/credential-provider-web-identity": "3.502.0",
"@aws-sdk/credential-provider-sso": "3.504.0",
"@aws-sdk/credential-provider-web-identity": "3.504.0",
"@aws-sdk/types": "3.502.0",
"@smithy/credential-provider-imds": "^2.2.1",
"@smithy/property-provider": "^2.1.1",
@ -958,12 +978,12 @@
}
},
"node_modules/@aws-sdk/credential-provider-sso": {
"version": "3.502.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.502.0.tgz",
"integrity": "sha512-/2Nyvo+cWQpH283lmZBimTJ9JDhES9FzQUkhUXZgxQo3Ez4sguLVi2V9xoFFyG0cMff5fuNivdKHfj4FeMGjZw==",
"version": "3.504.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.504.0.tgz",
"integrity": "sha512-4MgH2or2SjPzaxM08DCW+BjaX4DSsEGJlicHKmz6fh+w9JmLh750oXcTnbvgUeVz075jcs6qTKjvUcsdGM/t8Q==",
"dependencies": {
"@aws-sdk/client-sso": "3.502.0",
"@aws-sdk/token-providers": "3.502.0",
"@aws-sdk/token-providers": "3.504.0",
"@aws-sdk/types": "3.502.0",
"@smithy/property-provider": "^2.1.1",
"@smithy/shared-ini-file-loader": "^2.3.1",
@ -975,11 +995,11 @@
}
},
"node_modules/@aws-sdk/credential-provider-web-identity": {
"version": "3.502.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.502.0.tgz",
"integrity": "sha512-veBAjDqjMMgA2Qxxf9ywDfHYLeJpaeHWLWCQ9XCHwJJ6ZIGWmAZPTq3he/UMr5JIQXooIccqqyqXMDIXPenXpA==",
"version": "3.504.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.504.0.tgz",
"integrity": "sha512-L1ljCvGpIEFdJk087ijf2ohg7HBclOeB1UgBxUBBzf4iPRZTQzd2chGaKj0hm2VVaXz7nglswJeURH5PFcS5oA==",
"dependencies": {
"@aws-sdk/client-sts": "3.502.0",
"@aws-sdk/client-sts": "3.504.0",
"@aws-sdk/types": "3.502.0",
"@smithy/property-provider": "^2.1.1",
"@smithy/types": "^2.9.1",
@ -1079,11 +1099,11 @@
}
},
"node_modules/@aws-sdk/token-providers": {
"version": "3.502.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.502.0.tgz",
"integrity": "sha512-RQgMgIXYlSf0xGl6EUeD+pqIPBlb7e29dbqHOBFc66hJVYUC2ULZX7Y+jLvcGIEaMiIaTPyvntZRFip+U+9hag==",
"version": "3.504.0",
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.504.0.tgz",
"integrity": "sha512-YIJWWsZi2ClUiILS1uh5L6VjmCUSTI6KKMuL9DkGjYqJ0aI6M8bd8fT9Wm7QmXCyjcArTgr/Atkhia4T7oKvzQ==",
"dependencies": {
"@aws-sdk/client-sso-oidc": "3.502.0",
"@aws-sdk/client-sso-oidc": "3.504.0",
"@aws-sdk/types": "3.502.0",
"@smithy/property-provider": "^2.1.1",
"@smithy/shared-ini-file-loader": "^2.3.1",
@ -1676,12 +1696,12 @@
}
},
"node_modules/@fastify/cors": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-8.4.1.tgz",
"integrity": "sha512-iYQJtrY3pFiDS5mo5zRaudzg2OcUdJ96PD6xfkKOOEilly5nnrFZx/W6Sce2T79xxlEn2qpU3t5+qS2phS369w==",
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-8.5.0.tgz",
"integrity": "sha512-/oZ1QSb02XjP0IK1U0IXktEsw/dUBTxJOW7IpIeO8c/tNalw/KjoNSJv1Sf6eqoBPO+TDGkifq6ynFK3v68HFQ==",
"dependencies": {
"fastify-plugin": "^4.0.0",
"mnemonist": "0.39.5"
"mnemonist": "0.39.6"
}
},
"node_modules/@fastify/deepmerge": {
@ -1790,9 +1810,9 @@
}
},
"node_modules/@fastify/swagger": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/@fastify/swagger/-/swagger-8.12.0.tgz",
"integrity": "sha512-IMRc0xYuzRvtFDMuaWHyVbvM7CuAi0g3o2jaVgLDvETXPrXWAMWsHYR5niIdWBDPgGUq+soHkag1DKXyhPDB0w==",
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/@fastify/swagger/-/swagger-8.14.0.tgz",
"integrity": "sha512-sGiznEb3rl6pKGGUZ+JmfI7ct5cwbTQGo+IjewaTvtzfrshnryu4dZwEsjw0YHABpBA+kCz3kpRaHB7qpa67jg==",
"dependencies": {
"fastify-plugin": "^4.0.0",
"json-schema-resolver": "^2.0.0",
@ -5169,9 +5189,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/aws-sdk": {
"version": "2.1545.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1545.0.tgz",
"integrity": "sha512-iDUv6ksG7lTA0l/HlOgYdO6vfYFA1D2/JzAEXSdgKY0C901WgJqBtfs2CncOkCgDe2CjmlMuqciBzAfxCIiKFA==",
"version": "2.1549.0",
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1549.0.tgz",
"integrity": "sha512-SoVfrrV3A2mxH+NV2tA0eMtG301glhewvhL3Ob4107qLWjvwjy/CoWLclMLmfXniTGxbI8tsgN0r5mLZUKey3Q==",
"dependencies": {
"buffer": "4.9.2",
"events": "1.1.1",
@ -5250,9 +5270,9 @@
}
},
"node_modules/axios": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.4.tgz",
"integrity": "sha512-heJnIs6N4aa1eSthhN9M5ioILu8Wi8vmQW9iHQ9NUvfkJb0lEEDUiIdQNAuBtfUt3FxReaKdpQA5DbmMOqzF/A==",
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
"integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
"dependencies": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
@ -5472,15 +5492,15 @@
}
},
"node_modules/bullmq": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.1.1.tgz",
"integrity": "sha512-j3zbNEQWsyHjpqGWiem2XBfmxAjYcArbwsmGlkM1E9MAVcrqB5hQUsXmyy9gEBAdL+PVotMICr7xTquR4Y2sKQ==",
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.1.6.tgz",
"integrity": "sha512-VkLfig+xm4U3hc4QChzuuAy0NGQ9dfPB8o54hmcZHCX9ofp0Zn6bEY+W3Ytkk76eYwPAgXfywDBlAb2Unjl1Rg==",
"dependencies": {
"cron-parser": "^4.6.0",
"glob": "^8.0.3",
"ioredis": "^5.3.2",
"lodash": "^4.17.21",
"msgpackr": "^1.6.2",
"msgpackr": "^1.10.1",
"node-abort-controller": "^3.1.1",
"semver": "^7.5.4",
"tslib": "^2.0.0",
@ -5995,9 +6015,9 @@
}
},
"node_modules/dotenv": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"version": "16.4.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz",
"integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==",
"engines": {
"node": ">=12"
},
@ -6972,9 +6992,19 @@
}
},
"node_modules/fastify": {
"version": "4.24.3",
"resolved": "https://registry.npmjs.org/fastify/-/fastify-4.24.3.tgz",
"integrity": "sha512-6HHJ+R2x2LS3y1PqxnwEIjOTZxFl+8h4kSC/TuDPXtA+v2JnV9yEtOsNSKK1RMD7sIR2y1ZsA4BEFaid/cK5pg==",
"version": "4.26.0",
"resolved": "https://registry.npmjs.org/fastify/-/fastify-4.26.0.tgz",
"integrity": "sha512-Fq/7ziWKc6pYLYLIlCRaqJqEVTIZ5tZYfcW/mDK2AQ9v/sqjGFpj0On0/7hU50kbPVjLO4de+larPA1WwPZSfw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"dependencies": {
"@fastify/ajv-compiler": "^3.5.0",
"@fastify/error": "^3.4.0",
@ -6983,10 +7013,10 @@
"avvio": "^8.2.1",
"fast-content-type-parse": "^1.1.0",
"fast-json-stringify": "^5.8.0",
"find-my-way": "^7.7.0",
"find-my-way": "^8.0.0",
"light-my-request": "^5.11.0",
"pino": "^8.16.0",
"process-warning": "^2.2.0",
"pino": "^8.17.0",
"process-warning": "^3.0.0",
"proxy-addr": "^2.0.7",
"rfdc": "^1.3.0",
"secure-json-parse": "^2.7.0",
@ -6999,6 +7029,11 @@
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz",
"integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ=="
},
"node_modules/fastify/node_modules/process-warning": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz",
"integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="
},
"node_modules/fastq": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
@ -7062,9 +7097,9 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/find-my-way": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-7.7.0.tgz",
"integrity": "sha512-+SrHpvQ52Q6W9f3wJoJBbAQULJuNEEQwBvlvYwACDhBTLOTMiQ0HYWh4+vC3OivGP2ENcTI1oKlFA2OepJNjhQ==",
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.1.0.tgz",
"integrity": "sha512-41QwjCGcVTODUmLLqTMeoHeiozbMXYMAE1CKFiDyi9zVZ2Vjh0yz3MF0WQZoIb+cmzP/XlbFjlF2NtJmvZHznA==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-querystring": "^1.0.0",
@ -9049,9 +9084,9 @@
}
},
"node_modules/mnemonist": {
"version": "0.39.5",
"resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.5.tgz",
"integrity": "sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==",
"version": "0.39.6",
"resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.6.tgz",
"integrity": "sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==",
"dependencies": {
"obliterator": "^2.0.1"
}
@ -9112,9 +9147,9 @@
}
},
"node_modules/mysql2": {
"version": "3.6.5",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.6.5.tgz",
"integrity": "sha512-pS/KqIb0xlXmtmqEuTvBXTmLoQ5LmAz5NW/r8UyQ1ldvnprNEj3P9GbmuQQ2J0A4LO+ynotGi6TbscPa8OUb+w==",
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.1.tgz",
"integrity": "sha512-3njoWAAhGBYy0tWBabqUQcLtczZUxrmmtc2vszQUekg3kTJyZ5/IeLC3Fo04u6y6Iy5Sba7pIIa2P/gs8D3ZeQ==",
"dependencies": {
"denque": "^2.1.0",
"generate-function": "^2.3.1",
@ -13812,9 +13847,9 @@
}
},
"node_modules/zod-to-json-schema": {
"version": "3.22.0",
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.22.0.tgz",
"integrity": "sha512-XQr8EwxPMzJGhoR+d/nRFWdi15VaZ+R5Uhssm+Xx5yS30xCpuutfKRm4rerE0SK9j2dWB5Z3FvDD0w8WMVGzkA==",
"version": "3.22.4",
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.22.4.tgz",
"integrity": "sha512-2Ed5dJ+n/O3cU383xSY28cuVi0BCQhF8nYqWU5paEpl7fVdqdAmiLdqLyfblbNdfOFwFfi/mqU4O1pwc60iBhQ==",
"peerDependencies": {
"zod": "^3.22.4"
}

@ -70,17 +70,17 @@
"vitest": "^1.2.2"
},
"dependencies": {
"@aws-sdk/client-secrets-manager": "^3.502.0",
"@aws-sdk/client-secrets-manager": "^3.504.0",
"@casl/ability": "^6.5.0",
"@fastify/cookie": "^9.2.0",
"@fastify/cors": "^8.4.1",
"@fastify/cors": "^8.5.0",
"@fastify/etag": "^5.1.0",
"@fastify/formbody": "^7.4.0",
"@fastify/helmet": "^11.1.1",
"@fastify/passport": "^2.4.0",
"@fastify/rate-limit": "^9.0.0",
"@fastify/session": "^10.7.0",
"@fastify/swagger": "^8.12.0",
"@fastify/swagger": "^8.14.0",
"@fastify/swagger-ui": "^2.1.0",
"@node-saml/passport-saml": "^4.0.4",
"@octokit/rest": "^20.0.2",
@ -90,13 +90,13 @@
"@ucast/mongo2js": "^1.3.4",
"ajv": "^8.12.0",
"argon2": "^0.31.2",
"aws-sdk": "^2.1545.0",
"axios": "^1.6.4",
"aws-sdk": "^2.1549.0",
"axios": "^1.6.7",
"axios-retry": "^4.0.0",
"bcrypt": "^5.1.1",
"bullmq": "^5.1.1",
"dotenv": "^16.3.1",
"fastify": "^4.24.3",
"bullmq": "^5.1.6",
"dotenv": "^16.4.1",
"fastify": "^4.26.0",
"fastify-plugin": "^4.5.1",
"handlebars": "^4.7.8",
"ioredis": "^5.3.2",
@ -106,7 +106,7 @@
"knex": "^3.0.1",
"libsodium-wrappers": "^0.7.13",
"lodash.isequal": "^4.5.0",
"mysql2": "^3.6.5",
"mysql2": "^3.9.1",
"nanoid": "^5.0.4",
"node-cache": "^5.1.2",
"nodemailer": "^6.9.9",
@ -124,6 +124,6 @@
"tweetnacl-util": "^0.15.1",
"uuid": "^9.0.1",
"zod": "^3.22.4",
"zod-to-json-schema": "^3.22.0"
"zod-to-json-schema": "^3.22.4"
}
}

@ -0,0 +1,20 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
const isTablePresent = await knex.schema.hasTable(TableName.SuperAdmin);
if (isTablePresent) {
await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
t.string("allowedSignUpDomain");
});
}
}
export async function down(knex: Knex): Promise<void> {
if (await knex.schema.hasColumn(TableName.SuperAdmin, "allowedSignUpDomain")) {
await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
t.dropColumn("allowedSignUpDomain");
});
}
}

@ -12,7 +12,8 @@ export const SuperAdminSchema = z.object({
initialized: z.boolean().default(false).nullable().optional(),
allowSignUp: z.boolean().default(true).nullable().optional(),
createdAt: z.date(),
updatedAt: z.date()
updatedAt: z.date(),
allowedSignUpDomain: z.string().nullable().optional()
});
export type TSuperAdmin = z.infer<typeof SuperAdminSchema>;

@ -5,7 +5,7 @@ import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
export const registerScimRouter = async (server: FastifyZodProvider) => {
server.addContentTypeParser("application/scim+json", { parseAs: "string" }, function (req, body, done) {
server.addContentTypeParser("application/scim+json", { parseAs: "string" }, (_, body, done) => {
try {
const strBody = body instanceof Buffer ? body.toString() : body;

@ -177,6 +177,8 @@ export const permissionServiceFactory = ({
const getServiceTokenProjectPermission = async (serviceTokenId: string, projectId: string) => {
const serviceToken = await serviceTokenDAL.findById(serviceTokenId);
if (!serviceToken) throw new BadRequestError({ message: "Service token not found" });
if (serviceToken.projectId !== projectId)
throw new UnauthorizedError({
message: "Failed to find service authorization for given project"

@ -0,0 +1,17 @@
import { FastifyRequest } from "fastify";
import { ActorType } from "@app/services/auth/auth-type";
// this is a unique id for sending posthog event
export const getTelemetryDistinctId = (req: FastifyRequest) => {
if (req.auth.actor === ActorType.USER) {
return req.auth.user.email;
}
if (req.auth.actor === ActorType.IDENTITY) {
return `identity-${req.auth.identityId}`;
}
if (req.auth.actor === ActorType.SERVICE) {
return req.auth.serviceToken.createdByEmail || `service-token-null-creator-${req.auth.serviceTokenId}`; // when user gets removed from system
}
return "unknown-auth-data";
};

@ -27,7 +27,7 @@ export type TAuthMode =
}
| {
authMode: AuthMode.SERVICE_TOKEN;
serviceToken: TServiceTokens;
serviceToken: TServiceTokens & { createdByEmail: string };
actor: ActorType.SERVICE;
serviceTokenId: string;
}

@ -585,4 +585,8 @@ export const registerRoutes = async (
);
await server.register(registerV2Routes, { prefix: "/api/v2" });
await server.register(registerV3Routes, { prefix: "/api/v3" });
server.addHook("onClose", async () => {
await telemetryService.flushAll();
});
};

@ -31,7 +31,8 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => {
method: "PATCH",
schema: {
body: z.object({
allowSignUp: z.boolean().optional()
allowSignUp: z.boolean().optional(),
allowedSignUpDomain: z.string().optional().nullable()
}),
response: {
200: z.object({

@ -2,8 +2,10 @@ import { z } from "zod";
import { IdentitiesSchema, OrgMembershipRole } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
export const registerIdentityRouter = async (server: FastifyZodProvider) => {
server.route({
@ -49,6 +51,17 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
}
});
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.MachineIdentityCreated,
distinctId: getTelemetryDistinctId(req),
properties: {
orgId: req.body.organizationId,
name: identity.name,
identityId: identity.id,
...req.auditLogInfo
}
});
return { identity };
}
});

@ -3,8 +3,10 @@ import { z } from "zod";
import { IntegrationsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { removeTrailingSlash, shake } from "@app/lib/fn";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { PostHogEventTypes, TIntegrationCreatedEvent } from "@app/services/telemetry/telemetry-types";
export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
server.route({
@ -53,28 +55,40 @@ export const registerIntegrationRouter = async (server: FastifyZodProvider) => {
actorOrgId: req.permission.orgId,
...req.body
});
const createIntegrationEventProperty = shake({
integrationId: integration.id.toString(),
integration: integration.integration,
environment: req.body.sourceEnvironment,
secretPath: req.body.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
}) as TIntegrationCreatedEvent["properties"];
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
projectId: integrationAuth.projectId,
event: {
type: EventType.CREATE_INTEGRATION,
// eslint-disable-next-line
metadata: shake({
integrationId: integration.id.toString(),
integration: integration.integration,
environment: req.body.sourceEnvironment,
secretPath: req.body.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
// eslint-disable-next-line
}) as any
metadata: createIntegrationEventProperty
}
});
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.IntegrationCreated,
distinctId: getTelemetryDistinctId(req),
properties: {
...createIntegrationEventProperty,
projectId: integrationAuth.projectId,
...req.auditLogInfo
}
});
return { integration };

@ -1,8 +1,10 @@
import { z } from "zod";
import { UsersSchema } from "@app/db/schemas";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
server.route({
@ -30,6 +32,15 @@ export const registerInviteOrgRouter = async (server: FastifyZodProvider) => {
actorOrgId: req.permission.orgId
});
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.UserOrgInvitation,
distinctId: getTelemetryDistinctId(req),
properties: {
inviteeEmail: req.body.inviteeEmail,
...req.auditLogInfo
}
});
return {
completeInviteLink,
message: `Send an invite link to ${req.body.inviteeEmail}`

@ -18,7 +18,6 @@ import { BadRequestError } from "@app/lib/errors";
import { logger } from "@app/lib/logger";
import { fetchGithubEmails } from "@app/lib/requests/github";
import { AuthMethod } from "@app/services/auth/auth-type";
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
export const registerSsoRouter = async (server: FastifyZodProvider) => {
const appCfg = getConfig();
@ -42,7 +41,6 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
async (req, _accessToken, _refreshToken, profile, cb) => {
try {
const email = profile?.emails?.[0]?.value;
const serverCfg = await getServerCfg();
if (!email)
throw new BadRequestError({
message: "Email not found",
@ -54,8 +52,7 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
firstName: profile?.name?.givenName || "",
lastName: profile?.name?.familyName || "",
authMethod: AuthMethod.GOOGLE,
callbackPort: req.query.state as string,
isSignupAllowed: Boolean(serverCfg.allowSignUp)
callbackPort: req.query.state as string
});
cb(null, { isUserCompleted, providerAuthToken });
} catch (error) {
@ -84,14 +81,12 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
try {
const ghEmails = await fetchGithubEmails(accessToken);
const { email } = ghEmails.filter((gitHubEmail) => gitHubEmail.primary)[0];
const serverCfg = await getServerCfg();
const { isUserCompleted, providerAuthToken } = await server.services.login.oauth2Login({
email,
firstName: profile.displayName,
lastName: "",
authMethod: AuthMethod.GITHUB,
callbackPort: req.query.state as string,
isSignupAllowed: Boolean(serverCfg.allowSignUp)
callbackPort: req.query.state as string
});
return cb(null, { isUserCompleted, providerAuthToken });
} catch (error) {
@ -120,14 +115,12 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
async (req: any, _accessToken: string, _refreshToken: string, profile: any, cb: any) => {
try {
const email = profile.emails[0].value;
const serverCfg = await getServerCfg();
const { isUserCompleted, providerAuthToken } = await server.services.login.oauth2Login({
email,
firstName: profile.displayName,
lastName: "",
authMethod: AuthMethod.GITLAB,
callbackPort: req.query.state as string,
isSignupAllowed: Boolean(serverCfg.allowSignUp)
callbackPort: req.query.state as string
});
return cb(null, { isUserCompleted, providerAuthToken });

@ -4,8 +4,10 @@ import { z } from "zod";
import { ProjectKeysSchema, ProjectsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { authRateLimit } from "@app/server/config/rateLimiter";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
const projectWithEnv = ProjectsSchema.merge(
z.object({
@ -152,6 +154,16 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
slug: req.body.slug
});
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.ProjectCreated,
distinctId: getTelemetryDistinctId(req),
properties: {
orgId: req.body.organizationId,
name: project.name,
...req.auditLogInfo
}
});
return { project };
}
});

@ -1,4 +1,3 @@
import { FastifyRequest } from "fastify";
import picomatch from "picomatch";
import { z } from "zod";
@ -13,6 +12,7 @@ import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { CommitType } from "@app/ee/services/secret-approval-request/secret-approval-request-types";
import { BadRequestError } from "@app/lib/errors";
import { removeTrailingSlash } from "@app/lib/fn";
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
import { getUserAgentType } from "@app/server/plugins/audit-log";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
@ -20,19 +20,6 @@ import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
import { secretRawSchema } from "../sanitizedSchemas";
const getDistinctId = (req: FastifyRequest) => {
if (req.auth.actor === ActorType.USER) {
return req.auth.user.email;
}
if (req.auth.actor === ActorType.IDENTITY) {
return `identity-${req.auth.identityId}`;
}
if (req.auth.actor === ActorType.SERVICE) {
return `service-token-${req.auth.serviceToken.id}`;
}
return "unknown-auth-data";
};
export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.route({
url: "/raw",
@ -110,7 +97,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: secrets.length,
workspaceId,
@ -200,7 +187,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: 1,
workspaceId,
@ -276,7 +263,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretCreated,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: 1,
workspaceId: req.body.workspaceId,
@ -351,7 +338,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretUpdated,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: 1,
workspaceId: req.body.workspaceId,
@ -421,7 +408,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretDeleted,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: 1,
workspaceId: req.body.workspaceId,
@ -527,7 +514,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
if (shouldCapture) {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: shouldRecordK8Event ? approximateNumberTotalSecrets : secrets.length,
workspaceId: req.query.workspaceId,
@ -604,7 +591,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretPulled,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: 1,
workspaceId: req.query.workspaceId,
@ -767,7 +754,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretCreated,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: 1,
workspaceId: req.body.workspaceId,
@ -949,7 +936,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretUpdated,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: 1,
workspaceId: req.body.workspaceId,
@ -1067,7 +1054,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretDeleted,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: 1,
workspaceId: req.body.workspaceId,
@ -1187,7 +1174,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretCreated,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: secrets.length,
workspaceId: req.body.workspaceId,
@ -1307,7 +1294,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretUpdated,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: secrets.length,
workspaceId: req.body.workspaceId,
@ -1415,7 +1402,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.SecretDeleted,
distinctId: getDistinctId(req),
distinctId: getTelemetryDistinctId(req),
properties: {
numberOfSecrets: secrets.length,
workspaceId: req.body.workspaceId,

@ -2,7 +2,9 @@ import { z } from "zod";
import { UsersSchema } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError } from "@app/lib/errors";
import { authRateLimit } from "@app/server/config/rateLimiter";
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
export const registerSignupRouter = async (server: FastifyZodProvider) => {
@ -23,8 +25,26 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
}
},
handler: async (req) => {
await server.services.signup.beginEmailSignupProcess(req.body.email);
return { message: `Sent an email verification code to ${req.body.email}` };
const { email } = req.body;
const serverCfg = await getServerCfg();
if (!serverCfg.allowSignUp) {
throw new BadRequestError({
message: "Sign up is disabled"
});
}
if (serverCfg?.allowedSignUpDomain) {
const domain = email.split("@")[1];
const allowedDomains = serverCfg.allowedSignUpDomain.split(",").map((e) => e.trim());
if (!allowedDomains.includes(domain)) {
throw new BadRequestError({
message: `Email with a domain (@${domain}) is not supported`
});
}
}
await server.services.signup.beginEmailSignupProcess(email);
return { message: `Sent an email verification code to ${email}` };
}
});
@ -48,6 +68,13 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
}
},
handler: async (req) => {
const serverCfg = await getServerCfg();
if (!serverCfg.allowSignUp) {
throw new BadRequestError({
message: "Sign up is disabled"
});
}
const { token, user } = await server.services.signup.verifyEmailSignup(req.body.email, req.body.code);
return { message: "Successfuly verified email", token, user };
}
@ -90,6 +117,13 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
if (!userAgent) throw new Error("user agent header is required");
const appCfg = getConfig();
const serverCfg = await getServerCfg();
if (!serverCfg.allowSignUp) {
throw new BadRequestError({
message: "Sign up is disabled"
});
}
const { user, accessToken, refreshToken } = await server.services.signup.completeEmailAccountSignup({
...req.body,
ip: req.realIp,

@ -4,6 +4,7 @@ import { TUsers, UserDeviceSchema } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env";
import { generateSrpServerKey, srpCheckClientProof } from "@app/lib/crypto";
import { BadRequestError } from "@app/lib/errors";
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
import { TokenType } from "../auth-token/auth-token-types";
@ -261,20 +262,26 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
/*
* OAuth2 login for google,github, and other oauth2 provider
* */
const oauth2Login = async ({
email,
firstName,
lastName,
authMethod,
callbackPort,
isSignupAllowed
}: TOauthLoginDTO) => {
const oauth2Login = async ({ email, firstName, lastName, authMethod, callbackPort }: TOauthLoginDTO) => {
let user = await userDAL.findUserByEmail(email);
const serverCfg = await getServerCfg();
const appCfg = getConfig();
const isOauthSignUpDisabled = !isSignupAllowed && !user;
if (isOauthSignUpDisabled) throw new BadRequestError({ message: "User signup disabled", name: "Oauth 2 login" });
if (!user) {
// Create a new user based on oAuth
if (!serverCfg?.allowSignUp) throw new BadRequestError({ message: "Sign up disabled", name: "Oauth 2 login" });
if (serverCfg?.allowedSignUpDomain) {
const domain = email.split("@")[1];
const allowedDomains = serverCfg.allowedSignUpDomain.split(",").map((e) => e.trim());
if (!allowedDomains.includes(domain))
throw new BadRequestError({
message: `Email with a domain (@${domain}) is not supported`,
name: "Oauth 2 login"
});
}
user = await userDAL.create({ email, firstName, lastName, authMethods: [authMethod], isGhost: false });
}
const isLinkingRequired = !user?.authMethods?.includes(authMethod);

@ -28,5 +28,4 @@ export type TOauthLoginDTO = {
lastName?: string;
authMethod: AuthMethod;
callbackPort?: string;
isSignupAllowed?: boolean;
};

@ -419,10 +419,6 @@ export const projectMembershipServiceFactory = ({
});
}
if (project.version === ProjectVersion.V1) {
throw new BadRequestError({ message: "Please upgrade your project on your dashboard" });
}
const projectMembers = await projectMembershipDAL.findMembershipsByEmail(projectId, emails);
if (projectMembers.length !== emails.length) {

@ -33,11 +33,12 @@ export const assignWorkspaceKeysToMembers = ({ members, decryptKey, userPrivateK
type TCreateProjectKeyDTO = {
publicKey: string;
privateKey: string;
plainProjectKey?: string;
};
export const createProjectKey = ({ publicKey, privateKey }: TCreateProjectKeyDTO) => {
export const createProjectKey = ({ publicKey, privateKey, plainProjectKey }: TCreateProjectKeyDTO) => {
// 3. Create a random key that we'll use as the project key.
const randomBytes = crypto.randomBytes(16).toString("hex");
const randomBytes = plainProjectKey || crypto.randomBytes(16).toString("hex");
// 4. Encrypt the project key with the users key pair.
const { ciphertext: encryptedProjectKey, nonce: encryptedProjectKeyIv } = encryptAsymmetric(

@ -122,6 +122,13 @@ export const projectQueueFactory = ({
tag: data.encryptedPrivateKey.encryptedKeyTag
});
const decryptedPlainProjectKey = decryptAsymmetric({
ciphertext: oldProjectKey.encryptedKey,
nonce: oldProjectKey.nonce,
publicKey: oldProjectKey.sender.publicKey,
privateKey: userPrivateKey
});
const projectEnvs = await projectEnvDAL.find({
projectId: project.id
});
@ -199,6 +206,7 @@ export const projectQueueFactory = ({
// Create a project key
const { key: newEncryptedProjectKey, iv: newEncryptedProjectKeyIv } = createProjectKey({
plainProjectKey: decryptedPlainProjectKey,
publicKey: ghostUser.keys.publicKey,
privateKey: ghostUser.keys.plainPrivateKey
});

@ -1,10 +1,32 @@
import { Knex } from "knex";
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex";
import { TableName, TUsers } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols } from "@app/lib/knex";
export type TServiceTokenDALFactory = ReturnType<typeof serviceTokenDALFactory>;
export const serviceTokenDALFactory = (db: TDbClient) => {
const stOrm = ormify(db, TableName.ServiceToken);
return stOrm;
const findById = async (id: string, tx?: Knex) => {
try {
const doc = await (tx || db)(TableName.ServiceToken)
.leftJoin<TUsers>(
TableName.Users,
`${TableName.Users}.id`,
db.raw(`${TableName.ServiceToken}."createdBy"::uuid`)
)
.where(`${TableName.ServiceToken}.id`, id)
.select(selectAllTableCols(TableName.ServiceToken))
.select(db.ref("email").withSchema(TableName.Users).as("createdByEmail"))
.first();
return doc;
} catch (err) {
throw new DatabaseError({ error: err, name: "FindById" });
}
};
return { ...stOrm, findById };
};

@ -142,7 +142,7 @@ export const serviceTokenServiceFactory = ({
const updatedToken = await serviceTokenDAL.updateById(serviceToken.id, {
lastUsed: new Date()
});
return updatedToken;
return { ...serviceToken, lastUsed: updatedToken.lastUsed };
};
return {

@ -61,8 +61,15 @@ To opt into telemetry, you can set "TELEMETRY_ENABLED=true" within the environme
}
};
const flushAll = async () => {
if (postHog) {
await postHog.shutdownAsync();
}
};
return {
sendLoopsEvent,
sendPostHogEvents
sendPostHogEvents,
flushAll
};
};

@ -8,7 +8,11 @@ export enum PostHogEventTypes {
UserSignedUp = "User Signed Up",
SecretRotated = "secrets rotated",
SecretScannerFull = "historical cloud secret scan",
SecretScannerPush = "cloud secret scan"
SecretScannerPush = "cloud secret scan",
ProjectCreated = "Project Created",
IntegrationCreated = "Integration Created",
MachineIdentityCreated = "Machine Identity Created",
UserOrgInvitation = "User Org Invitation"
}
export type TSecretModifiedEvent = {
@ -53,9 +57,57 @@ export type TSecretScannerEvent = {
};
};
export type TProjectCreateEvent = {
event: PostHogEventTypes.ProjectCreated;
properties: {
name: string;
orgId: string;
};
};
export type TMachineIdentityCreatedEvent = {
event: PostHogEventTypes.MachineIdentityCreated;
properties: {
name: string;
orgId: string;
identityId: string;
};
};
export type TIntegrationCreatedEvent = {
event: PostHogEventTypes.IntegrationCreated;
properties: {
projectId: string;
integrationId: string;
integration: string; // TODO: fix type
environment: string;
secretPath: string;
url?: string;
app?: string;
appId?: string;
targetEnvironment?: string;
targetEnvironmentId?: string;
targetService?: string;
targetServiceId?: string;
path?: string;
region?: string;
};
};
export type TUserOrgInvitedEvent = {
event: PostHogEventTypes.UserOrgInvitation;
properties: {
inviteeEmail: string;
};
};
export type TPostHogEvent = { distinctId: string } & (
| TSecretModifiedEvent
| TAdminInitEvent
| TUserSignedUpEvent
| TSecretScannerEvent
| TUserOrgInvitedEvent
| TMachineIdentityCreatedEvent
| TIntegrationCreatedEvent
| TProjectCreateEvent
);

@ -1,4 +1,4 @@
---
title: "Create Workspace"
title: "Create Project"
openapi: "POST /api/v2/workspace"
---

@ -1,5 +1,5 @@
---
title: "Delete Workspace"
title: "Delete Project"
openapi: "DELETE /api/v1/workspace/{workspaceId}"
---

@ -1,4 +1,4 @@
---
title: "Get Workspace"
title: "Get Project"
openapi: "GET /api/v1/workspace/{workspaceId}"
---

@ -1,4 +1,4 @@
---
title: "Update Workspace"
title: "Update Project"
openapi: "PATCH /api/v1/workspace/{workspaceId}"
---

@ -75,7 +75,7 @@ app.get("/", async (req, res) => {
app.listen(PORT, async () => {
// initialize client
console.log(`App listening on port ${port}`);
console.log(`App listening on port ${PORT}`);
});
```

@ -163,10 +163,12 @@
{
"group": "Self-host Infisical",
"pages": [
"self-hosting/overview",
"self-hosting/configuration/requirements",
"self-hosting/configuration/schema-migrations",
{
"group": "Deployment options",
"group": "Installation methods",
"pages": [
"self-hosting/overview",
"self-hosting/deployment-options/standalone-infisical",
"self-hosting/deployment-options/docker-compose",
"self-hosting/deployment-options/kubernetes-helm",
@ -181,9 +183,6 @@
]
},
"self-hosting/configuration/envars",
"self-hosting/configuration/email",
"self-hosting/configuration/redis",
"self-hosting/configuration/sso",
"self-hosting/faq"
]
},

@ -42,7 +42,7 @@ app.get("/", async (req, res) => {
app.listen(PORT, async () => {
// initialize client
console.log(`App listening on port ${port}`);
console.log(`App listening on port ${PORT}`);
});
```

@ -1,242 +0,0 @@
---
title: "Configure email service"
description: "How to configure your email when self-hosting Infisical."
---
By default, the core functions of Infisical work without any email service configuration. Without email service, basic sign up/login and secret operations will function without any issue.
However, the following functionality will be disabled.
- Multi-factor authentication
- Sending invite links via email for projects to teammates
- Sending alerts such as suspicious login attempts
## Configuration
If you choose to setup email service, you need to configure the following SMTP [environment variables](https://infisical.com/docs/self-hosting/configuration/envars):
- `SMTP_HOST`: Hostname to connect to for establishing SMTP connections.
- `SMTP_USERNAME`: Credential to connect to host (e.g. team@infisical.com)
- `SMTP_PASSWORD`: Credential to connect to host.
- `SMTP_PORT`: Port to connect to for establishing SMTP connections.
- `SMTP_SECURE`: If `true`, the connection will use TLS when connecting to server with special configs for SendGrid and Mailgun. If `false` (the default) then TLS is used if server supports the STARTTLS extension.
- `SMTP_FROM_ADDRESS`: Email address to be used for sending emails (e.g. team@infisical.com).
- `SMTP_FROM_NAME`: Name label to be used in `From` field (e.g. Team).
Below you will find details on how to configure common email providers:
<AccordionGroup>
<Accordion title="Resend">
1. Create an account on [Resend](https://resend.com).
2. Add a [Domain](https://resend.com/domains).
![adding resend domain](../../images/self-hosting/configuration/email/email-resend-create-domain.png)
3. Create an [API Key](https://resend.com/api-keys).
![creating resend api key](../../images/self-hosting/configuration/email/email-resend-create-key.png)
4. Go to the [SMTP page](https://resend.com/settings/smtp) and copy the values.
![go to resend smtp settings](../../images/self-hosting/configuration/email/email-resend-smtp-settings.png)
5. With the API Key, you can now set your SMTP environment variables variables:
```
SMTP_HOST=smtp.resend.com
SMTP_USERNAME=resend
SMTP_PASSWORD=YOUR_API_KEY
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
<Accordion title="Twilio SendGrid">
1. Create an account and configure [SendGrid](https://sendgrid.com) to send emails.
2. Create a SendGrid API Key under Settings > [API Keys](https://app.sendgrid.com/settings/api_keys)
3. Set a name for your API Key, we recommend using "Infisical," and select the "Restricted Key" option. You will need to enable the "Mail Send" permission as shown below:
![creating sendgrid api key](../../images/self-hosting/configuration/email/email-sendgrid-create-key.png)
![setting sendgrid api key restriction](../../images/self-hosting/configuration/email/email-sendgrid-restrictions.png)
4. With the API Key, you can now set your SMTP environment variables:
```
SMTP_HOST=smtp.sendgrid.net
SMTP_USERNAME=apikey
SMTP_PASSWORD=SG.rqFsfjxYPiqE1lqZTgD_lz7x8IVLx # your SendGrid API Key from step above
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
<Accordion title="Mailgun">
1. Create an account and configure [Mailgun](https://www.mailgun.com) to send emails.
2. Obtain your Mailgun credentials in Sending > Overview > SMTP
![obtain mailhog api key estriction](../../images/self-hosting/configuration/email/email-mailhog-credentials.png)
3. With your Mailgun credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=smtp.mailgun.org # obtained from credentials page
SMTP_USERNAME=postmaster@example.mailgun.org # obtained from credentials page
SMTP_PASSWORD=password # obtained from credentials page
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
</Accordion>
<Accordion title="AWS SES">
1. Create an account and [configure AWS SES](https://aws.amazon.com/premiumsupport/knowledge-center/ses-set-up-connect-smtp/) to send emails in the Amazon SES console.
2. Create an IAM user for SMTP authentication and obtain SMTP credentials in SMTP settings > Create SMTP credentials
![opening AWS SES console](../../images/self-hosting/configuration/email/email-aws-ses-console.png)
![creating AWS IAM SES user](../../images/self-hosting/configuration/email/email-aws-ses-user.png)
3. With your AWS SES SMTP credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=email-smtp.ap-northeast-1.amazonaws.com # SMTP endpoint obtained from SMTP settings
SMTP_USERNAME=xxx # your SMTP username
SMTP_PASSWORD=xxx # your SMTP password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
<Accordion title="SocketLabs">
1. Create an account and configure [SocketLabs](https://www.socketlabs.com/) to send emails.
2. From the dashboard, navigate to SMTP Credentials > SMTP & APIs > SMTP Credentials to obtain your SocketLabs SMTP credentials.
![opening SocketLabs dashboard](../../images/self-hosting/configuration/email/email-socketlabs-dashboard.png)
![obtaining SocketLabs credentials](../../images/self-hosting/configuration/email/email-socketlabs-credentials.png)
3. With your SocketLabs SMTP credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=smtp.socketlabs.com
SMTP_USERNAME=username # obtained from your credentials
SMTP_PASSWORD=password # obtained from your credentials
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
<Note>
The `SMTP_FROM_ADDRESS` environment variable should be an email for an
authenticated domain under Configuration > Domain Management in SocketLabs.
For example, if you're using SocketLabs in sandbox mode, then you may use an
email like `team@sandbox.socketlabs.dev`.
</Note>
![SocketLabs domain management](../../images/self-hosting/configuration/email/email-socketlabs-domains.png)
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
<Accordion title="Gmail">
Create an account and enable "less secure app access" in Gmail Account Settings > Security. This will allow
applications like Infisical to authenticate with Gmail via your username and password.
![Gmail secure app access](../../images/self-hosting/configuration/email/email-gmail-app-access.png)
With your Gmail username and password, you can set your SMTP environment variables:
```
SMTP_HOST=smtp.gmail.com
SMTP_USERNAME=hey@gmail.com # your email
SMTP_PASSWORD=password # your password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@gmail.com
SMTP_FROM_NAME=Infisical
```
<Warning>
As per the [notice](https://support.google.com/accounts/answer/6010255?hl=en) by Google, you should note that using Gmail credentials for SMTP configuration
will only work for Google Workspace or Google Cloud Identity customers as of May 30, 2022.
Put differently, the SMTP configuration is only possible with business (not personal) Gmail credentials.
</Warning>
</Accordion>
<Accordion title="Office365">
1. Create an account and configure [Office365](https://www.office.com/) to send emails.
2. With your login credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=smtp.office365.com
SMTP_USERNAME=username@yourdomain.com # your username
SMTP_PASSWORD=password # your password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=username@yourdomain.com
SMTP_FROM_NAME=Infisical
```
</Accordion>
<Accordion title="Zoho Mail">
1. Create an account and configure [Zoho Mail](https://www.zoho.com/mail/) to send emails.
2. With your email credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=smtp.zoho.com
SMTP_USERNAME=username # your email
SMTP_PASSWORD=password # your password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your personal Zoho email or domain-based email linked to Zoho Mail
SMTP_FROM_NAME=Infisical
```
<Note>
You can use either your personal Zoho email address like `you@zohomail.com` or
a domain-based email address like `you@yourdomain.com`. If using a
domain-based email address, then please make sure that you've configured and
verified it with Zoho Mail.
</Note>
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
</AccordionGroup>

@ -1,188 +1,426 @@
---
title: "All environment variables"
description: "Configure your environment variables when self-hosting Infisical."
title: "Configurations"
description: "Configure environment variables for self-hosted Infisical"
---
## Environment variables
Depending on your chosen self hosted deployment method, you may need to configured at least the required environment variable listed below.
Other environment variables are listed below to increase the functionality of your self hosted instance based on your use case.
Infisical accepts all configurations via environment variables. For a basic self-hosted instance, at least `ENCRYPTION_KEY`, `AUTH_SECRET`, `DB_CONNECTION_URI` and `REDIS_URL` must be defined.
However, you can configure additional settings to activate more features as needed.
<Tabs>
<Tab title="Required">
<ParamField query="ENCRYPTION_KEY" type="string" default="none" required>
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
</ParamField>
## General platform
Used to configure platform-specific security and operational settings
<ParamField query="AUTH_SECRET" type="string" default="none" required>
Must be a random 32 byte base64 string. Can be generated with `openssl rand -base64 32`
</ParamField>
<ParamField query="DB_CONNECTION_URI" type="string" default="none" required>
Postgres database connection string.
</ParamField>
<ParamField query="REDIS_URL" type="string" default="none" required>
Redis connection string
</ParamField>
</Tab>
<Tab title="Email service">
<Info>When email service is not configured, Infisical will have limited functionality</Info>
<ParamField query="SMTP_HOST" type="string" default="none" optional>
Hostname to connect to for establishing SMTP connections
</ParamField>
<ParamField query="SMTP_USERNAME" type="string" default="none" optional>
Credential to connect to host (e.g. team@infisical.com)
</ParamField>
<ParamField query="SMTP_PASSWORD" type="string" default="none" optional>
Credential to connect to host
</ParamField>
<ParamField query="SMTP_PORT" type="string" default="587" optional>
Port to connect to for establishing SMTP connections
</ParamField>
<ParamField query="SMTP_SECURE" type="string" default="none" optional>
If true, use TLS when connecting to host. If false, TLS will be used if STARTTLS is supported
</ParamField>
<ParamField query="SMTP_FROM_ADDRESS" type="string" default="none" optional>
Email address to be used for sending emails
</ParamField>
<ParamField query="SMTP_FROM_NAME" type="string" default="none" optional>
Name label to be used in From field (e.g. Team)
</ParamField>
</Tab>
<Tab title="Secret Integrations">
To sync secret to third party services, provide value for the related services
<ParamField query="CLIENT_ID_HEROKU" type="string" default="none" optional>
OAuth2 client ID for Heroku integration
</ParamField>
<ParamField query="CLIENT_SECRET_HEROKU" type="string" default="none" optional>
OAuth2 client secret for Heroku integration
</ParamField>
<ParamField query="CLIENT_ID_VERCEL" type="string" default="none" optional>
OAuth2 client ID for Vercel integration
</ParamField>
<ParamField query="CLIENT_SECRET_VERCEL" type="string" default="none" optional>
OAuth2 client secret for Vercel integration
</ParamField>
<ParamField query="CLIENT_ID_NETLIFY" type="string" default="none" optional>
OAuth2 client ID for Netlify integration
</ParamField>
<ParamField query="CLIENT_SECRET_NETLIFY" type="string" default="none" optional>
OAuth2 client secret for Netlify integration
</ParamField>
<ParamField query="CLIENT_ID_GITHUB" type="string" default="none" optional>
OAuth2 client ID for GitHub integration
</ParamField>
<ParamField query="CLIENT_SECRET_GITHUB" type="string" default="none" optional>
OAuth2 client secret for GitHub integration
</ParamField>
<ParamField query="CLIENT_SLUG_VERCEL" type="string" default="none" optional>
OAuth2 slug for Vercel integration
</ParamField>
<ParamField query="CLIENT_ID_BITBUCKET" type="string" default="none" optional>
OAuth2 client ID for BitBucket integration
</ParamField>
<ParamField query="CLIENT_SECRET_BITBUCKET" type="string" default="none" optional>
OAuth2 client secret for BitBucket integration
</ParamField>
</Tab>
<Tab title="Auth Integrations">
To integrate with external auth providers, provide value for the related keys
<ParamField query="CLIENT_ID_GOOGLE_LOGIN" type="string" default="none" optional>
OAuth2 client ID for Google login
</ParamField>
<ParamField query="CLIENT_SECRET_GOOGLE_LOGIN" type="string" default="none" optional>
OAuth2 client secret for Google login
</ParamField>
<ParamField query="CLIENT_ID_GITHUB_LOGIN" type="string" default="none" optional>
OAuth2 client ID for GitHub login
</ParamField>
<ParamField query="CLIENT_SECRET_GITHUB_LOGIN" type="string" default="none" optional>
OAuth2 client secret for GitHub login
</ParamField>
<ParamField query="CLIENT_ID_GITLAB_LOGIN" type="string" default="none" optional>
OAuth2 client ID for GitLab login
</ParamField>
<ParamField query="CLIENT_SECRET_GITLAB_LOGIN" type="string" default="none" optional>
OAuth2 client secret for GitLab login
</ParamField>
<ParamField query="URL_GITLAB_LOGIN" type="string" default="https://gitlab.com" optional>
URL of your self-hosted instance of GitLab where the OAuth application is registered
</ParamField>
</Tab>
<Tab title="Others">
#### JWT
<ParamField query="JWT_SIGNUP_LIFETIME" type="string" default="15m" optional>
JWT token lifetime expressed in seconds or a string describing a time span
</ParamField>
<ParamField query="JWT_REFRESH_LIFETIME" type="string" default="90d" optional>
JWT token lifetime expressed in seconds or a string describing a time span
</ParamField>
<ParamField query="JWT_AUTH_LIFETIME" type="string" default="10d" optional>
JWT token lifetime expressed in seconds or a string describing a time span
</ParamField>
<ParamField query="JWT_MFA_LIFETIME" type="string" default="5m" optional>
JWT token lifetime expressed in seconds or a string describing a time span
</ParamField>
<ParamField query="JWT_PROVIDER_AUTH_LIFETIME" type="string" default="5m" optional>
JWT token lifetime expressed in seconds or a string describing a time span
</ParamField>
#### Logging
Infisical uses Sentry to report error logs
<ParamField
query="PINO_LOG_LEVEL"
type="string"
default="info"
optional
>
The minimum log level for application logging; can be one of `trace`, `debug`, `info`, `warn`, `error`, or `fatal`.
<ParamField query="ENCRYPTION_KEY" type="string" default="none" required>
Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16`
</ParamField>
<ParamField
query="SENTRY_DSN"
type="string"
default="none"
optional
></ParamField>
#### Settings
{" "}
<ParamField query="INVITE_ONLY_SIGNUP" type="string" default="false" optional>
Only allow users who are invited to sign up
<ParamField query="AUTH_SECRET" type="string" default="none" required>
Must be a random 32 byte base64 string. Can be generated with `openssl rand -base64 32`
</ParamField>
<ParamField query="SITE_URL" type="string" default="none" optional>
Site URL - should be an absolute URL including the protocol (e.g. https://app.infisical.com)
<ParamField query="SITE_URL" type="string" default="none" optional>
Must be an absolute URL including the protocol (e.g. https://app.infisical.com).
</ParamField>
## Data Layer
The platform utilizes Postgres to persist all of its data and Redis for caching and backgroud tasks
<ParamField query="DB_CONNECTION_URI" type="string" default="" required>
Postgres database connection string.
</ParamField>
<ParamField query="DB_ROOT_CERT" type="string" default="" optional>
Configure the SSL certificate for securing a Postgres connection by first encoding it in base64.
Use the command below to encode your certificate:
`echo "<certificate>" | base64`
</ParamField>
<ParamField query="REDIS_URL" type="string" default="none" required>
Redis connection string.
</ParamField>
## Email service
Without email configuration, Infisical's core functions like sign-up/login and secret operations work, but this disables multi-factor authentication, email invites for projects, alerts for suspicious logins, and all other email-dependent features.
<Accordion title="Generic Configuration">
<ParamField query="SMTP_HOST" type="string" default="none" optional>
Hostname to connect to for establishing SMTP connections
</ParamField>
<ParamField query="TELEMETRY_ENABLED" type="string" default="true" optional></ParamField>
</Tab>
</Tabs>
<ParamField query="SMTP_USERNAME" type="string" default="none" optional>
Credential to connect to host (e.g. team@infisical.com)
</ParamField>
<ParamField query="SMTP_PASSWORD" type="string" default="none" optional>
Credential to connect to host
</ParamField>
<ParamField query="SMTP_PORT" type="string" default="587" optional>
Port to connect to for establishing SMTP connections
</ParamField>
<ParamField query="SMTP_SECURE" type="string" default="none" optional>
If true, use TLS when connecting to host. If false, TLS will be used if STARTTLS is supported
</ParamField>
<ParamField query="SMTP_FROM_ADDRESS" type="string" default="none" optional>
Email address to be used for sending emails
</ParamField>
<ParamField query="SMTP_FROM_NAME" type="string" default="none" optional>
Name label to be used in From field (e.g. Team)
</ParamField>
</Accordion>
<Accordion title="Twilio SendGrid">
1. Create an account and configure [SendGrid](https://sendgrid.com) to send emails.
2. Create a SendGrid API Key under Settings > [API Keys](https://app.sendgrid.com/settings/api_keys)
3. Set a name for your API Key, we recommend using "Infisical," and select the "Restricted Key" option. You will need to enable the "Mail Send" permission as shown below:
![creating sendgrid api key](../../images/self-hosting/configuration/email/email-sendgrid-create-key.png)
![setting sendgrid api key restriction](../../images/self-hosting/configuration/email/email-sendgrid-restrictions.png)
4. With the API Key, you can now set your SMTP environment variables:
```
SMTP_HOST=smtp.sendgrid.net
SMTP_USERNAME=apikey
SMTP_PASSWORD=SG.rqFsfjxYPiqE1lqZTgD_lz7x8IVLx # your SendGrid API Key from step above
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
<Accordion title="Mailgun">
1. Create an account and configure [Mailgun](https://www.mailgun.com) to send emails.
2. Obtain your Mailgun credentials in Sending > Overview > SMTP
![obtain mailhog api key estriction](../../images/self-hosting/configuration/email/email-mailhog-credentials.png)
3. With your Mailgun credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=smtp.mailgun.org # obtained from credentials page
SMTP_USERNAME=postmaster@example.mailgun.org # obtained from credentials page
SMTP_PASSWORD=password # obtained from credentials page
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
</Accordion>
<Accordion title="AWS SES">
1. Create an account and [configure AWS SES](https://aws.amazon.com/premiumsupport/knowledge-center/ses-set-up-connect-smtp/) to send emails in the Amazon SES console.
2. Create an IAM user for SMTP authentication and obtain SMTP credentials in SMTP settings > Create SMTP credentials
![opening AWS SES console](../../images/self-hosting/configuration/email/email-aws-ses-console.png)
![creating AWS IAM SES user](../../images/self-hosting/configuration/email/email-aws-ses-user.png)
3. With your AWS SES SMTP credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=email-smtp.ap-northeast-1.amazonaws.com # SMTP endpoint obtained from SMTP settings
SMTP_USERNAME=xxx # your SMTP username
SMTP_PASSWORD=xxx # your SMTP password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
<Accordion title="SocketLabs">
1. Create an account and configure [SocketLabs](https://www.socketlabs.com/) to send emails.
2. From the dashboard, navigate to SMTP Credentials > SMTP & APIs > SMTP Credentials to obtain your SocketLabs SMTP credentials.
![opening SocketLabs dashboard](../../images/self-hosting/configuration/email/email-socketlabs-dashboard.png)
![obtaining SocketLabs credentials](../../images/self-hosting/configuration/email/email-socketlabs-credentials.png)
3. With your SocketLabs SMTP credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=smtp.socketlabs.com
SMTP_USERNAME=username # obtained from your credentials
SMTP_PASSWORD=password # obtained from your credentials
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
<Note>
The `SMTP_FROM_ADDRESS` environment variable should be an email for an
authenticated domain under Configuration > Domain Management in SocketLabs.
For example, if you're using SocketLabs in sandbox mode, then you may use an
email like `team@sandbox.socketlabs.dev`.
</Note>
![SocketLabs domain management](../../images/self-hosting/configuration/email/email-socketlabs-domains.png)
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
<Accordion title="Resend">
1. Create an account on [Resend](https://resend.com).
2. Add a [Domain](https://resend.com/domains).
![adding resend domain](../../images/self-hosting/configuration/email/email-resend-create-domain.png)
3. Create an [API Key](https://resend.com/api-keys).
![creating resend api key](../../images/self-hosting/configuration/email/email-resend-create-key.png)
4. Go to the [SMTP page](https://resend.com/settings/smtp) and copy the values.
![go to resend smtp settings](../../images/self-hosting/configuration/email/email-resend-smtp-settings.png)
5. With the API Key, you can now set your SMTP environment variables variables:
```
SMTP_HOST=smtp.resend.com
SMTP_USERNAME=resend
SMTP_PASSWORD=YOUR_API_KEY
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your email address being used to send out emails
SMTP_FROM_NAME=Infisical
```
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
<Accordion title="Gmail">
Create an account and enable "less secure app access" in Gmail Account Settings > Security. This will allow
applications like Infisical to authenticate with Gmail via your username and password.
![Gmail secure app access](../../images/self-hosting/configuration/email/email-gmail-app-access.png)
With your Gmail username and password, you can set your SMTP environment variables:
```
SMTP_HOST=smtp.gmail.com
SMTP_USERNAME=hey@gmail.com # your email
SMTP_PASSWORD=password # your password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@gmail.com
SMTP_FROM_NAME=Infisical
```
<Warning>
As per the [notice](https://support.google.com/accounts/answer/6010255?hl=en) by Google, you should note that using Gmail credentials for SMTP configuration
will only work for Google Workspace or Google Cloud Identity customers as of May 30, 2022.
Put differently, the SMTP configuration is only possible with business (not personal) Gmail credentials.
</Warning>
</Accordion>
<Accordion title="Office365">
1. Create an account and configure [Office365](https://www.office.com/) to send emails.
2. With your login credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=smtp.office365.com
SMTP_USERNAME=username@yourdomain.com # your username
SMTP_PASSWORD=password # your password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=username@yourdomain.com
SMTP_FROM_NAME=Infisical
```
</Accordion>
<Accordion title="Zoho Mail">
1. Create an account and configure [Zoho Mail](https://www.zoho.com/mail/) to send emails.
2. With your email credentials, you can now set up your SMTP environment variables:
```
SMTP_HOST=smtp.zoho.com
SMTP_USERNAME=username # your email
SMTP_PASSWORD=password # your password
SMTP_PORT=587
SMTP_SECURE=true
SMTP_FROM_ADDRESS=hey@example.com # your personal Zoho email or domain-based email linked to Zoho Mail
SMTP_FROM_NAME=Infisical
```
<Note>
You can use either your personal Zoho email address like `you@zohomail.com` or
a domain-based email address like `you@yourdomain.com`. If using a
domain-based email address, then please make sure that you've configured and
verified it with Zoho Mail.
</Note>
<Info>
Remember that you will need to restart Infisical for this to work properly.
</Info>
</Accordion>
## SSO based login
By default, users can only login via email/password based login method.
To login into Infisical with OAuth providers such as Google, configure the associated variables.
<Accordion title="Google">
Follow detailed guide to configure [Google SSO](/documentation/platform/sso/google)
<ParamField query="CLIENT_ID_GOOGLE_LOGIN" type="string" default="none" optional>
OAuth2 client ID for Google login
</ParamField>
<ParamField query="CLIENT_SECRET_GOOGLE_LOGIN" type="string" default="none" optional>
OAuth2 client secret for Google login
</ParamField>
</Accordion>
<Accordion title="Github">
Follow detailed guide to configure [GitHub SSO](/documentation/platform/sso/github)
<ParamField query="CLIENT_ID_GITHUB_LOGIN" type="string" default="none" optional>
OAuth2 client ID for GitHub login
</ParamField>
<ParamField query="CLIENT_SECRET_GITHUB_LOGIN" type="string" default="none" optional>
OAuth2 client secret for GitHub login
</ParamField>
</Accordion>
<Accordion title="Gitlab">
Follow detailed guide to configure [GitLab SSO](/documentation/platform/sso/gitlab)
<ParamField query="CLIENT_ID_GITLAB_LOGIN" type="string" default="none" optional>
OAuth2 client ID for GitLab login
</ParamField>
<ParamField query="CLIENT_SECRET_GITLAB_LOGIN" type="string" default="none" optional>
OAuth2 client secret for GitLab login
</ParamField>
<ParamField query="URL_GITLAB_LOGIN" type="string" default="https://gitlab.com" optional>
URL of your self-hosted instance of GitLab where the OAuth application is registered
</ParamField>
</Accordion>
<Accordion title="Okta SAML">
Requires enterprise license. Please contact team@infisical.com to get more information.
</Accordion>
<Accordion title="Azure SAML">
Requires enterprise license. Please contact team@infisical.com to get more information.
</Accordion>
<Accordion title="JumpCloud SAML">
Requires enterprise license. Please contact team@infisical.com to get more information.
</Accordion>
## Native secret integrations
To help you sync secrets from Infisical to services such as Github and Gitlab, Infisical provides native integrations out of the box.
<Accordion title="Heroku">
<ParamField query="CLIENT_ID_HEROKU" type="string" default="none" optional>
OAuth2 client ID for Heroku integration
</ParamField>
<ParamField query="CLIENT_SECRET_HEROKU" type="string" default="none" optional>
OAuth2 client secret for Heroku integration
</ParamField>
</Accordion>
<Accordion title="Vercel">
<ParamField query="CLIENT_ID_VERCEL" type="string" default="none" optional>
OAuth2 client ID for Vercel integration
</ParamField>
<ParamField query="CLIENT_SECRET_VERCEL" type="string" default="none" optional>
OAuth2 client secret for Vercel integration
</ParamField>
<ParamField query="CLIENT_SLUG_VERCEL" type="string" default="none" optional>
OAuth2 slug for Vercel integration
</ParamField>
</Accordion>
<Accordion title="Netlify">
<ParamField query="CLIENT_ID_NETLIFY" type="string" default="none" optional>
OAuth2 client ID for Netlify integration
</ParamField>
<ParamField query="CLIENT_SECRET_NETLIFY" type="string" default="none" optional>
OAuth2 client secret for Netlify integration
</ParamField>
</Accordion>
<Accordion title="Github">
<ParamField query="CLIENT_ID_GITHUB" type="string" default="none" optional>
OAuth2 client ID for GitHub integration
</ParamField>
<ParamField query="CLIENT_SECRET_GITHUB" type="string" default="none" optional>
OAuth2 client secret for GitHub integration
</ParamField>
</Accordion>
<Accordion title="Bitbucket">
<ParamField query="CLIENT_ID_BITBUCKET" type="string" default="none" optional>
OAuth2 client ID for BitBucket integration
</ParamField>
<ParamField query="CLIENT_SECRET_BITBUCKET" type="string" default="none" optional>
OAuth2 client secret for BitBucket integration
</ParamField>
</Accordion>
<Accordion title="GCP Secrets Manager">
<ParamField query="CLIENT_ID_GCP_SECRET_MANAGER" type="string" default="none" optional>
OAuth2 client id for GCP secrets manager integration
</ParamField>
<ParamField query="CLIENT_SECRET_GCP_SECRET_MANAGER" type="string" default="none" optional>
OAuth2 client secret for GCP secrets manager integration
</ParamField>
</Accordion>
<Accordion title="Azure">
<ParamField query="CLIENT_ID_AZURE" type="string" default="none" optional>
OAuth2 client id for Azure integration
</ParamField>
<ParamField query="CLIENT_SECRET_AZURE" type="string" default="none" optional>
OAuth2 client secret for Azure integration
</ParamField>
</Accordion>
<Accordion title="Gitlab">
<ParamField query="CLIENT_ID_GITLAB" type="string" default="none" optional>
OAuth2 client id for Gitlab integration
</ParamField>
<ParamField query="CLIENT_SECRET_GITLAB" type="string" default="none" optional>
OAuth2 client secret for Gitlab integration
</ParamField>
</Accordion>

@ -1,83 +0,0 @@
---
title: "Configure Redis"
description: "Learn to configure Redis with your self hosted Infisical"
---
## Why Redis?
As the features and use case of Infisical have grown, the need for a fast and reliable in-memory data storage has become clear.
By adding Redis to Infisical, we can now support more complex workflows such as queuing system to run long running asynchronous tasks, cron jobs, and access reliable cache to speed up frequently used resources.
<Info>
Starting with Infisical version v0.31.0, Redis will be required to fully use Infisical
</Info>
### Adding Redis to your self hosted instance of Infisical
To add Redis to your self hosted instance, follow the instructions for the deployment method you used.
<Tabs>
<Tab title="Kubernetes Helm chart">
### In cluster Redis
By default, new versions of the Infisical Helm chart already comes with an in-cluster Redis instance. To deploy a in-cluster Redis instance along with your Infisical instance, update your Infisical chart then redeploy/upgrade your release.
This will spin up a Redis instance and automatically configure it with your Infisical backend.
1. Update Infisical Helm chart
```bash
helm repo update
```
2. Upgrade Infisical release
```bash
helm upgrade <infisical release name> infisical-helm-charts/infisical --values <path to your values file>
```
### External Redis
If you want to use an external Redis instance, please add a Redis connection URL under the backend environments variables and then upgrade/redeploy your Infisical instance.
1. Update your helm values file
```yaml your-values.yaml
backendEnvironmentVariables:
REDIS_URL=<your redis connection string>
```
2. Upgrade Infisical release
```bash
helm upgrade <infisical release name> infisical-helm-charts/infisical --values <path to your values file>
```
</Tab>
<Tab title="Docker compose">
### Internal Redis service
By default, new versions of the docker compose file already comes with a Redis service. To use the pre-configured Redis service, please update your docker compose file to the latest version.
1. Download the new docker compose file
```
wget -O docker-compose.yml https://raw.githubusercontent.com/Infisical/infisical/main/docker-compose.yml
```
2. Add Redis environment variable to your .env file
```.env .env
REDIS_URL=redis://redis:6379
```
3. Restart your docker compose services
</Tab>
<Tab title="Standalone Docker image">
This standalone version of Infisical does not have an internal Redis service. To configure Redis with your Infisical instance, you must connect to a external Redis service by setting the connection string as an environment variable.
Example:
```bash
docker run -p 80:80 \
-e ENCRYPTION_KEY=f40c9178624764ad85a6830b37ce239a \
-e JWT_SIGNUP_SECRET=38ea90fb7998b92176080f457d890392 \
-e JWT_REFRESH_SECRET=7764c7bbf3928ad501591a3e005eb364 \
-e JWT_AUTH_SECRET=5239fea3a4720c0e524f814a540e14a2 \
-e JWT_SERVICE_SECRET=8509fb8b90c9b53e9e61d1e35826dcb5 \
-e REDIS_URL=<> \
-e MONGO_URL="<>" \
infisical/infisical:latest
```
Redis environment variable name: `REDIS_URL`
</Tab>
</Tabs>
## Support
If you have questions or need support, please join our [slack channel](https://infisical-users.slack.com) and one of our teammates will be happy to guide you.

@ -0,0 +1,71 @@
---
title: "Requirements"
description: ""
---
This page details the minimum requirements necessary for installing and using Infisical.
The actual resource requirements will vary in direct proportion to the operations performed by Infisical and the level of utilization by the end users.
## Deployment Sizes
**Small** suitable for most initial production setups, as well as development and testing scenarios.
**Large** suitable for high-demand production environments, characterized by either a high volume of transactions, large number of secrets, or both.
## Hardware Requirements
### Storage
Infisical doesnt require file storage as all persisted data is saved in the database.
However, its logs and metrics are saved to disk for later viewing. As a result, we recommend provisioning 1-2 GB of storage.
### CPU
CPU requirements vary heavily on the volume of secret operations (reads and writes) you anticipate.
Processing large volumes of secrets frequently and consistently will require higher CPU.
Recommended minimum CPU hardware for different sizes of deployments:
- **small:** 2-4 core is the **recommended** minimum
- **large:** 4-8 cores are suitable for larger deployments
### Memory Allocation
Memory needs depend on expected workload, including factors like user activity, automation level, and the frequency of secret operations.
Recommended minimum memory hardware for different sizes of deployments:
- **small:** 4-8 GB is the **recommended** minimum
- **large:** 16-32 GB are suitable for larger deployments
## Database & caching layer
### Postgres
PostgreSQL is the only database supported by Infisical. Infisical has been extensively tested with Postgres version 16. We recommend using versions 14 and up for optimal compatibility.
Recommended resource allocation based on deployment size:
- **small:** 1 vCPU / 2 GB RAM / 10 GB Disk
- **large:** 4vCPU / 16 GB RAM / 100 GB Disk
### Redis
Redis is utilized for session management and background tasks in Infisical.
Redis requirements:
- Use Redis versions 6.x or 7.x. We advise upgrading to at least Redis 6.2.
- Redis Cluster mode is currently not supported; use Redis Standalone, with or without High Availability (HA).
- Redis storage needs are minimal: a setup with 1 vCPU, 1 GB RAM, and 1GB SSD will be sufficient for most deployments.
## Supported Web Browsers
Infisical supports a range of web browsers. However, features such as browser-based CLI login only work on Google Chrome and Firefox at the moment.
- [Mozilla Firefox](https://www.mozilla.org/en-US/firefox/new/)
- [Google Chrome](https://www.google.com/chrome/)
- [Chromium](https://www.chromium.org/getting-involved/dev-channel/)
- [Apple Safari](https://www.apple.com/safari/)
- [Microsoft Edge](https://www.microsoft.com/en-us/edge?form=MA13FJ)

@ -0,0 +1,60 @@
---
title: "Schema migration"
description: "Run Postgres schema migrations"
---
Running schema migrations is a requirement before deploying Infisical.
Each time you decide to upgrade your version of Infisical, it's necessary to run schema migrations for that specific version.
The guide below outlines a step-by-step guide to help you through this process.
### Prerequisites
- Docker installed on your machine
- An active PostgreSQL database
- Postgres database connection string
<Steps>
<Step title="Pull the Infisical Docker Image">
First, ensure you have the correct version of the Infisical Docker image. You can pull it from Docker Hub using the following command:
```bash
docker pull infisical/infisical:<version>
```
Replace `<version>` with the specific version number you intend to deploy. View available versions [here](https://hub.docker.com/r/infisical/infisical/tags)
</Step>
<Step title="Set Up the Environment Variable">
The Docker image requires a `DB_CONNECTION_URI` environment variable. This connection string should point to your PostgreSQL database. The format generally looks like this: `postgresql://username:password@host:port/database`.
</Step>
<Step title="Run the Migration ">
To run the schema migration for the version of Infisical you want to deploy, use the following Docker command:
```bash
docker run --env DB_CONNECTION_URI=<your_connection_string> infisical/infisical:<version> npm run migration:latest
```
Replace `<your_connection_string>` with your actual PostgreSQL connection string, and `<version>` with the desired version number.
</Step>
<Step title="Verify the Migration">
After running the migration, it's good practice to check if the migration was successful. You can do this by checking the logs or accessing your database to ensure the schema has been updated accordingly.
</Step>
<Step title="Rollback If Needed">
If you need to rollback a migration by one step, use the following command:
```bash
docker run --env DB_CONNECTION_URI=<your_connection_string> infisical/infisical:<version> npm run migration:rollback
```
</Step>
<Step title="Repeat for Each Version">
It's important to run schema migrations for each version of the Infisical you deploy. For instance, if you're updating from `infisical/infisical:1` to `infisical/infisical:2`, ensure you run the schema migrations for `infisical/infisical:2` before deploying it.
</Step>
</Steps>
<Tip>
In a production setting, we recommend a more structured approach to deploying migrations prior to upgrading Infisical. This can be accomplished via CI automation.
</Tip>
### Additional discussion
- Always back up your database before running migrations, especially in a production environment.
- Test the migration process in a staging environment before applying it to production.
- Keep track of the versions and their corresponding migrations to avoid any inconsistencies.

@ -1,21 +0,0 @@
---
title: "Configure SSO"
description: "How to configure SSO when self-hosting Infisical."
---
<Warning>
Infisical offers Google SSO and GitHub SSO for free.
Infisical also offers SAML SSO authentication but as paid features that can be unlocked via enterprise license; if this is of interest, please contact team@infisical.com.
On this front, we currently support Okta, Azure AD, and JumpCloud and are expanding support for other IdPs in the coming months; stay tuned and feel free to request a IdP at this
[issue](https://github.com/Infisical/infisical/issues/442).
</Warning>
You can view specific documentation for how to set up each SSO authentication method below:
- [Google SSO](/documentation/platform/sso/google)
- [GitHub SSO](/documentation/platform/sso/github)
- [GitLab SSO](/documentation/platform/sso/gitlab)
- [Okta SAML](/documentation/platform/sso/okta)
- [Azure SAML](/documentation/platform/sso/azure)
- [JumpCloud SAML](/documentation/platform/sso/jumpcloud)

@ -67,7 +67,8 @@ View all available configurations [here](/self-hosting/configuration/envars).
<Warning>
The default .env file contains credentials that are intended solely for testing purposes.
For production use, please generate a new `ENCRYPTION_KEY` and `AUTH_SECRET`. Instructions to do so, can be found [here](/self-hosting/configuration/envars)
Please generate a new `ENCRYPTION_KEY` and `AUTH_SECRET` for use outside of testing.
Instructions to do so, can be found [here](/self-hosting/configuration/envars).
</Warning>
## Start Infisical

@ -7,18 +7,29 @@ Prerequisites:
- Basic knowledge of [Docker](https://www.docker.com/)
- Have Docker installed on your system. If not, follow the installation guide [here](https://docs.docker.com/get-docker/).
Infisical is available as a single Docker image to ease deployment.
This Docker image only includes the application code, meaning you must supply a connection to a Postgres database and a Redis instance.
The following guide provides a detailed step-by-step walkthrough on how you can deploy Infisical with Docker.
<Steps>
<Step title="Pull the Infisical Docker image">
Run the following command in your terminal to pull the Infisical Docker image:
Visit [Docker Hub](https://hub.docker.com/r/infisical/infisical/tags) and select a version of Infisical image you would like to deploy.
Then run the following command in your terminal to pull the specific Infisical Docker image.
```
docker pull infisical/infisical:latest
docker pull infisical/infisical:<version>
```
Remember to replace `<version>` with the docker image tag of your choice.
</Step>
<Step title="Run Postgres schema migration ">
Before you can start the instance of Infisical, you need to run the database schema migrations.
Follow the step by [step guide here](/self-hosting/configuration/schema-migrations) on running schema migrations for Infisical.
</Step>
<Step title="Start Infisical">
2.1. Running Infisical requires a few environment variables to be set.
At minimum, Infisical requires that you set the variables `ENCRYPTION_KEY`, `AUTH_SECRET`, `MONGO_URL`, and `REDIS_URL`
which you can read more about [here](/self-hosting/configuration/envars).
For a minimal installation of Infisical, you must configure `ENCRYPTION_KEY`, `AUTH_SECRET`, `DB_CONNECTION_URI`, and `REDIS_URL`.
[View all available configurations](/self-hosting/configuration/envars).
Once you have added the required environment variables to your docker run command, execute it in your terminal to get Infisical up and running.
@ -28,22 +39,20 @@ Prerequisites:
docker run -p 80:8080 \
-e ENCRYPTION_KEY=f40c9178624764ad85a6830b37ce239a \
-e AUTH_SECRET="q6LRi7c717a3DQ8JUxlWYkZpMhG4+RHLoFUVt3Bvo2U=" \
-e MONGO_URL="<>" \
infisical/infisical:latest
-e DB_CONNECTION_URI="<>" \
-e REDIS_URL="<>" \
infisical/infisical:<version>
```
<Warning>
The above environment variable values are only to be used as an example and should not be used in production
</Warning>
2.2. Once the container is running, verify the installation by opening your web browser and navigating to `http://localhost:80`.
Once the container is running, verify the installation by opening your web browser and navigating to `http://localhost:80`.
</Step>
</Steps>
<AccordionGroup>
<Accordion title="What are the system requirements for running Infisical?">
To have a functional deployment, we recommended compute with 2GB of RAM and 1 CPU.
However, depending on your usage, you may need to further scale up system resources to meet demand.
</Accordion>
</AccordionGroup>
### Additional discussion
It's important to note that the above is a basic example of deploying Infisical using Docker.
In practice, for production deployments, you may want to use container orchestration platforms such as AWS ECS, Google Cloud Run, or Kubernetes.
These platforms offer additional features like scalability, load balancing, and automated deployment, making them suitable for handling production-level traffic and providing high availability.

@ -1,138 +0,0 @@
---
title: "Kubernetes"
description: "How to deploy Infisical with Kubernetes"
---
<Info>
Self-host vs. Infisical Cloud
Self-hosting Infisical means managing the service yourself, taking care of upgrades, scaling, security, etc.
If you're less technical and looking for a hands-free experience with minimal overhead then we recommend Infisical Cloud.
</Info>
**Prerequisites**
- You have understanding of [Kubernetes](https://kubernetes.io/)
- You have understanding of [Helm package manager](https://helm.sh/)
- You have [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) installed and connected to your kubernetes cluster
#### 1. Fill our environment variables
Before you can deploy the Helm chart, you must fill out the required environment variables. To do so, please copy the below file to a `.yaml` file.
Refer to the available [environment variables](../../self-hosting/configuration/envars) to learn more
<Accordion title="values.yaml">
[View all available Helm chart values parameters](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical)
```yaml
frontend:
enabled: true
name: frontend
podAnnotations: {}
deploymentAnnotations: {}
replicaCount: 2
image:
repository: infisical/frontend
tag: "latest"
pullPolicy: IfNotPresent
kubeSecretRef: ""
service:
annotations: {}
type: ClusterIP
nodePort: ""
frontendEnvironmentVariables:
SITE_URL: infisical.local
backend:
enabled: true
name: backend
podAnnotations: {}
deploymentAnnotations: {}
replicaCount: 2
image:
repository: infisical/backend
tag: "latest"
pullPolicy: IfNotPresent
kubeSecretRef: ""
service:
annotations: {}
type: ClusterIP
nodePort: ""
backendEnvironmentVariables:
ENCRYPTION_KEY: MUST_REPLACE
JWT_SIGNUP_SECRET: MUST_REPLACE
JWT_REFRESH_SECRET: MUST_REPLACE
JWT_AUTH_SECRET: MUST_REPLACE
JWT_SERVICE_SECRET: MUST_REPLACE
SMTP_HOST: MUST_REPLACE
SMTP_PORT: 587
SMTP_SECURE: false
SMTP_FROM_NAME: Infisical
SMTP_FROM_ADDRESS: MUST_REPLACE
SMTP_USERNAME: MUST_REPLACE
SMTP_PASSWORD: MUST_REPLACE
SITE_URL: infisical.local
## Mongo DB persistence
mongodb:
enabled: true
## By default the backend will be connected to a Mongo instance within the cluster
## However, it is recommended to add a managed document DB connection string for production-use (DBaaS)
## Learn about connection string type here https://www.mongodb.com/docs/manual/reference/connection-string/
## e.g. "mongodb://<user>:<pass>@<host>:<port>/<database-name>"
mongodbConnection:
externalMongoDBConnectionString: ""
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
# cert-manager.io/issuer: letsencrypt-nginx
hostName: infisical.local ## <- Replace with your own domain
frontend:
path: /
pathType: Prefix
backend:
path: /api
pathType: Prefix
tls: []
# - secretName: letsencrypt-nginx
# hosts:
# - infisical.local
mailhog:
enabled: false
```
</Accordion>
Once you have a local copy of the values file, fill our the required environment variables and save the file.
#### 2. Install Infisical Helm repository
```bash
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
```
#### 3. Install the Helm chart
By default, the helm chart will be installed on your default namespace. If you wish to install the Chart on a different namespace, you may specify
that by adding the `--namespace <namespace-to-install-to>` to your `helm install` command.
```bash
## Installs to default namespace
helm install infisical-helm-charts/infisical --generate-name --values <path to the values.yaml you downloaded/created in step 2>
```
<Note>
If you have not filled out all of the required environment variables, you will see an error message prompting you to
do so.
</Note>
#### 4. Your Infisical installation is complete and should be running on the host name you specified in Ingress in `values.yaml`.

@ -1,53 +0,0 @@
---
title: "Linux VM"
description: "How to deploy Infisical with Docker-Compose"
---
<Info>
Self-host vs. Infisical Cloud
Self-hosting Infisical means managing the service yourself, taking care of upgrades, scaling, security, etc.
If you're less technical and looking for a hands-free experience with minimal overhead then we recommend Infisical Cloud.
</Info>
We provide a docker-compose deployment option for those who want to deploy Infisical onto a Linux VM easily.
1. Install Docker on your VM
```bash
# Example in ubuntu
apt-get update
apt-get upgrade
apt install docker-compose
```
2. Download the required files
```bash
# Download env file template
wget -O .env https://raw.githubusercontent.com/Infisical/infisical/main/.env.example
# Download docker compose template
wget -O docker-compose.yml https://raw.githubusercontent.com/Infisical/infisical/main/docker-compose.yml
# Download nginx config
mkdir nginx && wget -O ./nginx/default.conf https://raw.githubusercontent.com/Infisical/infisical/main/nginx/default.dev.conf
```
3. Tweak the `.env` according to your preferences. Refer to the available [environment variables](../../self-hosting/configuration/envars)
```bash
# update environment variables like mongo login
nano .env
```
4. Get the service up and running.
```bash
# Start up services in detached mode
docker-compose -f docker-compose.yml up -d
```
5. Your Infisical installation is complete and should be running on [http://localhost:80](http://localhost:80). Please note that the containers are not exposed to the internet and only bind to the localhost. It's up to you to configure a firewall, SSL certificates, and implement any additional security measures.

@ -1,5 +1,5 @@
{
"name": "npm-proj-1708142380787-0.9952765718063858vJAsWg",
"name": "npm-proj-1708687711895-0.8280111363176879xoEiUg",
"lockfileVersion": 3,
"requires": true,
"packages": {
@ -82,7 +82,7 @@
"react-markdown": "^8.0.3",
"react-redux": "^8.0.2",
"react-table": "^7.8.0",
"sanitize-html": "^2.11.0",
"sanitize-html": "^2.12.1",
"set-cookie-parser": "^2.5.1",
"sharp": "^0.33.2",
"styled-components": "^5.3.7",
@ -21111,9 +21111,9 @@
"dev": true
},
"node_modules/sanitize-html": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.11.0.tgz",
"integrity": "sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==",
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.12.1.tgz",
"integrity": "sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA==",
"dependencies": {
"deepmerge": "^4.2.2",
"escape-string-regexp": "^4.0.0",

@ -90,7 +90,7 @@
"react-markdown": "^8.0.3",
"react-redux": "^8.0.2",
"react-table": "^7.8.0",
"sanitize-html": "^2.11.0",
"sanitize-html": "^2.12.1",
"set-cookie-parser": "^2.5.1",
"sharp": "^0.33.2",
"styled-components": "^5.3.7",

@ -1,7 +1,9 @@
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import Link from "next/link";
import axios from "axios";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { useSendVerificationEmail } from "@app/hooks/api";
import { Button, Input } from "../v2";
@ -25,6 +27,7 @@ export default function EnterEmailStep({
setEmail,
incrementStep
}: DownloadBackupPDFStepProps): JSX.Element {
const { createNotification } = useNotificationContext();
const { mutateAsync } = useSendVerificationEmail();
const [emailError, setEmailError] = useState(false);
const { t } = useTranslation();
@ -46,8 +49,18 @@ export default function EnterEmailStep({
// If everything is correct, go to the next step
if (!emailCheckBool) {
await mutateAsync({ email });
incrementStep();
try {
await mutateAsync({ email });
incrementStep();
} catch(e) {
if (axios.isAxiosError(e)) {
const { message = "Something went wrong" } = e.response?.data as { message: string};
createNotification({
type: "error",
text: message
})
}
}
}
};

@ -33,9 +33,7 @@ export const UpgradeOverlay = () => {
return null;
}
// for non admin this would throw an error
// so no need to render
return !isUpgradeStatusLoading && isUpgrading ? ( // isUpgrading
return !isUpgradeStatusLoading && isUpgrading ? (
<div className="absolute top-0 left-0 z-50 flex h-screen w-screen items-center justify-center bg-bunker-500 bg-opacity-80">
<Spinner size="lg" className="text-primary" />
<div className="ml-4 flex flex-col space-y-1">

@ -2,6 +2,7 @@ import { useCallback, useState } from "react";
import { useRouter } from "next/router";
import { faWarning } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { twMerge } from "tailwind-merge";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import { useProjectPermission } from "@app/context";
@ -10,6 +11,7 @@ import { Workspace } from "@app/hooks/api/types";
import { ProjectVersion } from "@app/hooks/api/workspace/types";
import { Button } from "../Button";
import { Tooltip } from "../Tooltip";
export type UpgradeProjectAlertProps = {
project: Workspace;
@ -83,20 +85,44 @@ export const UpgradeProjectAlert = ({ project }: UpgradeProjectAlertProps): JSX.
projectStatus?.status !== "FAILED");
if (project.version !== ProjectVersion.V1) return null;
if (membership.role !== "admin") return null;
return (
<div className="mt-4 flex w-full flex-row items-center rounded-md border border-primary-600/70 bg-primary/[.07] p-4 text-base text-white">
<div
className={twMerge(
"mt-4 flex w-full flex-row items-center rounded-md border border-primary-600/70 bg-primary/[.07] p-4 text-base text-white",
membership.role !== "admin" && "opacity-80"
)}
>
<FontAwesomeIcon icon={faWarning} className="pr-6 text-6xl text-white/80" />
<div className="flex w-full flex-col text-sm">
<span className="mb-2 text-lg font-semibold">Upgrade your project</span>
Upgrade your project version to continue receiving the latest improvements and patches.
{membership.role === "admin" ? (
<p>
Upgrade your project version to continue receiving the latest improvements and patches.
</p>
) : (
<p>
<span className="font-bold">Please ask a project admin to upgrade the project.</span>
<br />
Upgrading the project version is required to continue receiving the latest improvements
and patches.
</p>
)}
{currentStatus && <p className="mt-2 opacity-80">Status: {currentStatus}</p>}
</div>
<div className="my-2">
<Button isLoading={isLoading} isDisabled={isLoading} onClick={onUpgradeProject}>
Upgrade
</Button>
<Tooltip
className={twMerge(membership.role === "admin" && "hidden")}
content="You need to be an admin to upgrade the project."
>
<Button
isLoading={isLoading}
isDisabled={isLoading || membership.role !== "admin"}
onClick={onUpgradeProject}
>
Upgrade
</Button>
</Tooltip>
</div>
</div>
);

@ -1,6 +1,7 @@
export type TServerConfig = {
initialized: boolean;
allowSignUp: boolean;
allowedSignUpDomain?: string | null;
isMigrationModeOn?: boolean;
};

@ -2,7 +2,6 @@ export type ServerStatus = {
date: string;
message: string;
emailConfigured: boolean;
inviteOnlySignup: boolean;
secretScanningConfigured: boolean
redisConfigured: boolean
};
};

@ -2,7 +2,7 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import crypto from "crypto";
import { useState } from "react";
import { useEffect, useState } from "react";
import Head from "next/head";
import Image from "next/image";
import Link from "next/link";
@ -22,6 +22,7 @@ import { deriveArgonKey } from "@app/components/utilities/cryptography/crypto";
import issueBackupKey from "@app/components/utilities/cryptography/issueBackupKey";
import { saveTokenToLocalStorage } from "@app/components/utilities/saveTokenToLocalStorage";
import SecurityClient from "@app/components/utilities/SecurityClient";
import { useServerConfig } from "@app/context";
import { completeAccountSignupInvite, verifySignupInvite } from "@app/hooks/api/auth/queries";
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
@ -56,6 +57,13 @@ export default function SignupInvite() {
const token = parsedUrl.token as string;
const organizationId = parsedUrl.organization_id as string;
const email = (parsedUrl.to as string)?.replace(" ", "+").trim();
const { config } = useServerConfig();
useEffect(() => {
if (!config.allowSignUp) {
router.push("/login");
}
}, [config.allowSignUp]);
// Verifies if the information that the users entered (name, workspace) is there, and if the password matched the criteria.
const signupErrorCheck = async () => {

@ -141,10 +141,10 @@ export const OrgMembersTable = ({ handlePopUpOpen, setCompleteInviteLink }: Prop
() =>
members?.filter(
({ user: u, inviteEmail }) =>
u?.firstName?.toLowerCase().includes(searchMemberFilter) ||
u?.lastName?.toLowerCase().includes(searchMemberFilter) ||
u?.email?.toLowerCase().includes(searchMemberFilter) ||
inviteEmail?.includes(searchMemberFilter)
u?.firstName?.toLowerCase().includes(searchMemberFilter.toLowerCase()) ||
u?.lastName?.toLowerCase().includes(searchMemberFilter.toLowerCase()) ||
u?.email?.toLowerCase().includes(searchMemberFilter.toLowerCase()) ||
inviteEmail?.includes(searchMemberFilter.toLowerCase())
),
[members, searchMemberFilter]
);

@ -218,10 +218,10 @@ export const MemberListTab = () => {
() =>
members?.filter(
({ user: u, inviteEmail }) =>
u?.firstName?.toLowerCase().includes(searchMemberFilter) ||
u?.lastName?.toLowerCase().includes(searchMemberFilter) ||
u?.email?.toLowerCase().includes(searchMemberFilter) ||
inviteEmail?.includes(searchMemberFilter)
u?.firstName?.toLowerCase().includes(searchMemberFilter.toLowerCase()) ||
u?.lastName?.toLowerCase().includes(searchMemberFilter.toLowerCase()) ||
u?.email?.toLowerCase().includes(searchMemberFilter.toLowerCase()) ||
inviteEmail?.includes(searchMemberFilter.toLowerCase())
),
[members, searchMemberFilter]
);

@ -274,65 +274,65 @@ export const SecretOverviewPage = () => {
<div className="relative right-5 ml-4">
<NavHeader pageName={t("dashboard.title")} isProjectRelated />
</div>
<div className="mt-6">
<p className="text-3xl font-semibold text-bunker-100">Secrets Overview</p>
<p className="text-md text-bunker-300">
Inject your secrets using
<a
className="ml-1 text-mineshaft-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/docs/cli/overview"
target="_blank"
rel="noopener noreferrer"
>
Infisical CLI
</a>
,
<a
className="ml-1 text-mineshaft-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/docs/documentation/getting-started/api"
target="_blank"
rel="noopener noreferrer"
>
Infisical API
</a>
,
<a
className="ml-1 text-mineshaft-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/docs/sdks/overview"
target="_blank"
rel="noopener noreferrer"
>
Infisical SDKs
</a>
, and
<a
className="ml-1 text-mineshaft-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/docs/documentation/getting-started/introduction"
target="_blank"
rel="noopener noreferrer"
>
more
</a>
.
</p>
</div>
<div className="space-y-8">
<div className="mt-6">
<p className="text-3xl font-semibold text-bunker-100">Secrets Overview</p>
<p className="text-md text-bunker-300">
Inject your secrets using
<a
className="ml-1 text-mineshaft-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/docs/cli/overview"
target="_blank"
rel="noopener noreferrer"
>
Infisical CLI
</a>
,
<a
className="ml-1 text-mineshaft-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/docs/documentation/getting-started/api"
target="_blank"
rel="noopener noreferrer"
>
Infisical API
</a>
,
<a
className="ml-1 text-mineshaft-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/docs/sdks/overview"
target="_blank"
rel="noopener noreferrer"
>
Infisical SDKs
</a>
, and
<a
className="ml-1 text-mineshaft-300 underline decoration-primary-800 underline-offset-4 duration-200 hover:text-mineshaft-100 hover:decoration-primary-600"
href="https://infisical.com/docs/documentation/getting-started/introduction"
target="_blank"
rel="noopener noreferrer"
>
more
</a>
.
</p>
</div>
{currentWorkspace?.version === ProjectVersion.V1 && (
<>
{currentWorkspace?.version === ProjectVersion.V1 && (
<UpgradeProjectAlert project={currentWorkspace} />
{/* <UpgradeOverlay /> */}
</>
)}
<div className="mt-8 flex items-center justify-between">
<FolderBreadCrumbs secretPath={secretPath} onResetSearch={handleResetSearch} />
<div className="w-80">
<Input
className="h-[2.3rem] bg-mineshaft-800 placeholder-mineshaft-50 duration-200 focus:bg-mineshaft-700/80"
placeholder="Search by secret/folder name..."
value={searchFilter}
onChange={(e) => setSearchFilter(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
/>
)}
<div className="flex items-center justify-between">
<FolderBreadCrumbs secretPath={secretPath} onResetSearch={handleResetSearch} />
<div className="w-80">
<Input
className="h-[2.3rem] bg-mineshaft-800 placeholder-mineshaft-50 duration-200 focus:bg-mineshaft-700/80"
placeholder="Search by secret/folder name..."
value={searchFilter}
onChange={(e) => setSearchFilter(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
/>
</div>
</div>
</div>
<div className="thin-scrollbar mt-4" ref={parentTableRef}>

@ -1,7 +1,24 @@
import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import { useRouter } from "next/router";
import { faAt } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { ContentLoader, Switch, Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
import {
Button,
ContentLoader,
FormControl,
Input,
Select,
SelectItem,
Tab,
TabList,
TabPanel,
Tabs
} from "@app/components/v2";
import { useOrganization, useServerConfig, useUser } from "@app/context";
import { useUpdateServerConfig } from "@app/hooks/api";
@ -9,16 +26,47 @@ enum TabSections {
Settings = "settings"
}
enum SignUpModes {
Disabled = "disabled",
Anyone = "anyone"
}
const formSchema = z.object({
signUpMode: z.nativeEnum(SignUpModes),
allowedSignUpDomain: z.string().optional().nullable()
});
type TDashboardForm = z.infer<typeof formSchema>;
export const AdminDashboardPage = () => {
const router = useRouter();
const data = useServerConfig();
const { config } = data;
const {
control,
handleSubmit,
watch,
formState: { isSubmitting, isDirty }
} = useForm<TDashboardForm>({
resolver: zodResolver(formSchema),
values: {
// eslint-disable-next-line
signUpMode: config.allowSignUp ? SignUpModes.Anyone : SignUpModes.Disabled,
allowedSignUpDomain: config.allowedSignUpDomain
}
});
const signupMode = watch("signUpMode");
const { user, isLoading: isUserLoading } = useUser();
const { orgs } = useOrganization();
const { mutate: updateServerConfig } = useUpdateServerConfig();
const { mutateAsync: updateServerConfig } = useUpdateServerConfig();
const { createNotification } = useNotificationContext();
const isNotAllowed = !user?.superAdmin;
// TODO(akhilmhdh): on nextjs 14 roadmap this will be properly addressed with context split
useEffect(() => {
if (isNotAllowed && !isUserLoading) {
if (orgs?.length) {
@ -28,37 +76,115 @@ export const AdminDashboardPage = () => {
}
}, [isNotAllowed, isUserLoading]);
const onFormSubmit = async (formData: TDashboardForm) => {
try {
const { signUpMode, allowedSignUpDomain } = formData;
await updateServerConfig({
allowSignUp: signUpMode !== SignUpModes.Disabled,
allowedSignUpDomain: signUpMode === SignUpModes.Anyone ? allowedSignUpDomain : null
});
createNotification({
text: "Successfully changed sign up setting.",
type: "success"
});
} catch (e) {
console.error(e);
createNotification({
type: "error",
text: "Failed to update sign up setting."
});
}
};
return (
<div className="container mx-auto max-w-7xl pb-12 text-white dark:[color-scheme:dark]">
<div className="mx-auto mb-6 w-full max-w-7xl py-6 px-6">
<div className="container mx-auto max-w-7xl px-4 pb-12 text-white dark:[color-scheme:dark]">
<div className="mx-auto mb-6 w-full max-w-7xl pt-6">
<div className="mb-8 flex flex-col items-start justify-between text-xl">
<h1 className="text-3xl font-semibold">Admin Dashboard</h1>
<p className="text-base text-bunker-300">Manage your Infisical instance.</p>
</div>
{isUserLoading || isNotAllowed ? (
<ContentLoader text={isNotAllowed ? "Redirecting to org page..." : undefined} />
) : (
<div>
<Tabs defaultValue={TabSections.Settings}>
<TabList>
<div className="flex w-full flex-row border-b border-mineshaft-600">
<Tab value={TabSections.Settings}>General</Tab>
</div>
</TabList>
<TabPanel value={TabSections.Settings}>
<div className="flex items-center space-x-4">
<Switch
id="disable-invite"
isChecked={Boolean(config?.allowSignUp)}
onCheckedChange={(isChecked) => updateServerConfig({ allowSignUp: isChecked })}
/>
<div className="flex-grow">Enable signup or invite</div>
</div>
</TabPanel>
</Tabs>
</div>
)}
</div>
{isUserLoading || isNotAllowed ? (
<ContentLoader text={isNotAllowed ? "Redirecting to org page..." : undefined} />
) : (
<div>
<Tabs defaultValue={TabSections.Settings}>
<TabList>
<div className="flex w-full flex-row border-b border-mineshaft-600">
<Tab value={TabSections.Settings}>General</Tab>
</div>
</TabList>
<TabPanel value={TabSections.Settings}>
<form
className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
onSubmit={handleSubmit(onFormSubmit)}
>
<div className="flex justify-between">
<div className="mb-4 text-xl font-semibold text-mineshaft-100">
Allow user sign up
</div>
<Controller
control={control}
name="signUpMode"
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl
className="max-w-72 w-72"
errorText={error?.message}
isError={Boolean(error)}
>
<Select
className="w-72 bg-mineshaft-700"
dropdownContainerClassName="bg-mineshaft-700"
defaultValue={field.value}
onValueChange={(e) => onChange(e)}
{...field}
>
<SelectItem value={SignUpModes.Disabled}>Disabled</SelectItem>
<SelectItem value={SignUpModes.Anyone}>Anyone</SelectItem>
</Select>
</FormControl>
)}
/>
</div>
{signupMode === "anyone" && (
<div className="mt-4 flex items-center justify-between">
<div className="mb-4 flex text-mineshaft-100">
Restrict sign up by email domain(s)
</div>
<Controller
control={control}
defaultValue=""
name="allowedSignUpDomain"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Leave blank to allow any email domains"
className="w-72"
isError={Boolean(error)}
errorText={error?.message}
>
<Input
{...field}
value={field.value || ""}
placeholder="gmail.com, aws.com, redhat.com"
leftIcon={<FontAwesomeIcon icon={faAt} />}
/>
</FormControl>
)}
/>
</div>
)}
<Button
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting || !isDirty}
>
Save
</Button>
</form>
</TabPanel>
</Tabs>
</div>
)}
</div>
);
};