Merge remote-tracking branch 'origin/main' into misc/add-infisical-specific-otel-metrics

This commit is contained in:
Sheen Capadngan
2025-10-29 21:16:50 +08:00
14 changed files with 203 additions and 55 deletions
@@ -2,7 +2,7 @@ import { Knex } from "knex";
import { dropConstraintIfExists } from "@app/db/migrations/utils/dropConstraintIfExists"; import { dropConstraintIfExists } from "@app/db/migrations/utils/dropConstraintIfExists";
import { AccessScope, TableName } from "../schemas"; import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> { export async function up(knex: Knex): Promise<void> {
const hasParentOrgId = await knex.schema.hasColumn(TableName.Organization, "parentOrgId"); const hasParentOrgId = await knex.schema.hasColumn(TableName.Organization, "parentOrgId");
@@ -18,8 +18,6 @@ export async function up(knex: Knex): Promise<void> {
await dropConstraintIfExists(TableName.Organization, "organizations_slug_unique", knex); await dropConstraintIfExists(TableName.Organization, "organizations_slug_unique", knex);
t.unique(["rootOrgId", "parentOrgId", "slug"]); t.unique(["rootOrgId", "parentOrgId", "slug"]);
}); });
// had to switch to raw for null not distinct
} }
const hasIdentityOrgCol = await knex.schema.hasColumn(TableName.Identity, "orgId"); const hasIdentityOrgCol = await knex.schema.hasColumn(TableName.Identity, "orgId");
@@ -28,24 +26,6 @@ export async function up(knex: Knex): Promise<void> {
t.uuid("orgId"); t.uuid("orgId");
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE"); t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
}); });
await knex.raw(
`
UPDATE ?? AS identity
SET "orgId" = membership."scopeOrgId"
FROM ?? AS membership
WHERE
membership."actorIdentityId" = identity."id"
AND membership."scope" = ?
`,
[TableName.Identity, TableName.Membership, AccessScope.Organization]
);
await knex.raw(`DELETE FROM ?? WHERE "orgId" IS NULL`, [TableName.Identity]);
await knex.schema.alterTable(TableName.Identity, (t) => {
t.uuid("orgId").notNullable().alter();
});
} }
} }
@@ -0,0 +1,48 @@
import { Knex } from "knex";
import { chunkArray } from "@app/lib/fn";
import { AccessScope, TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
await knex.transaction(async (tx) => {
const hasIdentityOrgCol = await tx.schema.hasColumn(TableName.Identity, "orgId");
if (hasIdentityOrgCol) {
const identityMemberships = await tx(TableName.Membership)
.where({
scope: AccessScope.Organization
})
.whereNotNull("actorIdentityId")
.select("actorIdentityId", "scopeOrgId");
const identityToOrgMapping: Record<string, string> = {};
identityMemberships.forEach((el) => {
if (el.actorIdentityId) {
identityToOrgMapping[el.actorIdentityId] = el.scopeOrgId;
}
});
const batchMemberships = chunkArray(identityMemberships, 500);
for await (const membership of batchMemberships) {
const identityIds = membership.map((el) => el.actorIdentityId).filter(Boolean) as string[];
if (identityIds.length) {
const identities = await tx(TableName.Identity).whereIn("id", identityIds).select("*");
await tx(TableName.Identity)
.insert(
identities.map((el) => ({
...el,
orgId: identityToOrgMapping[el.id]
}))
)
.onConflict("id")
.merge();
}
}
}
});
}
export async function down(): Promise<void> {}
const config = { transaction: false };
export { config };
@@ -0,0 +1,22 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
await knex.transaction(async (tx) => {
await tx.schema.alterTable(TableName.IdentityAccessToken, (table) => {
table.dropForeign("identityId");
});
});
}
export async function down(knex: Knex): Promise<void> {
await knex.transaction(async (tx) => {
await tx.schema.alterTable(TableName.IdentityAccessToken, (table) => {
table.foreign("identityId").references("id").inTable(TableName.Identity);
});
});
}
const config = { transaction: false };
export { config };
@@ -0,0 +1,30 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
const MIGRATION_TIMEOUT = 30 * 60 * 1000; // 30 minutes
export async function up(knex: Knex): Promise<void> {
const result = await knex.raw("SHOW statement_timeout");
const originalTimeout = result.rows[0].statement_timeout;
await knex.transaction(async (tx) => {
try {
await tx.raw(`SET statement_timeout = ${MIGRATION_TIMEOUT}`);
const hasIdentityOrgCol = await tx.schema.hasColumn(TableName.Identity, "orgId");
if (hasIdentityOrgCol) {
await tx(TableName.Identity).whereNull("orgId").delete();
await tx.schema.alterTable(TableName.Identity, (t) => {
t.uuid("orgId").notNullable().alter();
});
}
} finally {
await tx.raw(`SET statement_timeout = '${originalTimeout}'`);
}
});
}
export async function down(): Promise<void> {}
const config = { transaction: false };
export { config };
+4 -2
View File
@@ -182,7 +182,8 @@ export const registerKmipSpecRouter = async (server: FastifyZodProvider) => {
algorithm: z.string(), algorithm: z.string(),
isActive: z.boolean(), isActive: z.boolean(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date() updatedAt: z.date(),
kmipMetadata: z.record(z.any()).nullish()
}) })
} }
}, },
@@ -384,7 +385,8 @@ export const registerKmipSpecRouter = async (server: FastifyZodProvider) => {
isActive: z.boolean(), isActive: z.boolean(),
algorithm: z.string(), algorithm: z.string(),
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date() updatedAt: z.date(),
kmipMetadata: z.record(z.any()).nullish()
}) })
.array() .array()
}) })
@@ -341,7 +341,8 @@ export const kmipOperationServiceFactory = ({
algorithm: completeKeyDetails.internalKms.encryptionAlgorithm, algorithm: completeKeyDetails.internalKms.encryptionAlgorithm,
isActive: !key.isDisabled, isActive: !key.isDisabled,
createdAt: key.createdAt, createdAt: key.createdAt,
updatedAt: key.updatedAt updatedAt: key.updatedAt,
kmipMetadata: key.kmipMetadata as Record<string, unknown>
}; };
}; };
@@ -5,5 +5,6 @@ export enum GitLabConnectionMethod {
export enum GitLabAccessTokenType { export enum GitLabAccessTokenType {
Project = "project", Project = "project",
Personal = "personal" Personal = "personal",
Group = "group"
} }
@@ -772,13 +772,14 @@ export const externalMigrationServiceFactory = ({
namespace: string; namespace: string;
mountPath: string; mountPath: string;
}) => { }) => {
const { hasRole } = await permissionService.getOrgPermission( const { hasRole } = await permissionService.getOrgPermission({
actor.type, scope: OrganizationActionScope.Any,
actor.id, actor: actor.type,
actor.orgId, actorId: actor.id,
actor.authMethod, orgId: actor.orgId,
actor.orgId actorAuthMethod: actor.authMethod,
); actorOrgId: actor.orgId
});
if (!hasRole(OrgMembershipRole.Admin)) { if (!hasRole(OrgMembershipRole.Admin)) {
throw new ForbiddenRequestError({ message: "Only admins can get Kubernetes roles" }); throw new ForbiddenRequestError({ message: "Only admins can get Kubernetes roles" });
+2 -1
View File
@@ -112,7 +112,8 @@ export const kmskeyDALFactory = (db: TDbClient) => {
...KmsKeysSchema.parse(entry), ...KmsKeysSchema.parse(entry),
isActive: !entry.isDisabled, isActive: !entry.isDisabled,
algorithm: entry.internalKmsEncryptionAlgorithm, algorithm: entry.internalKmsEncryptionAlgorithm,
version: entry.internalKmsVersion version: entry.internalKmsVersion,
kmipMetadata: entry.kmipMetadata as Record<string, unknown>
})); }));
} catch (error) { } catch (error) {
throw new DatabaseError({ error, name: "Find project cmeks" }); throw new DatabaseError({ error, name: "Find project cmeks" });
Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

+82 -21
View File
@@ -187,31 +187,92 @@ Infisical supports two methods for connecting to GitLab: **OAuth** and **Access
</Step> </Step>
</Steps> </Steps>
</Tab> </Tab>
</Tabs>
## Setup GitLab Access Token Connection in Infisical <Tab title="Group Access Token">
Group access tokens provide access to all projects within a GitLab group, offering group-level control.
<Steps> <Steps>
<Step title="Navigate to App Connections"> <Step title="Navigate to Group Settings">
Navigate to the **App Connections** page in the desired project. Go to your GitLab group and navigate to Settings > Access Tokens. Click **Add new token** to create a new group access token.
![App Connections Tab](/images/app-connections/general/add-connection.png) ![GitLab Group Access Tokens](/images/app-connections/gitlab/gitlab-group-access-token-list.png)
</Step> </Step>
<Step title="Add Connection"> <Step title="Configure Token">
Select the **GitLab Connection** option from the connection options modal. Fill in the token details:
![Select GitLab Connection](/images/app-connections/gitlab/select-gitlab-connection.png) - **Token name**: A descriptive name for the token
</Step> - **Expiration date**: Set an appropriate expiration date
<Step title="Configure Access Token"> - **Select role and scopes**: Depending on your use case, add the required role and one or more of the following scopes:
Select the **Access Token** method, paste your GitLab access token in the provided field, and select the appropriate token type.
![Configure Access Token](/images/app-connections/gitlab/create-gitlab-access-token-connection.png) <Tabs>
<Tab title="Secret Sync">
For Secret Syncs, the required role depends on your sync destination:
- **Project variables**: Requires **Maintainer** role or higher
- **Group variables**: Requires **Owner** role
Click **Connect** to establish the connection. Your token will require the `api` scope.
</Step>
<Step title="Connection Created"> ![GitLab Create Group Token](/images/app-connections/gitlab/gitlab-group-access-token-form-secret-sync.png)
Your **GitLab Connection** is now available for use.
![GitLab Access Token Connection](/images/app-connections/gitlab/gitlab-access-token-connection.png) Click **Create group access token** to create the token.
</Step>
</Steps> <Note>
Use the **Owner** role if you need to sync to group-level variables. The **Maintainer** role is sufficient only for project-level variables.
</Note>
</Tab>
<Tab title="Secret Scanning">
To set up Secret Scanning, the required permissions depend on the data source level:
- **Project-level data source:** Requires **Maintainer** role or higher
- **Group-level data source:** Requires **Owner** role
Your token will require the `api` scope.
![GitLab Create Group Token](/images/app-connections/gitlab/gitlab-group-access-token-form-secret-sync.png)
Click **Create group access token** to create the token.
</Tab>
</Tabs>
<Info>
Group Access Token connections require manual token rotation when your GitLab access token expires or is regenerated. Monitor your connection status and update the token as needed.
</Info>
</Step>
<Step title="Copy Token">
Copy the generated token immediately as it won't be shown again.
![GitLab Group Token Created](/images/app-connections/gitlab/gitlab-group-access-token-created.png)
<Warning>
Keep your access token secure and do not share it. Anyone with access to this token can access all projects within your GitLab group.
</Warning>
</Step>
</Steps>
</Tab>
</Tabs>
## Setup GitLab Access Token Connection in Infisical
<Steps>
<Step title="Navigate to App Connections">
Navigate to the **App Connections** page in the desired project.
![App Connections Tab](/images/app-connections/general/add-connection.png)
</Step>
<Step title="Add Connection">
Select the **GitLab Connection** option from the connection options modal.
![Select GitLab Connection](/images/app-connections/gitlab/select-gitlab-connection.png)
</Step>
<Step title="Configure Access Token">
Select the **Access Token** method, paste your GitLab access token in the provided field, and select the appropriate token type.
![Configure Access Token](/images/app-connections/gitlab/create-gitlab-access-token-connection.png)
Click **Connect** to establish the connection.
</Step>
<Step title="Connection Created">
Your **GitLab Connection** is now available for use.
![GitLab Access Token Connection](/images/app-connections/gitlab/gitlab-access-token-connection.png)
</Step>
</Steps>
</Tab> </Tab>
</Tabs> </Tabs>
@@ -10,5 +10,6 @@ export type TGitLabGroup = {
export enum GitLabAccessTokenType { export enum GitLabAccessTokenType {
Personal = "personal", Personal = "personal",
Project = "project" Project = "project",
Group = "group"
} }