mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 17:27:40 +00:00
Merge branch 'main' into ENG-2633
This commit is contained in:
@@ -234,6 +234,7 @@ export enum EventType {
|
|||||||
GET_PROJECT_KMS_BACKUP = "get-project-kms-backup",
|
GET_PROJECT_KMS_BACKUP = "get-project-kms-backup",
|
||||||
LOAD_PROJECT_KMS_BACKUP = "load-project-kms-backup",
|
LOAD_PROJECT_KMS_BACKUP = "load-project-kms-backup",
|
||||||
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
|
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
|
||||||
|
ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso",
|
||||||
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
|
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
|
||||||
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
|
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
|
||||||
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
|
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
|
||||||
@@ -1907,6 +1908,11 @@ interface OrgAdminAccessProjectEvent {
|
|||||||
}; // no metadata yet
|
}; // no metadata yet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OrgAdminBypassSSOEvent {
|
||||||
|
type: EventType.ORG_ADMIN_BYPASS_SSO;
|
||||||
|
metadata: Record<string, string>; // no metadata yet
|
||||||
|
}
|
||||||
|
|
||||||
interface CreateCertificateTemplateEstConfig {
|
interface CreateCertificateTemplateEstConfig {
|
||||||
type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG;
|
type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG;
|
||||||
metadata: {
|
metadata: {
|
||||||
@@ -2656,6 +2662,7 @@ export type Event =
|
|||||||
| GetProjectKmsBackupEvent
|
| GetProjectKmsBackupEvent
|
||||||
| LoadProjectKmsBackupEvent
|
| LoadProjectKmsBackupEvent
|
||||||
| OrgAdminAccessProjectEvent
|
| OrgAdminAccessProjectEvent
|
||||||
|
| OrgAdminBypassSSOEvent
|
||||||
| CreateCertificateTemplate
|
| CreateCertificateTemplate
|
||||||
| UpdateCertificateTemplate
|
| UpdateCertificateTemplate
|
||||||
| GetCertificateTemplate
|
| GetCertificateTemplate
|
||||||
|
|||||||
@@ -596,7 +596,14 @@ export const registerRoutes = async (
|
|||||||
kmsService
|
kmsService
|
||||||
});
|
});
|
||||||
|
|
||||||
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService, orgDAL, totpService });
|
const loginService = authLoginServiceFactory({
|
||||||
|
userDAL,
|
||||||
|
smtpService,
|
||||||
|
tokenService,
|
||||||
|
orgDAL,
|
||||||
|
totpService,
|
||||||
|
auditLogService
|
||||||
|
});
|
||||||
const passwordService = authPaswordServiceFactory({
|
const passwordService = authPaswordServiceFactory({
|
||||||
tokenService,
|
tokenService,
|
||||||
smtpService,
|
smtpService,
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import jwt from "jsonwebtoken";
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { OrgMembershipRole, TUsers, UserDeviceSchema } from "@app/db/schemas";
|
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 { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { request } from "@app/lib/config/request";
|
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 { getUserPrivateKey } from "@app/lib/crypto/srp";
|
||||||
import { BadRequestError, DatabaseError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
import { BadRequestError, DatabaseError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||||
import { logger } from "@app/lib/logger";
|
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 { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
||||||
|
|
||||||
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
|
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
|
||||||
@@ -28,7 +31,15 @@ import {
|
|||||||
TOauthTokenExchangeDTO,
|
TOauthTokenExchangeDTO,
|
||||||
TVerifyMfaTokenDTO
|
TVerifyMfaTokenDTO
|
||||||
} from "./auth-login-type";
|
} 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 = {
|
type TAuthLoginServiceFactoryDep = {
|
||||||
userDAL: TUserDALFactory;
|
userDAL: TUserDALFactory;
|
||||||
@@ -36,6 +47,7 @@ type TAuthLoginServiceFactoryDep = {
|
|||||||
tokenService: TAuthTokenServiceFactory;
|
tokenService: TAuthTokenServiceFactory;
|
||||||
smtpService: TSmtpService;
|
smtpService: TSmtpService;
|
||||||
totpService: Pick<TTotpServiceFactory, "verifyUserTotp" | "verifyWithUserRecoveryCode">;
|
totpService: Pick<TTotpServiceFactory, "verifyUserTotp" | "verifyWithUserRecoveryCode">;
|
||||||
|
auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>;
|
export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>;
|
||||||
@@ -44,7 +56,8 @@ export const authLoginServiceFactory = ({
|
|||||||
tokenService,
|
tokenService,
|
||||||
smtpService,
|
smtpService,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
totpService
|
totpService,
|
||||||
|
auditLogService
|
||||||
}: TAuthLoginServiceFactoryDep) => {
|
}: TAuthLoginServiceFactoryDep) => {
|
||||||
/*
|
/*
|
||||||
* Private
|
* Private
|
||||||
@@ -412,6 +425,55 @@ export const authLoginServiceFactory = ({
|
|||||||
mfaMethod: decodedToken.mfaMethod
|
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 {
|
return {
|
||||||
...tokens,
|
...tokens,
|
||||||
isMfaEnabled: false
|
isMfaEnabled: false
|
||||||
|
|||||||
@@ -787,13 +787,19 @@ export const kmsServiceFactory = ({
|
|||||||
return projectDataKey;
|
return projectDataKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(
|
||||||
|
error,
|
||||||
|
`getProjectSecretManagerKmsDataKey: Failed to get project data key for [projectId=${projectId}]`
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
} finally {
|
} finally {
|
||||||
await lock?.release();
|
await lock?.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!project.kmsSecretManagerEncryptedDataKey) {
|
if (!project.kmsSecretManagerEncryptedDataKey) {
|
||||||
throw new Error("Missing project data key");
|
throw new BadRequestError({ message: "Missing project data key" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const kmsDecryptor = await decryptWithKmsKey({
|
const kmsDecryptor = await decryptWithKmsKey({
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Knex } from "knex";
|
|||||||
|
|
||||||
import { TDbClient } from "@app/db";
|
import { TDbClient } from "@app/db";
|
||||||
import {
|
import {
|
||||||
|
OrgMembershipRole,
|
||||||
TableName,
|
TableName,
|
||||||
TOrganizations,
|
TOrganizations,
|
||||||
TOrganizationsInsert,
|
TOrganizationsInsert,
|
||||||
@@ -216,9 +217,8 @@ export const orgDALFactory = (db: TDbClient) => {
|
|||||||
|
|
||||||
const findOrgMembersByUsername = async (orgId: string, usernames: string[], tx?: Knex) => {
|
const findOrgMembersByUsername = async (orgId: string, usernames: string[], tx?: Knex) => {
|
||||||
try {
|
try {
|
||||||
const conn = tx || db;
|
const conn = tx || db.replicaNode();
|
||||||
const members = await conn(TableName.OrgMembership)
|
const members = await conn(TableName.OrgMembership)
|
||||||
// .replicaNode()(TableName.OrgMembership)
|
|
||||||
.where(`${TableName.OrgMembership}.orgId`, orgId)
|
.where(`${TableName.OrgMembership}.orgId`, orgId)
|
||||||
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
|
.join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`)
|
||||||
.leftJoin<TUserEncryptionKeys>(
|
.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) => {
|
const findOrgGhostUser = async (orgId: string) => {
|
||||||
try {
|
try {
|
||||||
const member = await db
|
const member = await db
|
||||||
@@ -472,6 +509,7 @@ export const orgDALFactory = (db: TDbClient) => {
|
|||||||
findAllOrgsByUserId,
|
findAllOrgsByUserId,
|
||||||
ghostUserExists,
|
ghostUserExists,
|
||||||
findOrgMembersByUsername,
|
findOrgMembersByUsername,
|
||||||
|
findOrgMembersByRole,
|
||||||
findOrgGhostUser,
|
findOrgGhostUser,
|
||||||
create,
|
create,
|
||||||
updateById,
|
updateById,
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export enum SmtpTemplates {
|
|||||||
SecretRotationFailed = "secretRotationFailed.handlebars",
|
SecretRotationFailed = "secretRotationFailed.handlebars",
|
||||||
ProjectAccessRequest = "projectAccess.handlebars",
|
ProjectAccessRequest = "projectAccess.handlebars",
|
||||||
OrgAdminProjectDirectAccess = "orgAdminProjectGrantAccess.handlebars",
|
OrgAdminProjectDirectAccess = "orgAdminProjectGrantAccess.handlebars",
|
||||||
|
OrgAdminBreakglassAccess = "orgAdminBreakglassAccess.handlebars",
|
||||||
ServiceTokenExpired = "serviceTokenExpired.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>
|
||||||
@@ -313,6 +313,13 @@
|
|||||||
"self-hosting/deployment-options/kubernetes-helm"
|
"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/guides/upgrading-infisical",
|
||||||
"self-hosting/configuration/envars",
|
"self-hosting/configuration/envars",
|
||||||
"self-hosting/configuration/requirements",
|
"self-hosting/configuration/requirements",
|
||||||
|
|||||||
@@ -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.
|
Use our Helm chart to Install Infisical on your Kubernetes cluster.
|
||||||
</Card>
|
</Card>
|
||||||
</CardGroup>
|
</CardGroup>
|
||||||
{/* <CardGroup cols={2}>
|
<Card
|
||||||
<Card
|
title="Linux package"
|
||||||
title="Native Deployment"
|
|
||||||
color="#000000"
|
color="#000000"
|
||||||
icon="box"
|
href="deployment-options/native/linux-package/installation"
|
||||||
href="deployment-options/native/standalone-binary"
|
|
||||||
>
|
>
|
||||||
Install Infisical on your Debian-based system without containers using our standalone binary.
|
Install Infisical on your system without containers using our Linux package.
|
||||||
</Card>
|
</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> */}
|
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ export const eventToNameMap: { [K in EventType]: string } = {
|
|||||||
[EventType.ADD_PKI_COLLECTION_ITEM]: "Add PKI collection item",
|
[EventType.ADD_PKI_COLLECTION_ITEM]: "Add PKI collection item",
|
||||||
[EventType.DELETE_PKI_COLLECTION_ITEM]: "Delete PKI collection item",
|
[EventType.DELETE_PKI_COLLECTION_ITEM]: "Delete PKI collection item",
|
||||||
[EventType.ORG_ADMIN_ACCESS_PROJECT]: "Org admin accessed project",
|
[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.CREATE_CERTIFICATE_TEMPLATE]: "Create certificate template",
|
||||||
[EventType.UPDATE_CERTIFICATE_TEMPLATE]: "Update certificate template",
|
[EventType.UPDATE_CERTIFICATE_TEMPLATE]: "Update certificate template",
|
||||||
[EventType.DELETE_CERTIFICATE_TEMPLATE]: "Delete certificate template",
|
[EventType.DELETE_CERTIFICATE_TEMPLATE]: "Delete certificate template",
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export enum EventType {
|
|||||||
ADD_PKI_COLLECTION_ITEM = "add-pki-collection-item",
|
ADD_PKI_COLLECTION_ITEM = "add-pki-collection-item",
|
||||||
DELETE_PKI_COLLECTION_ITEM = "delete-pki-collection-item",
|
DELETE_PKI_COLLECTION_ITEM = "delete-pki-collection-item",
|
||||||
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
|
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
|
||||||
|
ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso",
|
||||||
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
|
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
|
||||||
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
|
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
|
||||||
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
|
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
|
||||||
|
|||||||
@@ -718,6 +718,11 @@ interface OrgAdminAccessProjectEvent {
|
|||||||
}; // no metadata yet
|
}; // no metadata yet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OrgAdminBypassSSOEvent {
|
||||||
|
type: EventType.ORG_ADMIN_BYPASS_SSO;
|
||||||
|
metadata: Record<string, string>; // no metadata yet
|
||||||
|
}
|
||||||
|
|
||||||
interface CreateCertificateTemplate {
|
interface CreateCertificateTemplate {
|
||||||
type: EventType.CREATE_CERTIFICATE_TEMPLATE;
|
type: EventType.CREATE_CERTIFICATE_TEMPLATE;
|
||||||
metadata: {
|
metadata: {
|
||||||
@@ -885,6 +890,7 @@ export type Event =
|
|||||||
| AddPkiCollectionItem
|
| AddPkiCollectionItem
|
||||||
| DeletePkiCollectionItem
|
| DeletePkiCollectionItem
|
||||||
| OrgAdminAccessProjectEvent
|
| OrgAdminAccessProjectEvent
|
||||||
|
| OrgAdminBypassSSOEvent
|
||||||
| CreateCertificateTemplate
|
| CreateCertificateTemplate
|
||||||
| UpdateCertificateTemplate
|
| UpdateCertificateTemplate
|
||||||
| GetCertificateTemplate
|
| GetCertificateTemplate
|
||||||
|
|||||||
+16
-10
@@ -3,7 +3,7 @@ import { useNavigate } from "@tanstack/react-router";
|
|||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
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 { LeaveProjectModal } from "@app/components/v2/LeaveProjectModal";
|
||||||
import {
|
import {
|
||||||
ProjectPermissionActions,
|
ProjectPermissionActions,
|
||||||
@@ -142,16 +142,22 @@ export const DeleteProjectSection = () => {
|
|||||||
<div className="space-x-4">
|
<div className="space-x-4">
|
||||||
<ProjectPermissionCan I={ProjectPermissionActions.Delete} a={ProjectPermissionSub.Project}>
|
<ProjectPermissionCan I={ProjectPermissionActions.Delete} a={ProjectPermissionSub.Project}>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<Button
|
<Tooltip
|
||||||
isLoading={isDeleting}
|
className="max-w-sm"
|
||||||
isDisabled={!isAllowed || isDeleting || currentWorkspace?.hasDeleteProtection}
|
content="This project is protected from deletion. To delete it, disable delete protection first."
|
||||||
colorSchema="danger"
|
isDisabled={!currentWorkspace?.hasDeleteProtection}
|
||||||
variant="outline_bg"
|
|
||||||
type="submit"
|
|
||||||
onClick={() => handlePopUpOpen("deleteWorkspace")}
|
|
||||||
>
|
>
|
||||||
{`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>
|
</ProjectPermissionCan>
|
||||||
{!isOnlyAdminMember && (
|
{!isOnlyAdminMember && (
|
||||||
|
|||||||
Reference in New Issue
Block a user