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

This commit is contained in:
Akhil Mohan
2024-01-15 14:10:54 +05:30
parent d90fdac5ce
commit 9f813d72f2
8 changed files with 57 additions and 34 deletions

View File

@@ -88,7 +88,9 @@ export const ormify = <DbOps extends object, Tname extends keyof Tables>(
},
create: async (data: Tables[Tname]["insert"], tx?: Knex) => {
try {
const [res] = await (tx || db)(tableName).insert(data).returning("*");
const [res] = await (tx || db)(tableName)
.insert(data as any)
.returning("*");
return res;
} catch (error) {
throw new DatabaseError({ error, name: "Create" });

View File

@@ -392,7 +392,8 @@ export const registerRoutes = async (
permissionService,
folderDal,
integrationDal,
integrationAuthDal
integrationAuthDal,
secretQueueService
});
const serviceTokenService = serviceTokenServiceFactory({
projectEnvDal,

View File

@@ -81,14 +81,14 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
})
.array()
.min(1)
.default([{ ipAddress: "0.0.0.0/0" }]),
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]),
accessTokenTrustedIps: z
.object({
ipAddress: z.string().trim()
})
.array()
.min(1)
.default([{ ipAddress: "0.0.0.0/0" }]),
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]),
accessTokenTTL: z
.number()
.int()

View File

@@ -69,7 +69,7 @@ export const tokenServiceFactory = ({ tokenDal, userDal }: TAuthTokenServiceFact
const newToken = await tokenDal.create(
{
tokenHash,
expiresAt: tkCfg.expiresAt.toUTCString(),
expiresAt: tkCfg.expiresAt,
type,
userId,
orgId,

View File

@@ -14,7 +14,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
import { isAtLeastAsPrivileged } from "@app/lib/casl";
import { getConfig } from "@app/lib/config/env";
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 { TIdentityDalFactory } from "../identity/identity-dal";
@@ -176,7 +176,11 @@ export const identityUaServiceFactory = ({
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map(
(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({
message:
"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) => {
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({
message:
"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 reformattedClientSecretTrustedIps = clientSecretTrustedIps?.map(
(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({
message:
"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) => {
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({
message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."

View File

@@ -234,13 +234,7 @@ export const integrationAuthServiceFactory = ({
updateDoc.accessIdCiphertext = accessEncToken.ciphertext;
}
}
return integrationAuthDal.transaction(async (tx) => {
const doc = await integrationAuthDal.findOne({ projectId, integration }, tx);
if (!doc) {
return integrationAuthDal.create(updateDoc, tx);
}
return integrationAuthDal.updateById(doc.id, updateDoc, tx);
});
return integrationAuthDal.create(updateDoc);
};
// helper function

View File

@@ -16,12 +16,14 @@ import {
TDeleteIntegrationDTO,
TUpdateIntegrationDTO
} from "./integration-types";
import { TSecretQueueFactory } from "../secret/secret-queue";
type TIntegrationServiceFactoryDep = {
integrationDal: TIntegrationDalFactory;
integrationAuthDal: TIntegrationAuthDalFactory;
folderDal: Pick<TSecretFolderDalFactory, "findBySecretPath">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
secretQueueService: Pick<TSecretQueueFactory, "syncIntegrations">;
};
export type TIntegrationServiceFactory = ReturnType<typeof integrationServiceFactory>;
@@ -30,7 +32,8 @@ export const integrationServiceFactory = ({
integrationDal,
integrationAuthDal,
folderDal,
permissionService
permissionService,
secretQueueService
}: TIntegrationServiceFactoryDep) => {
const createIntegration = async ({
app,
@@ -90,7 +93,11 @@ export const integrationServiceFactory = ({
integration: integrationAuth.integration
});
await secretQueueService.syncIntegrations({
environment: sourceEnvironment,
secretPath,
projectId: integrationAuth.projectId
});
return { integration, integrationAuth };
};

View File

@@ -48,20 +48,8 @@ export const secretQueueFactory = ({
webhookDal,
projectEnvDal
}: TSecretQueueFactoryDep) => {
const syncSecrets = async (dto: TGetSecrets) => {
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
}
});
queueService.queue(QueueName.IntegrationSync, QueueJobs.IntegrationSync, dto, {
const syncIntegrations = async (dto: TGetSecrets) => {
await queueService.queue(QueueName.IntegrationSync, QueueJobs.IntegrationSync, dto, {
attempts: 5,
delay: 1000,
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 secrets = await secretDal.findByFolderId(dto.folderId);
if (!secrets.length) return {};
@@ -226,5 +229,5 @@ export const secretQueueFactory = ({
await fnTriggerWebhook({ ...job.data, projectEnvDal, webhookDal });
});
return { syncSecrets };
return { syncSecrets, syncIntegrations };
};