mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 07:27:43 +00:00
Merge branch 'main' of https://github.com/Infisical/infisical into feat/adds-PAT-to-github-integration
This commit is contained in:
@@ -1,57 +0,0 @@
|
|||||||
## @section Common parameters
|
|
||||||
##
|
|
||||||
|
|
||||||
## @param nameOverride Override release name
|
|
||||||
##
|
|
||||||
nameOverride: ""
|
|
||||||
## @param fullnameOverride Override release fullname
|
|
||||||
##
|
|
||||||
fullnameOverride: ""
|
|
||||||
|
|
||||||
## @section Infisical backend parameters
|
|
||||||
## Documentation : https://infisical.com/docs/self-hosting/deployments/kubernetes
|
|
||||||
##
|
|
||||||
|
|
||||||
infisical:
|
|
||||||
autoDatabaseSchemaMigration: false
|
|
||||||
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
name: infisical
|
|
||||||
replicaCount: 3
|
|
||||||
image:
|
|
||||||
repository: infisical/staging_infisical
|
|
||||||
tag: "latest"
|
|
||||||
pullPolicy: Always
|
|
||||||
|
|
||||||
deploymentAnnotations:
|
|
||||||
secrets.infisical.com/auto-reload: "true"
|
|
||||||
|
|
||||||
kubeSecretRef: "managed-secret"
|
|
||||||
|
|
||||||
ingress:
|
|
||||||
## @param ingress.enabled Enable ingress
|
|
||||||
##
|
|
||||||
enabled: true
|
|
||||||
## @param ingress.ingressClassName Ingress class name
|
|
||||||
##
|
|
||||||
ingressClassName: nginx
|
|
||||||
## @param ingress.nginx.enabled Ingress controller
|
|
||||||
##
|
|
||||||
# nginx:
|
|
||||||
# enabled: true
|
|
||||||
## @param ingress.annotations Ingress annotations
|
|
||||||
##
|
|
||||||
annotations:
|
|
||||||
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
|
||||||
hostName: "gamma.infisical.com"
|
|
||||||
tls:
|
|
||||||
- secretName: letsencrypt-prod
|
|
||||||
hosts:
|
|
||||||
- gamma.infisical.com
|
|
||||||
|
|
||||||
postgresql:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
redis:
|
|
||||||
enabled: false
|
|
||||||
@@ -56,7 +56,7 @@ jobs:
|
|||||||
--config ct.yaml \
|
--config ct.yaml \
|
||||||
--charts helm-charts/infisical-standalone-postgres \
|
--charts helm-charts/infisical-standalone-postgres \
|
||||||
--helm-extra-args="--timeout=300s" \
|
--helm-extra-args="--timeout=300s" \
|
||||||
--helm-extra-set-args="--set ingress.nginx.enabled=false --set infisical.autoDatabaseSchemaMigration=false --set infisical.replicaCount=1 --set infisical.image.tag=v0.132.2-postgres" \
|
--helm-extra-set-args="--set ingress.nginx.enabled=false --set infisical.replicaCount=1 --set infisical.image.tag=v0.151.0" \
|
||||||
--namespace infisical-standalone-postgres
|
--namespace infisical-standalone-postgres
|
||||||
|
|
||||||
release:
|
release:
|
||||||
|
|||||||
@@ -66,5 +66,5 @@ jobs:
|
|||||||
--config ct.yaml \
|
--config ct.yaml \
|
||||||
--charts helm-charts/infisical-standalone-postgres \
|
--charts helm-charts/infisical-standalone-postgres \
|
||||||
--helm-extra-args="--timeout=300s" \
|
--helm-extra-args="--timeout=300s" \
|
||||||
--helm-extra-set-args="--set ingress.nginx.enabled=false --set infisical.autoDatabaseSchemaMigration=false --set infisical.replicaCount=1 --set infisical.image.tag=v0.132.2-postgres --set infisical.autoBootstrap.enabled=true" \
|
--helm-extra-set-args="--set ingress.nginx.enabled=false --set infisical.replicaCount=1 --set infisical.image.tag=v0.151.0 --set infisical.autoBootstrap.enabled=true" \
|
||||||
--namespace infisical-standalone-postgres
|
--namespace infisical-standalone-postgres
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import {
|
|||||||
TOrgPlanDTO,
|
TOrgPlanDTO,
|
||||||
TOrgPlansTableDTO,
|
TOrgPlansTableDTO,
|
||||||
TOrgPmtMethodsDTO,
|
TOrgPmtMethodsDTO,
|
||||||
|
TPlanBillingInfo,
|
||||||
TStartOrgTrialDTO,
|
TStartOrgTrialDTO,
|
||||||
TUpdateOrgBillingDetailsDTO
|
TUpdateOrgBillingDetailsDTO
|
||||||
} from "./license-types";
|
} from "./license-types";
|
||||||
@@ -465,6 +466,21 @@ export const licenseServiceFactory = ({
|
|||||||
return { url };
|
return { url };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getUsageMetrics = async (orgId: string) => {
|
||||||
|
const [orgMembersUsed, identityUsed, projectCount] = await Promise.all([
|
||||||
|
orgDAL.countAllOrgMembers(orgId),
|
||||||
|
licenseDAL.countOfOrgIdentities(orgId),
|
||||||
|
projectDAL.countOfOrgProjects(orgId)
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
orgMembersUsed,
|
||||||
|
identityUsed,
|
||||||
|
projectCount,
|
||||||
|
totalIdentities: identityUsed + orgMembersUsed
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const getOrgBillingInfo = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TGetOrgBillInfoDTO) => {
|
const getOrgBillingInfo = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TGetOrgBillInfoDTO) => {
|
||||||
const { permission } = await permissionService.getOrgPermission({
|
const { permission } = await permissionService.getOrgPermission({
|
||||||
actorId,
|
actorId,
|
||||||
@@ -483,10 +499,16 @@ export const licenseServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (instanceType === InstanceType.Cloud) {
|
if (instanceType === InstanceType.Cloud) {
|
||||||
const { data } = await licenseServerCloudApi.request.get(
|
const { data } = await licenseServerCloudApi.request.get<TPlanBillingInfo>(
|
||||||
`/api/license-server/v1/customers/${organization.customerId}/cloud-plan/billing`
|
`/api/license-server/v1/customers/${organization.customerId}/cloud-plan/billing`
|
||||||
);
|
);
|
||||||
return data;
|
const { identityUsed, orgMembersUsed } = await getUsageMetrics(orgId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
users: orgMembersUsed,
|
||||||
|
identities: identityUsed
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -495,7 +517,9 @@ export const licenseServiceFactory = ({
|
|||||||
interval: "month",
|
interval: "month",
|
||||||
intervalCount: 1,
|
intervalCount: 1,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
quantity: 1
|
quantity: 1,
|
||||||
|
users: 0,
|
||||||
|
identities: 0
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -539,21 +563,6 @@ export const licenseServiceFactory = ({
|
|||||||
throw new Error(`Unsupported instance type for server-based plan table: ${instanceType}`);
|
throw new Error(`Unsupported instance type for server-based plan table: ${instanceType}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUsageMetrics = async (orgId: string) => {
|
|
||||||
const [orgMembersUsed, identityUsed, projectCount] = await Promise.all([
|
|
||||||
orgDAL.countAllOrgMembers(orgId),
|
|
||||||
licenseDAL.countOfOrgIdentities(orgId),
|
|
||||||
projectDAL.countOfOrgProjects(orgId)
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
orgMembersUsed,
|
|
||||||
identityUsed,
|
|
||||||
projectCount,
|
|
||||||
totalIdentities: identityUsed + orgMembersUsed
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// returns org current plan feature table
|
// returns org current plan feature table
|
||||||
const getOrgPlanTable = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TGetOrgBillInfoDTO) => {
|
const getOrgPlanTable = async ({ orgId, actor, actorId, actorAuthMethod, actorOrgId }: TGetOrgBillInfoDTO) => {
|
||||||
const { permission } = await permissionService.getOrgPermission({
|
const { permission } = await permissionService.getOrgPermission({
|
||||||
|
|||||||
@@ -22,6 +22,15 @@ export type TOfflineLicense = {
|
|||||||
features: TFeatureSet;
|
features: TFeatureSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TPlanBillingInfo = {
|
||||||
|
currentPeriodStart: number;
|
||||||
|
currentPeriodEnd: number;
|
||||||
|
interval: "month" | "year";
|
||||||
|
intervalCount: number;
|
||||||
|
amount: number;
|
||||||
|
quantity: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type TFeatureSet = {
|
export type TFeatureSet = {
|
||||||
_id: null;
|
_id: null;
|
||||||
slug: string | null;
|
slug: string | null;
|
||||||
|
|||||||
@@ -83,9 +83,11 @@ export const extractPrincipalArnEntity = (arn: string, formatAsIamRole: boolean
|
|||||||
* Extracts the identity ARN from the GetCallerIdentity response to one of the following formats:
|
* Extracts the identity ARN from the GetCallerIdentity response to one of the following formats:
|
||||||
* - arn:aws:iam::123456789012:user/MyUserName
|
* - arn:aws:iam::123456789012:user/MyUserName
|
||||||
* - arn:aws:iam::123456789012:role/MyRoleName
|
* - arn:aws:iam::123456789012:role/MyRoleName
|
||||||
|
* - arn:aws-us-gov:iam::123456789012:user/MyUserName (GovCloud)
|
||||||
|
* - arn:aws-us-gov:iam::123456789012:role/MyRoleName (GovCloud)
|
||||||
*/
|
*/
|
||||||
export const extractPrincipalArn = (arn: string, formatAsIamRole: boolean = false) => {
|
export const extractPrincipalArn = (arn: string, formatAsIamRole: boolean = false) => {
|
||||||
const entity = extractPrincipalArnEntity(arn, formatAsIamRole);
|
const entity = extractPrincipalArnEntity(arn, formatAsIamRole);
|
||||||
|
|
||||||
return `arn:aws:${formatAsIamRole ? "iam" : entity.Service}::${entity.AccountNumber}:${entity.Type}/${entity.FriendlyName}`;
|
return `arn:${entity.Partition}:${formatAsIamRole ? "iam" : entity.Service}::${entity.AccountNumber}:${entity.Type}/${entity.FriendlyName}`;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const twelveDigitRegex = new RE2(/^\d{12}$/);
|
|||||||
// akhilmhdh: change this to a normal function later. Checked no redosable at the moment
|
// akhilmhdh: change this to a normal function later. Checked no redosable at the moment
|
||||||
|
|
||||||
const arnRegex = new RE2(
|
const arnRegex = new RE2(
|
||||||
/^arn:aws:(iam|sts)::\d{12}:(user\/[a-zA-Z0-9_.@+*/-]+|role\/[a-zA-Z0-9_.@+*/-]+|assumed-role\/[a-zA-Z0-9_.@+*/-]+|\*)$/
|
/^arn:aws(?:-us-gov)?:(iam|sts)::\d{12}:(user\/[a-zA-Z0-9_.@+*/-]+|role\/[a-zA-Z0-9_.@+*/-]+|assumed-role\/[a-zA-Z0-9_.@+*/-]+|\*)$/
|
||||||
);
|
);
|
||||||
|
|
||||||
export const validateAccountIds = z
|
export const validateAccountIds = z
|
||||||
@@ -55,7 +55,7 @@ export const validatePrincipalArns = z
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
message:
|
message:
|
||||||
"Each ARN must be in the format of 'arn:aws:iam::123456789012:user/UserName', 'arn:aws:iam::123456789012:role/RoleName', or 'arn:aws:iam::123456789012:*', 'arn:aws:sts::123456789012:assumed-role/RoleName'."
|
"Each ARN must be in the format of 'arn:aws:iam::123456789012:user/UserName', 'arn:aws:iam::123456789012:role/RoleName', or 'arn:aws:iam::123456789012:*', 'arn:aws:sts::123456789012:assumed-role/RoleName'. GovCloud ARNs (arn:aws-us-gov:...) are also supported."
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// Transform to normalize the spaces around commas
|
// Transform to normalize the spaces around commas
|
||||||
|
|||||||
@@ -1428,7 +1428,7 @@ Enabling HSM encryption has a set of key benefits:
|
|||||||
infisical:
|
infisical:
|
||||||
image:
|
image:
|
||||||
repository: infisical/infisical
|
repository: infisical/infisical
|
||||||
tag: "v0.151.0-nightly-20251013.1"
|
tag: "v0.151.0"
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
extraVolumeMounts:
|
extraVolumeMounts:
|
||||||
|
|||||||
@@ -116,6 +116,27 @@ The platform utilizes Postgres to persist all of its data and Redis for caching
|
|||||||
<ParamField query="DB_ROOT_CERT" type="string" default="" optional>
|
<ParamField query="DB_ROOT_CERT" type="string" default="" optional>
|
||||||
Configure the SSL certificate for securing a Postgres connection by first encoding it in base64.
|
Configure the SSL certificate for securing a Postgres connection by first encoding it in base64.
|
||||||
Use the following command to encode your certificate: `echo "<certificate>" | base64`
|
Use the following command to encode your certificate: `echo "<certificate>" | base64`
|
||||||
|
|
||||||
|
Many cloud providers provide a CA certificate for their data regions that you can use to secure your connection with SSL.
|
||||||
|
|
||||||
|
<AccordionGroup>
|
||||||
|
<Accordion title="AWS RDS">
|
||||||
|
If you're hosting your database on AWS RDS, you can use their publicly available CA certificate as the database root certificate.
|
||||||
|
|
||||||
|
You can find all the available CA certificates for AWS RDS on the official [AWS RDS documentation](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html).
|
||||||
|
|
||||||
|
As an example, if your RDS cluster is hosted in `us-east-1` _(US East, N. Virginia)_, you can use the following root certificate: https://truststore.pki.rds.amazonaws.com/us-east-1/us-east-1-bundle.pem.
|
||||||
|
|
||||||
|
All the available CA certificates can be found in the AWS RDS documentation linked above.
|
||||||
|
|
||||||
|
Remember to base64 encode the certificate before setting it as the `DB_ROOT_CERT` environment variable. `cat /path/to/certificate.pem | base64`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DB_ROOT_CERT=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1 # .... (base64 encoded certificate)
|
||||||
|
DB_CONNECTION_URI=<rds-endpoint>?sslmode=verify-ca # or verify-full depending on your security policies
|
||||||
|
```
|
||||||
|
</Accordion>
|
||||||
|
</AccordionGroup>
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField query="DB_READ_REPLICAS" type="string" default="" optional>
|
<ParamField query="DB_READ_REPLICAS" type="string" default="" optional>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
---
|
---
|
||||||
title: "Kubernetes via Helm Chart"
|
title: "Kubernetes via Helm Chart"
|
||||||
description: "Learn how to use Helm chart to install Infisical on your Kubernetes cluster."
|
description: "Learn how to use Helm chart to install Infisical on your Kubernetes cluster."
|
||||||
---
|
---
|
||||||
|
|
||||||
**Prerequisites**
|
**Prerequisites**
|
||||||
|
|
||||||
- You have extensive understanding of [Kubernetes](https://kubernetes.io/)
|
- You have extensive understanding of [Kubernetes](https://kubernetes.io/)
|
||||||
- Installed [Helm package manager](https://helm.sh/) version v3.11.3 or greater
|
- Installed [Helm package manager](https://helm.sh/) version v3.11.3 or greater
|
||||||
- You have [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) installed and connected to your kubernetes cluster
|
- You have [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) installed and connected to your kubernetes cluster
|
||||||
@@ -12,7 +14,7 @@ description: "Learn how to use Helm chart to install Infisical on your Kubernete
|
|||||||
```bash
|
```bash
|
||||||
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
|
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
|
||||||
```
|
```
|
||||||
```
|
```bash
|
||||||
helm repo update
|
helm repo update
|
||||||
```
|
```
|
||||||
</Step>
|
</Step>
|
||||||
@@ -61,6 +63,7 @@ description: "Learn how to use Helm chart to install Infisical on your Kubernete
|
|||||||
</Tab>
|
</Tab>
|
||||||
<Tab title="Production deployment">
|
<Tab title="Production deployment">
|
||||||
For production environments, we recommend using Cloud-based Platform as a Service (PaaS) solutions for PostgreSQL and Redis to ensure high availability. In on-premise setups, it's recommended to configure Redis and Postgres for high availability, either by using Bitnami charts or a custom configuration.
|
For production environments, we recommend using Cloud-based Platform as a Service (PaaS) solutions for PostgreSQL and Redis to ensure high availability. In on-premise setups, it's recommended to configure Redis and Postgres for high availability, either by using Bitnami charts or a custom configuration.
|
||||||
|
|
||||||
```yaml simple-values-example.yaml
|
```yaml simple-values-example.yaml
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
@@ -74,6 +77,10 @@ description: "Learn how to use Helm chart to install Infisical on your Kubernete
|
|||||||
DB_CONNECTION_URI: <>
|
DB_CONNECTION_URI: <>
|
||||||
SITE_URL: <>
|
SITE_URL: <>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<Tip>
|
||||||
|
If you need to configure the SSL certificate for your production Postgres instance, you can use the `DB_ROOT_CERT` environment variable. [Learn more about configuring the SSL certificate](/self-hosting/configuration/envars#aws-rds).
|
||||||
|
</Tip>
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Step>
|
</Step>
|
||||||
|
|||||||
@@ -8,22 +8,40 @@ type Props = {
|
|||||||
isOpen?: boolean;
|
isOpen?: boolean;
|
||||||
onOpenChange?: (isOpen: boolean) => void;
|
onOpenChange?: (isOpen: boolean) => void;
|
||||||
text: string;
|
text: string;
|
||||||
|
isEnterpriseFeature?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UpgradePlanModal = ({ text, isOpen, onOpenChange }: Props): JSX.Element => {
|
export const UpgradePlanModal = ({
|
||||||
|
text,
|
||||||
|
isOpen,
|
||||||
|
onOpenChange,
|
||||||
|
isEnterpriseFeature = false
|
||||||
|
}: Props): JSX.Element => {
|
||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
const { currentOrg } = useOrganization();
|
const { currentOrg } = useOrganization();
|
||||||
const { mutateAsync, isPending } = useGetOrgTrialUrl();
|
const { mutateAsync, isPending } = useGetOrgTrialUrl();
|
||||||
const link =
|
|
||||||
subscription && subscription.slug !== null
|
const getLink = () => {
|
||||||
? ("/organization/billing" as const)
|
// self-hosting
|
||||||
: "https://infisical.com/scheduledemo";
|
if (!subscription || subscription.slug === null) {
|
||||||
|
return "https://infisical.com/scheduledemo";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infisical cloud
|
||||||
|
if (isEnterpriseFeature) {
|
||||||
|
return "https://infisical.com/talk-to-us";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "/organization/billing" as const;
|
||||||
|
};
|
||||||
|
|
||||||
|
const link = getLink();
|
||||||
|
|
||||||
const handleUpgradeBtnClick = async () => {
|
const handleUpgradeBtnClick = async () => {
|
||||||
try {
|
try {
|
||||||
if (!subscription || !currentOrg) return;
|
if (!subscription || !currentOrg) return;
|
||||||
|
|
||||||
if (!subscription.has_used_trial) {
|
if (!subscription.has_used_trial && !isEnterpriseFeature) {
|
||||||
// direct user to start pro trial
|
// direct user to start pro trial
|
||||||
|
|
||||||
const url = await mutateAsync({
|
const url = await mutateAsync({
|
||||||
@@ -40,6 +58,17 @@ export const UpgradePlanModal = ({ text, isOpen, onOpenChange }: Props): JSX.Ele
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const getUpgradePlanLabel = () => {
|
||||||
|
if (subscription) {
|
||||||
|
if (isEnterpriseFeature) {
|
||||||
|
return "Talk to Us";
|
||||||
|
}
|
||||||
|
if (!subscription.has_used_trial) {
|
||||||
|
return "Start Pro Free Trial";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "Upgrade Plan";
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||||
@@ -55,7 +84,7 @@ export const UpgradePlanModal = ({ text, isOpen, onOpenChange }: Props): JSX.Ele
|
|||||||
onClick={handleUpgradeBtnClick}
|
onClick={handleUpgradeBtnClick}
|
||||||
className="mr-4"
|
className="mr-4"
|
||||||
>
|
>
|
||||||
{subscription && !subscription.has_used_trial ? "Start Pro Free Trial" : "Upgrade Plan"}
|
{getUpgradePlanLabel()}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
colorSchema="secondary"
|
colorSchema="secondary"
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ export type PlanBillingInfo = {
|
|||||||
interval: "month" | "year";
|
interval: "month" | "year";
|
||||||
intervalCount: number;
|
intervalCount: number;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
users: number;
|
||||||
|
identities: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Invoice = {
|
export type Invoice = {
|
||||||
|
|||||||
+27
-10
@@ -1,10 +1,10 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { faArrowUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowUpRightFromSquare, faInfoCircle } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
import { Button } from "@app/components/v2";
|
import { Button, Tooltip } from "@app/components/v2";
|
||||||
import {
|
import {
|
||||||
OrgPermissionBillingActions,
|
OrgPermissionBillingActions,
|
||||||
OrgPermissionSubjects,
|
OrgPermissionSubjects,
|
||||||
@@ -27,6 +27,9 @@ export const PreviewSection = () => {
|
|||||||
const { subscription } = useSubscription(true);
|
const { subscription } = useSubscription(true);
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { data, isPending } = useGetOrgPlanBillingInfo(currentOrg?.id ?? "");
|
const { data, isPending } = useGetOrgPlanBillingInfo(currentOrg?.id ?? "");
|
||||||
|
|
||||||
|
const totalAmount = data?.amount ? data.amount * (data.users + data.identities) : 0;
|
||||||
|
|
||||||
const getOrgTrialUrl = useGetOrgTrialUrl();
|
const getOrgTrialUrl = useGetOrgTrialUrl();
|
||||||
const createCustomerPortalSession = useCreateCustomerPortalSession();
|
const createCustomerPortalSession = useCreateCustomerPortalSession();
|
||||||
|
|
||||||
@@ -190,14 +193,28 @@ export const PreviewSection = () => {
|
|||||||
</OrgPermissionCan>
|
</OrgPermissionCan>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="mr-4 flex-1 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
{subscription.slug !== "enterprise" ? (
|
||||||
<p className="mb-2 text-gray-400">Price</p>
|
<div className="mr-4 flex-1 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
<p className="mb-8 text-2xl font-medium text-mineshaft-50">
|
<p className="mb-2 text-gray-400">Price</p>
|
||||||
{subscription.status === "trialing"
|
<p className="mb-8 text-2xl font-medium text-mineshaft-50">
|
||||||
? "$0.00 / month"
|
{subscription.status === "trialing" ? (
|
||||||
: `${formatAmount(data.amount)} / ${data.interval}`}
|
"$0.00 / month"
|
||||||
</p>
|
) : (
|
||||||
</div>
|
<>
|
||||||
|
{formatAmount(totalAmount)} / {data.interval}
|
||||||
|
{(subscription.slug === "pro" || subscription.slug === "pro-annual") && (
|
||||||
|
<Tooltip
|
||||||
|
content={`Total price is based on the number of users and machine identities at ${formatAmount(data.amount)} each. You have ${data.users} ${data.users > 1 ? "users" : "user"} and ${data.identities} ${data.identities > 1 ? "machine identities" : "machine identity"}.`}
|
||||||
|
className="max-w-lg"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faInfoCircle} className="ml-2" size="xs" />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
<div className="flex-1 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
<div className="flex-1 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
<p className="mb-2 text-gray-400">Subscription renews on</p>
|
<p className="mb-2 text-gray-400">Subscription renews on</p>
|
||||||
<p className="mb-8 text-2xl font-medium text-mineshaft-50">
|
<p className="mb-8 text-2xl font-medium text-mineshaft-50">
|
||||||
|
|||||||
@@ -1172,7 +1172,9 @@ export const OverviewPage = () => {
|
|||||||
handlePopUpClose("misc");
|
handlePopUpClose("misc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handlePopUpOpen("upgradePlan");
|
handlePopUpOpen("upgradePlan", {
|
||||||
|
isEnterpriseFeature: true
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
isDisabled={userAvailableDynamicSecretEnvs.length === 0}
|
isDisabled={userAvailableDynamicSecretEnvs.length === 0}
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
@@ -1679,10 +1681,11 @@ export const OverviewPage = () => {
|
|||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
|
isEnterpriseFeature={popUp.upgradePlan.data?.isEnterpriseFeature}
|
||||||
text={
|
text={
|
||||||
subscription.slug === null
|
subscription.slug === null
|
||||||
? "You can perform this action under an Enterprise license"
|
? "You can perform this action under an Enterprise license"
|
||||||
: "You can perform this action if you switch to Infisical's Team plan"
|
: "You can perform this action if you switch to Infisical's Enterprise plan"
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+7
-2
@@ -1019,7 +1019,9 @@ export const ActionBar = ({
|
|||||||
handlePopUpClose("misc");
|
handlePopUpClose("misc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handlePopUpOpen("upgradePlan");
|
handlePopUpOpen("upgradePlan", {
|
||||||
|
isEnterpriseFeature: true
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
variant="outline_bg"
|
variant="outline_bg"
|
||||||
@@ -1274,10 +1276,13 @@ export const ActionBar = ({
|
|||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
|
isEnterpriseFeature={popUp.upgradePlan.data?.isEnterpriseFeature}
|
||||||
text={
|
text={
|
||||||
subscription.slug === null
|
subscription.slug === null
|
||||||
? "You can perform this action under an Enterprise license"
|
? "You can perform this action under an Enterprise license"
|
||||||
: "You can perform this action if you switch to Infisical's Team plan"
|
: `You can perform this action if you switch to Infisical's ${
|
||||||
|
popUp.upgradePlan.data.isEnterpriseFeature ? "Enterprise" : "Pro"
|
||||||
|
} plan`
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+1
-1
@@ -226,7 +226,7 @@ export const EnvironmentTabs = ({ secretPath }: Props) => {
|
|||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
text="You can add custom environments if you switch to Infisical's Team plan."
|
text="You can add custom environments if you switch to Infisical's Pro plan."
|
||||||
/>
|
/>
|
||||||
<AddEnvironmentModal
|
<AddEnvironmentModal
|
||||||
isOpen={popUp.createEnvironment.isOpen}
|
isOpen={popUp.createEnvironment.isOpen}
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ const Page = () => {
|
|||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
text="You can add secret rotation if you switch to Infisical's Team plan."
|
text="You can add secret rotation if you switch to Infisical's Pro plan."
|
||||||
/>
|
/>
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={popUp.secretRotationV2.isOpen}
|
isOpen={popUp.secretRotationV2.isOpen}
|
||||||
|
|||||||
+1
-1
@@ -123,7 +123,7 @@ export const EnvironmentSection = () => {
|
|||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
text="You can add custom environments if you switch to Infisical's Team plan."
|
text="You can add custom environments if you switch to Infisical's Pro plan."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
## 1.7.2 (October 20, 2025)
|
||||||
|
Changes:
|
||||||
|
* Updated the default `infisical.image.tag` value to `v0.151.0`.
|
||||||
|
* `autoDatabaseSchemaMigration` has been fully removed as all newer versions of Infisical automatically run migrations as apart of the startup process.
|
||||||
|
|
||||||
## 1.7.1 (October 10, 2025)
|
## 1.7.1 (October 10, 2025)
|
||||||
|
|
||||||
Changes:
|
Changes:
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ dependencies:
|
|||||||
repository: oci://registry-1.docker.io/bitnamicharts
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
version: 18.14.1
|
version: 18.14.1
|
||||||
digest: sha256:57a18fb5258fc153d27b633f6570104c7628af651f08f3ae7e1cf8920c2c31fa
|
digest: sha256:57a18fb5258fc153d27b633f6570104c7628af651f08f3ae7e1cf8920c2c31fa
|
||||||
generated: "2025-09-30T18:44:50.303037+04:00"
|
generated: "2025-10-21T22:30:21.313884+04:00"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 1.7.1
|
version: 1.7.2
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# 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
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ A helm chart to deploy Infisical
|
|||||||
|-----|------|---------|-------------|
|
|-----|------|---------|-------------|
|
||||||
| fullnameOverride | string | `""` | Overrides the full name of the release, affecting resource names |
|
| fullnameOverride | string | `""` | Overrides the full name of the release, affecting resource names |
|
||||||
| infisical.affinity | object | `{}` | Node affinity settings for pod placement |
|
| infisical.affinity | object | `{}` | Node affinity settings for pod placement |
|
||||||
| infisical.autoDatabaseSchemaMigration | bool | `true` | Automatically migrates new database schema when deploying |
|
|
||||||
| infisical.databaseSchemaMigrationJob.image.pullPolicy | string | `"IfNotPresent"` | Pulls image only if not present on the node |
|
| infisical.databaseSchemaMigrationJob.image.pullPolicy | string | `"IfNotPresent"` | Pulls image only if not present on the node |
|
||||||
| infisical.databaseSchemaMigrationJob.image.repository | string | `"ghcr.io/groundnuty/k8s-wait-for"` | Image repository for migration wait job |
|
| infisical.databaseSchemaMigrationJob.image.repository | string | `"ghcr.io/groundnuty/k8s-wait-for"` | Image repository for migration wait job |
|
||||||
| infisical.databaseSchemaMigrationJob.image.tag | string | `"no-root-v2.0"` | Image tag version |
|
| infisical.databaseSchemaMigrationJob.image.tag | string | `"no-root-v2.0"` | Image tag version |
|
||||||
|
|||||||
@@ -44,16 +44,6 @@ spec:
|
|||||||
{{- if $infisicalValues.image.imagePullSecrets }}
|
{{- if $infisicalValues.image.imagePullSecrets }}
|
||||||
imagePullSecrets:
|
imagePullSecrets:
|
||||||
{{- toYaml $infisicalValues.image.imagePullSecrets | nindent 6 }}
|
{{- toYaml $infisicalValues.image.imagePullSecrets | nindent 6 }}
|
||||||
{{- end }}
|
|
||||||
{{- if $infisicalValues.autoDatabaseSchemaMigration }}
|
|
||||||
serviceAccountName: {{ include "infisical.serviceAccountName" . }}
|
|
||||||
initContainers:
|
|
||||||
- name: "migration-init"
|
|
||||||
image: "{{ $infisicalValues.databaseSchemaMigrationJob.image.repository }}:{{ $infisicalValues.databaseSchemaMigrationJob.image.tag }}"
|
|
||||||
imagePullPolicy: {{ $infisicalValues.databaseSchemaMigrationJob.image.pullPolicy }}
|
|
||||||
args:
|
|
||||||
- "job"
|
|
||||||
- "{{ .Release.Name }}-schema-migration-{{ .Release.Revision }}"
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
containers:
|
containers:
|
||||||
- name: {{ template "infisical.name" . }}-{{ $infisicalValues.name }}
|
- name: {{ template "infisical.name" . }}-{{ $infisicalValues.name }}
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
{{- $infisicalValues := .Values.infisical }}
|
|
||||||
{{- if $infisicalValues.autoDatabaseSchemaMigration }}
|
|
||||||
apiVersion: batch/v1
|
|
||||||
kind: Job
|
|
||||||
metadata:
|
|
||||||
name: "{{ .Release.Name }}-schema-migration-{{ .Release.Revision }}"
|
|
||||||
labels:
|
|
||||||
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
|
||||||
spec:
|
|
||||||
backoffLimit: 10
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
name: "{{ .Release.Name }}-create-tables"
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name | quote }}
|
|
||||||
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
|
||||||
spec:
|
|
||||||
serviceAccountName: {{ include "infisical.serviceAccountName" . }}
|
|
||||||
{{- if $infisicalValues.image.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml $infisicalValues.image.imagePullSecrets | nindent 6 }}
|
|
||||||
{{- end }}
|
|
||||||
restartPolicy: OnFailure
|
|
||||||
containers:
|
|
||||||
- name: infisical-schema-migration
|
|
||||||
image: "{{ $infisicalValues.image.repository }}:{{ $infisicalValues.image.tag }}"
|
|
||||||
command: ["npm", "run", "migration:latest"]
|
|
||||||
env:
|
|
||||||
{{- if .Values.postgresql.useExistingPostgresSecret.enabled }}
|
|
||||||
- name: DB_CONNECTION_URI
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: {{ .Values.postgresql.useExistingPostgresSecret.existingConnectionStringSecret.name }}
|
|
||||||
key: {{ .Values.postgresql.useExistingPostgresSecret.existingConnectionStringSecret.key }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.postgresql.enabled }}
|
|
||||||
- name: DB_CONNECTION_URI
|
|
||||||
value: {{ include "infisical.postgresDBConnectionString" . }}
|
|
||||||
{{- end }}
|
|
||||||
envFrom:
|
|
||||||
- secretRef:
|
|
||||||
name: {{ $infisicalValues.kubeSecretRef }}
|
|
||||||
{{- with $infisicalValues.extraVolumeMounts }}
|
|
||||||
volumeMounts:
|
|
||||||
{{- toYaml . | nindent 10 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with $infisicalValues.extraVolumes }}
|
|
||||||
volumes:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -10,9 +10,6 @@ infisical:
|
|||||||
# -- Sets the name of the deployment within this chart
|
# -- Sets the name of the deployment within this chart
|
||||||
name: infisical
|
name: infisical
|
||||||
|
|
||||||
# -- Automatically migrates new database schema when deploying
|
|
||||||
autoDatabaseSchemaMigration: true
|
|
||||||
|
|
||||||
autoBootstrap:
|
autoBootstrap:
|
||||||
# -- Enable auto-bootstrap of the Infisical instance
|
# -- Enable auto-bootstrap of the Infisical instance
|
||||||
enabled: false
|
enabled: false
|
||||||
@@ -68,7 +65,7 @@ infisical:
|
|||||||
# -- Image repository for the Infisical service
|
# -- Image repository for the Infisical service
|
||||||
repository: infisical/infisical
|
repository: infisical/infisical
|
||||||
# -- Specific version tag of the Infisical image. View the latest version here https://hub.docker.com/r/infisical/infisical
|
# -- Specific version tag of the Infisical image. View the latest version here https://hub.docker.com/r/infisical/infisical
|
||||||
tag: "v0.93.1-postgres"
|
tag: "v0.151.0"
|
||||||
# -- Pulls image only if not already present on the node
|
# -- Pulls image only if not already present on the node
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
# -- Secret references for pulling the image, if needed
|
# -- Secret references for pulling the image, if needed
|
||||||
@@ -118,8 +115,7 @@ ingress:
|
|||||||
# -- Custom annotations for ingress resource
|
# -- Custom annotations for ingress resource
|
||||||
annotations: {}
|
annotations: {}
|
||||||
# -- TLS settings for HTTPS access
|
# -- TLS settings for HTTPS access
|
||||||
tls:
|
tls: []
|
||||||
[]
|
|
||||||
# -- TLS secret name for HTTPS
|
# -- TLS secret name for HTTPS
|
||||||
# - secretName: letsencrypt-prod
|
# - secretName: letsencrypt-prod
|
||||||
# -- Domain name to associate with the TLS certificate
|
# -- Domain name to associate with the TLS certificate
|
||||||
|
|||||||
Reference in New Issue
Block a user