feat(infisical-pg): resolved multi integration auth and ip v6 support in ua

This commit is contained in:
Akhil Mohan
2024-01-27 12:38:23 +05:30
parent d90fdac5ce
commit 9f813d72f2
8 changed files with 57 additions and 34 deletions
+3 -1
View File
@@ -88,7 +88,9 @@ export const ormify = <DbOps extends object, Tname extends keyof Tables>(
}, },
create: async (data: Tables[Tname]["insert"], tx?: Knex) => { create: async (data: Tables[Tname]["insert"], tx?: Knex) => {
try { try {
const [res] = await (tx || db)(tableName).insert(data).returning("*"); const [res] = await (tx || db)(tableName)
.insert(data as any)
.returning("*");
return res; return res;
} catch (error) { } catch (error) {
throw new DatabaseError({ error, name: "Create" }); throw new DatabaseError({ error, name: "Create" });
+2 -1
View File
@@ -392,7 +392,8 @@ export const registerRoutes = async (
permissionService, permissionService,
folderDal, folderDal,
integrationDal, integrationDal,
integrationAuthDal integrationAuthDal,
secretQueueService
}); });
const serviceTokenService = serviceTokenServiceFactory({ const serviceTokenService = serviceTokenServiceFactory({
projectEnvDal, projectEnvDal,
@@ -81,14 +81,14 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}) })
.array() .array()
.min(1) .min(1)
.default([{ ipAddress: "0.0.0.0/0" }]), .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]),
accessTokenTrustedIps: z accessTokenTrustedIps: z
.object({ .object({
ipAddress: z.string().trim() ipAddress: z.string().trim()
}) })
.array() .array()
.min(1) .min(1)
.default([{ ipAddress: "0.0.0.0/0" }]), .default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]),
accessTokenTTL: z accessTokenTTL: z
.number() .number()
.int() .int()
@@ -69,7 +69,7 @@ export const tokenServiceFactory = ({ tokenDal, userDal }: TAuthTokenServiceFact
const newToken = await tokenDal.create( const newToken = await tokenDal.create(
{ {
tokenHash, tokenHash,
expiresAt: tkCfg.expiresAt.toUTCString(), expiresAt: tkCfg.expiresAt,
type, type,
userId, userId,
orgId, orgId,
@@ -14,7 +14,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
import { isAtLeastAsPrivileged } from "@app/lib/casl"; import { isAtLeastAsPrivileged } from "@app/lib/casl";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors";
import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr,TIp } from "@app/lib/ip"; import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr, TIp } from "@app/lib/ip";
import { ActorType, AuthTokenType } from "../auth/auth-type"; import { ActorType, AuthTokenType } from "../auth/auth-type";
import { TIdentityDalFactory } from "../identity/identity-dal"; import { TIdentityDalFactory } from "../identity/identity-dal";
@@ -176,7 +176,11 @@ export const identityUaServiceFactory = ({
const plan = await licenseService.getPlan(identityMembershipOrg.orgId); const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map( const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map(
(clientSecretTrustedIp) => { (clientSecretTrustedIp) => {
if (!plan.ipAllowlisting && clientSecretTrustedIp.ipAddress !== "0.0.0.0/0") if (
!plan.ipAllowlisting &&
clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" &&
clientSecretTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({ throw new BadRequestError({
message: message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range." "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
@@ -189,7 +193,11 @@ export const identityUaServiceFactory = ({
} }
); );
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => { const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (!plan.ipAllowlisting && accessTokenTrustedIp.ipAddress !== "0.0.0.0/0") if (
!plan.ipAllowlisting &&
accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" &&
accessTokenTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({ throw new BadRequestError({
message: message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range." "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
@@ -266,7 +274,11 @@ export const identityUaServiceFactory = ({
const plan = await licenseService.getPlan(identityMembershipOrg.orgId); const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps?.map( const reformattedClientSecretTrustedIps = clientSecretTrustedIps?.map(
(clientSecretTrustedIp) => { (clientSecretTrustedIp) => {
if (!plan.ipAllowlisting && clientSecretTrustedIp.ipAddress !== "0.0.0.0/0") if (
!plan.ipAllowlisting &&
clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" &&
clientSecretTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({ throw new BadRequestError({
message: message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range." "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
@@ -279,7 +291,11 @@ export const identityUaServiceFactory = ({
} }
); );
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => { const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (!plan.ipAllowlisting && accessTokenTrustedIp.ipAddress !== "0.0.0.0/0") if (
!plan.ipAllowlisting &&
accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" &&
accessTokenTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({ throw new BadRequestError({
message: message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range." "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
@@ -234,13 +234,7 @@ export const integrationAuthServiceFactory = ({
updateDoc.accessIdCiphertext = accessEncToken.ciphertext; updateDoc.accessIdCiphertext = accessEncToken.ciphertext;
} }
} }
return integrationAuthDal.transaction(async (tx) => { return integrationAuthDal.create(updateDoc);
const doc = await integrationAuthDal.findOne({ projectId, integration }, tx);
if (!doc) {
return integrationAuthDal.create(updateDoc, tx);
}
return integrationAuthDal.updateById(doc.id, updateDoc, tx);
});
}; };
// helper function // helper function
@@ -16,12 +16,14 @@ import {
TDeleteIntegrationDTO, TDeleteIntegrationDTO,
TUpdateIntegrationDTO TUpdateIntegrationDTO
} from "./integration-types"; } from "./integration-types";
import { TSecretQueueFactory } from "../secret/secret-queue";
type TIntegrationServiceFactoryDep = { type TIntegrationServiceFactoryDep = {
integrationDal: TIntegrationDalFactory; integrationDal: TIntegrationDalFactory;
integrationAuthDal: TIntegrationAuthDalFactory; integrationAuthDal: TIntegrationAuthDalFactory;
folderDal: Pick<TSecretFolderDalFactory, "findBySecretPath">; folderDal: Pick<TSecretFolderDalFactory, "findBySecretPath">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
secretQueueService: Pick<TSecretQueueFactory, "syncIntegrations">;
}; };
export type TIntegrationServiceFactory = ReturnType<typeof integrationServiceFactory>; export type TIntegrationServiceFactory = ReturnType<typeof integrationServiceFactory>;
@@ -30,7 +32,8 @@ export const integrationServiceFactory = ({
integrationDal, integrationDal,
integrationAuthDal, integrationAuthDal,
folderDal, folderDal,
permissionService permissionService,
secretQueueService
}: TIntegrationServiceFactoryDep) => { }: TIntegrationServiceFactoryDep) => {
const createIntegration = async ({ const createIntegration = async ({
app, app,
@@ -90,7 +93,11 @@ export const integrationServiceFactory = ({
integration: integrationAuth.integration integration: integrationAuth.integration
}); });
await secretQueueService.syncIntegrations({
environment: sourceEnvironment,
secretPath,
projectId: integrationAuth.projectId
});
return { integration, integrationAuth }; return { integration, integrationAuth };
}; };
+18 -15
View File
@@ -48,20 +48,8 @@ export const secretQueueFactory = ({
webhookDal, webhookDal,
projectEnvDal projectEnvDal
}: TSecretQueueFactoryDep) => { }: TSecretQueueFactoryDep) => {
const syncSecrets = async (dto: TGetSecrets) => { const syncIntegrations = async (dto: TGetSecrets) => {
queueService.queue(QueueName.SecretWebhook, QueueJobs.SecWebhook, dto, { await queueService.queue(QueueName.IntegrationSync, QueueJobs.IntegrationSync, dto, {
jobId: `secret-webhook-${dto.environment}-${dto.projectId}-${dto.secretPath}`,
removeOnFail: { count: 5 },
removeOnComplete: true,
delay: 1000,
attempts: 5,
backoff: {
type: "exponential",
delay: 3000
}
});
queueService.queue(QueueName.IntegrationSync, QueueJobs.IntegrationSync, dto, {
attempts: 5, attempts: 5,
delay: 1000, delay: 1000,
backoff: { backoff: {
@@ -75,6 +63,21 @@ export const secretQueueFactory = ({
}); });
}; };
const syncSecrets = async (dto: TGetSecrets) => {
await queueService.queue(QueueName.SecretWebhook, QueueJobs.SecWebhook, dto, {
jobId: `secret-webhook-${dto.environment}-${dto.projectId}-${dto.secretPath}`,
removeOnFail: { count: 5 },
removeOnComplete: true,
delay: 1000,
attempts: 5,
backoff: {
type: "exponential",
delay: 3000
}
});
await syncIntegrations(dto);
};
const getIntegrationSecrets = async (dto: TGetSecrets & { folderId: string }, key: string) => { const getIntegrationSecrets = async (dto: TGetSecrets & { folderId: string }, key: string) => {
const secrets = await secretDal.findByFolderId(dto.folderId); const secrets = await secretDal.findByFolderId(dto.folderId);
if (!secrets.length) return {}; if (!secrets.length) return {};
@@ -226,5 +229,5 @@ export const secretQueueFactory = ({
await fnTriggerWebhook({ ...job.data, projectEnvDal, webhookDal }); await fnTriggerWebhook({ ...job.data, projectEnvDal, webhookDal });
}); });
return { syncSecrets }; return { syncSecrets, syncIntegrations };
}; };