mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 07:30:20 +00:00
Merge pull request #2606 from Infisical/daniel/multiple-auth-methods
feat: multiple auth methods for identities
This commit is contained in:
@@ -34,7 +34,7 @@ describe("Identity v1", async () => {
|
||||
test("Create identity", async () => {
|
||||
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
||||
expect(newIdentity.name).toBe("mac1");
|
||||
expect(newIdentity.authMethod).toBeNull();
|
||||
expect(newIdentity.authMethods).toEqual([]);
|
||||
|
||||
await deleteIdentity(newIdentity.id);
|
||||
});
|
||||
@@ -42,7 +42,7 @@ describe("Identity v1", async () => {
|
||||
test("Update identity", async () => {
|
||||
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
||||
expect(newIdentity.name).toBe("mac1");
|
||||
expect(newIdentity.authMethod).toBeNull();
|
||||
expect(newIdentity.authMethods).toEqual([]);
|
||||
|
||||
const updatedIdentity = await testServer.inject({
|
||||
method: "PATCH",
|
||||
|
||||
Generated
+1
-1
@@ -51,7 +51,7 @@
|
||||
"connect-redis": "^7.1.1",
|
||||
"cron": "^3.1.7",
|
||||
"dotenv": "^16.4.1",
|
||||
"fastify": "^4.26.0",
|
||||
"fastify": "^4.28.1",
|
||||
"fastify-plugin": "^4.5.1",
|
||||
"google-auth-library": "^9.9.0",
|
||||
"googleapis": "^137.1.0",
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"test:e2e-watch": "vitest -c vitest.e2e.config.ts --bail=1",
|
||||
"test:e2e-coverage": "vitest run --coverage -c vitest.e2e.config.ts",
|
||||
"generate:component": "tsx ./scripts/create-backend-file.ts",
|
||||
"generate:schema": "tsx ./scripts/generate-schema-types.ts",
|
||||
"generate:schema": "tsx ./scripts/generate-schema-types.ts && eslint --fix --ext ts ./src/db/schemas",
|
||||
"auditlog-migration:latest": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:latest",
|
||||
"auditlog-migration:up": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:up",
|
||||
"auditlog-migration:down": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:down",
|
||||
@@ -156,7 +156,7 @@
|
||||
"connect-redis": "^7.1.1",
|
||||
"cron": "^3.1.7",
|
||||
"dotenv": "^16.4.1",
|
||||
"fastify": "^4.26.0",
|
||||
"fastify": "^4.28.1",
|
||||
"fastify-plugin": "^4.5.1",
|
||||
"google-auth-library": "^9.9.0",
|
||||
"googleapis": "^137.1.0",
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
const BATCH_SIZE = 10_000;
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const hasAuthMethodColumnAccessToken = await knex.schema.hasColumn(TableName.IdentityAccessToken, "authMethod");
|
||||
|
||||
if (!hasAuthMethodColumnAccessToken) {
|
||||
await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => {
|
||||
t.string("authMethod").nullable();
|
||||
});
|
||||
|
||||
let nullableAccessTokens = await knex(TableName.IdentityAccessToken).whereNull("authMethod").limit(BATCH_SIZE);
|
||||
let totalUpdated = 0;
|
||||
|
||||
do {
|
||||
const batchIds = nullableAccessTokens.map((token) => token.id);
|
||||
|
||||
// ! Update the auth method column in batches for the current batch
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await knex(TableName.IdentityAccessToken)
|
||||
.whereIn("id", batchIds)
|
||||
.update({
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore because generate schema happens after this
|
||||
authMethod: knex(TableName.Identity)
|
||||
.select("authMethod")
|
||||
.whereRaw(`${TableName.IdentityAccessToken}."identityId" = ${TableName.Identity}.id`)
|
||||
.whereNotNull("authMethod")
|
||||
.first()
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
nullableAccessTokens = await knex(TableName.IdentityAccessToken).whereNull("authMethod").limit(BATCH_SIZE);
|
||||
|
||||
totalUpdated += batchIds.length;
|
||||
console.log(`Updated ${batchIds.length} access tokens in batch <> Total updated: ${totalUpdated}`);
|
||||
} while (nullableAccessTokens.length > 0);
|
||||
|
||||
// ! We delete all access tokens where the identity has no auth method set!
|
||||
// ! Which means un-configured identities that for some reason have access tokens, will have their access tokens deleted.
|
||||
await knex(TableName.IdentityAccessToken)
|
||||
.whereNotExists((queryBuilder) => {
|
||||
void queryBuilder
|
||||
.select("id")
|
||||
.from(TableName.Identity)
|
||||
.whereRaw(`${TableName.IdentityAccessToken}."identityId" = ${TableName.Identity}.id`)
|
||||
.whereNotNull("authMethod");
|
||||
})
|
||||
.delete();
|
||||
|
||||
// Finally we set the authMethod to notNullable after populating the column.
|
||||
// This will fail if the data is not populated correctly, so it's safe.
|
||||
await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => {
|
||||
t.string("authMethod").notNullable().alter();
|
||||
});
|
||||
}
|
||||
|
||||
// ! We aren't dropping the authMethod column from the Identity itself, because we wan't to be able to easily rollback for the time being.
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
const hasAuthMethodColumnAccessToken = await knex.schema.hasColumn(TableName.IdentityAccessToken, "authMethod");
|
||||
|
||||
if (hasAuthMethodColumnAccessToken) {
|
||||
await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => {
|
||||
t.dropColumn("authMethod");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,8 @@ export const IdentityAccessTokensSchema = z.object({
|
||||
identityId: z.string().uuid(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
name: z.string().nullable().optional()
|
||||
name: z.string().nullable().optional(),
|
||||
authMethod: z.string()
|
||||
});
|
||||
|
||||
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
||||
|
||||
@@ -189,7 +189,7 @@ export enum ProjectUpgradeStatus {
|
||||
|
||||
export enum IdentityAuthMethod {
|
||||
TOKEN_AUTH = "token-auth",
|
||||
Univeral = "universal-auth",
|
||||
UNIVERSAL_AUTH = "universal-auth",
|
||||
KUBERNETES_AUTH = "kubernetes-auth",
|
||||
GCP_AUTH = "gcp-auth",
|
||||
AWS_AUTH = "aws-auth",
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function seed(knex: Knex): Promise<void> {
|
||||
// @ts-ignore
|
||||
id: seedData1.machineIdentity.id,
|
||||
name: seedData1.machineIdentity.name,
|
||||
authMethod: IdentityAuthMethod.Univeral
|
||||
authMethod: IdentityAuthMethod.UNIVERSAL_AUTH
|
||||
}
|
||||
]);
|
||||
const identityUa = await knex(TableName.IdentityUniversalAuth)
|
||||
|
||||
@@ -1087,7 +1087,6 @@ export const registerRoutes = async (
|
||||
|
||||
const identityTokenAuthService = identityTokenAuthServiceFactory({
|
||||
identityTokenAuthDAL,
|
||||
identityDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
permissionService,
|
||||
@@ -1096,7 +1095,6 @@ export const registerRoutes = async (
|
||||
const identityUaService = identityUaServiceFactory({
|
||||
identityOrgMembershipDAL,
|
||||
permissionService,
|
||||
identityDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityUaClientSecretDAL,
|
||||
identityUaDAL,
|
||||
@@ -1106,7 +1104,6 @@ export const registerRoutes = async (
|
||||
identityKubernetesAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityDAL,
|
||||
orgBotDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
@@ -1115,7 +1112,6 @@ export const registerRoutes = async (
|
||||
identityGcpAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
});
|
||||
@@ -1124,7 +1120,6 @@ export const registerRoutes = async (
|
||||
identityAccessTokenDAL,
|
||||
identityAwsAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityDAL,
|
||||
licenseService,
|
||||
permissionService
|
||||
});
|
||||
@@ -1133,7 +1128,6 @@ export const registerRoutes = async (
|
||||
identityAzureAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
});
|
||||
@@ -1142,7 +1136,6 @@ export const registerRoutes = async (
|
||||
identityOidcAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityDAL,
|
||||
permissionService,
|
||||
licenseService,
|
||||
orgBotDAL
|
||||
|
||||
@@ -37,7 +37,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
identity: IdentitiesSchema
|
||||
identity: IdentitiesSchema.extend({
|
||||
authMethods: z.array(z.string())
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
@@ -216,7 +218,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
permissions: true,
|
||||
description: true
|
||||
}).optional(),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, authMethod: true })
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -261,7 +265,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
permissions: true,
|
||||
description: true
|
||||
}).optional(),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, authMethod: true })
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
})
|
||||
}).array(),
|
||||
totalCount: z.number()
|
||||
})
|
||||
@@ -319,7 +325,9 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, authMethod: true }),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
}),
|
||||
project: SanitizedProjectSchema.pick({ name: true, id: true })
|
||||
})
|
||||
)
|
||||
|
||||
@@ -58,7 +58,9 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
|
||||
permissions: true,
|
||||
description: true
|
||||
}).optional(),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, authMethod: true })
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
})
|
||||
})
|
||||
).array(),
|
||||
totalCount: z.number()
|
||||
|
||||
@@ -264,7 +264,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, authMethod: true }),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
}),
|
||||
project: SanitizedProjectSchema.pick({ name: true, id: true })
|
||||
})
|
||||
.array(),
|
||||
@@ -285,6 +287,7 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
orderDirection: req.query.orderDirection,
|
||||
search: req.query.search
|
||||
});
|
||||
|
||||
return { identityMemberships, totalCount };
|
||||
}
|
||||
});
|
||||
@@ -328,7 +331,9 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, authMethod: true }),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
}),
|
||||
project: SanitizedProjectSchema.pick({ name: true, id: true })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { IdentityAuthMethod, TableName, TIdentityAccessTokens } from "@app/db/schemas";
|
||||
import { TableName, TIdentityAccessTokens } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
||||
import { logger } from "@app/lib/logger";
|
||||
@@ -17,54 +17,27 @@ export const identityAccessTokenDALFactory = (db: TDbClient) => {
|
||||
const doc = await (tx || db.replicaNode())(TableName.IdentityAccessToken)
|
||||
.where(filter)
|
||||
.join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityAccessToken}.identityId`)
|
||||
.leftJoin(TableName.IdentityUaClientSecret, (qb) => {
|
||||
qb.on(`${TableName.Identity}.authMethod`, db.raw("?", [IdentityAuthMethod.Univeral])).andOn(
|
||||
`${TableName.IdentityAccessToken}.identityUAClientSecretId`,
|
||||
`${TableName.IdentityUaClientSecret}.id`
|
||||
);
|
||||
})
|
||||
.leftJoin(TableName.IdentityUniversalAuth, (qb) => {
|
||||
qb.on(`${TableName.Identity}.authMethod`, db.raw("?", [IdentityAuthMethod.Univeral])).andOn(
|
||||
`${TableName.IdentityUaClientSecret}.identityUAId`,
|
||||
`${TableName.IdentityUniversalAuth}.id`
|
||||
);
|
||||
})
|
||||
.leftJoin(TableName.IdentityGcpAuth, (qb) => {
|
||||
qb.on(`${TableName.Identity}.authMethod`, db.raw("?", [IdentityAuthMethod.GCP_AUTH])).andOn(
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityGcpAuth}.identityId`
|
||||
);
|
||||
})
|
||||
.leftJoin(TableName.IdentityAwsAuth, (qb) => {
|
||||
qb.on(`${TableName.Identity}.authMethod`, db.raw("?", [IdentityAuthMethod.AWS_AUTH])).andOn(
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityAwsAuth}.identityId`
|
||||
);
|
||||
})
|
||||
.leftJoin(TableName.IdentityAzureAuth, (qb) => {
|
||||
qb.on(`${TableName.Identity}.authMethod`, db.raw("?", [IdentityAuthMethod.AZURE_AUTH])).andOn(
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityAzureAuth}.identityId`
|
||||
);
|
||||
})
|
||||
.leftJoin(TableName.IdentityKubernetesAuth, (qb) => {
|
||||
qb.on(`${TableName.Identity}.authMethod`, db.raw("?", [IdentityAuthMethod.KUBERNETES_AUTH])).andOn(
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityKubernetesAuth}.identityId`
|
||||
);
|
||||
})
|
||||
.leftJoin(TableName.IdentityOidcAuth, (qb) => {
|
||||
qb.on(`${TableName.Identity}.authMethod`, db.raw("?", [IdentityAuthMethod.OIDC_AUTH])).andOn(
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityOidcAuth}.identityId`
|
||||
);
|
||||
})
|
||||
.leftJoin(TableName.IdentityTokenAuth, (qb) => {
|
||||
qb.on(`${TableName.Identity}.authMethod`, db.raw("?", [IdentityAuthMethod.TOKEN_AUTH])).andOn(
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityTokenAuth}.identityId`
|
||||
);
|
||||
})
|
||||
.leftJoin(
|
||||
TableName.IdentityUaClientSecret,
|
||||
`${TableName.IdentityAccessToken}.identityUAClientSecretId`,
|
||||
`${TableName.IdentityUaClientSecret}.id`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.IdentityUniversalAuth,
|
||||
`${TableName.IdentityUaClientSecret}.identityUAId`,
|
||||
`${TableName.IdentityUniversalAuth}.id`
|
||||
)
|
||||
.leftJoin(TableName.IdentityGcpAuth, `${TableName.Identity}.id`, `${TableName.IdentityGcpAuth}.identityId`)
|
||||
.leftJoin(TableName.IdentityAwsAuth, `${TableName.Identity}.id`, `${TableName.IdentityAwsAuth}.identityId`)
|
||||
.leftJoin(TableName.IdentityAzureAuth, `${TableName.Identity}.id`, `${TableName.IdentityAzureAuth}.identityId`)
|
||||
.leftJoin(
|
||||
TableName.IdentityKubernetesAuth,
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityKubernetesAuth}.identityId`
|
||||
)
|
||||
.leftJoin(TableName.IdentityOidcAuth, `${TableName.Identity}.id`, `${TableName.IdentityOidcAuth}.identityId`)
|
||||
.leftJoin(TableName.IdentityTokenAuth, `${TableName.Identity}.id`, `${TableName.IdentityTokenAuth}.identityId`)
|
||||
|
||||
.select(selectAllTableCols(TableName.IdentityAccessToken))
|
||||
.select(
|
||||
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityUniversalAuth).as("accessTokenTrustedIpsUa"),
|
||||
@@ -82,14 +55,13 @@ export const identityAccessTokenDALFactory = (db: TDbClient) => {
|
||||
|
||||
return {
|
||||
...doc,
|
||||
accessTokenTrustedIps:
|
||||
doc.accessTokenTrustedIpsUa ||
|
||||
doc.accessTokenTrustedIpsGcp ||
|
||||
doc.accessTokenTrustedIpsAws ||
|
||||
doc.accessTokenTrustedIpsAzure ||
|
||||
doc.accessTokenTrustedIpsK8s ||
|
||||
doc.accessTokenTrustedIpsOidc ||
|
||||
doc.accessTokenTrustedIpsToken
|
||||
trustedIpsUniversalAuth: doc.accessTokenTrustedIpsUa,
|
||||
trustedIpsGcpAuth: doc.accessTokenTrustedIpsGcp,
|
||||
trustedIpsAwsAuth: doc.accessTokenTrustedIpsAws,
|
||||
trustedIpsAzureAuth: doc.accessTokenTrustedIpsAzure,
|
||||
trustedIpsKubernetesAuth: doc.accessTokenTrustedIpsK8s,
|
||||
trustedIpsOidcAuth: doc.accessTokenTrustedIpsOidc,
|
||||
trustedIpsAccessTokenAuth: doc.accessTokenTrustedIpsToken
|
||||
};
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "IdAccessTokenFindOne" });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import jwt, { JwtPayload } from "jsonwebtoken";
|
||||
|
||||
import { TableName, TIdentityAccessTokens } from "@app/db/schemas";
|
||||
import { IdentityAuthMethod, TableName, TIdentityAccessTokens } from "@app/db/schemas";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip";
|
||||
@@ -164,10 +164,22 @@ export const identityAccessTokenServiceFactory = ({
|
||||
message: "Failed to authorize revoked access token, access token is revoked"
|
||||
});
|
||||
|
||||
if (ipAddress && identityAccessToken) {
|
||||
const trustedIpsMap: Record<IdentityAuthMethod, unknown> = {
|
||||
[IdentityAuthMethod.UNIVERSAL_AUTH]: identityAccessToken.trustedIpsUniversalAuth,
|
||||
[IdentityAuthMethod.GCP_AUTH]: identityAccessToken.trustedIpsGcpAuth,
|
||||
[IdentityAuthMethod.AWS_AUTH]: identityAccessToken.trustedIpsAwsAuth,
|
||||
[IdentityAuthMethod.AZURE_AUTH]: identityAccessToken.trustedIpsAzureAuth,
|
||||
[IdentityAuthMethod.KUBERNETES_AUTH]: identityAccessToken.trustedIpsKubernetesAuth,
|
||||
[IdentityAuthMethod.OIDC_AUTH]: identityAccessToken.trustedIpsOidcAuth,
|
||||
[IdentityAuthMethod.TOKEN_AUTH]: identityAccessToken.trustedIpsAccessTokenAuth
|
||||
};
|
||||
|
||||
const trustedIps = trustedIpsMap[identityAccessToken.authMethod as IdentityAuthMethod];
|
||||
|
||||
if (ipAddress) {
|
||||
checkIPAgainstBlocklist({
|
||||
ipAddress,
|
||||
trustedIps: identityAccessToken?.accessTokenTrustedIps as TIp[]
|
||||
trustedIps: trustedIps as TIp[]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedErro
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
import { TIdentityDALFactory } from "../identity/identity-dal";
|
||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
|
||||
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
|
||||
@@ -33,7 +32,6 @@ type TIdentityAwsAuthServiceFactoryDep = {
|
||||
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create">;
|
||||
identityAwsAuthDAL: Pick<TIdentityAwsAuthDALFactory, "findOne" | "transaction" | "create" | "updateById" | "delete">;
|
||||
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
|
||||
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||
};
|
||||
@@ -44,7 +42,6 @@ export const identityAwsAuthServiceFactory = ({
|
||||
identityAccessTokenDAL,
|
||||
identityAwsAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityDAL,
|
||||
licenseService,
|
||||
permissionService
|
||||
}: TIdentityAwsAuthServiceFactoryDep) => {
|
||||
@@ -113,7 +110,8 @@ export const identityAwsAuthServiceFactory = ({
|
||||
accessTokenTTL: identityAwsAuth.accessTokenTTL,
|
||||
accessTokenMaxTTL: identityAwsAuth.accessTokenMaxTTL,
|
||||
accessTokenNumUses: 0,
|
||||
accessTokenNumUsesLimit: identityAwsAuth.accessTokenNumUsesLimit
|
||||
accessTokenNumUsesLimit: identityAwsAuth.accessTokenNumUsesLimit,
|
||||
authMethod: IdentityAuthMethod.AWS_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
@@ -155,10 +153,12 @@ export const identityAwsAuthServiceFactory = ({
|
||||
}: TAttachAwsAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
|
||||
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add AWS Auth to already configured identity"
|
||||
});
|
||||
}
|
||||
|
||||
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
|
||||
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
|
||||
@@ -206,13 +206,6 @@ export const identityAwsAuthServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await identityDAL.updateById(
|
||||
identityMembershipOrg.identityId,
|
||||
{
|
||||
authMethod: IdentityAuthMethod.AWS_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
return doc;
|
||||
});
|
||||
return { ...identityAwsAuth, orgId: identityMembershipOrg.orgId };
|
||||
@@ -234,10 +227,12 @@ export const identityAwsAuthServiceFactory = ({
|
||||
}: TUpdateAwsAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH)
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update AWS Auth"
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
|
||||
throw new NotFoundError({
|
||||
message: "The identity does not have AWS Auth attached"
|
||||
});
|
||||
}
|
||||
|
||||
const identityAwsAuth = await identityAwsAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -293,10 +288,12 @@ export const identityAwsAuthServiceFactory = ({
|
||||
const getAwsAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAwsAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have AWS Auth attached"
|
||||
});
|
||||
}
|
||||
|
||||
const awsIdentityAuth = await identityAwsAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -320,10 +317,11 @@ export const identityAwsAuthServiceFactory = ({
|
||||
}: TRevokeAwsAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AWS_AUTH)
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AWS_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have aws auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -348,7 +346,6 @@ export const identityAwsAuthServiceFactory = ({
|
||||
|
||||
const revokedIdentityAwsAuth = await identityAwsAuthDAL.transaction(async (tx) => {
|
||||
const deletedAwsAuth = await identityAwsAuthDAL.delete({ identityId }, tx);
|
||||
await identityDAL.updateById(identityId, { authMethod: null }, tx);
|
||||
return { ...deletedAwsAuth?.[0], orgId: identityMembershipOrg.orgId };
|
||||
});
|
||||
return revokedIdentityAwsAuth;
|
||||
|
||||
@@ -11,7 +11,6 @@ import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedErro
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
import { TIdentityDALFactory } from "../identity/identity-dal";
|
||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
|
||||
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
|
||||
@@ -32,7 +31,6 @@ type TIdentityAzureAuthServiceFactoryDep = {
|
||||
>;
|
||||
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
|
||||
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create">;
|
||||
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
};
|
||||
@@ -43,7 +41,6 @@ export const identityAzureAuthServiceFactory = ({
|
||||
identityAzureAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
}: TIdentityAzureAuthServiceFactoryDep) => {
|
||||
@@ -84,7 +81,8 @@ export const identityAzureAuthServiceFactory = ({
|
||||
accessTokenTTL: identityAzureAuth.accessTokenTTL,
|
||||
accessTokenMaxTTL: identityAzureAuth.accessTokenMaxTTL,
|
||||
accessTokenNumUses: 0,
|
||||
accessTokenNumUsesLimit: identityAzureAuth.accessTokenNumUsesLimit
|
||||
accessTokenNumUsesLimit: identityAzureAuth.accessTokenNumUsesLimit,
|
||||
authMethod: IdentityAuthMethod.AZURE_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
@@ -126,11 +124,12 @@ export const identityAzureAuthServiceFactory = ({
|
||||
}: TAttachAzureAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
|
||||
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add Azure Auth to already configured identity"
|
||||
});
|
||||
|
||||
}
|
||||
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
|
||||
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
|
||||
}
|
||||
@@ -176,13 +175,7 @@ export const identityAzureAuthServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await identityDAL.updateById(
|
||||
identityMembershipOrg.identityId,
|
||||
{
|
||||
authMethod: IdentityAuthMethod.AZURE_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
|
||||
return doc;
|
||||
});
|
||||
return { ...identityAzureAuth, orgId: identityMembershipOrg.orgId };
|
||||
@@ -204,10 +197,11 @@ export const identityAzureAuthServiceFactory = ({
|
||||
}: TUpdateAzureAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH)
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update Azure Auth"
|
||||
});
|
||||
}
|
||||
|
||||
const identityGcpAuth = await identityAzureAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -266,10 +260,11 @@ export const identityAzureAuthServiceFactory = ({
|
||||
const getAzureAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAzureAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH)
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Azure Auth attached"
|
||||
});
|
||||
}
|
||||
|
||||
const identityAzureAuth = await identityAzureAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -294,10 +289,11 @@ export const identityAzureAuthServiceFactory = ({
|
||||
}: TRevokeAzureAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.AZURE_AUTH)
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.AZURE_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have azure auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -321,7 +317,6 @@ export const identityAzureAuthServiceFactory = ({
|
||||
|
||||
const revokedIdentityAzureAuth = await identityAzureAuthDAL.transaction(async (tx) => {
|
||||
const deletedAzureAuth = await identityAzureAuthDAL.delete({ identityId }, tx);
|
||||
await identityDAL.updateById(identityId, { authMethod: null }, tx);
|
||||
return { ...deletedAzureAuth?.[0], orgId: identityMembershipOrg.orgId };
|
||||
});
|
||||
return revokedIdentityAzureAuth;
|
||||
|
||||
@@ -11,7 +11,6 @@ import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedErro
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
import { TIdentityDALFactory } from "../identity/identity-dal";
|
||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
|
||||
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
|
||||
@@ -30,7 +29,6 @@ type TIdentityGcpAuthServiceFactoryDep = {
|
||||
identityGcpAuthDAL: Pick<TIdentityGcpAuthDALFactory, "findOne" | "transaction" | "create" | "updateById" | "delete">;
|
||||
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
|
||||
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create">;
|
||||
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
};
|
||||
@@ -41,7 +39,6 @@ export const identityGcpAuthServiceFactory = ({
|
||||
identityGcpAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
}: TIdentityGcpAuthServiceFactoryDep) => {
|
||||
@@ -125,7 +122,8 @@ export const identityGcpAuthServiceFactory = ({
|
||||
accessTokenTTL: identityGcpAuth.accessTokenTTL,
|
||||
accessTokenMaxTTL: identityGcpAuth.accessTokenMaxTTL,
|
||||
accessTokenNumUses: 0,
|
||||
accessTokenNumUsesLimit: identityGcpAuth.accessTokenNumUsesLimit
|
||||
accessTokenNumUsesLimit: identityGcpAuth.accessTokenNumUsesLimit,
|
||||
authMethod: IdentityAuthMethod.GCP_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
@@ -168,10 +166,12 @@ export const identityGcpAuthServiceFactory = ({
|
||||
}: TAttachGcpAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
|
||||
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add GCP Auth to already configured identity"
|
||||
});
|
||||
}
|
||||
|
||||
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
|
||||
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
|
||||
@@ -219,13 +219,6 @@ export const identityGcpAuthServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await identityDAL.updateById(
|
||||
identityMembershipOrg.identityId,
|
||||
{
|
||||
authMethod: IdentityAuthMethod.GCP_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
return doc;
|
||||
});
|
||||
return { ...identityGcpAuth, orgId: identityMembershipOrg.orgId };
|
||||
@@ -248,10 +241,12 @@ export const identityGcpAuthServiceFactory = ({
|
||||
}: TUpdateGcpAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update GCP Auth"
|
||||
});
|
||||
}
|
||||
|
||||
const identityGcpAuth = await identityGcpAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -311,10 +306,12 @@ export const identityGcpAuthServiceFactory = ({
|
||||
const getGcpAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetGcpAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have GCP Auth attached"
|
||||
});
|
||||
}
|
||||
|
||||
const identityGcpAuth = await identityGcpAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -339,10 +336,12 @@ export const identityGcpAuthServiceFactory = ({
|
||||
}: TRevokeGcpAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.GCP_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.GCP_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have gcp auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -366,7 +365,6 @@ export const identityGcpAuthServiceFactory = ({
|
||||
|
||||
const revokedIdentityGcpAuth = await identityGcpAuthDAL.transaction(async (tx) => {
|
||||
const deletedGcpAuth = await identityGcpAuthDAL.delete({ identityId }, tx);
|
||||
await identityDAL.updateById(identityId, { authMethod: null }, tx);
|
||||
return { ...deletedGcpAuth?.[0], orgId: identityMembershipOrg.orgId };
|
||||
});
|
||||
return revokedIdentityGcpAuth;
|
||||
|
||||
@@ -22,7 +22,6 @@ import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
import { TOrgBotDALFactory } from "@app/services/org/org-bot-dal";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
import { TIdentityDALFactory } from "../identity/identity-dal";
|
||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
|
||||
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
|
||||
@@ -44,7 +43,6 @@ type TIdentityKubernetesAuthServiceFactoryDep = {
|
||||
>;
|
||||
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create">;
|
||||
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne" | "findById">;
|
||||
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
||||
orgBotDAL: Pick<TOrgBotDALFactory, "findOne" | "transaction" | "create">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
@@ -56,7 +54,6 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
identityKubernetesAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityDAL,
|
||||
orgBotDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
@@ -215,7 +212,8 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
accessTokenTTL: identityKubernetesAuth.accessTokenTTL,
|
||||
accessTokenMaxTTL: identityKubernetesAuth.accessTokenMaxTTL,
|
||||
accessTokenNumUses: 0,
|
||||
accessTokenNumUsesLimit: identityKubernetesAuth.accessTokenNumUsesLimit
|
||||
accessTokenNumUsesLimit: identityKubernetesAuth.accessTokenNumUsesLimit,
|
||||
authMethod: IdentityAuthMethod.KUBERNETES_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
@@ -260,10 +258,12 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
}: TAttachKubernetesAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
|
||||
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add Kubernetes Auth to already configured identity"
|
||||
});
|
||||
}
|
||||
|
||||
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
|
||||
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
|
||||
@@ -372,13 +372,6 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await identityDAL.updateById(
|
||||
identityMembershipOrg.identityId,
|
||||
{
|
||||
authMethod: IdentityAuthMethod.KUBERNETES_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
return doc;
|
||||
});
|
||||
|
||||
@@ -404,10 +397,12 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
}: TUpdateKubernetesAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update Kubernetes Auth"
|
||||
});
|
||||
}
|
||||
|
||||
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -532,11 +527,12 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
}: TGetKubernetesAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Kubernetes Auth attached"
|
||||
});
|
||||
|
||||
}
|
||||
const identityKubernetesAuth = await identityKubernetesAuthDAL.findOne({ identityId });
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
@@ -597,10 +593,12 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
}: TRevokeKubernetesAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.KUBERNETES_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.KUBERNETES_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have kubernetes auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -624,7 +622,6 @@ export const identityKubernetesAuthServiceFactory = ({
|
||||
|
||||
const revokedIdentityKubernetesAuth = await identityKubernetesAuthDAL.transaction(async (tx) => {
|
||||
const deletedKubernetesAuth = await identityKubernetesAuthDAL.delete({ identityId }, tx);
|
||||
await identityDAL.updateById(identityId, { authMethod: null }, tx);
|
||||
return { ...deletedKubernetesAuth?.[0], orgId: identityMembershipOrg.orgId };
|
||||
});
|
||||
return revokedIdentityKubernetesAuth;
|
||||
|
||||
@@ -22,7 +22,6 @@ import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedErro
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
import { TIdentityDALFactory } from "../identity/identity-dal";
|
||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
|
||||
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
|
||||
@@ -41,7 +40,6 @@ type TIdentityOidcAuthServiceFactoryDep = {
|
||||
identityOidcAuthDAL: TIdentityOidcAuthDALFactory;
|
||||
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
|
||||
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create">;
|
||||
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
orgBotDAL: Pick<TOrgBotDALFactory, "findOne" | "transaction" | "create">;
|
||||
@@ -52,7 +50,6 @@ export type TIdentityOidcAuthServiceFactory = ReturnType<typeof identityOidcAuth
|
||||
export const identityOidcAuthServiceFactory = ({
|
||||
identityOidcAuthDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityDAL,
|
||||
permissionService,
|
||||
licenseService,
|
||||
identityAccessTokenDAL,
|
||||
@@ -61,7 +58,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
const login = async ({ identityId, jwt: oidcJwt }: TLoginOidcAuthDTO) => {
|
||||
const identityOidcAuth = await identityOidcAuthDAL.findOne({ identityId });
|
||||
if (!identityOidcAuth) {
|
||||
throw new NotFoundError({ message: "GCP auth method not found for identity, did you configure GCP auth?" });
|
||||
throw new NotFoundError({ message: "OIDC auth method not found for identity, did you configure OIDC auth?" });
|
||||
}
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
|
||||
@@ -181,7 +178,8 @@ export const identityOidcAuthServiceFactory = ({
|
||||
accessTokenTTL: identityOidcAuth.accessTokenTTL,
|
||||
accessTokenMaxTTL: identityOidcAuth.accessTokenMaxTTL,
|
||||
accessTokenNumUses: 0,
|
||||
accessTokenNumUsesLimit: identityOidcAuth.accessTokenNumUsesLimit
|
||||
accessTokenNumUsesLimit: identityOidcAuth.accessTokenNumUsesLimit,
|
||||
authMethod: IdentityAuthMethod.OIDC_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
@@ -228,10 +226,11 @@ export const identityOidcAuthServiceFactory = ({
|
||||
if (!identityMembershipOrg) {
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
}
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add OIDC Auth to already configured identity"
|
||||
});
|
||||
}
|
||||
|
||||
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
|
||||
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
|
||||
@@ -334,13 +333,6 @@ export const identityOidcAuthServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await identityDAL.updateById(
|
||||
identityMembershipOrg.identityId,
|
||||
{
|
||||
authMethod: IdentityAuthMethod.OIDC_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
return doc;
|
||||
});
|
||||
return { ...identityOidcAuth, orgId: identityMembershipOrg.orgId, caCert };
|
||||
@@ -364,11 +356,9 @@ export const identityOidcAuthServiceFactory = ({
|
||||
actorOrgId
|
||||
}: TUpdateOidcAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) {
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
}
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.OIDC_AUTH) {
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update OIDC Auth"
|
||||
});
|
||||
@@ -467,11 +457,9 @@ export const identityOidcAuthServiceFactory = ({
|
||||
|
||||
const getOidcAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetOidcAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) {
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
}
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.OIDC_AUTH) {
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have OIDC Auth attached"
|
||||
});
|
||||
@@ -519,7 +507,7 @@ export const identityOidcAuthServiceFactory = ({
|
||||
throw new NotFoundError({ message: "Failed to find identity" });
|
||||
}
|
||||
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.OIDC_AUTH) {
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.OIDC_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have OIDC auth"
|
||||
});
|
||||
@@ -551,7 +539,6 @@ export const identityOidcAuthServiceFactory = ({
|
||||
|
||||
const revokedIdentityOidcAuth = await identityOidcAuthDAL.transaction(async (tx) => {
|
||||
const deletedOidcAuth = await identityOidcAuthDAL.delete({ identityId }, tx);
|
||||
await identityDAL.updateById(identityId, { authMethod: null }, tx);
|
||||
return { ...deletedOidcAuth?.[0], orgId: identityMembershipOrg.orgId };
|
||||
});
|
||||
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName, TIdentities } from "@app/db/schemas";
|
||||
import {
|
||||
TableName,
|
||||
TIdentities,
|
||||
TIdentityAwsAuths,
|
||||
TIdentityAzureAuths,
|
||||
TIdentityGcpAuths,
|
||||
TIdentityKubernetesAuths,
|
||||
TIdentityOidcAuths,
|
||||
TIdentityTokenAuths,
|
||||
TIdentityUniversalAuths
|
||||
} from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
|
||||
import { OrderByDirection } from "@app/lib/types";
|
||||
import { ProjectIdentityOrderBy, TListProjectIdentityDTO } from "@app/services/identity-project/identity-project-types";
|
||||
|
||||
import { buildAuthMethods } from "../identity/identity-fns";
|
||||
|
||||
export type TIdentityProjectDALFactory = ReturnType<typeof identityProjectDALFactory>;
|
||||
|
||||
export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
@@ -33,11 +45,48 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
`${TableName.IdentityProjectMembership}.id`,
|
||||
`${TableName.IdentityProjectAdditionalPrivilege}.projectMembershipId`
|
||||
)
|
||||
|
||||
.leftJoin(
|
||||
TableName.IdentityUniversalAuth,
|
||||
`${TableName.IdentityProjectMembership}.identityId`,
|
||||
`${TableName.IdentityUniversalAuth}.identityId`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.IdentityGcpAuth,
|
||||
`${TableName.IdentityProjectMembership}.identityId`,
|
||||
`${TableName.IdentityGcpAuth}.identityId`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.IdentityAwsAuth,
|
||||
`${TableName.IdentityProjectMembership}.identityId`,
|
||||
`${TableName.IdentityAwsAuth}.identityId`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.IdentityKubernetesAuth,
|
||||
`${TableName.IdentityProjectMembership}.identityId`,
|
||||
`${TableName.IdentityKubernetesAuth}.identityId`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.IdentityOidcAuth,
|
||||
`${TableName.IdentityProjectMembership}.identityId`,
|
||||
`${TableName.IdentityOidcAuth}.identityId`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.IdentityAzureAuth,
|
||||
`${TableName.IdentityProjectMembership}.identityId`,
|
||||
`${TableName.IdentityAzureAuth}.identityId`
|
||||
)
|
||||
.leftJoin(
|
||||
TableName.IdentityTokenAuth,
|
||||
`${TableName.IdentityProjectMembership}.identityId`,
|
||||
`${TableName.IdentityTokenAuth}.identityId`
|
||||
)
|
||||
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.IdentityProjectMembership),
|
||||
db.ref("createdAt").withSchema(TableName.IdentityProjectMembership),
|
||||
db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership),
|
||||
db.ref("authMethod").as("identityAuthMethod").withSchema(TableName.Identity),
|
||||
|
||||
db.ref("id").as("identityId").withSchema(TableName.Identity),
|
||||
db.ref("name").as("identityName").withSchema(TableName.Identity),
|
||||
db.ref("id").withSchema(TableName.IdentityProjectMembership),
|
||||
@@ -52,12 +101,33 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
db.ref("temporaryAccessStartTime").withSchema(TableName.IdentityProjectMembershipRole),
|
||||
db.ref("temporaryAccessEndTime").withSchema(TableName.IdentityProjectMembershipRole),
|
||||
db.ref("projectId").withSchema(TableName.IdentityProjectMembership),
|
||||
db.ref("name").as("projectName").withSchema(TableName.Project)
|
||||
db.ref("name").as("projectName").withSchema(TableName.Project),
|
||||
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
|
||||
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
|
||||
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
|
||||
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
|
||||
db.ref("id").as("oidcId").withSchema(TableName.IdentityOidcAuth),
|
||||
db.ref("id").as("azureId").withSchema(TableName.IdentityAzureAuth),
|
||||
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth)
|
||||
);
|
||||
|
||||
const members = sqlNestRelationships({
|
||||
data: docs,
|
||||
parentMapper: ({ identityName, identityAuthMethod, id, createdAt, updatedAt, projectId, projectName }) => ({
|
||||
parentMapper: ({
|
||||
identityName,
|
||||
uaId,
|
||||
awsId,
|
||||
gcpId,
|
||||
kubernetesId,
|
||||
oidcId,
|
||||
azureId,
|
||||
tokenId,
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
projectId,
|
||||
projectName
|
||||
}) => ({
|
||||
id,
|
||||
identityId,
|
||||
createdAt,
|
||||
@@ -65,7 +135,15 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
identity: {
|
||||
id: identityId,
|
||||
name: identityName,
|
||||
authMethod: identityAuthMethod
|
||||
authMethods: buildAuthMethods({
|
||||
uaId,
|
||||
awsId,
|
||||
gcpId,
|
||||
kubernetesId,
|
||||
oidcId,
|
||||
azureId,
|
||||
tokenId
|
||||
})
|
||||
},
|
||||
project: {
|
||||
id: projectId,
|
||||
@@ -150,7 +228,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
})
|
||||
.where((qb) => {
|
||||
if (filter.identityId) {
|
||||
void qb.where("identityId", filter.identityId);
|
||||
void qb.where(`${TableName.IdentityProjectMembership}.identityId`, filter.identityId);
|
||||
}
|
||||
})
|
||||
.join(
|
||||
@@ -168,6 +246,43 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
`${TableName.IdentityProjectMembership}.id`,
|
||||
`${TableName.IdentityProjectAdditionalPrivilege}.projectMembershipId`
|
||||
)
|
||||
|
||||
.leftJoin<TIdentityUniversalAuths>(
|
||||
TableName.IdentityUniversalAuth,
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityUniversalAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityGcpAuths>(
|
||||
TableName.IdentityGcpAuth,
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityGcpAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityAwsAuths>(
|
||||
TableName.IdentityAwsAuth,
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityAwsAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityKubernetesAuths>(
|
||||
TableName.IdentityKubernetesAuth,
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityKubernetesAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityOidcAuths>(
|
||||
TableName.IdentityOidcAuth,
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityOidcAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityAzureAuths>(
|
||||
TableName.IdentityAzureAuth,
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityAzureAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityTokenAuths>(
|
||||
TableName.IdentityTokenAuth,
|
||||
`${TableName.Identity}.id`,
|
||||
`${TableName.IdentityTokenAuth}.identityId`
|
||||
)
|
||||
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.IdentityProjectMembership),
|
||||
db.ref("createdAt").withSchema(TableName.IdentityProjectMembership),
|
||||
@@ -186,7 +301,14 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
db.ref("temporaryRange").withSchema(TableName.IdentityProjectMembershipRole),
|
||||
db.ref("temporaryAccessStartTime").withSchema(TableName.IdentityProjectMembershipRole),
|
||||
db.ref("temporaryAccessEndTime").withSchema(TableName.IdentityProjectMembershipRole),
|
||||
db.ref("name").as("projectName").withSchema(TableName.Project)
|
||||
db.ref("name").as("projectName").withSchema(TableName.Project),
|
||||
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
|
||||
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
|
||||
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
|
||||
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
|
||||
db.ref("id").as("oidcId").withSchema(TableName.IdentityOidcAuth),
|
||||
db.ref("id").as("azureId").withSchema(TableName.IdentityAzureAuth),
|
||||
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth)
|
||||
);
|
||||
|
||||
// TODO: scott - joins seem to reorder identities so need to order again, for the sake of urgency will optimize at a later point
|
||||
@@ -204,7 +326,21 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
|
||||
const members = sqlNestRelationships({
|
||||
data: docs,
|
||||
parentMapper: ({ identityId, identityName, identityAuthMethod, id, createdAt, updatedAt, projectName }) => ({
|
||||
parentMapper: ({
|
||||
identityId,
|
||||
identityName,
|
||||
uaId,
|
||||
awsId,
|
||||
gcpId,
|
||||
kubernetesId,
|
||||
oidcId,
|
||||
azureId,
|
||||
tokenId,
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
projectName
|
||||
}) => ({
|
||||
id,
|
||||
identityId,
|
||||
createdAt,
|
||||
@@ -212,7 +348,15 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
identity: {
|
||||
id: identityId,
|
||||
name: identityName,
|
||||
authMethod: identityAuthMethod
|
||||
authMethods: buildAuthMethods({
|
||||
uaId,
|
||||
awsId,
|
||||
gcpId,
|
||||
kubernetesId,
|
||||
oidcId,
|
||||
azureId,
|
||||
tokenId
|
||||
})
|
||||
},
|
||||
project: {
|
||||
id: projectId,
|
||||
|
||||
@@ -11,7 +11,6 @@ import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/
|
||||
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
import { TIdentityDALFactory } from "../identity/identity-dal";
|
||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
|
||||
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
|
||||
@@ -32,11 +31,10 @@ type TIdentityTokenAuthServiceFactoryDep = {
|
||||
TIdentityTokenAuthDALFactory,
|
||||
"transaction" | "create" | "findOne" | "updateById" | "delete"
|
||||
>;
|
||||
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
||||
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
|
||||
identityAccessTokenDAL: Pick<
|
||||
TIdentityAccessTokenDALFactory,
|
||||
"create" | "find" | "update" | "findById" | "findOne" | "updateById"
|
||||
"create" | "find" | "update" | "findById" | "findOne" | "updateById" | "delete"
|
||||
>;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
@@ -46,7 +44,7 @@ export type TIdentityTokenAuthServiceFactory = ReturnType<typeof identityTokenAu
|
||||
|
||||
export const identityTokenAuthServiceFactory = ({
|
||||
identityTokenAuthDAL,
|
||||
identityDAL,
|
||||
// identityDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityAccessTokenDAL,
|
||||
permissionService,
|
||||
@@ -65,10 +63,12 @@ export const identityTokenAuthServiceFactory = ({
|
||||
}: TAttachTokenAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
|
||||
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add Token Auth to already configured identity"
|
||||
});
|
||||
}
|
||||
|
||||
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
|
||||
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
|
||||
@@ -112,13 +112,6 @@ export const identityTokenAuthServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await identityDAL.updateById(
|
||||
identityMembershipOrg.identityId,
|
||||
{
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
return doc;
|
||||
});
|
||||
return { ...identityTokenAuth, orgId: identityMembershipOrg.orgId };
|
||||
@@ -137,10 +130,12 @@ export const identityTokenAuthServiceFactory = ({
|
||||
}: TUpdateTokenAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to update Token Auth"
|
||||
message: "The identity does not have token auth"
|
||||
});
|
||||
}
|
||||
|
||||
const identityTokenAuth = await identityTokenAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -197,10 +192,12 @@ export const identityTokenAuthServiceFactory = ({
|
||||
const getTokenAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetTokenAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth attached"
|
||||
});
|
||||
}
|
||||
|
||||
const identityTokenAuth = await identityTokenAuthDAL.findOne({ identityId });
|
||||
|
||||
@@ -225,10 +222,12 @@ export const identityTokenAuthServiceFactory = ({
|
||||
}: TRevokeTokenAuthDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -254,7 +253,11 @@ export const identityTokenAuthServiceFactory = ({
|
||||
|
||||
const revokedIdentityTokenAuth = await identityTokenAuthDAL.transaction(async (tx) => {
|
||||
const deletedTokenAuth = await identityTokenAuthDAL.delete({ identityId }, tx);
|
||||
await identityDAL.updateById(identityId, { authMethod: null }, tx);
|
||||
await identityAccessTokenDAL.delete({
|
||||
identityId,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
});
|
||||
|
||||
return { ...deletedTokenAuth?.[0], orgId: identityMembershipOrg.orgId };
|
||||
});
|
||||
return revokedIdentityTokenAuth;
|
||||
@@ -270,10 +273,12 @@ export const identityTokenAuthServiceFactory = ({
|
||||
}: TCreateTokenAuthTokenDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -307,7 +312,8 @@ export const identityTokenAuthServiceFactory = ({
|
||||
accessTokenMaxTTL: identityTokenAuth.accessTokenMaxTTL,
|
||||
accessTokenNumUses: 0,
|
||||
accessTokenNumUsesLimit: identityTokenAuth.accessTokenNumUsesLimit,
|
||||
name
|
||||
name,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
@@ -344,10 +350,12 @@ export const identityTokenAuthServiceFactory = ({
|
||||
}: TGetTokenAuthTokensDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -359,7 +367,8 @@ export const identityTokenAuthServiceFactory = ({
|
||||
|
||||
const tokens = await identityAccessTokenDAL.find(
|
||||
{
|
||||
identityId
|
||||
identityId,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
},
|
||||
{ offset, limit, sort: [["updatedAt", "desc"]] }
|
||||
);
|
||||
@@ -375,16 +384,21 @@ export const identityTokenAuthServiceFactory = ({
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
}: TUpdateTokenAuthTokenDTO) => {
|
||||
const foundToken = await identityAccessTokenDAL.findById(tokenId);
|
||||
const foundToken = await identityAccessTokenDAL.findOne({
|
||||
id: tokenId,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
});
|
||||
if (!foundToken) throw new NotFoundError({ message: `Token with ID ${tokenId} not found` });
|
||||
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: foundToken.identityId });
|
||||
if (!identityMembershipOrg) {
|
||||
throw new NotFoundError({ message: `Failed to find identity with ID ${foundToken.identityId}` });
|
||||
}
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have Token Auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -409,6 +423,7 @@ export const identityTokenAuthServiceFactory = ({
|
||||
|
||||
const [token] = await identityAccessTokenDAL.update(
|
||||
{
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH,
|
||||
identityId: foundToken.identityId,
|
||||
id: tokenId
|
||||
},
|
||||
@@ -429,7 +444,8 @@ export const identityTokenAuthServiceFactory = ({
|
||||
}: TRevokeTokenAuthTokenDTO) => {
|
||||
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
||||
[`${TableName.IdentityAccessToken}.id` as "id"]: tokenId,
|
||||
isAccessTokenRevoked: false
|
||||
isAccessTokenRevoked: false,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
});
|
||||
if (!identityAccessToken)
|
||||
throw new NotFoundError({
|
||||
@@ -453,9 +469,15 @@ export const identityTokenAuthServiceFactory = ({
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
|
||||
|
||||
const revokedToken = await identityAccessTokenDAL.updateById(identityAccessToken.id, {
|
||||
isAccessTokenRevoked: true
|
||||
});
|
||||
const [revokedToken] = await identityAccessTokenDAL.update(
|
||||
{
|
||||
id: identityAccessToken.id,
|
||||
authMethod: IdentityAuthMethod.TOKEN_AUTH
|
||||
},
|
||||
{
|
||||
isAccessTokenRevoked: true
|
||||
}
|
||||
);
|
||||
|
||||
return { revokedToken };
|
||||
};
|
||||
|
||||
@@ -14,7 +14,6 @@ import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedErro
|
||||
import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr, TIp } from "@app/lib/ip";
|
||||
|
||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
||||
import { TIdentityDALFactory } from "../identity/identity-dal";
|
||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||
import { TIdentityAccessTokenDALFactory } from "../identity-access-token/identity-access-token-dal";
|
||||
import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identity-access-token-types";
|
||||
@@ -36,7 +35,6 @@ type TIdentityUaServiceFactoryDep = {
|
||||
identityUaClientSecretDAL: TIdentityUaClientSecretDALFactory;
|
||||
identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
|
||||
identityOrgMembershipDAL: TIdentityOrgDALFactory;
|
||||
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
};
|
||||
@@ -48,7 +46,6 @@ export const identityUaServiceFactory = ({
|
||||
identityUaClientSecretDAL,
|
||||
identityAccessTokenDAL,
|
||||
identityOrgMembershipDAL,
|
||||
identityDAL,
|
||||
permissionService,
|
||||
licenseService
|
||||
}: TIdentityUaServiceFactoryDep) => {
|
||||
@@ -115,7 +112,8 @@ export const identityUaServiceFactory = ({
|
||||
accessTokenTTL: identityUa.accessTokenTTL,
|
||||
accessTokenMaxTTL: identityUa.accessTokenMaxTTL,
|
||||
accessTokenNumUses: 0,
|
||||
accessTokenNumUsesLimit: identityUa.accessTokenNumUsesLimit
|
||||
accessTokenNumUsesLimit: identityUa.accessTokenNumUsesLimit,
|
||||
authMethod: IdentityAuthMethod.UNIVERSAL_AUTH
|
||||
},
|
||||
tx
|
||||
);
|
||||
@@ -156,10 +154,12 @@ export const identityUaServiceFactory = ({
|
||||
}: TAttachUaDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity.authMethod)
|
||||
|
||||
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to add universal auth to already configured identity"
|
||||
});
|
||||
}
|
||||
|
||||
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
|
||||
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
|
||||
@@ -221,13 +221,6 @@ export const identityUaServiceFactory = ({
|
||||
},
|
||||
tx
|
||||
);
|
||||
await identityDAL.updateById(
|
||||
identityMembershipOrg.identityId,
|
||||
{
|
||||
authMethod: IdentityAuthMethod.Univeral
|
||||
},
|
||||
tx
|
||||
);
|
||||
return doc;
|
||||
});
|
||||
return { ...identityUa, orgId: identityMembershipOrg.orgId };
|
||||
@@ -247,10 +240,12 @@ export const identityUaServiceFactory = ({
|
||||
}: TUpdateUaDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "Failed to updated universal auth"
|
||||
message: "The identity does not have universal auth"
|
||||
});
|
||||
}
|
||||
|
||||
const uaIdentityAuth = await identityUaDAL.findOne({ identityId });
|
||||
|
||||
@@ -321,10 +316,12 @@ export const identityUaServiceFactory = ({
|
||||
const getIdentityUniversalAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetUaDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
});
|
||||
}
|
||||
|
||||
const uaIdentityAuth = await identityUaDAL.findOne({ identityId });
|
||||
|
||||
@@ -348,10 +345,12 @@ export const identityUaServiceFactory = ({
|
||||
}: TRevokeUaDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -375,7 +374,6 @@ export const identityUaServiceFactory = ({
|
||||
|
||||
const revokedIdentityUniversalAuth = await identityUaDAL.transaction(async (tx) => {
|
||||
const deletedUniversalAuth = await identityUaDAL.delete({ identityId }, tx);
|
||||
await identityDAL.updateById(identityId, { authMethod: null }, tx);
|
||||
return { ...deletedUniversalAuth?.[0], orgId: identityMembershipOrg.orgId };
|
||||
});
|
||||
return revokedIdentityUniversalAuth;
|
||||
@@ -393,10 +391,13 @@ export const identityUaServiceFactory = ({
|
||||
}: TCreateUaClientSecretDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
});
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -422,12 +423,11 @@ export const identityUaServiceFactory = ({
|
||||
const appCfg = getConfig();
|
||||
const clientSecret = crypto.randomBytes(32).toString("hex");
|
||||
const clientSecretHash = await bcrypt.hash(clientSecret, appCfg.SALT_ROUNDS);
|
||||
const identityUniversalAuth = await identityUaDAL.findOne({
|
||||
identityId
|
||||
});
|
||||
|
||||
const identityUaAuth = await identityUaDAL.findOne({ identityId: identityMembershipOrg.identityId });
|
||||
|
||||
const identityUaClientSecret = await identityUaClientSecretDAL.create({
|
||||
identityUAId: identityUniversalAuth.id,
|
||||
identityUAId: identityUaAuth.id,
|
||||
description,
|
||||
clientSecretPrefix: clientSecret.slice(0, 4),
|
||||
clientSecretHash,
|
||||
@@ -439,7 +439,6 @@ export const identityUaServiceFactory = ({
|
||||
return {
|
||||
clientSecret,
|
||||
clientSecretData: identityUaClientSecret,
|
||||
uaAuth: identityUniversalAuth,
|
||||
orgId: identityMembershipOrg.orgId
|
||||
};
|
||||
};
|
||||
@@ -453,10 +452,12 @@ export const identityUaServiceFactory = ({
|
||||
}: TGetUaClientSecretsDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
});
|
||||
}
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -500,10 +501,13 @@ export const identityUaServiceFactory = ({
|
||||
}: TGetUniversalAuthClientSecretByIdDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
});
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -539,10 +543,13 @@ export const identityUaServiceFactory = ({
|
||||
}: TRevokeUaClientSecretDTO) => {
|
||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
|
||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
|
||||
|
||||
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.UNIVERSAL_AUTH)) {
|
||||
throw new BadRequestError({
|
||||
message: "The identity does not have universal auth"
|
||||
});
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission(
|
||||
actor,
|
||||
actorId,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { IdentityAuthMethod } from "@app/db/schemas";
|
||||
|
||||
export const buildAuthMethods = ({
|
||||
uaId,
|
||||
gcpId,
|
||||
awsId,
|
||||
kubernetesId,
|
||||
oidcId,
|
||||
azureId,
|
||||
tokenId
|
||||
}: {
|
||||
uaId?: string;
|
||||
gcpId?: string;
|
||||
awsId?: string;
|
||||
kubernetesId?: string;
|
||||
oidcId?: string;
|
||||
azureId?: string;
|
||||
tokenId?: string;
|
||||
}) => {
|
||||
return [
|
||||
...[uaId ? IdentityAuthMethod.UNIVERSAL_AUTH : null],
|
||||
...[gcpId ? IdentityAuthMethod.GCP_AUTH : null],
|
||||
...[awsId ? IdentityAuthMethod.AWS_AUTH : null],
|
||||
...[kubernetesId ? IdentityAuthMethod.KUBERNETES_AUTH : null],
|
||||
...[oidcId ? IdentityAuthMethod.OIDC_AUTH : null],
|
||||
...[azureId ? IdentityAuthMethod.AZURE_AUTH : null],
|
||||
...[tokenId ? IdentityAuthMethod.TOKEN_AUTH : null]
|
||||
].filter((authMethod) => authMethod) as IdentityAuthMethod[];
|
||||
};
|
||||
@@ -1,12 +1,25 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName, TIdentityOrgMemberships, TOrgRoles } from "@app/db/schemas";
|
||||
import {
|
||||
TableName,
|
||||
TIdentityAwsAuths,
|
||||
TIdentityAzureAuths,
|
||||
TIdentityGcpAuths,
|
||||
TIdentityKubernetesAuths,
|
||||
TIdentityOidcAuths,
|
||||
TIdentityOrgMemberships,
|
||||
TIdentityTokenAuths,
|
||||
TIdentityUniversalAuths,
|
||||
TOrgRoles
|
||||
} from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
|
||||
import { OrderByDirection } from "@app/lib/types";
|
||||
import { OrgIdentityOrderBy, TListOrgIdentitiesByOrgIdDTO } from "@app/services/identity/identity-types";
|
||||
|
||||
import { buildAuthMethods } from "./identity-fns";
|
||||
|
||||
export type TIdentityOrgDALFactory = ReturnType<typeof identityOrgDALFactory>;
|
||||
|
||||
export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
@@ -15,14 +28,73 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
const findOne = async (filter: Partial<TIdentityOrgMemberships>, tx?: Knex) => {
|
||||
try {
|
||||
const [data] = await (tx || db.replicaNode())(TableName.IdentityOrgMembership)
|
||||
.where(filter)
|
||||
.where((queryBuilder) => {
|
||||
Object.entries(filter).forEach(([key, value]) => {
|
||||
void queryBuilder.where(`${TableName.IdentityOrgMembership}.${key}`, value);
|
||||
});
|
||||
})
|
||||
.join(TableName.Identity, `${TableName.IdentityOrgMembership}.identityId`, `${TableName.Identity}.id`)
|
||||
.select(selectAllTableCols(TableName.IdentityOrgMembership))
|
||||
.select(db.ref("name").withSchema(TableName.Identity))
|
||||
.select(db.ref("authMethod").withSchema(TableName.Identity));
|
||||
|
||||
.leftJoin<TIdentityUniversalAuths>(
|
||||
TableName.IdentityUniversalAuth,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.IdentityUniversalAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityGcpAuths>(
|
||||
TableName.IdentityGcpAuth,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.IdentityGcpAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityAwsAuths>(
|
||||
TableName.IdentityAwsAuth,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.IdentityAwsAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityKubernetesAuths>(
|
||||
TableName.IdentityKubernetesAuth,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.IdentityKubernetesAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityOidcAuths>(
|
||||
TableName.IdentityOidcAuth,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.IdentityOidcAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityAzureAuths>(
|
||||
TableName.IdentityAzureAuth,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.IdentityAzureAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityTokenAuths>(
|
||||
TableName.IdentityTokenAuth,
|
||||
`${TableName.IdentityOrgMembership}.identityId`,
|
||||
`${TableName.IdentityTokenAuth}.identityId`
|
||||
)
|
||||
|
||||
.select(
|
||||
selectAllTableCols(TableName.IdentityOrgMembership),
|
||||
|
||||
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
|
||||
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
|
||||
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
|
||||
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
|
||||
db.ref("id").as("oidcId").withSchema(TableName.IdentityOidcAuth),
|
||||
db.ref("id").as("azureId").withSchema(TableName.IdentityAzureAuth),
|
||||
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth),
|
||||
|
||||
db.ref("name").withSchema(TableName.Identity)
|
||||
);
|
||||
|
||||
if (data) {
|
||||
const { name, authMethod } = data;
|
||||
return { ...data, identity: { id: data.identityId, name, authMethod } };
|
||||
const { name } = data;
|
||||
return {
|
||||
...data,
|
||||
identity: {
|
||||
id: data.identityId,
|
||||
name,
|
||||
authMethods: buildAuthMethods(data)
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "FindOne" });
|
||||
@@ -51,8 +123,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
.orderBy(`${TableName.Identity}.${orderBy}`, orderDirection)
|
||||
.select(
|
||||
selectAllTableCols(TableName.IdentityOrgMembership),
|
||||
db.ref("name").withSchema(TableName.Identity).as("identityName"),
|
||||
db.ref("authMethod").withSchema(TableName.Identity).as("identityAuthMethod")
|
||||
db.ref("name").withSchema(TableName.Identity).as("identityName")
|
||||
)
|
||||
.where(filter)
|
||||
.as("paginatedIdentity");
|
||||
@@ -70,11 +141,49 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
const query = (tx || db.replicaNode())
|
||||
.from<TSubquery[number], TSubquery>(paginatedIdentity)
|
||||
.leftJoin<TOrgRoles>(TableName.OrgRoles, `paginatedIdentity.roleId`, `${TableName.OrgRoles}.id`)
|
||||
|
||||
.leftJoin(TableName.IdentityMetadata, (queryBuilder) => {
|
||||
void queryBuilder
|
||||
.on(`paginatedIdentity.identityId`, `${TableName.IdentityMetadata}.identityId`)
|
||||
.andOn(`paginatedIdentity.orgId`, `${TableName.IdentityMetadata}.orgId`);
|
||||
})
|
||||
|
||||
.leftJoin<TIdentityUniversalAuths>(
|
||||
TableName.IdentityUniversalAuth,
|
||||
"paginatedIdentity.identityId",
|
||||
`${TableName.IdentityUniversalAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityGcpAuths>(
|
||||
TableName.IdentityGcpAuth,
|
||||
"paginatedIdentity.identityId",
|
||||
`${TableName.IdentityGcpAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityAwsAuths>(
|
||||
TableName.IdentityAwsAuth,
|
||||
"paginatedIdentity.identityId",
|
||||
`${TableName.IdentityAwsAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityKubernetesAuths>(
|
||||
TableName.IdentityKubernetesAuth,
|
||||
"paginatedIdentity.identityId",
|
||||
`${TableName.IdentityKubernetesAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityOidcAuths>(
|
||||
TableName.IdentityOidcAuth,
|
||||
"paginatedIdentity.identityId",
|
||||
`${TableName.IdentityOidcAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityAzureAuths>(
|
||||
TableName.IdentityAzureAuth,
|
||||
"paginatedIdentity.identityId",
|
||||
`${TableName.IdentityAzureAuth}.identityId`
|
||||
)
|
||||
.leftJoin<TIdentityTokenAuths>(
|
||||
TableName.IdentityTokenAuth,
|
||||
"paginatedIdentity.identityId",
|
||||
`${TableName.IdentityTokenAuth}.identityId`
|
||||
)
|
||||
|
||||
.select(
|
||||
db.ref("id").withSchema("paginatedIdentity"),
|
||||
db.ref("role").withSchema("paginatedIdentity"),
|
||||
@@ -82,9 +191,16 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
db.ref("orgId").withSchema("paginatedIdentity"),
|
||||
db.ref("createdAt").withSchema("paginatedIdentity"),
|
||||
db.ref("updatedAt").withSchema("paginatedIdentity"),
|
||||
db.ref("identityId").withSchema("paginatedIdentity"),
|
||||
db.ref("identityId").withSchema("paginatedIdentity").as("identityId"),
|
||||
db.ref("identityName").withSchema("paginatedIdentity"),
|
||||
db.ref("identityAuthMethod").withSchema("paginatedIdentity")
|
||||
|
||||
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
|
||||
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
|
||||
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
|
||||
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
|
||||
db.ref("id").as("oidcId").withSchema(TableName.IdentityOidcAuth),
|
||||
db.ref("id").as("azureId").withSchema(TableName.IdentityAzureAuth),
|
||||
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth)
|
||||
)
|
||||
// cr stands for custom role
|
||||
.select(db.ref("id").as("crId").withSchema(TableName.OrgRoles))
|
||||
@@ -114,11 +230,17 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
crName,
|
||||
identityId,
|
||||
identityName,
|
||||
identityAuthMethod,
|
||||
role,
|
||||
roleId,
|
||||
id,
|
||||
orgId,
|
||||
uaId,
|
||||
awsId,
|
||||
gcpId,
|
||||
kubernetesId,
|
||||
oidcId,
|
||||
azureId,
|
||||
tokenId,
|
||||
createdAt,
|
||||
updatedAt
|
||||
}) => ({
|
||||
@@ -126,6 +248,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
roleId,
|
||||
identityId,
|
||||
id,
|
||||
|
||||
orgId,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
@@ -141,7 +264,15 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
identity: {
|
||||
id: identityId,
|
||||
name: identityName,
|
||||
authMethod: identityAuthMethod as string
|
||||
authMethods: buildAuthMethods({
|
||||
uaId,
|
||||
awsId,
|
||||
gcpId,
|
||||
kubernetesId,
|
||||
oidcId,
|
||||
azureId,
|
||||
tokenId
|
||||
})
|
||||
}
|
||||
}),
|
||||
childrenMapper: [
|
||||
|
||||
@@ -93,7 +93,7 @@ export const identityServiceFactory = ({
|
||||
tx
|
||||
);
|
||||
}
|
||||
return newIdentity;
|
||||
return { ...newIdentity, authMethods: [] };
|
||||
});
|
||||
await licenseService.updateSubscriptionOrgMemberCount(orgId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user