From 5704dfb35f959ef2e9a1636ef80f3861a7400af6 Mon Sep 17 00:00:00 2001 From: MohamadTahir Date: Sat, 2 Sep 2023 09:29:23 +0300 Subject: [PATCH 01/56] add resource specification to frontend and backend deployment containers --- helm-charts/infisical/CHANGELOG.md | 3 ++ helm-charts/infisical/Chart.yaml | 2 +- helm-charts/infisical/README.md | 34 ++++++++++--------- .../templates/backend-deployment.yaml | 4 ++- .../templates/frontend-deployment.yaml | 4 ++- helm-charts/infisical/values.yaml | 14 ++++++++ 6 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 helm-charts/infisical/CHANGELOG.md diff --git a/helm-charts/infisical/CHANGELOG.md b/helm-charts/infisical/CHANGELOG.md new file mode 100644 index 000000000..131fbda94 --- /dev/null +++ b/helm-charts/infisical/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.3.3 +### Changes since 0.3.2 [#933](https://github.com/Infisical/infisical/pull/933) +- added resource specs to both the frontend and backend diff --git a/helm-charts/infisical/Chart.yaml b/helm-charts/infisical/Chart.yaml index 5f3684346..5964553df 100644 --- a/helm-charts/infisical/Chart.yaml +++ b/helm-charts/infisical/Chart.yaml @@ -7,7 +7,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.3.2 +version: 0.3.3 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/helm-charts/infisical/README.md b/helm-charts/infisical/README.md index de001d4f7..f09330ea5 100644 --- a/helm-charts/infisical/README.md +++ b/helm-charts/infisical/README.md @@ -61,22 +61,23 @@ kubectl get secrets -n \ ### Infisical frontend parameters -| Name | Description | Value | -| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | -| `frontend.enabled` | Enable frontend | `true` | -| `frontend.name` | Backend name | `frontend` | -| `frontend.fullnameOverride` | Backend fullnameOverride | `""` | -| `frontend.podAnnotations` | Backend pod annotations | `{}` | -| `frontend.deploymentAnnotations` | Backend deployment annotations | `{}` | -| `frontend.replicaCount` | Backend replica count | `2` | -| `frontend.image.repository` | Backend image repository | `infisical/frontend` | -| `frontend.image.tag` | Backend image tag | `latest` | -| `frontend.image.pullPolicy` | Backend image pullPolicy | `IfNotPresent` | -| `frontend.kubeSecretRef` | Backend secret resource reference name (containing required [frontend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) | `""` | -| `frontend.service.annotations` | Backend service annotations | `{}` | -| `frontend.service.type` | Backend service type | `ClusterIP` | -| `frontend.service.nodePort` | Backend service nodePort (used if above type is `NodePort`) | `""` | -| `frontendEnvironmentVariables.SITE_URL` | Absolute URL including the protocol (e.g. https://app.infisical.com) | `infisical.local` | +| Name | Description | Value | +| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- | +| `frontend.enabled` | Enable frontend | `true` | +| `frontend.name` | Backend name | `frontend` | +| `frontend.fullnameOverride` | Backend fullnameOverride | `""` | +| `frontend.podAnnotations` | Backend pod annotations | `{}` | +| `frontend.deploymentAnnotations` | Backend deployment annotations | `{}` | +| `frontend.replicaCount` | Backend replica count | `2` | +| `frontend.image.repository` | Backend image repository | `infisical/frontend` | +| `frontend.image.tag` | Backend image tag | `latest` | +| `frontend.image.pullPolicy` | Backend image pullPolicy | `IfNotPresent` | +| `frontend.kubeSecretRef` | Backend secret resource reference name (containing required [frontend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) | `""` | +| `frontend.service.annotations` | Backend service annotations | `{}` | +| `frontend.service.type` | Backend service type | `ClusterIP` | +| `frontend.service.nodePort` | Backend service nodePort (used if above type is `NodePort`) | `""` | +| `frontend.resources` | Frontend container resource spesification, check the offical [kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `` | +| `frontendEnvironmentVariables.SITE_URL` | Absolute URL including the protocol (e.g. https://app.infisical.com) | `infisical.local` | ### Infisical backend parameters @@ -91,6 +92,7 @@ kubectl get secrets -n \ | `backend.image.repository` | Backend image repository | `infisical/backend` | | `backend.image.tag` | Backend image tag | `latest` | | `backend.image.pullPolicy` | Backend image pullPolicy | `IfNotPresent` | +| `backend.resources` | Backend container resource spesification, check the offical [kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `` | | `backend.kubeSecretRef` | Backend secret resource reference name (containing required [backend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) | `""` | | `backend.service.annotations` | Backend service annotations | `{}` | | `backend.service.type` | Backend service type | `ClusterIP` | diff --git a/helm-charts/infisical/templates/backend-deployment.yaml b/helm-charts/infisical/templates/backend-deployment.yaml index 5646d368b..95fb11744 100644 --- a/helm-charts/infisical/templates/backend-deployment.yaml +++ b/helm-charts/infisical/templates/backend-deployment.yaml @@ -40,7 +40,9 @@ spec: envFrom: - secretRef: name: {{ $backend.kubeSecretRef | default (include "infisical.backend.fullname" .) }} - + {{- if $backend.resources }} + resources: {{- toYaml $backend.resources | nindent 12 }} + {{- end }} --- apiVersion: v1 diff --git a/helm-charts/infisical/templates/frontend-deployment.yaml b/helm-charts/infisical/templates/frontend-deployment.yaml index 9c5cd1560..162f7154e 100644 --- a/helm-charts/infisical/templates/frontend-deployment.yaml +++ b/helm-charts/infisical/templates/frontend-deployment.yaml @@ -40,7 +40,9 @@ spec: name: {{ $frontend.kubeSecretRef | default (include "infisical.frontend.fullname" .) }} ports: - containerPort: 3000 - + {{- if $frontend.resources }} + resources: {{- toYaml $frontend.resources | nindent 12 }} + {{- end }} --- apiVersion: v1 diff --git a/helm-charts/infisical/values.yaml b/helm-charts/infisical/values.yaml index 1ffbc318f..1dafd8995 100644 --- a/helm-charts/infisical/values.yaml +++ b/helm-charts/infisical/values.yaml @@ -43,6 +43,13 @@ frontend: ## @param frontend.image.pullPolicy Backend image pullPolicy ## pullPolicy: IfNotPresent + ## container resource specifications [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) + ## + resources: + limits: + memory: 100Mi + requests: + cpu: 10m ## @param frontend.kubeSecretRef Backend secret resource reference name (containing required [frontend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) ## kubeSecretRef: "" @@ -102,6 +109,13 @@ backend: ## @param backend.image.pullPolicy Backend image pullPolicy ## pullPolicy: IfNotPresent + ## container resource specifications [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) + ## + resources: + limits: + memory: 200Mi + requests: + cpu: 150m ## @param backend.kubeSecretRef Backend secret resource reference name (containing required [backend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) ## kubeSecretRef: "" From ae37d80891c79dd3fe2efefa10a7f4a0cf7c912d Mon Sep 17 00:00:00 2001 From: JesseBot Date: Thu, 7 Sep 2023 19:55:21 +0200 Subject: [PATCH 02/56] Update values.yaml - add mongodb.auth.existingSecret parameter --- helm-charts/infisical/values.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/helm-charts/infisical/values.yaml b/helm-charts/infisical/values.yaml index 1ffbc318f..03454f565 100644 --- a/helm-charts/infisical/values.yaml +++ b/helm-charts/infisical/values.yaml @@ -269,6 +269,12 @@ mongodb: ## @param mongodb.auth.rootPassword Database root user password ## rootPassword: root + + ## @param auth.existingSecret Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, `mongodb-replica-set-key`) + ## NOTE: When it's set the previous parameters are ignored. + ## + existingSecret: "" + ## MongoDB persistence configuration ## persistence: From 6c126606da8f23215fec11984fd6d8addaedb390 Mon Sep 17 00:00:00 2001 From: JesseBot Date: Thu, 7 Sep 2023 20:02:15 +0200 Subject: [PATCH 03/56] Update README.md for helm chart parameters to include mongodb.auth.existingSecret --- helm-charts/infisical/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helm-charts/infisical/README.md b/helm-charts/infisical/README.md index de001d4f7..ee0a3b9cd 100644 --- a/helm-charts/infisical/README.md +++ b/helm-charts/infisical/README.md @@ -147,6 +147,7 @@ kubectl get secrets -n \ | `mongodb.auth.databases` | Custom databases list ([special characters warning](https://www.mongodb.com/docs/manual/reference/connection-string/#standard-connection-string-format)) | `["infisical"]` | | `mongodb.auth.rootUser` | Database root user name | `root` | | `mongodb.auth.rootPassword` | Database root user password | `root` | +| `mongodb.auth.existingSecret` | Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, `mongodb-replica-set-key`) | `""` | | `mongodb.persistence.enabled` | Enable database persistence | `true` | | `mongodb.persistence.existingClaim` | Existing persistent volume claim name | `""` | | `mongodb.persistence.resourcePolicy` | Keep the persistent volume even on deletion (`keep` or `""`) | `keep` | @@ -341,4 +342,4 @@ for component in $components; do -o jsonpath='{.spec.template.spec.containers[0].env[*]}' | \ jq -r '.name + ":" + .value' > infisical-$component-conf.bak done -``` \ No newline at end of file +``` From e37810f30275e0a5592913045f61d42a496965d0 Mon Sep 17 00:00:00 2001 From: JesseBot Date: Fri, 8 Sep 2023 18:52:16 +0200 Subject: [PATCH 04/56] Update Chart.yaml - bump helm chart version after adding mongodb.auth.existingSecret parameter to values.yaml --- helm-charts/infisical/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm-charts/infisical/Chart.yaml b/helm-charts/infisical/Chart.yaml index 5f3684346..5964553df 100644 --- a/helm-charts/infisical/Chart.yaml +++ b/helm-charts/infisical/Chart.yaml @@ -7,7 +7,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.3.2 +version: 0.3.3 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to From 86b2b95d11b35c3bca5fb5c9e6eaa944d36a3601 Mon Sep 17 00:00:00 2001 From: MohamadTahir Date: Mon, 11 Sep 2023 22:10:47 +0300 Subject: [PATCH 05/56] update readme file and values.yaml documentations --- helm-charts/infisical/README.md | 40 ++++++++++++++++--------------- helm-charts/infisical/values.yaml | 6 +++-- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/helm-charts/infisical/README.md b/helm-charts/infisical/README.md index f09330ea5..5bc23b73a 100644 --- a/helm-charts/infisical/README.md +++ b/helm-charts/infisical/README.md @@ -61,23 +61,24 @@ kubectl get secrets -n \ ### Infisical frontend parameters -| Name | Description | Value | -| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------- | -| `frontend.enabled` | Enable frontend | `true` | -| `frontend.name` | Backend name | `frontend` | -| `frontend.fullnameOverride` | Backend fullnameOverride | `""` | -| `frontend.podAnnotations` | Backend pod annotations | `{}` | -| `frontend.deploymentAnnotations` | Backend deployment annotations | `{}` | -| `frontend.replicaCount` | Backend replica count | `2` | -| `frontend.image.repository` | Backend image repository | `infisical/frontend` | -| `frontend.image.tag` | Backend image tag | `latest` | -| `frontend.image.pullPolicy` | Backend image pullPolicy | `IfNotPresent` | -| `frontend.kubeSecretRef` | Backend secret resource reference name (containing required [frontend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) | `""` | -| `frontend.service.annotations` | Backend service annotations | `{}` | -| `frontend.service.type` | Backend service type | `ClusterIP` | -| `frontend.service.nodePort` | Backend service nodePort (used if above type is `NodePort`) | `""` | -| `frontend.resources` | Frontend container resource spesification, check the offical [kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `` | -| `frontendEnvironmentVariables.SITE_URL` | Absolute URL including the protocol (e.g. https://app.infisical.com) | `infisical.local` | +| Name | Description | Value | +| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| `frontend.enabled` | Enable frontend | `true` | +| `frontend.name` | Backend name | `frontend` | +| `frontend.fullnameOverride` | Backend fullnameOverride | `""` | +| `frontend.podAnnotations` | Backend pod annotations | `{}` | +| `frontend.deploymentAnnotations` | Backend deployment annotations | `{}` | +| `frontend.replicaCount` | Backend replica count | `2` | +| `frontend.image.repository` | Backend image repository | `infisical/frontend` | +| `frontend.image.tag` | Backend image tag | `latest` | +| `frontend.image.pullPolicy` | Backend image pullPolicy | `IfNotPresent` | +| `frontend.resources.limits.memory` | container memory limit [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `100Mi` | +| `frontend.resources.requests.cpu` | container CPU request [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `10m` | +| `frontend.kubeSecretRef` | Backend secret resource reference name (containing required [frontend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) | `""` | +| `frontend.service.annotations` | Backend service annotations | `{}` | +| `frontend.service.type` | Backend service type | `ClusterIP` | +| `frontend.service.nodePort` | Backend service nodePort (used if above type is `NodePort`) | `""` | +| `frontendEnvironmentVariables.SITE_URL` | Absolute URL including the protocol (e.g. https://app.infisical.com) | `infisical.local` | ### Infisical backend parameters @@ -92,7 +93,8 @@ kubectl get secrets -n \ | `backend.image.repository` | Backend image repository | `infisical/backend` | | `backend.image.tag` | Backend image tag | `latest` | | `backend.image.pullPolicy` | Backend image pullPolicy | `IfNotPresent` | -| `backend.resources` | Backend container resource spesification, check the offical [kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `` | +| `backend.resources.limits.memory` | container memory limit [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `200Mi` | +| `backend.resources.requests.cpu` | container CPU request [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `150m` | | `backend.kubeSecretRef` | Backend secret resource reference name (containing required [backend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) | `""` | | `backend.service.annotations` | Backend service annotations | `{}` | | `backend.service.type` | Backend service type | `ClusterIP` | @@ -343,4 +345,4 @@ for component in $components; do -o jsonpath='{.spec.template.spec.containers[0].env[*]}' | \ jq -r '.name + ":" + .value' > infisical-$component-conf.bak done -``` \ No newline at end of file +``` diff --git a/helm-charts/infisical/values.yaml b/helm-charts/infisical/values.yaml index 1dafd8995..99d39e4d8 100644 --- a/helm-charts/infisical/values.yaml +++ b/helm-charts/infisical/values.yaml @@ -43,7 +43,8 @@ frontend: ## @param frontend.image.pullPolicy Backend image pullPolicy ## pullPolicy: IfNotPresent - ## container resource specifications [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) + ## @param frontend.resources.limits.memory container memory limit [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) + ## @param frontend.resources.requests.cpu container CPU request [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) ## resources: limits: @@ -109,7 +110,8 @@ backend: ## @param backend.image.pullPolicy Backend image pullPolicy ## pullPolicy: IfNotPresent - ## container resource specifications [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) + ## @param backend.resources.limits.memory container memory limit [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) + ## @param backend.resources.requests.cpu container CPU request [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) ## resources: limits: From d46a6f7270a617837bb68c8502e19950a853e6c2 Mon Sep 17 00:00:00 2001 From: quinton11 Date: Tue, 12 Sep 2023 22:11:15 +0000 Subject: [PATCH 06/56] fix: `path` option for `secret get` sub cmd --- cli/packages/cmd/secrets.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 0e42eab8e..672beefcd 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -402,7 +402,12 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { util.HandleError(err, "Unable to parse flag") } - secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs}) + secretsPath, err := cmd.Flags().GetString("path") + if err != nil { + util.HandleError(err, "Unable to parse path flag") + } + + secrets, err := util.GetAllEnvironmentVariables(models.GetAllSecretsParameters{Environment: environmentName, InfisicalToken: infisicalToken, TagSlugs: tagSlugs, SecretsPath: secretsPath}) if err != nil { util.HandleError(err, "To fetch all secrets") } @@ -651,10 +656,11 @@ func init() { secretsGetCmd.Flags().String("token", "", "Fetch secrets using the Infisical Token") secretsCmd.AddCommand(secretsGetCmd) + secretsGetCmd.Flags().String("path", "/", "get secrets within a folder path") secretsCmd.Flags().Bool("secret-overriding", true, "Prioritizes personal secrets, if any, with the same name over shared secrets") secretsCmd.AddCommand(secretsSetCmd) - secretsSetCmd.Flags().String("path", "/", "get secrets within a folder path") + secretsSetCmd.Flags().String("path", "/", "set secrets within a folder path") secretsSetCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { util.RequireLogin() From 0f02ef701ec30ef3cba6a8de98d151e61383ed0d Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Wed, 13 Sep 2023 19:02:24 -0700 Subject: [PATCH 07/56] change some permissioning text --- frontend/src/hoc/withPermission/withPermission.tsx | 3 +-- .../ProjectRoleModifySection/WsProjectPermission.tsx | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/src/hoc/withPermission/withPermission.tsx b/frontend/src/hoc/withPermission/withPermission.tsx index 870c54f81..e0c402af3 100644 --- a/frontend/src/hoc/withPermission/withPermission.tsx +++ b/frontend/src/hoc/withPermission/withPermission.tsx @@ -45,8 +45,7 @@ export const withPermission = (
Access Restricted
- Your role has limited permissions, please
You do not have permission to this - page. + Your role has limited permissions, please
contact your admin to gain access
diff --git a/frontend/src/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/WsProjectPermission.tsx b/frontend/src/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/WsProjectPermission.tsx index c08dbdb9b..985b7b09d 100644 --- a/frontend/src/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/WsProjectPermission.tsx +++ b/frontend/src/views/Project/MembersPage/components/ProjectRoleListTab/components/ProjectRoleModifySection/WsProjectPermission.tsx @@ -23,8 +23,8 @@ enum Permission { } const PERMISSIONS = [ - { action: "edit", label: "Update workspace details" }, - { action: "delete", label: "Delete workspace" } + { action: "edit", label: "Update project details" }, + { action: "delete", label: "Delete projects" } ] as const; export const WsProjectPermission = ({ isNonEditable, setValue, control }: Props) => { From 3d2a2651b8d91e87cba05e2046d1952a62cc499a Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Thu, 14 Sep 2023 13:20:42 +0530 Subject: [PATCH 08/56] feat(rbac): removed owner role and changed member permissions --- .../controllers/v1/organizationController.ts | 4 +- .../src/ee/controllers/v1/roleController.ts | 14 +-- backend/src/ee/services/ProjectRoleService.ts | 28 +++++- backend/src/ee/services/RoleService.ts | 8 +- backend/src/helpers/signup.ts | 66 ++++++------- backend/src/models/membershipOrg.ts | 4 +- backend/src/utils/setup/backfillData.ts | 14 +++ frontend/src/styles/globals.css | 4 + .../OrgRoleModifySection.tsx | 10 -- .../MemberListTab/MemberListTab.tsx | 92 ++++++++++--------- .../ProjectRoleModifySection.tsx | 12 --- .../SingleProjectPermission.tsx | 18 +++- 12 files changed, 154 insertions(+), 120 deletions(-) diff --git a/backend/src/controllers/v1/organizationController.ts b/backend/src/controllers/v1/organizationController.ts index edd57a3b8..757d1aed7 100644 --- a/backend/src/controllers/v1/organizationController.ts +++ b/backend/src/controllers/v1/organizationController.ts @@ -8,7 +8,7 @@ import { } from "../../models"; import { createOrganization as create } from "../../helpers/organization"; import { addMembershipsOrg } from "../../helpers/membershipOrg"; -import { ACCEPTED, OWNER } from "../../variables"; +import { ACCEPTED, ADMIN } from "../../variables"; import { getLicenseServerUrl, getSiteURL } from "../../config"; import { licenseServerKeyRequest } from "../../config/request"; import { validateRequest } from "../../helpers/validation"; @@ -55,7 +55,7 @@ export const createOrganization = async (req: Request, res: Response) => { await addMembershipsOrg({ userIds: [req.user._id.toString()], organizationId: organization._id.toString(), - roles: [OWNER], + roles: [ADMIN], statuses: [ACCEPTED] }); diff --git a/backend/src/ee/controllers/v1/roleController.ts b/backend/src/ee/controllers/v1/roleController.ts index 2c87b9ff8..0d5f105ea 100644 --- a/backend/src/ee/controllers/v1/roleController.ts +++ b/backend/src/ee/controllers/v1/roleController.ts @@ -171,18 +171,6 @@ export const getRoles = async (req: Request, res: Response) => { const customRoles = await Role.find({ organization: orgId, isOrgRole, workspace: workspaceId }); // as this is shared between org and workspace switch the rule set based on it const roles = [ - // owner is only in org level role - ...(isOrgRole - ? [ - { - _id: "owner", - name: "Owner", - slug: "owner", - description: "Complete administration access over the organization.", - permissions: adminPermissions.rules - } - ] - : []), { _id: "admin", name: "Admin", @@ -192,7 +180,7 @@ export const getRoles = async (req: Request, res: Response) => { }, { _id: "member", - name: "Member", + name: isOrgRole ? "Member" : "Developer", slug: "member", description: "Non-administrative role in an organization", permissions: isOrgRole ? memberPermissions.rules : memberProjectPermissions.rules diff --git a/backend/src/ee/services/ProjectRoleService.ts b/backend/src/ee/services/ProjectRoleService.ts index 26491fab2..51f4a26f1 100644 --- a/backend/src/ee/services/ProjectRoleService.ts +++ b/backend/src/ee/services/ProjectRoleService.ts @@ -158,13 +158,39 @@ const buildMemberPermission = () => { can(ProjectPermissionActions.Create, ProjectPermissionSub.SecretRollback); can(ProjectPermissionActions.Read, ProjectPermissionSub.Member); - can(ProjectPermissionActions.Read, ProjectPermissionSub.Role); + can(ProjectPermissionActions.Create, ProjectPermissionSub.Member); + can(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations); + can(ProjectPermissionActions.Create, ProjectPermissionSub.Integrations); + can(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations); + can(ProjectPermissionActions.Delete, ProjectPermissionSub.Integrations); + can(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks); + can(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks); + can(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks); + can(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks); + can(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens); + can(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens); + can(ProjectPermissionActions.Edit, ProjectPermissionSub.ServiceTokens); + can(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens); + can(ProjectPermissionActions.Read, ProjectPermissionSub.Settings); + can(ProjectPermissionActions.Create, ProjectPermissionSub.Settings); + can(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings); + can(ProjectPermissionActions.Delete, ProjectPermissionSub.Settings); + can(ProjectPermissionActions.Read, ProjectPermissionSub.Environments); + can(ProjectPermissionActions.Create, ProjectPermissionSub.Environments); + can(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments); + can(ProjectPermissionActions.Delete, ProjectPermissionSub.Environments); + can(ProjectPermissionActions.Read, ProjectPermissionSub.Tags); + can(ProjectPermissionActions.Create, ProjectPermissionSub.Tags); + can(ProjectPermissionActions.Edit, ProjectPermissionSub.Tags); + can(ProjectPermissionActions.Delete, ProjectPermissionSub.Tags); + + can(ProjectPermissionActions.Read, ProjectPermissionSub.Role); can(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs); can(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList); diff --git a/backend/src/ee/services/RoleService.ts b/backend/src/ee/services/RoleService.ts index df5ebf29a..8f8c4f315 100644 --- a/backend/src/ee/services/RoleService.ts +++ b/backend/src/ee/services/RoleService.ts @@ -86,12 +86,17 @@ const buildMemberPermission = () => { can(OrgPermissionActions.Read, OrgPermissionSubjects.Workspace); can(OrgPermissionActions.Create, OrgPermissionSubjects.Workspace); can(OrgPermissionActions.Read, OrgPermissionSubjects.Member); + can(OrgPermissionActions.Create, OrgPermissionSubjects.Member); can(OrgPermissionActions.Read, OrgPermissionSubjects.Role); can(OrgPermissionActions.Read, OrgPermissionSubjects.Settings); can(OrgPermissionActions.Read, OrgPermissionSubjects.Billing); can(OrgPermissionActions.Read, OrgPermissionSubjects.Sso); can(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount); + can(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning); + can(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning); + can(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning); + can(OrgPermissionActions.Delete, OrgPermissionSubjects.SecretScanning); return build({ conditionsMatcher }); }; @@ -114,8 +119,7 @@ export const getUserOrgPermissions = async (userId: string, orgId: string) => { throw UnauthorizedRequestError({ message: "User doesn't belong to organization" }); } - if (membership.role === "admin" || membership.role === "owner") - return { permission: adminPermissions, membership }; + if (membership.role === "admin") return { permission: adminPermissions, membership }; if (membership.role === "member") return { permission: memberPermissions, membership }; diff --git a/backend/src/helpers/signup.ts b/backend/src/helpers/signup.ts index da494f4f7..27b1c16ab 100644 --- a/backend/src/helpers/signup.ts +++ b/backend/src/helpers/signup.ts @@ -1,7 +1,7 @@ import { IUser } from "../models"; import { createOrganization } from "./organization"; import { addMembershipsOrg } from "./membershipOrg"; -import { ACCEPTED, OWNER } from "../variables"; +import { ACCEPTED, ADMIN } from "../variables"; import { sendMail } from "../helpers/nodemailer"; import { TokenService } from "../services"; import { TOKEN_EMAIL_CONFIRMATION } from "../variables"; @@ -14,10 +14,10 @@ import { TOKEN_EMAIL_CONFIRMATION } from "../variables"; * @returns {Boolean} success - whether or not operation was successful */ export const sendEmailVerification = async ({ email }: { email: string }) => { - const token = await TokenService.createToken({ - type: TOKEN_EMAIL_CONFIRMATION, - email, - }); + const token = await TokenService.createToken({ + type: TOKEN_EMAIL_CONFIRMATION, + email + }); // send mail await sendMail({ @@ -25,8 +25,8 @@ export const sendEmailVerification = async ({ email }: { email: string }) => { subjectLine: "Infisical confirmation code", recipients: [email], substitutions: { - code: token, - }, + code: token + } }); }; @@ -36,17 +36,11 @@ export const sendEmailVerification = async ({ email }: { email: string }) => { * @param {String} obj.email - emai * @param {String} obj.code - code that was sent to [email] */ -export const checkEmailVerification = async ({ - email, - code, -}: { - email: string; - code: string; -}) => { +export const checkEmailVerification = async ({ email, code }: { email: string; code: string }) => { await TokenService.validateToken({ type: TOKEN_EMAIL_CONFIRMATION, email, - token: code, + token: code }); }; @@ -58,27 +52,27 @@ export const checkEmailVerification = async ({ * @param {IUser} obj.user - user who we are initializing for */ export const initializeDefaultOrg = async ({ - organizationName, - user, + organizationName, + user }: { - organizationName: string; - user: IUser; + organizationName: string; + user: IUser; }) => { - try { - // create organization with user as owner and initialize a free - // subscription - const organization = await createOrganization({ - email: user.email, - name: organizationName, - }); + try { + // create organization with user as owner and initialize a free + // subscription + const organization = await createOrganization({ + email: user.email, + name: organizationName + }); - await addMembershipsOrg({ - userIds: [user._id.toString()], - organizationId: organization._id.toString(), - roles: [OWNER], - statuses: [ACCEPTED], - }); - } catch (err) { - throw new Error(`Failed to initialize default organization and workspace [err=${err}]`); - } -}; \ No newline at end of file + await addMembershipsOrg({ + userIds: [user._id.toString()], + organizationId: organization._id.toString(), + roles: [ADMIN], + statuses: [ACCEPTED] + }); + } catch (err) { + throw new Error(`Failed to initialize default organization and workspace [err=${err}]`); + } +}; diff --git a/backend/src/models/membershipOrg.ts b/backend/src/models/membershipOrg.ts index 530797379..09b16be84 100644 --- a/backend/src/models/membershipOrg.ts +++ b/backend/src/models/membershipOrg.ts @@ -1,5 +1,5 @@ import { Document, Schema, Types, model } from "mongoose"; -import { ACCEPTED, ADMIN, CUSTOM, INVITED, MEMBER, OWNER } from "../variables"; +import { ACCEPTED, ADMIN, CUSTOM, INVITED, MEMBER } from "../variables"; export interface IMembershipOrg extends Document { _id: Types.ObjectId; @@ -26,7 +26,7 @@ const membershipOrgSchema = new Schema( }, role: { type: String, - enum: [OWNER, ADMIN, MEMBER, CUSTOM], + enum: [ADMIN, MEMBER, CUSTOM], required: true }, status: { diff --git a/backend/src/utils/setup/backfillData.ts b/backend/src/utils/setup/backfillData.ts index ae6279bfc..1a9af7864 100644 --- a/backend/src/utils/setup/backfillData.ts +++ b/backend/src/utils/setup/backfillData.ts @@ -13,6 +13,7 @@ import { Integration, IntegrationAuth, Membership, + MembershipOrg, Organization, Secret, SecretBlindIndexData, @@ -23,10 +24,12 @@ import { import { generateKeyPair } from "../../utils/crypto"; import { client, getEncryptionKey, getRootEncryptionKey } from "../../config"; import { + ADMIN, ALGORITHM_AES_256_GCM, ENCODING_SCHEME_BASE64, ENCODING_SCHEME_UTF8, MEMBER, + OWNER, VIEWER } from "../../variables"; import { InternalServerError } from "../errors"; @@ -691,5 +694,16 @@ export const backfillPermission = async () => { } ] ); + + await MembershipOrg.updateMany( + { + role: OWNER + }, + { + $set: { + role: ADMIN + } + } + ); console.log("Backfill: Finishing converting old denied permission in workspace to viewers"); }; diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css index a895d1b87..a47d38831 100644 --- a/frontend/src/styles/globals.css +++ b/frontend/src/styles/globals.css @@ -1,6 +1,10 @@ @tailwind base; @tailwind components; +html { + @apply overflow-hidden; +} + .rdp-day, .rdp-nav_button { @apply rounded-md hover:text-mineshaft-500; diff --git a/frontend/src/views/Org/MembersPage/components/OrgRoleTabSection/OrgRoleModifySection/OrgRoleModifySection.tsx b/frontend/src/views/Org/MembersPage/components/OrgRoleTabSection/OrgRoleModifySection/OrgRoleModifySection.tsx index aa90c2fbf..4caeb4553 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgRoleTabSection/OrgRoleModifySection/OrgRoleModifySection.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgRoleTabSection/OrgRoleModifySection/OrgRoleModifySection.tsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import { useForm } from "react-hook-form"; import { faArrowLeft, @@ -80,7 +79,6 @@ const SIMPLE_PERMISSION_OPTIONS = [ ] as const; export const OrgRoleModifySection = ({ role, onGoBack }: Props) => { - const [searchPermission, setSearchPermission] = useState(""); const { subscription } = useSubscription(); const { popUp, handlePopUpToggle, handlePopUpOpen } = usePopUp(["upgradePlan"] as const); @@ -196,14 +194,6 @@ export const OrgRoleModifySection = ({ role, onGoBack }: Props) => {

Add Permission

-
- setSearchPermission(e.target.value)} - leftIcon={} - placeholder="Search permissions..." - /> -
{ title={t("section.members.add-dialog.add-member-to-project") as string} subTitle={t("section.members.add-dialog.user-will-email")} > -
- ( - - - - )} - /> -
- - + {filteredOrgUsers.length ? ( + + ( + + + + )} + /> +
+ + +
+ + ) : ( +
+
All the users in your organization are already invited.
+ + +
- + )} { - const [searchPermission, setSearchPermission] = useState(""); - const { popUp, handlePopUpToggle, handlePopUpOpen } = usePopUp(["upgradePlan"] as const); const isNonEditable = ["admin", "member", "viewer"].includes(role?.slug || ""); @@ -226,14 +222,6 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {

Add Permission

-
- setSearchPermission(e.target.value)} - leftIcon={} - placeholder="Search permissions..." - /> -
{ + switch (option) { + case "member": + return MEMBERS_PERMISSIONS; + default: + return PERMISSIONS; + } +}; + export const SingleProjectPermission = ({ isNonEditable, setValue, @@ -148,7 +164,7 @@ export const SingleProjectPermission = ({ className="overflow-hidden grid gap-8 grid-flow-col auto-cols-min" > {isCustom && - PERMISSIONS.map(({ action, label }) => ( + getPermissionList(formName).map(({ action, label }) => ( Date: Thu, 14 Sep 2023 10:14:10 +0100 Subject: [PATCH 09/56] Point getAppsGitLab method to self-hosted GitLab instance if applicable, fix integration revocation issue related to missing metadata param partly --- backend/src/helpers/integration.ts | 2 +- backend/src/integrations/apps.ts | 11 ++++++++--- backend/src/validation/integration.ts | 4 ++-- backend/src/validation/integrationAuth.ts | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/backend/src/helpers/integration.ts b/backend/src/helpers/integration.ts index 2775d79c6..803c92aca 100644 --- a/backend/src/helpers/integration.ts +++ b/backend/src/helpers/integration.ts @@ -160,7 +160,7 @@ export const getIntegrationAuthAccessHelper = async ({ let accessId; let accessToken; const integrationAuth = await IntegrationAuth.findById(integrationAuthId).select( - "workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt +refreshCiphertext +refreshIV +refreshTag +accessIdCiphertext +accessIdIV +accessIdTag" + "workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt +refreshCiphertext +refreshIV +refreshTag +accessIdCiphertext +accessIdIV +accessIdTag metadata" ); if (!integrationAuth) diff --git a/backend/src/integrations/apps.ts b/backend/src/integrations/apps.ts index 1eef252b1..dc947f6f1 100644 --- a/backend/src/integrations/apps.ts +++ b/backend/src/integrations/apps.ts @@ -120,6 +120,7 @@ const getApps = async ({ break; case INTEGRATION_GITLAB: apps = await getAppsGitlab({ + integrationAuth, accessToken, teamId, }); @@ -736,12 +737,16 @@ const getAppsTerraformCloud = async ({ * @returns {String} apps.name - name of GitLab site */ const getAppsGitlab = async ({ + integrationAuth, accessToken, teamId, }: { + integrationAuth: IIntegrationAuth; accessToken: string; teamId?: string; }) => { + const gitLabApiUrl = integrationAuth.url ? `${integrationAuth.url}/api` : INTEGRATION_GITLAB_API_URL; + const apps: App[] = []; let page = 1; @@ -758,7 +763,7 @@ const getAppsGitlab = async ({ }); const { data } = await standardRequest.get( - `${INTEGRATION_GITLAB_API_URL}/v4/groups/${teamId}/projects`, + `${gitLabApiUrl}/v4/groups/${teamId}/projects`, { params, headers: { @@ -785,7 +790,7 @@ const getAppsGitlab = async ({ // case: fetch projects for individual in GitLab const { id } = ( - await standardRequest.get(`${INTEGRATION_GITLAB_API_URL}/v4/user`, { + await standardRequest.get(`${gitLabApiUrl}/v4/user`, { headers: { Authorization: `Bearer ${accessToken}`, "Accept-Encoding": "application/json", @@ -800,7 +805,7 @@ const getAppsGitlab = async ({ }); const { data } = await standardRequest.get( - `${INTEGRATION_GITLAB_API_URL}/v4/users/${id}/projects`, + `${gitLabApiUrl}/v4/users/${id}/projects`, { params, headers: { diff --git a/backend/src/validation/integration.ts b/backend/src/validation/integration.ts index 7ec0d0875..9058b68a2 100644 --- a/backend/src/validation/integration.ts +++ b/backend/src/validation/integration.ts @@ -34,9 +34,9 @@ export const validateClientForIntegration = async ({ if (!integration) throw IntegrationNotFoundError(); const integrationAuth = await IntegrationAuth.findById(integration.integrationAuth).select( - "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt" + "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt +metadata" ); - + if (!integrationAuth) throw IntegrationAuthNotFoundError(); const accessToken = ( diff --git a/backend/src/validation/integrationAuth.ts b/backend/src/validation/integrationAuth.ts index 18ff191af..c8c4e8105 100644 --- a/backend/src/validation/integrationAuth.ts +++ b/backend/src/validation/integrationAuth.ts @@ -30,9 +30,9 @@ const validateClientForIntegrationAuth = async ({ const integrationAuth = await IntegrationAuth.findById(integrationAuthId) .populate<{ workspace: IWorkspace }>("workspace") .select( - "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt" + "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt +metadata" ); - + if (!integrationAuth) throw IntegrationAuthNotFoundError(); let accessToken, accessId; From f1e1ca07dfc2bbe16a4c8602473ba4b98ff49187 Mon Sep 17 00:00:00 2001 From: Henri Courdent <122811744+hcourdent@users.noreply.github.com> Date: Thu, 14 Sep 2023 11:20:44 +0200 Subject: [PATCH 10/56] Backlink to Windmill.dev in windmill.mdx --- docs/integrations/cloud/windmill.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/integrations/cloud/windmill.mdx b/docs/integrations/cloud/windmill.mdx index 594d483b0..1ca0a6d34 100644 --- a/docs/integrations/cloud/windmill.mdx +++ b/docs/integrations/cloud/windmill.mdx @@ -1,6 +1,6 @@ --- title: "Windmill" -description: "How to sync secrets from Infisical to Windmill" +description: "How to sync secrets from Infisical to [Windmill](https://www.windmill.dev/)" --- Prerequisites: @@ -13,7 +13,7 @@ Prerequisites: ## Enter your Windmill Access Token -Obtain a Windmill access token in Access Tokens +Obtain a [Windmill](https://www.windmill.dev/) access token in Access Tokens ![integrations windmill dashboard](../../images/integrations-windmill-dashboard.png) ![integrations windmill token](../../images/integrations-windmill-token.png) From 8e88a3a25faaeb264b3f51636e9b149ccdf4867f Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Thu, 14 Sep 2023 10:59:09 +0100 Subject: [PATCH 11/56] Point getTeamsGitLab method to self-hosted GitLab instance if applicable --- backend/src/integrations/teams.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/src/integrations/teams.ts b/backend/src/integrations/teams.ts index 3b0564322..46791c5b3 100644 --- a/backend/src/integrations/teams.ts +++ b/backend/src/integrations/teams.ts @@ -34,6 +34,7 @@ const getTeams = async ({ switch (integrationAuth.integration) { case INTEGRATION_GITLAB: teams = await getTeamsGitLab({ + integrationAuth, accessToken, }); break; @@ -51,13 +52,17 @@ const getTeams = async ({ * @returns {String} teams.teamId - id of team */ const getTeamsGitLab = async ({ + integrationAuth, accessToken, }: { + integrationAuth: IIntegrationAuth; accessToken: string; }) => { + const gitLabApiUrl = integrationAuth.url ? `${integrationAuth.url}/api` : INTEGRATION_GITLAB_API_URL; + let teams: Team[] = []; const res = (await standardRequest.get( - `${INTEGRATION_GITLAB_API_URL}/v4/groups`, + `${gitLabApiUrl}/v4/groups`, { headers: { Authorization: `Bearer ${accessToken}`, From 88842951cb85f0b42cd47b847b4c182ca34ca69c Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Thu, 14 Sep 2023 11:16:59 +0100 Subject: [PATCH 12/56] Change +metadata to metadata --- backend/src/validation/integration.ts | 2 +- backend/src/validation/integrationAuth.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/validation/integration.ts b/backend/src/validation/integration.ts index 9058b68a2..dfe1ed505 100644 --- a/backend/src/validation/integration.ts +++ b/backend/src/validation/integration.ts @@ -34,7 +34,7 @@ export const validateClientForIntegration = async ({ if (!integration) throw IntegrationNotFoundError(); const integrationAuth = await IntegrationAuth.findById(integration.integrationAuth).select( - "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt +metadata" + "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt metadata" ); if (!integrationAuth) throw IntegrationAuthNotFoundError(); diff --git a/backend/src/validation/integrationAuth.ts b/backend/src/validation/integrationAuth.ts index c8c4e8105..cf3f936a9 100644 --- a/backend/src/validation/integrationAuth.ts +++ b/backend/src/validation/integrationAuth.ts @@ -30,7 +30,7 @@ const validateClientForIntegrationAuth = async ({ const integrationAuth = await IntegrationAuth.findById(integrationAuthId) .populate<{ workspace: IWorkspace }>("workspace") .select( - "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt +metadata" + "+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt metadata" ); if (!integrationAuth) throw IntegrationAuthNotFoundError(); From ee9632503419f830053bbcea67d2a6565965f176 Mon Sep 17 00:00:00 2001 From: Joel Biddle Date: Thu, 14 Sep 2023 23:24:32 +1000 Subject: [PATCH 13/56] Update FAQ for Alpine CDN error --- docs/self-hosting/faq.mdx | 88 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/docs/self-hosting/faq.mdx b/docs/self-hosting/faq.mdx index 6cef86b9c..6299b8240 100644 --- a/docs/self-hosting/faq.mdx +++ b/docs/self-hosting/faq.mdx @@ -6,7 +6,7 @@ description: "Frequently Asked Questions about Infisical self hosting" Frequently asked questions about self hosted instance of Infisical can be found on this page. If you can't find the answer you are looking for, please create an issue on our GitHub repository or join our Slack channel for additional support. - + This issue is typically seen when you haven't set up SSL for your self hosted instance of Infisical. When SSL is not enabled, you can't receive secure cookies, preventing the session data to not be saved. To fix this, we highly recommend that you set up SSL for your instance. @@ -25,3 +25,89 @@ However, in the event you choose to use Infisical without SSL, you can do so by To further increase data redundancy, we recommend that you use a managed MongoDB service for your self hosted instance of Infisical. + + +The Alpine Linux CDN may be unavailable/down in your region infrequently (eg. there is an unplanned outage). One possible fix is to add a retry mechanism and a fallback mirrors array to the Dockerfile. You can also use this as an opportunity to pin the Alpine Linux version for Docker to use in case there are issues with the latest version. Ensure to use https for the mirrors. + +#### Make the following changes to the backend Dockerfile +```bash +# Pin Alpine version from list: https://dl-cdn.alpinelinux.org/alpine/ +ARG ALPINE_VERSION=3.17 +ARG ALPINE_APPEND=v3.17/main + +# Specify number of retries for each mirror +ARG MAX_RETRIES=3 + +# Define base Alpine mirror URLs in attempt order from list: https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt +ARG BASE_ALPINE_MIRRORS="https://dl-cdn.alpinelinux.org/alpine https://ftp.halifax.rwth-aachen.de/alpine https://uk.alpinelinux.org/alpine" + +# Build stage +# Add the Alpine version arg +FROM node:16-alpine$ALPINE_VERSION AS build + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci --only-production + +COPY . . +RUN npm run build + +# Production stage +# Add the Alpine version arg +FROM node:16-alpine$ALPINE_VERSION + +WORKDIR /app + +ENV npm_config_cache /home/node/.npm + +COPY package*.json ./ +RUN npm ci --only-production + +COPY --from=build /app . + +# Add retry mechanism and loop through the specified mirrors +RUN retries_left=$MAX_RETRIES; \ + for mirror in $ALPINE_MIRRORS; do \ + full_mirror="$mirror/$ALPINE_APPEND"; \ + echo "Trying mirror: $full_mirror"; \ + echo >>/etc/apk/repositories "$full_mirror"; \ + for i in $(seq $retries_left); do \ + echo "Retrying... Attempt $i (Retries Left: $((retries_left - i)))"; \ + if apk add --no-cache bash curl git && \ + curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash && \ + apk add --no-cache infisical=0.8.1; then \ + break; \ + fi; \ + sleep 10; \ + done; \ + if [ $? -eq 0 ]; then \ + break; \ + fi; \ + done + +HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \ + CMD node healthcheck.js + +EXPOSE 4000 + +CMD ["npm", "run", "start"] + ``` + + + [Alpine Linux (mirrors) - official site](https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt) + + + + [Alpine Linux (mirrors) - archived site](https://web.archive.org/web/20230914123159/https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt) + + + + [Alpine Linux (versions) - official site](https://dl-cdn.alpinelinux.org/alpine/) + + + + [Alpine Linux (versions) - archived site](https://web.archive.org/web/20230914123455/https://dl-cdn.alpinelinux.org/alpine/) + + + From 18d843f3e68f3a0685b8af77d6339b010d8b68b2 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Thu, 14 Sep 2023 20:40:57 +0530 Subject: [PATCH 14/56] feat(rbac): fixed ip allow list api --- .../ee/controllers/v1/workspaceController.ts | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/backend/src/ee/controllers/v1/workspaceController.ts b/backend/src/ee/controllers/v1/workspaceController.ts index 14ea8978d..7c9502656 100644 --- a/backend/src/ee/controllers/v1/workspaceController.ts +++ b/backend/src/ee/controllers/v1/workspaceController.ts @@ -1,6 +1,14 @@ import { Request, Response } from "express"; import { PipelineStage, Types } from "mongoose"; -import { Folder, Membership, Secret, ServiceTokenData, TFolderSchema, User } from "../../../models"; +import { + Folder, + Membership, + Secret, + ServiceTokenData, + TFolderSchema, + User, + Workspace +} from "../../../models"; import { ActorType, AuditLog, @@ -41,6 +49,7 @@ import { getUserProjectPermissions } from "../../services/ProjectRoleService"; import { ForbiddenError } from "@casl/ability"; +import { BadRequestError } from "../../../utils/errors"; /** * Return secret snapshots for workspace with id [workspaceId] @@ -781,7 +790,10 @@ export const addWorkspaceTrustedIp = async (req: Request, res: Response) => { ProjectPermissionSub.IpAllowList ); - const plan = await EELicenseService.getPlan(req.workspace.organization); + const workspace = await Workspace.findById(workspaceId); + if (!workspace) throw BadRequestError({ message: "Workspace not found" }); + + const plan = await EELicenseService.getPlan(workspace.organization); if (!plan.ipAllowlisting) return res.status(400).send({ @@ -844,7 +856,10 @@ export const updateWorkspaceTrustedIp = async (req: Request, res: Response) => { ProjectPermissionSub.IpAllowList ); - const plan = await EELicenseService.getPlan(req.workspace.organization); + const workspace = await Workspace.findById(workspaceId); + if (!workspace) throw BadRequestError({ message: "Workspace not found" }); + + const plan = await EELicenseService.getPlan(workspace.organization); if (!plan.ipAllowlisting) return res.status(400).send({ @@ -933,7 +948,10 @@ export const deleteWorkspaceTrustedIp = async (req: Request, res: Response) => { ProjectPermissionSub.IpAllowList ); - const plan = await EELicenseService.getPlan(req.workspace.organization); + const workspace = await Workspace.findById(workspaceId); + if (!workspace) throw BadRequestError({ message: "Workspace not found" }); + + const plan = await EELicenseService.getPlan(workspace.organization); if (!plan.ipAllowlisting) return res.status(400).send({ From 13083d76768993dbbb0c469719414db73b450d09 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Thu, 14 Sep 2023 11:35:33 -0400 Subject: [PATCH 15/56] remove link from description - anti pattern in docs --- docs/integrations/cloud/windmill.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/cloud/windmill.mdx b/docs/integrations/cloud/windmill.mdx index 1ca0a6d34..c79931b70 100644 --- a/docs/integrations/cloud/windmill.mdx +++ b/docs/integrations/cloud/windmill.mdx @@ -1,6 +1,6 @@ --- title: "Windmill" -description: "How to sync secrets from Infisical to [Windmill](https://www.windmill.dev/)" +description: "How to sync secrets from Infisical to Windmill" --- Prerequisites: From 942e1a82c284caf1648e450437f362ebf25b7c34 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Thu, 14 Sep 2023 21:34:13 +0530 Subject: [PATCH 16/56] feat(rbac): removed audit log option for time being, v3 secret patch and reload permission flash screen fix --- .../src/controllers/v3/secretsController.ts | 3 +++ backend/src/validation/secrets.ts | 4 +-- .../ProjectPermissionContext.tsx | 16 ++++++------ frontend/src/layouts/AppLayout/AppLayout.tsx | 26 +------------------ .../ProjectRoleModifySection.tsx | 7 ----- 5 files changed, 14 insertions(+), 42 deletions(-) diff --git a/backend/src/controllers/v3/secretsController.ts b/backend/src/controllers/v3/secretsController.ts index fad50b0ca..a528436af 100644 --- a/backend/src/controllers/v3/secretsController.ts +++ b/backend/src/controllers/v3/secretsController.ts @@ -55,6 +55,9 @@ export const getSecretsRaw = async (req: Request, res: Response) => { secretPath = getFolderWithPathFromId(folder.nodes, folderId).folderPath; } + if (!environment || !workspaceId) + throw BadRequestError({ message: "Missing environment or workspace id" }); + let permissionCheckFn: (env: string, secPath: string) => boolean; // used to pass as callback function to import secret if (req.user?._id) { const { permission } = await getUserProjectPermissions(req.user._id, workspaceId); diff --git a/backend/src/validation/secrets.ts b/backend/src/validation/secrets.ts index 700a3ea5d..cc541ab9e 100644 --- a/backend/src/validation/secrets.ts +++ b/backend/src/validation/secrets.ts @@ -225,8 +225,8 @@ export const GetSecretsV2 = z.object({ export const GetSecretsRawV3 = z.object({ query: z.object({ - workspaceId: z.string().trim(), - environment: z.string().trim(), + workspaceId: z.string().trim().optional(), + environment: z.string().trim().optional(), secretPath: z.string().trim().default("/"), folderId: z.string().trim().optional(), include_imports: z diff --git a/frontend/src/context/ProjectPermissionContext/ProjectPermissionContext.tsx b/frontend/src/context/ProjectPermissionContext/ProjectPermissionContext.tsx index 732466cf6..bb7fab7ec 100644 --- a/frontend/src/context/ProjectPermissionContext/ProjectPermissionContext.tsx +++ b/frontend/src/context/ProjectPermissionContext/ProjectPermissionContext.tsx @@ -16,14 +16,6 @@ export const ProjectPermissionProvider = ({ children }: Props): JSX.Element => { const workspaceId = currentWorkspace?._id || ""; const { data: permission, isLoading } = useGetUserProjectPermissions({ workspaceId }); - if (!permission && currentWorkspace) { - return ( -
- Failed to load user permissions -
- ); - } - if ((isLoading && currentWorkspace) || isWsLoading) { return (
@@ -37,6 +29,14 @@ export const ProjectPermissionProvider = ({ children }: Props): JSX.Element => { ); } + if (!permission && currentWorkspace) { + return ( +
+ Failed to load user permissions +
+ ); + } + return ( {children} diff --git a/frontend/src/layouts/AppLayout/AppLayout.tsx b/frontend/src/layouts/AppLayout/AppLayout.tsx index d03161f30..47f7570d8 100644 --- a/frontend/src/layouts/AppLayout/AppLayout.tsx +++ b/frontend/src/layouts/AppLayout/AppLayout.tsx @@ -138,7 +138,6 @@ export const AppLayout = ({ children }: LayoutProps) => { const { t } = useTranslation(); - const logout = useLogoutUser(); const logOutUser = async () => { try { @@ -488,7 +487,7 @@ export const AppLayout = ({ children }: LayoutProps) => { - + {/* { Audit Logs - - {/* - - - Audit Logs - - */} - {/* - - } - icon="system-outline-82-extension" - > - Audit Logs - - - */} Date: Thu, 14 Sep 2023 21:56:57 +0530 Subject: [PATCH 17/56] fix(integrations): resolved integration bot deactive revoke bug --- .../views/IntegrationsPage/IntegrationsPage.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx b/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx index e8e4e5b2c..0f2f8a97d 100644 --- a/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx +++ b/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx @@ -85,7 +85,13 @@ export const IntegrationsPage = withProjectPermission( // details: so onsuccessfully deleting an integration auth, immediately integration list is refeteched // After the refetch is completed check if its empty. Then set bot active and reset the submit hook useEffect(() => { - if (isDeleteIntegrationAuthSuccess && !isIntegrationFetching && !integrations?.length) { + if ( + isDeleteIntegrationAuthSuccess && + !isIntegrationFetching && + !isIntegrationAuthLoading && + !integrations?.length && + !integrationAuths?.length + ) { if (bot?._id) updateBotActiveStatusSync({ isActive: false, @@ -94,7 +100,13 @@ export const IntegrationsPage = withProjectPermission( }); resetDeleteIntegrationAuth(); } - }, [isIntegrationFetching, isDeleteIntegrationAuthSuccess, integrations?.length]); + }, [ + isIntegrationFetching, + isDeleteIntegrationAuthSuccess, + isIntegrationAuthLoading, + integrationAuths?.length, + integrations?.length + ]); const handleProviderIntegration = async (provider: string) => { const selectedCloudIntegration = cloudIntegrations?.find(({ slug }) => provider === slug); From a073a746f26221534716e411812b4222ab65e1bf Mon Sep 17 00:00:00 2001 From: xphyr Date: Thu, 14 Sep 2023 13:33:15 -0400 Subject: [PATCH 18/56] changing CMD for Dockerfile to use node instead of npm to address issue #984 --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 4c3abfcc1..63cb59fbd 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -30,4 +30,4 @@ HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \ EXPOSE 4000 -CMD ["npm", "run", "start"] +CMD ["node", "build/index.js"] From 44d2a6c55315b1b5a3bbe7f1ef03c0fadbc677f8 Mon Sep 17 00:00:00 2001 From: xphyr Date: Thu, 14 Sep 2023 13:57:58 -0400 Subject: [PATCH 19/56] clearing npm cache to save space --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 63cb59fbd..06448ad91 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -17,7 +17,7 @@ WORKDIR /app ENV npm_config_cache /home/node/.npm COPY package*.json ./ -RUN npm ci --only-production +RUN npm ci --only-production && npm cache clean --force COPY --from=build /app . From 36b5ba285585b8a3c5d42ea20d2073b5dfde2364 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Thu, 14 Sep 2023 16:35:13 -0400 Subject: [PATCH 20/56] remove change log bc will get replaced by auto generated one soon --- helm-charts/infisical/CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 helm-charts/infisical/CHANGELOG.md diff --git a/helm-charts/infisical/CHANGELOG.md b/helm-charts/infisical/CHANGELOG.md deleted file mode 100644 index 131fbda94..000000000 --- a/helm-charts/infisical/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -# 0.3.3 -### Changes since 0.3.2 [#933](https://github.com/Infisical/infisical/pull/933) -- added resource specs to both the frontend and backend From 019024e4aef15e399d8286697b04c2cd84f3414b Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Thu, 14 Sep 2023 18:23:59 -0400 Subject: [PATCH 21/56] remove the use of owner everywhere else --- .../githubScanFullRepository.ts | 29 +++++++++---------- .../secret-scanning/githubScanPushEvent.ts | 7 ++--- backend/src/routes/v2/organizations.ts | 4 +-- backend/src/utils/setup/backfillData.ts | 1 + backend/src/variables/organization.ts | 2 +- 5 files changed, 19 insertions(+), 24 deletions(-) diff --git a/backend/src/queues/secret-scanning/githubScanFullRepository.ts b/backend/src/queues/secret-scanning/githubScanFullRepository.ts index 61d53acbb..eeb6aaf1e 100644 --- a/backend/src/queues/secret-scanning/githubScanFullRepository.ts +++ b/backend/src/queues/secret-scanning/githubScanFullRepository.ts @@ -4,7 +4,7 @@ import TelemetryService from "../../services/TelemetryService"; import { sendMail } from "../../helpers"; import GitRisks from "../../ee/models/gitRisks"; import { MembershipOrg, User } from "../../models"; -import { ADMIN, OWNER } from "../../variables"; +import { ADMIN } from "../../variables"; import { convertKeysToLowercase, scanFullRepoContentAndGetFindings } from "../../ee/services/GithubSecretScanning/helper"; import { getSecretScanningGitAppId, getSecretScanningPrivateKey } from "../../config"; import { SecretMatch } from "../../ee/services/GithubSecretScanning/types"; @@ -13,7 +13,7 @@ export const githubFullRepositorySecretScan = new Queue("github-full-repository- type TScanPushEventQueueDetails = { organizationId: string, - installationId: number, + installationId: number, repository: { id: number, fullName: string, @@ -24,22 +24,22 @@ githubFullRepositorySecretScan.process(async (job: Job, done: Queue.DoneCallback const { organizationId, repository, installationId }: TScanPushEventQueueDetails = job.data try { const octokit = new ProbotOctokit({ - auth: { + auth: { appId: await getSecretScanningGitAppId(), privateKey: await getSecretScanningPrivateKey(), installationId: installationId - }, + }, }); - const findings : SecretMatch[] = await scanFullRepoContentAndGetFindings(octokit, installationId, repository.fullName) + const findings: SecretMatch[] = await scanFullRepoContentAndGetFindings(octokit, installationId, repository.fullName) for (const finding of findings) { - await GitRisks.findOneAndUpdate({ fingerprint: finding.Fingerprint}, + await GitRisks.findOneAndUpdate({ fingerprint: finding.Fingerprint }, { - ...convertKeysToLowercase(finding), - installationId: installationId, - organization: organizationId, - repositoryFullName: repository.fullName, - repositoryId: repository.id - }, { + ...convertKeysToLowercase(finding), + installationId: installationId, + organization: organizationId, + repositoryFullName: repository.fullName, + repositoryId: repository.id + }, { upsert: true }).lean() } @@ -47,10 +47,7 @@ githubFullRepositorySecretScan.process(async (job: Job, done: Queue.DoneCallback // get emails of admins const adminsOfWork = await MembershipOrg.find({ organization: organizationId, - $or: [ - { role: OWNER }, - { role: ADMIN } - ] + role: ADMIN, }).lean() const userEmails = await User.find({ diff --git a/backend/src/queues/secret-scanning/githubScanPushEvent.ts b/backend/src/queues/secret-scanning/githubScanPushEvent.ts index 71a7e92d4..09261e235 100644 --- a/backend/src/queues/secret-scanning/githubScanPushEvent.ts +++ b/backend/src/queues/secret-scanning/githubScanPushEvent.ts @@ -5,7 +5,7 @@ import TelemetryService from "../../services/TelemetryService"; import { sendMail } from "../../helpers"; import GitRisks from "../../ee/models/gitRisks"; import { MembershipOrg, User } from "../../models"; -import { ADMIN, OWNER } from "../../variables"; +import { ADMIN } from "../../variables"; import { convertKeysToLowercase, scanContentAndGetFindings } from "../../ee/services/GithubSecretScanning/helper"; import { getSecretScanningGitAppId, getSecretScanningPrivateKey } from "../../config"; import { SecretMatch } from "../../ee/services/GithubSecretScanning/types"; @@ -88,10 +88,7 @@ githubPushEventSecretScan.process(async (job: Job, done: Queue.DoneCallback) => // get emails of admins const adminsOfWork = await MembershipOrg.find({ organization: organizationId, - $or: [ - { role: OWNER }, - { role: ADMIN } - ] + role: ADMIN }).lean() const userEmails = await User.find({ diff --git a/backend/src/routes/v2/organizations.ts b/backend/src/routes/v2/organizations.ts index a12288886..d1387bd42 100644 --- a/backend/src/routes/v2/organizations.ts +++ b/backend/src/routes/v2/organizations.ts @@ -4,7 +4,7 @@ import { requireAuth, requireOrganizationAuth } from "../../middleware"; -import { ACCEPTED, ADMIN, AuthMode, OWNER } from "../../variables"; +import { ACCEPTED, ADMIN, AuthMode } from "../../variables"; import { organizationsController } from "../../controllers/v2"; // TODO: /POST to create membership @@ -48,7 +48,7 @@ router.get( acceptedAuthModes: [AuthMode.JWT] }), requireOrganizationAuth({ - acceptedRoles: [OWNER, ADMIN], + acceptedRoles: [ADMIN], acceptedStatuses: [ACCEPTED] }), organizationsController.getOrganizationServiceAccounts diff --git a/backend/src/utils/setup/backfillData.ts b/backend/src/utils/setup/backfillData.ts index 1a9af7864..ccd38edcf 100644 --- a/backend/src/utils/setup/backfillData.ts +++ b/backend/src/utils/setup/backfillData.ts @@ -32,6 +32,7 @@ import { OWNER, VIEWER } from "../../variables"; + import { InternalServerError } from "../errors"; /** diff --git a/backend/src/variables/organization.ts b/backend/src/variables/organization.ts index bccabc6e6..5e796e357 100644 --- a/backend/src/variables/organization.ts +++ b/backend/src/variables/organization.ts @@ -1,5 +1,5 @@ // membership roles -export const OWNER = "owner"; +export const OWNER = "owner"; // depreciated export const ADMIN = "admin"; export const MEMBER = "member"; export const VIEWER = "viewer"; From 7982b1d668ab18464fb8754960c00b6931f7599e Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Thu, 14 Sep 2023 19:27:23 -0400 Subject: [PATCH 22/56] replace owner role for local dev user --- backend/src/utils/addDevelopmentUser.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/utils/addDevelopmentUser.ts b/backend/src/utils/addDevelopmentUser.ts index d8b668909..b5b0f3495 100644 --- a/backend/src/utils/addDevelopmentUser.ts +++ b/backend/src/utils/addDevelopmentUser.ts @@ -80,7 +80,7 @@ export const createTestUserForDevelopment = async () => { const testMembershipOrg = { _id: testMembershipOrgId, organization: testOrgId, - role: "owner", + role: "admin", status: "accepted", user: testUserId, } @@ -121,7 +121,7 @@ export const createTestUserForDevelopment = async () => { const workspaceInDB = await Workspace.findById(testWorkspaceId) if (!workspaceInDB) { const workspace = await Workspace.create(testWorkspace) - + // initialize blind index salt for workspace await SecretService.createSecretBlindIndexData({ workspaceId: workspace._id, From 7fe94d66cd13cb8cbc076bf0ef42bc41eb2bf323 Mon Sep 17 00:00:00 2001 From: Joel Biddle Date: Fri, 15 Sep 2023 11:59:15 +1000 Subject: [PATCH 23/56] Create new FAQ page under developer setup docs --- docs/contributing/faq.mdx | 93 +++++++++++++++++++++++++++++++++++++++ docs/mint.json | 3 +- docs/self-hosting/faq.mdx | 86 ------------------------------------ 3 files changed, 95 insertions(+), 87 deletions(-) create mode 100644 docs/contributing/faq.mdx diff --git a/docs/contributing/faq.mdx b/docs/contributing/faq.mdx new file mode 100644 index 000000000..31863687f --- /dev/null +++ b/docs/contributing/faq.mdx @@ -0,0 +1,93 @@ +--- +title: "FAQ" +description: "Frequently Asked Questions about contributing to Infisical" +--- + +Frequently asked questions about contributing to Infisical can be found on this page. +If you can't find the answer you are looking for, please create an issue on our GitHub repository or join our Slack channel for additional support. + + +The Alpine Linux CDN may be unavailable/down in your region infrequently (eg. there is an unplanned outage). One possible fix is to add a retry mechanism and a fallback mirrors array to the Dockerfile. You can also use this as an opportunity to pin the Alpine Linux version for Docker to use in case there are issues with the latest version. Ensure to use https for the mirrors. + +#### Make the following changes to the backend Dockerfile +```bash +# Pin Alpine version from list: https://dl-cdn.alpinelinux.org/alpine/ +ARG ALPINE_VERSION=3.17 +ARG ALPINE_APPEND=v3.17/main + +# Specify number of retries for each mirror +ARG MAX_RETRIES=3 + +# Define base Alpine mirror URLs in attempt order from list: https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt +ARG BASE_ALPINE_MIRRORS="https://dl-cdn.alpinelinux.org/alpine https://ftp.halifax.rwth-aachen.de/alpine https://uk.alpinelinux.org/alpine" + +# Build stage +# Add the Alpine version arg +FROM node:16-alpine$ALPINE_VERSION AS build + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci --only-production + +COPY . . +RUN npm run build + +# Production stage +# Add the Alpine version arg +FROM node:16-alpine$ALPINE_VERSION + +WORKDIR /app + +ENV npm_config_cache /home/node/.npm + +COPY package*.json ./ +RUN npm ci --only-production + +COPY --from=build /app . + +# Add retry mechanism and loop through the specified mirrors +RUN retries_left=$MAX_RETRIES; \ + for mirror in $ALPINE_MIRRORS; do \ + full_mirror="$mirror/$ALPINE_APPEND"; \ + echo "Trying mirror: $full_mirror"; \ + echo >>/etc/apk/repositories "$full_mirror"; \ + for i in $(seq $retries_left); do \ + echo "Retrying... Attempt $i (Retries Left: $((retries_left - i)))"; \ + if apk add --no-cache bash curl git && \ + curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash && \ + apk add --no-cache infisical=0.8.1; then \ + break; \ + fi; \ + sleep 10; \ + done; \ + if [ $? -eq 0 ]; then \ + break; \ + fi; \ + done + +HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \ + CMD node healthcheck.js + +EXPOSE 4000 + +CMD ["npm", "run", "start"] + ``` + + + [Alpine Linux (mirrors) - official site](https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt) + + + + [Alpine Linux (mirrors) - archived site](https://web.archive.org/web/20230914123159/https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt) + + + + [Alpine Linux (versions) - official site](https://dl-cdn.alpinelinux.org/alpine/) + + + + [Alpine Linux (versions) - archived site](https://web.archive.org/web/20230914123455/https://dl-cdn.alpinelinux.org/alpine/) + + + diff --git a/docs/mint.json b/docs/mint.json index 8c39483ea..9eaeddb1f 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -396,7 +396,8 @@ "contributing/overview", "contributing/code-of-conduct", "contributing/developing", - "contributing/pull-requests" + "contributing/pull-requests", + "contributing/faq" ] } ], diff --git a/docs/self-hosting/faq.mdx b/docs/self-hosting/faq.mdx index 6299b8240..b940f2f13 100644 --- a/docs/self-hosting/faq.mdx +++ b/docs/self-hosting/faq.mdx @@ -25,89 +25,3 @@ However, in the event you choose to use Infisical without SSL, you can do so by To further increase data redundancy, we recommend that you use a managed MongoDB service for your self hosted instance of Infisical. - - -The Alpine Linux CDN may be unavailable/down in your region infrequently (eg. there is an unplanned outage). One possible fix is to add a retry mechanism and a fallback mirrors array to the Dockerfile. You can also use this as an opportunity to pin the Alpine Linux version for Docker to use in case there are issues with the latest version. Ensure to use https for the mirrors. - -#### Make the following changes to the backend Dockerfile -```bash -# Pin Alpine version from list: https://dl-cdn.alpinelinux.org/alpine/ -ARG ALPINE_VERSION=3.17 -ARG ALPINE_APPEND=v3.17/main - -# Specify number of retries for each mirror -ARG MAX_RETRIES=3 - -# Define base Alpine mirror URLs in attempt order from list: https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt -ARG BASE_ALPINE_MIRRORS="https://dl-cdn.alpinelinux.org/alpine https://ftp.halifax.rwth-aachen.de/alpine https://uk.alpinelinux.org/alpine" - -# Build stage -# Add the Alpine version arg -FROM node:16-alpine$ALPINE_VERSION AS build - -WORKDIR /app - -COPY package*.json ./ -RUN npm ci --only-production - -COPY . . -RUN npm run build - -# Production stage -# Add the Alpine version arg -FROM node:16-alpine$ALPINE_VERSION - -WORKDIR /app - -ENV npm_config_cache /home/node/.npm - -COPY package*.json ./ -RUN npm ci --only-production - -COPY --from=build /app . - -# Add retry mechanism and loop through the specified mirrors -RUN retries_left=$MAX_RETRIES; \ - for mirror in $ALPINE_MIRRORS; do \ - full_mirror="$mirror/$ALPINE_APPEND"; \ - echo "Trying mirror: $full_mirror"; \ - echo >>/etc/apk/repositories "$full_mirror"; \ - for i in $(seq $retries_left); do \ - echo "Retrying... Attempt $i (Retries Left: $((retries_left - i)))"; \ - if apk add --no-cache bash curl git && \ - curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash && \ - apk add --no-cache infisical=0.8.1; then \ - break; \ - fi; \ - sleep 10; \ - done; \ - if [ $? -eq 0 ]; then \ - break; \ - fi; \ - done - -HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \ - CMD node healthcheck.js - -EXPOSE 4000 - -CMD ["npm", "run", "start"] - ``` - - - [Alpine Linux (mirrors) - official site](https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt) - - - - [Alpine Linux (mirrors) - archived site](https://web.archive.org/web/20230914123159/https://dl-cdn.alpinelinux.org/alpine/MIRRORS.txt) - - - - [Alpine Linux (versions) - official site](https://dl-cdn.alpinelinux.org/alpine/) - - - - [Alpine Linux (versions) - archived site](https://web.archive.org/web/20230914123455/https://dl-cdn.alpinelinux.org/alpine/) - - - From 0a72dccdcfe6d5c7d9448c865762bd781a1049bb Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Fri, 15 Sep 2023 00:30:15 -0400 Subject: [PATCH 24/56] add back defaultOpen="true" --- docs/self-hosting/faq.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/self-hosting/faq.mdx b/docs/self-hosting/faq.mdx index b940f2f13..6cef86b9c 100644 --- a/docs/self-hosting/faq.mdx +++ b/docs/self-hosting/faq.mdx @@ -6,7 +6,7 @@ description: "Frequently Asked Questions about Infisical self hosting" Frequently asked questions about self hosted instance of Infisical can be found on this page. If you can't find the answer you are looking for, please create an issue on our GitHub repository or join our Slack channel for additional support. - + This issue is typically seen when you haven't set up SSL for your self hosted instance of Infisical. When SSL is not enabled, you can't receive secure cookies, preventing the session data to not be saved. To fix this, we highly recommend that you set up SSL for your instance. From bde788c4f6b03f318bcacdafa59dee55e0715f9c Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Thu, 14 Sep 2023 22:21:59 -0700 Subject: [PATCH 25/56] improved ui/ux for checkly, gcp, and vault integrations --- frontend/src/layouts/AppLayout/AppLayout.tsx | 2 +- .../pages/integrations/checkly/authorize.tsx | 26 ++++++- .../src/pages/integrations/checkly/create.tsx | 41 +++++++++-- .../gcp-secret-manager/authorize.tsx | 71 +++++++++++++------ .../gcp-secret-manager/create.tsx | 55 +++++++++++--- .../hashicorp-vault/authorize.tsx | 35 +++++++-- .../integrations/hashicorp-vault/create.tsx | 55 +++++++++++--- 7 files changed, 233 insertions(+), 52 deletions(-) diff --git a/frontend/src/layouts/AppLayout/AppLayout.tsx b/frontend/src/layouts/AppLayout/AppLayout.tsx index 47f7570d8..d139a2cc7 100644 --- a/frontend/src/layouts/AppLayout/AppLayout.tsx +++ b/frontend/src/layouts/AppLayout/AppLayout.tsx @@ -468,7 +468,7 @@ export const AppLayout = ({ children }: LayoutProps) => { {t("nav.menu.integrations")} diff --git a/frontend/src/pages/integrations/checkly/authorize.tsx b/frontend/src/pages/integrations/checkly/authorize.tsx index a84c9fe28..9d1ce3c5e 100644 --- a/frontend/src/pages/integrations/checkly/authorize.tsx +++ b/frontend/src/pages/integrations/checkly/authorize.tsx @@ -1,5 +1,9 @@ import { useState } from "react"; +import Head from "next/head"; +import Link from "next/link"; import { useRouter } from "next/router"; +import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useSaveIntegrationAccessToken @@ -41,8 +45,26 @@ export default function ChecklyCreateIntegrationPage() { return (
+ + Authorize Checkly Integration + + - Checkly Integration + + Checkly Integration + + +
+ + Docs + +
+
+ +