mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Merge branch 'main' into ENG-2625
This commit is contained in:
@@ -234,6 +234,7 @@ export enum EventType {
|
||||
GET_PROJECT_KMS_BACKUP = "get-project-kms-backup",
|
||||
LOAD_PROJECT_KMS_BACKUP = "load-project-kms-backup",
|
||||
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
|
||||
ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso",
|
||||
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
|
||||
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
|
||||
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
|
||||
@@ -1907,6 +1908,11 @@ interface OrgAdminAccessProjectEvent {
|
||||
}; // no metadata yet
|
||||
}
|
||||
|
||||
interface OrgAdminBypassSSOEvent {
|
||||
type: EventType.ORG_ADMIN_BYPASS_SSO;
|
||||
metadata: Record<string, string>; // no metadata yet
|
||||
}
|
||||
|
||||
interface CreateCertificateTemplateEstConfig {
|
||||
type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG;
|
||||
metadata: {
|
||||
@@ -2656,6 +2662,7 @@ export type Event =
|
||||
| GetProjectKmsBackupEvent
|
||||
| LoadProjectKmsBackupEvent
|
||||
| OrgAdminAccessProjectEvent
|
||||
| OrgAdminBypassSSOEvent
|
||||
| CreateCertificateTemplate
|
||||
| UpdateCertificateTemplate
|
||||
| GetCertificateTemplate
|
||||
|
||||
@@ -596,7 +596,14 @@ export const registerRoutes = async (
|
||||
kmsService
|
||||
});
|
||||
|
||||
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService, orgDAL, totpService });
|
||||
const loginService = authLoginServiceFactory({
|
||||
userDAL,
|
||||
smtpService,
|
||||
tokenService,
|
||||
orgDAL,
|
||||
totpService,
|
||||
auditLogService
|
||||
});
|
||||
const passwordService = authPaswordServiceFactory({
|
||||
tokenService,
|
||||
smtpService,
|
||||
|
||||
@@ -3,6 +3,8 @@ import jwt from "jsonwebtoken";
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { OrgMembershipRole, TUsers, UserDeviceSchema } from "@app/db/schemas";
|
||||
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { request } from "@app/lib/config/request";
|
||||
@@ -11,6 +13,7 @@ import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption";
|
||||
import { getUserPrivateKey } from "@app/lib/crypto/srp";
|
||||
import { BadRequestError, DatabaseError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { logger } from "@app/lib/logger";
|
||||
import { getUserAgentType } from "@app/server/plugins/audit-log";
|
||||
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
||||
|
||||
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
|
||||
@@ -28,7 +31,15 @@ import {
|
||||
TOauthTokenExchangeDTO,
|
||||
TVerifyMfaTokenDTO
|
||||
} from "./auth-login-type";
|
||||
import { AuthMethod, AuthModeJwtTokenPayload, AuthModeMfaJwtTokenPayload, AuthTokenType, MfaMethod } from "./auth-type";
|
||||
import {
|
||||
ActorType,
|
||||
AuthMethod,
|
||||
AuthModeJwtTokenPayload,
|
||||
AuthModeMfaJwtTokenPayload,
|
||||
AuthTokenType,
|
||||
MfaMethod
|
||||
} from "./auth-type";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
|
||||
type TAuthLoginServiceFactoryDep = {
|
||||
userDAL: TUserDALFactory;
|
||||
@@ -36,6 +47,7 @@ type TAuthLoginServiceFactoryDep = {
|
||||
tokenService: TAuthTokenServiceFactory;
|
||||
smtpService: TSmtpService;
|
||||
totpService: Pick<TTotpServiceFactory, "verifyUserTotp" | "verifyWithUserRecoveryCode">;
|
||||
auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
|
||||
};
|
||||
|
||||
export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>;
|
||||
@@ -44,7 +56,8 @@ export const authLoginServiceFactory = ({
|
||||
tokenService,
|
||||
smtpService,
|
||||
orgDAL,
|
||||
totpService
|
||||
totpService,
|
||||
auditLogService
|
||||
}: TAuthLoginServiceFactoryDep) => {
|
||||
/*
|
||||
* Private
|
||||
@@ -412,6 +425,55 @@ export const authLoginServiceFactory = ({
|
||||
mfaMethod: decodedToken.mfaMethod
|
||||
});
|
||||
|
||||
// In the event of this being a break-glass request (non-saml / non-oidc, when either is enforced)
|
||||
if (
|
||||
selectedOrg.authEnforced &&
|
||||
selectedOrg.bypassOrgAuthEnabled &&
|
||||
!isAuthMethodSaml(decodedToken.authMethod) &&
|
||||
decodedToken.authMethod !== AuthMethod.OIDC
|
||||
) {
|
||||
await auditLogService.createAuditLog({
|
||||
orgId: organizationId,
|
||||
ipAddress,
|
||||
userAgent,
|
||||
userAgentType: getUserAgentType(userAgent),
|
||||
actor: {
|
||||
type: ActorType.USER,
|
||||
metadata: {
|
||||
email: user.email,
|
||||
userId: user.id,
|
||||
username: user.username
|
||||
}
|
||||
},
|
||||
event: {
|
||||
type: EventType.ORG_ADMIN_BYPASS_SSO,
|
||||
metadata: {}
|
||||
}
|
||||
});
|
||||
|
||||
// Notify all admins via email (besides the actor)
|
||||
const orgAdmins = await orgDAL.findOrgMembersByRole(organizationId, OrgMembershipRole.Admin);
|
||||
const adminEmails = orgAdmins
|
||||
.filter((admin) => admin.user.id !== user.id)
|
||||
.map((admin) => admin.user.email)
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
if (adminEmails.length > 0) {
|
||||
await smtpService.sendMail({
|
||||
recipients: adminEmails,
|
||||
subjectLine: "Security Alert: Admin SSO Bypass",
|
||||
substitutions: {
|
||||
email: user.email,
|
||||
timestamp: new Date().toISOString(),
|
||||
ip: ipAddress,
|
||||
userAgent,
|
||||
siteUrl: removeTrailingSlash(cfg.SITE_URL || "https://app.infisical.com")
|
||||
},
|
||||
template: SmtpTemplates.OrgAdminBreakglassAccess
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...tokens,
|
||||
isMfaEnabled: false
|
||||
|
||||
@@ -787,13 +787,19 @@ export const kmsServiceFactory = ({
|
||||
return projectDataKey;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
error,
|
||||
`getProjectSecretManagerKmsDataKey: Failed to get project data key for [projectId=${projectId}]`
|
||||
);
|
||||
throw error;
|
||||
} finally {
|
||||
await lock?.release();
|
||||
}
|
||||
}
|
||||
|
||||
if (!project.kmsSecretManagerEncryptedDataKey) {
|
||||
throw new Error("Missing project data key");
|
||||
throw new BadRequestError({ message: "Missing project data key" });
|
||||
}
|
||||
|
||||
const kmsDecryptor = await decryptWithKmsKey({
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import {
|
||||
OrgMembershipRole,
|
||||
TableName,
|
||||
TOrganizations,
|
||||
TOrganizationsInsert,
|
||||
@@ -216,9 +217,8 @@ export const orgDALFactory = (db: TDbClient) => {
|
||||
|
||||
const findOrgMembersByUsername = async (orgId: string, usernames: string[], tx?: Knex) => {
|
||||
try {
|
||||
const conn = tx || db;
|
||||
const conn = tx || db.replicaNode();
|
||||
const members = await conn(TableName.OrgMembership)
|
||||
// .replicaNode()(TableName.OrgMembership)
|
||||
.where(`${TableName.OrgMembership}.orgId`, orgId)
|
||||
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
|
||||
.leftJoin<TUserEncryptionKeys>(
|
||||
@@ -251,6 +251,43 @@ export const orgDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
};
|
||||
|
||||
const findOrgMembersByRole = async (orgId: string, role: OrgMembershipRole, tx?: Knex) => {
|
||||
try {
|
||||
const conn = tx || db.replicaNode();
|
||||
const members = await conn(TableName.OrgMembership)
|
||||
.where(`${TableName.OrgMembership}.orgId`, orgId)
|
||||
.where(`${TableName.OrgMembership}.role`, role)
|
||||
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
|
||||
.leftJoin<TUserEncryptionKeys>(
|
||||
TableName.UserEncryptionKey,
|
||||
`${TableName.UserEncryptionKey}.userId`,
|
||||
`${TableName.Users}.id`
|
||||
)
|
||||
.select(
|
||||
conn.ref("id").withSchema(TableName.OrgMembership),
|
||||
conn.ref("inviteEmail").withSchema(TableName.OrgMembership),
|
||||
conn.ref("orgId").withSchema(TableName.OrgMembership),
|
||||
conn.ref("role").withSchema(TableName.OrgMembership),
|
||||
conn.ref("roleId").withSchema(TableName.OrgMembership),
|
||||
conn.ref("status").withSchema(TableName.OrgMembership),
|
||||
conn.ref("username").withSchema(TableName.Users),
|
||||
conn.ref("email").withSchema(TableName.Users),
|
||||
conn.ref("firstName").withSchema(TableName.Users),
|
||||
conn.ref("lastName").withSchema(TableName.Users),
|
||||
conn.ref("id").withSchema(TableName.Users).as("userId"),
|
||||
conn.ref("publicKey").withSchema(TableName.UserEncryptionKey)
|
||||
)
|
||||
.where({ isGhost: false });
|
||||
|
||||
return members.map(({ username, email, firstName, lastName, userId, publicKey, ...data }) => ({
|
||||
...data,
|
||||
user: { username, email, firstName, lastName, id: userId, publicKey }
|
||||
}));
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "Find org members by role" });
|
||||
}
|
||||
};
|
||||
|
||||
const findOrgGhostUser = async (orgId: string) => {
|
||||
try {
|
||||
const member = await db
|
||||
@@ -472,6 +509,7 @@ export const orgDALFactory = (db: TDbClient) => {
|
||||
findAllOrgsByUserId,
|
||||
ghostUserExists,
|
||||
findOrgMembersByUsername,
|
||||
findOrgMembersByRole,
|
||||
findOrgGhostUser,
|
||||
create,
|
||||
updateById,
|
||||
|
||||
@@ -207,7 +207,10 @@ export const fnSecretsV2FromImports = async ({
|
||||
);
|
||||
if (!importedFolders.length) continue;
|
||||
|
||||
const importedFolderIds = importedFolders.map((el) => el?.id) as string[];
|
||||
const importedFolderIds = importedFolders.filter(Boolean).map((el) => el?.id) as string[];
|
||||
|
||||
if (!importedFolderIds.length) continue;
|
||||
|
||||
const importedFolderGroupBySourceImport = groupBy(importedFolders, (i) => `${i?.envId}-${i?.path}`);
|
||||
|
||||
const importedSecrets = await secretDAL.find(
|
||||
|
||||
@@ -44,6 +44,7 @@ export enum SmtpTemplates {
|
||||
SecretRotationFailed = "secretRotationFailed.handlebars",
|
||||
ProjectAccessRequest = "projectAccess.handlebars",
|
||||
OrgAdminProjectDirectAccess = "orgAdminProjectGrantAccess.handlebars",
|
||||
OrgAdminBreakglassAccess = "orgAdminBreakglassAccess.handlebars",
|
||||
ServiceTokenExpired = "serviceTokenExpired.handlebars"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||
<title>Organization admin has bypassed SSO</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Infisical</h2>
|
||||
<p>The organization admin {{email}} has bypassed enforced SSO login.</p>
|
||||
<p><strong>Timestamp</strong>: {{timestamp}}</p>
|
||||
<p><strong>IP address</strong>: {{ip}}</p>
|
||||
<p><strong>User agent</strong>: {{userAgent}}</p>
|
||||
<p>If you'd like to disable Admin SSO Bypass, please visit <a href="{{siteUrl}}/organization/settings">Organization Settings</a> > Security.</p>
|
||||
|
||||
{{emailFooter}}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -6,40 +6,55 @@ description: "Learn how to structure your projects, secrets, and other resources
|
||||
|
||||
Infisical is designed to provide comprehensive, centralized, and efficient management of secrets, certificates, and encryption keys within organizations. Below is an overview of Infisical's structured components, which developers and administrators can leverage for optimal project management and security posture.
|
||||
|
||||
### 1. Projects
|
||||
### 0. Cluster/Instance
|
||||
|
||||
- **Best Practice**: In most cases, a single Infisical instance or cluster is sufficient. Multiple clusters are typically only necessary for large, globally distributed organizations.
|
||||
- **Use Cases**:
|
||||
- **Cloud-hosted** deployments typically use a single cluster. While technically possible, using multiple clusters is not a common practice and is generally unnecessary.
|
||||
- **Self-hosted** deployments can be configured with multiple clusters if needed.
|
||||
|
||||
|
||||
### 1. Organization
|
||||
|
||||
- **Definition**: An Infisical [organization](/documentation/platform/organization) is a set of projects that use the same billing.
|
||||
- **Use Cases**:
|
||||
- In **self-hosted** setups, you can create multiple organizations (e.g., one for each department or business unit).
|
||||
- In **cloud-hosted deployments**, it's standard to use a single organization.
|
||||
|
||||
### 2. Projects
|
||||
|
||||
- **Definition and Role**: [Projects](/documentation/platform/project) are the highest-level construct within an [organization](/documentation/platform/organization) in Infisical. They serve as the primary container for all functionalities.
|
||||
- **Correspondence to Code Repositories**: Projects typically align with specific code repositories.
|
||||
- **Functional Capabilities**: Each project encompasses features for managing secrets, certificates, and encryption keys, serving as the central hub for these resources.
|
||||
|
||||
### 2. Environments
|
||||
### 3. Environments
|
||||
|
||||
- **Purpose**: Environments are designed for organizing and compartmentalizing secrets within projects.
|
||||
- **Customization Options**: Environments can be tailored to align with existing infrastructure setups of any project. Default options include **Development**, **Staging**, and **Production**.
|
||||
- **Structure**: Each environment inherently has a root level for storing secrets, but additional sub-organizations can be created through [folders](/documentation/platform/folder) for better secret management.
|
||||
|
||||
### 3. Folders
|
||||
### 4. Folders
|
||||
|
||||
- **Use Case**: Folders are available for more advanced organizational needs, allowing logical separation of secrets.
|
||||
- **Typical Structure**: Folders can correspond to specific logical units, such as microservices or different layers of an application, providing refined control over secrets.
|
||||
|
||||
### 4. Imports
|
||||
### 5. Imports
|
||||
|
||||
- **Purpose and Benefits**: To promote reusability and avoid redundancy, Infisical supports the use of imports. This allows secrets, folders, or entire environments to be referenced across multiple projects as needed.
|
||||
- **Best Practice**: Utilizing [secret imports](/documentation/platform/secret-reference#secret-imports) or [references](/documentation/platform/secret-reference#secret-referencing) ensures consistency and minimizes manual overhead.
|
||||
|
||||
### 5. Approval Workflows
|
||||
### 6. Approval Workflows
|
||||
|
||||
- **Importance**: Implementing approval workflows is recommended for organizations aiming to enhance efficiency and strengthen their security posture.
|
||||
- **Types of Workflows**:
|
||||
- **[Access Requests](/documentation/platform/pr-workflows)**: This workflow allows developers to request access to sensitive resources. Such access can be configured for temporary use, a practice known as "just-in-time" access.
|
||||
- **[Change Requests](/documentation/platform/access-controls/access-requests)**: Facilitates reviews and approvals when changes are proposed for sensitive environments or specific folders, ensuring proper oversight.
|
||||
|
||||
### 6. Access Controls
|
||||
### 7. Access Controls
|
||||
|
||||
Infisical’s access control framework is unified for both human users and machine identities, ensuring consistent management across the board.
|
||||
|
||||
### 6.1 Roles
|
||||
### 7.1 Roles
|
||||
|
||||
- **2 Role Types**:
|
||||
- **Organization-Level Roles**: Provide broad access across the organization (e.g., ability to manage billing, configure settings, etc.).
|
||||
@@ -49,17 +64,17 @@ Infisical’s access control framework is unified for both human users and machi
|
||||
|
||||
<Note>Project access is defined not via an organization-level role, but rather through specific project memberships of both human and machine identities. Admin roles bypass this by default. </Note>
|
||||
|
||||
### 6.2 Additional Privileges
|
||||
### 7.2 Additional Privileges
|
||||
|
||||
[Additional privileges](/documentation/platform/access-controls/additional-privileges) can be assigned to users and machines on an ad-hoc basis for specific scenarios where roles alone are insufficient. If you find yourself using additional privileges too much, it is recommended to create custom roles. Additional privileges can be temporary or permanent.
|
||||
|
||||
|
||||
|
||||
### 6.3 Attribute-Based Access Control (ABAC)
|
||||
### 7.3 Attribute-Based Access Control (ABAC)
|
||||
|
||||
[Attribute-based Access Controls](/documentation/platform/access-controls/attribute-based-access-controls) allow restrictions based on tags or attributes linked to secrets. These can be integrated with SAML assertions and other security frameworks for dynamic access management.
|
||||
|
||||
### 6.4 User Groups
|
||||
### 7.4 User Groups
|
||||
|
||||
- **Application**: Organizations should use users groups in situations when they have a lot of developers with the same level of access (e.g., separated by team, department, seniority, etc.).
|
||||
- **Synchronization**: [User groups](/documentation/platform/groups) can be synced with an identity provider to maintain consistency and reduce manual management.
|
||||
|
||||
@@ -19,7 +19,7 @@ Before you begin, you'll first need to choose a method of authentication with AW
|
||||

|
||||
|
||||
2. Select **AWS Account** as the **Trusted Entity Type**.
|
||||
3. Choose **Another AWS Account** and enter **381492033652** (Infisical AWS Account ID). This restricts the role to be assumed only by Infisical. If you are self-hosting, provide the AWS account number where Infisical is hosted.
|
||||
3. Select **Another AWS Account** and provide the appropriate Infisical AWS Account ID: use **381492033652** for the **US region**, and **345594589636** for the **EU region**. This restricts the role to be assumed only by Infisical. If you are self-hosting, provide the AWS account number where Infisical is hosted.
|
||||
4. Optionally, enable **Require external ID** and enter your Infisical **project ID** to further enhance security.
|
||||
</Step>
|
||||
<Step title="Add Required Permissions for the IAM Role">
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 196 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 203 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 217 KiB |
@@ -55,7 +55,7 @@ Infisical supports two methods for connecting to AWS.
|
||||

|
||||
|
||||
2. Select **AWS Account** as the **Trusted Entity Type**.
|
||||
3. Choose **Another AWS Account** and enter **381492033652** (Infisical AWS Account ID). This restricts the role to be assumed only by Infisical. If self-hosting, provide your AWS account number instead.
|
||||
3. Select **Another AWS Account** and provide the appropriate Infisical AWS Account ID: use **381492033652** for the **US region**, and **345594589636** for the **EU region**. This restricts the role to be assumed only by Infisical. If self-hosting, provide your AWS account number instead.
|
||||
4. (Recommended) <strong>Enable "Require external ID"</strong> and input your **Organization ID** to strengthen security and mitigate the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html).
|
||||
|
||||
<Warning type="warning" title="Security Best Practice: Use External ID to Prevent Confused Deputy Attacks">
|
||||
@@ -362,4 +362,5 @@ Infisical supports two methods for connecting to AWS.
|
||||
</Steps>
|
||||
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
@@ -313,6 +313,13 @@
|
||||
"self-hosting/deployment-options/kubernetes-helm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Linux Package",
|
||||
"pages": [
|
||||
"self-hosting/deployment-options/native/linux-package/installation",
|
||||
"self-hosting/deployment-options/native/linux-package/commands-configuration"
|
||||
]
|
||||
},
|
||||
"self-hosting/guides/upgrading-infisical",
|
||||
"self-hosting/configuration/envars",
|
||||
"self-hosting/configuration/requirements",
|
||||
@@ -329,7 +336,8 @@
|
||||
"pages": [
|
||||
"self-hosting/reference-architectures/aws-ecs",
|
||||
"self-hosting/reference-architectures/linux-deployment-ha",
|
||||
"self-hosting/reference-architectures/on-prem-k8s-ha"
|
||||
"self-hosting/reference-architectures/on-prem-k8s-ha",
|
||||
"self-hosting/reference-architectures/google-cloud-run"
|
||||
]
|
||||
},
|
||||
"self-hosting/ee",
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: "Configurations"
|
||||
description: "Learn how to configure and manage the Infisical Linux package"
|
||||
---
|
||||
|
||||
## Configuration Overview
|
||||
|
||||
All configuration for the Infisical Linux package is managed through a single file called `infisical.rb`, located in the `/etc/infisical` directory.
|
||||
This file defines all necessary settings, including encryption keys, database connections, and environment-specific settings.
|
||||
|
||||
<Info> After making any changes to the `infisical.rb` file, always run `infisical-ctl reconfigure` to apply them. </Info>
|
||||
|
||||
### Example Configuration
|
||||
|
||||
```ruby infisical.rb
|
||||
# Important: Replace these values with secure keys in production
|
||||
infisical_core['ENCRYPTION_KEY'] = '6c1fe4e407b8911c104518103505b218'
|
||||
infisical_core['AUTH_SECRET'] = '5lrMXKKWCVocS/uerPsl7V+TX/aaUaI7iDkgl3tSmLE='
|
||||
|
||||
# Database connection strings
|
||||
infisical_core['DB_CONNECTION_URI'] = 'postgres://<username>:<password>@<host>:5432/<database>'
|
||||
infisical_core['REDIS_URL'] = 'redis://<host>:6379'
|
||||
```
|
||||
|
||||
For a full list of supported configuration variables, refer to the [configuration variables documentation](/self-hosting/configuration/envars).
|
||||
|
||||
## All `infisical-ctl` Commands
|
||||
|
||||
The Infisical Linux package includes the `infisical-ctl` command-line tool, which allows you to manage your deployment.
|
||||
The available commands are listed below.
|
||||
|
||||
| Command | Description |
|
||||
|-----------------------------|-----------------------------------------------------------------------------|
|
||||
| `infisical-ctl reconfigure` | Applies changes from `infisical.rb` and restarts the Infisical services. |
|
||||
| `infisical-ctl start` | Starts the Infisical services. |
|
||||
| `infisical-ctl stop` | Stops all running Infisical services. |
|
||||
| `infisical-ctl status` | Displays the current status of the Infisical services. |
|
||||
| `infisical-ctl tail` | Streams real-time logs from the Infisical application. |
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
title: "Installation"
|
||||
description: "Learn how to deploy Infisical using the Linux package"
|
||||
---
|
||||
|
||||
Infisical can be deployed on Linux virtual machines without the need for containers using our standalone Linux packages.
|
||||
These packages are available in both .deb (for Debian-based systems) and .rpm (for RHEL-based systems) formats.
|
||||
The installation includes the Infisical service, along with a CLI tool (infisical-ctl) to help you manage configurations, startup, and application logging.
|
||||
This approach is ideal for environments where containerization isn't desired, while still providing a lightweight deployment option.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This installation method only provides the Infisical application. You are responsible for configuring both PostgreSQL and Redis, either by using managed services (e.g., AWS RDS, Azure Database, GCP Cloud SQL/Memorystore) or by deploying them manually in your on-prem environment.
|
||||
Please ensure you have the following before beginning installation of Infisical:
|
||||
|
||||
- A Linux server running a Debian/Ubuntu or RHEL-based distribution
|
||||
- A running PostgreSQL database instance (version 14 and up)
|
||||
- A running Redis database instance (versions 6.x or 7.x)
|
||||
|
||||
## Installation Steps
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Install the Infisical Package">
|
||||
Select your Linux distribution to get started. Only AMD64-based systems are supported at this time, ARM support is coming soon.
|
||||
|
||||
<Tabs>
|
||||
|
||||
<Tab title="Debian/Ubuntu">
|
||||
Add the Infisical repository:
|
||||
```bash
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-core/setup.deb.sh' | sudo -E bash
|
||||
```
|
||||
|
||||
Install Infisical:
|
||||
```bash
|
||||
sudo apt-get update && sudo apt-get install -y infisical-core
|
||||
```
|
||||
|
||||
> **Note**: For production use, we recommend locking to a specific version to ensure consistency. [View available versions](https://cloudsmith.io/~infisical/repos/infisical-core/packages/).
|
||||
</Tab>
|
||||
|
||||
<Tab title="RedHat/CentOS/Amazon Linux">
|
||||
Add the Infisical repository:
|
||||
```bash
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-core/setup.rpm.sh' | sudo -E bash
|
||||
```
|
||||
|
||||
Install Infisical:
|
||||
```bash
|
||||
sudo yum install infisical-core
|
||||
```
|
||||
|
||||
> **Note**: For production use, we recommend locking to a specific version to ensure consistency. [View available versions](https://cloudsmith.io/~infisical/repos/infisical-core/packages/).
|
||||
</Tab>
|
||||
|
||||
</Tabs>
|
||||
|
||||
Verify the installation:
|
||||
```bash
|
||||
infisical-ctl help
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Create the Configuration File">
|
||||
Create an `infisical.rb` file at `/etc/infisical`. This file contains your database connection strings and other runtime settings.
|
||||
|
||||
```ruby
|
||||
# Important: Replace with secure values in production
|
||||
infisical_core['ENCRYPTION_KEY'] = '6c1fe4e407b8911c104518103505b218'
|
||||
infisical_core['AUTH_SECRET'] = '5lrMXKKWCVocS/uerPsl7V+TX/aaUaI7iDkgl3tSmLE='
|
||||
|
||||
# Example database connection strings
|
||||
infisical_core['DB_CONNECTION_URI'] = 'postgres://<db-username>:<db-password>@<db-host>:<db-port>/<db-name>'
|
||||
infisical_core['REDIS_URL'] = 'redis://<redis-host>:<redis-port>'
|
||||
```
|
||||
|
||||
See the full list of options in our [configuration documentation](/self-hosting/configuration/envars).
|
||||
</Step>
|
||||
|
||||
<Step title="Start Infisical">
|
||||
1. Start the Infisical service:
|
||||
```bash
|
||||
infisical-ctl reconfigure
|
||||
```
|
||||
The server runs on port `8080` by default (customizable in `infisical.rb`).
|
||||
|
||||
2. Check the service status:
|
||||
```bash
|
||||
infisical-ctl status
|
||||
```
|
||||
|
||||
View the service logs in real-time:
|
||||
```bash
|
||||
infisical-ctl tail
|
||||
```
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Platform Support
|
||||
|
||||
### Microsoft Windows
|
||||
Infisical is built for Linux-based systems. It is not supported on Microsoft Windows, and we do not plan to support it in the near future. For Windows users, consider running Infisical in a virtual machine or WSL2 environment.
|
||||
|
||||
### Unsupported Linux Distributions and Unix-like Systems
|
||||
Infisical is not tested or officially supported on the following:
|
||||
|
||||
- Arch Linux
|
||||
- Fedora
|
||||
- FreeBSD
|
||||
- Gentoo
|
||||
- macOS
|
||||
|
||||
We recommend sticking to officially supported distributions for the best experience.
|
||||
|
||||
## Linux vs Containerized Deployments
|
||||
|
||||
Infisical is a stateless application, which means it can be easily scaled and redeployed without maintaining internal state between instances.
|
||||
|
||||
If your use case requires rolling updates, self-healing, or auto-scaling, we recommend deploying Infisical in a containerized environment such as Kubernetes/OpenShift, or using managed container orchestration services like AWS ECS or Google Cloud Run.
|
||||
These platforms offer built-in capabilities for high availability and help simplify operational overhead for your deployment.
|
||||
@@ -33,21 +33,10 @@ Choose from a number of deployment options listed below to get started.
|
||||
Use our Helm chart to Install Infisical on your Kubernetes cluster.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
{/* <CardGroup cols={2}>
|
||||
<Card
|
||||
title="Native Deployment"
|
||||
<Card
|
||||
title="Linux package"
|
||||
color="#000000"
|
||||
icon="box"
|
||||
href="deployment-options/native/standalone-binary"
|
||||
href="deployment-options/native/linux-package/installation"
|
||||
>
|
||||
Install Infisical on your Debian-based system without containers using our standalone binary.
|
||||
</Card>
|
||||
<Card
|
||||
title="Native Deployment, High Availability"
|
||||
color="#000000"
|
||||
icon="boxes-stacked"
|
||||
href="deployment-options/native/high-availability"
|
||||
>
|
||||
Install Infisical on your Debian-based instances without containers using our standalone binary with high availability out of the box.
|
||||
</Card>
|
||||
</CardGroup> */}
|
||||
Install Infisical on your system without containers using our Linux package.
|
||||
</Card>
|
||||
|
||||
114
docs/self-hosting/reference-architectures/google-cloud-run.mdx
Normal file
114
docs/self-hosting/reference-architectures/google-cloud-run.mdx
Normal file
@@ -0,0 +1,114 @@
|
||||
---
|
||||
title: "Google Cloud Run"
|
||||
description: "Reference architecture for self-hosting Infisical on Google Cloud Run."
|
||||
---
|
||||
|
||||
## Overview
|
||||
This guide outlines a reference architecture for deploying Infisical in a self-hosted configuration using Google Cloud Run.
|
||||
It is intended to provide a scalable, secure, and production-ready baseline for organizations choosing Google Cloud Platform (GCP) as their infrastructure provider.
|
||||
|
||||
## Core Components
|
||||
|
||||
- **Cloud Run:** Infisical service is containerized and deployed as fully managed Cloud Run services.
|
||||
|
||||
- **Cloud SQL:** Infisical uses Postgres as its persistence layer. As such, Cloud SQL for PostgreSQL is used.
|
||||
|
||||
- **MemoryStore for Redis:** To schedule jobs, process audit logs and cache performance, Infisical requires Redis.
|
||||
|
||||
## Securing Infisical's root credential
|
||||
|
||||
- **Secrets Manager:** To secure Infisical’s root credentials (database connection string, encryption key, etc.),
|
||||
we highly recommend that you use Google Secrets Manager and only allow the tasks running Infisical to access them.
|
||||
|
||||
## High Availability and Scalability
|
||||
|
||||
This architecture leverages Google Cloud's managed services to achieve high availability and scalability out of the box:
|
||||
|
||||
**Cloud Run:**
|
||||
|
||||
- Automatically scales the number of container instances up or down based on incoming request volume.
|
||||
- Supports rapid scaling during traffic spikes, ensuring low latency.
|
||||
- Configurable minimum and maximum instances to handle baseline and peak loads.
|
||||
|
||||
**Cloud SQL:**
|
||||
|
||||
- Provides high availability configurations (regional instances with automatic failover) to ensure database uptime.
|
||||
- Automated backups, point-in-time recovery, and maintenance.
|
||||
|
||||
**MemoryStore:**
|
||||
|
||||
- Offers highly available Redis configurations with replication.
|
||||
- Fully managed with automatic scaling and patching.
|
||||
|
||||
**Cloud Load Balancer:**
|
||||
|
||||
- Distributes user traffic across available Cloud Run instances.
|
||||
- Provides SSL termination, global load balancing, and health checks.
|
||||
|
||||
<Info>
|
||||
**Note:** To further improve performance and availability, consider enabling multi-region deployment strategies,
|
||||
regional VPC Connectors, and database replicas for read-heavy workloads.
|
||||
</Info>
|
||||
|
||||
## Configuration
|
||||
|
||||
<Steps>
|
||||
<Step title="Provision Core Infrastructure">
|
||||
**Cloud SQL (PostgreSQL):**
|
||||
- Create a Cloud SQL instance.
|
||||
- Under `Zonal availability`, select the `Multiple zones` option to ensure High Availability.
|
||||
- Configure private IP access.
|
||||
|
||||
**MemoryStore (Redis):**
|
||||
- Deploy a Redis instance.
|
||||
- Configure VPC access.
|
||||
|
||||
</Step>
|
||||
<Step title="Get the Infisical Docker image">
|
||||
Visit [Docker Hub](https://hub.docker.com/r/infisical/infisical/tags) and select a version of Infisical image you would like to deploy.
|
||||
Then, within Cloud Run, paste the URL of the specific Infisical Docker image you would like to use within the `Container image URL` field.
|
||||
|
||||

|
||||
|
||||
Remember to replace `<version>` with the docker image tag of your choice.
|
||||
</Step>
|
||||
<Step title="Set the environment variables">
|
||||
For a minimal installation of Infisical, you must configure the following environment variables:
|
||||
|
||||
```bash
|
||||
ENCRYPTION_KEY=<your_encryption_key>
|
||||
AUTH_SECRET=<your_auth_secret>
|
||||
DB_CONNECTION_URI="<your_db_connection_uri>"
|
||||
SITE_URL="<your_site_url>"
|
||||
REDIS_URL="<your_redis_url>"
|
||||
```
|
||||
[View all available configurations](/self-hosting/configuration/envars).
|
||||
|
||||
You will want to setup Postgres and Redis within Google Cloud Platform to connect to Infisical.
|
||||
|
||||
Once you have added the required environment variables to the `Environment Variables` section within Cloud Run,
|
||||
create the container to get Infisical up and running.
|
||||
|
||||

|
||||
|
||||
<Warning>
|
||||
The above environment variable values are only to be used as an example and should not be used in production
|
||||
</Warning>
|
||||
|
||||
</Step>
|
||||
<Step title="Network Configuration">
|
||||
|
||||
Enable `Connect to a VPC for outbound traffic`: This enables the service to talk to private resources (e.g., a Cloud SQL database, Redis instance on a private IP) inside your Google Cloud VPC network.
|
||||
|
||||
Select `Send traffic directly to a VPC`: It gives lower latency and better performance, but uses more IPs from the subnet.
|
||||
|
||||
<Info>
|
||||
Your Cloud Run revision must be in the same VPC network
|
||||
</Info>
|
||||
|
||||

|
||||
|
||||
Once the container is running, verify the installation by opening your web browser and navigating to the Site URL.
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
@@ -84,6 +84,7 @@ export const eventToNameMap: { [K in EventType]: string } = {
|
||||
[EventType.ADD_PKI_COLLECTION_ITEM]: "Add PKI collection item",
|
||||
[EventType.DELETE_PKI_COLLECTION_ITEM]: "Delete PKI collection item",
|
||||
[EventType.ORG_ADMIN_ACCESS_PROJECT]: "Org admin accessed project",
|
||||
[EventType.ORG_ADMIN_BYPASS_SSO]: "Org admin bypassed SSO enforcement",
|
||||
[EventType.CREATE_CERTIFICATE_TEMPLATE]: "Create certificate template",
|
||||
[EventType.UPDATE_CERTIFICATE_TEMPLATE]: "Update certificate template",
|
||||
[EventType.DELETE_CERTIFICATE_TEMPLATE]: "Delete certificate template",
|
||||
|
||||
@@ -90,6 +90,7 @@ export enum EventType {
|
||||
ADD_PKI_COLLECTION_ITEM = "add-pki-collection-item",
|
||||
DELETE_PKI_COLLECTION_ITEM = "delete-pki-collection-item",
|
||||
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
|
||||
ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso",
|
||||
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
|
||||
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
|
||||
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
|
||||
|
||||
@@ -718,6 +718,11 @@ interface OrgAdminAccessProjectEvent {
|
||||
}; // no metadata yet
|
||||
}
|
||||
|
||||
interface OrgAdminBypassSSOEvent {
|
||||
type: EventType.ORG_ADMIN_BYPASS_SSO;
|
||||
metadata: Record<string, string>; // no metadata yet
|
||||
}
|
||||
|
||||
interface CreateCertificateTemplate {
|
||||
type: EventType.CREATE_CERTIFICATE_TEMPLATE;
|
||||
metadata: {
|
||||
@@ -885,6 +890,7 @@ export type Event =
|
||||
| AddPkiCollectionItem
|
||||
| DeletePkiCollectionItem
|
||||
| OrgAdminAccessProjectEvent
|
||||
| OrgAdminBypassSSOEvent
|
||||
| CreateCertificateTemplate
|
||||
| UpdateCertificateTemplate
|
||||
| GetCertificateTemplate
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useNavigate } from "@tanstack/react-router";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import { Button, DeleteActionModal, Tooltip } from "@app/components/v2";
|
||||
import { LeaveProjectModal } from "@app/components/v2/LeaveProjectModal";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
@@ -142,16 +142,22 @@ export const DeleteProjectSection = () => {
|
||||
<div className="space-x-4">
|
||||
<ProjectPermissionCan I={ProjectPermissionActions.Delete} a={ProjectPermissionSub.Project}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
isLoading={isDeleting}
|
||||
isDisabled={!isAllowed || isDeleting || currentWorkspace?.hasDeleteProtection}
|
||||
colorSchema="danger"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
onClick={() => handlePopUpOpen("deleteWorkspace")}
|
||||
<Tooltip
|
||||
className="max-w-sm"
|
||||
content="This project is protected from deletion. To delete it, disable delete protection first."
|
||||
isDisabled={!currentWorkspace?.hasDeleteProtection}
|
||||
>
|
||||
{`Delete ${currentWorkspace?.name}`}
|
||||
</Button>
|
||||
<Button
|
||||
isLoading={isDeleting}
|
||||
isDisabled={!isAllowed || isDeleting || currentWorkspace?.hasDeleteProtection}
|
||||
colorSchema="danger"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
onClick={() => handlePopUpOpen("deleteWorkspace")}
|
||||
>
|
||||
{`Delete ${currentWorkspace?.name}`}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
{!isOnlyAdminMember && (
|
||||
|
||||
Reference in New Issue
Block a user