feat(machine-identity): Alibaba Cloud

This commit is contained in:
x032205
2025-06-11 02:44:53 -04:00
parent 0d7cd357c3
commit c315eed4d4
43 changed files with 1879 additions and 7 deletions
+2
View File
@@ -65,6 +65,7 @@ import { TGroupProjectServiceFactory } from "@app/services/group-project/group-p
import { THsmServiceFactory } from "@app/services/hsm/hsm-service";
import { TIdentityServiceFactory } from "@app/services/identity/identity-service";
import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
import { TIdentityAliCloudAuthServiceFactory } from "@app/services/identity-alicloud-auth/identity-alicloud-auth-service";
import { TIdentityAwsAuthServiceFactory } from "@app/services/identity-aws-auth/identity-aws-auth-service";
import { TIdentityAzureAuthServiceFactory } from "@app/services/identity-azure-auth/identity-azure-auth-service";
import { TIdentityGcpAuthServiceFactory } from "@app/services/identity-gcp-auth/identity-gcp-auth-service";
@@ -218,6 +219,7 @@ declare module "fastify" {
identityUa: TIdentityUaServiceFactory;
identityKubernetesAuth: TIdentityKubernetesAuthServiceFactory;
identityGcpAuth: TIdentityGcpAuthServiceFactory;
identityAliCloudAuth: TIdentityAliCloudAuthServiceFactory;
identityAwsAuth: TIdentityAwsAuthServiceFactory;
identityAzureAuth: TIdentityAzureAuthServiceFactory;
identityOciAuth: TIdentityOciAuthServiceFactory;
+8
View File
@@ -125,6 +125,9 @@ import {
TIdentityAccessTokens,
TIdentityAccessTokensInsert,
TIdentityAccessTokensUpdate,
TIdentityAlicloudAuths,
TIdentityAlicloudAuthsInsert,
TIdentityAlicloudAuthsUpdate,
TIdentityAwsAuths,
TIdentityAwsAuthsInsert,
TIdentityAwsAuthsUpdate,
@@ -786,6 +789,11 @@ declare module "knex/types/tables" {
TIdentityGcpAuthsInsert,
TIdentityGcpAuthsUpdate
>;
[TableName.IdentityAliCloudAuth]: KnexOriginal.CompositeTableType<
TIdentityAlicloudAuths,
TIdentityAlicloudAuthsInsert,
TIdentityAlicloudAuthsUpdate
>;
[TableName.IdentityAwsAuth]: KnexOriginal.CompositeTableType<
TIdentityAwsAuths,
TIdentityAwsAuthsInsert,
@@ -0,0 +1,29 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
export async function up(knex: Knex): Promise<void> {
if (!(await knex.schema.hasTable(TableName.IdentityAliCloudAuth))) {
await knex.schema.createTable(TableName.IdentityAliCloudAuth, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.bigInteger("accessTokenTTL").defaultTo(7200).notNullable();
t.bigInteger("accessTokenMaxTTL").defaultTo(7200).notNullable();
t.bigInteger("accessTokenNumUsesLimit").defaultTo(0).notNullable();
t.jsonb("accessTokenTrustedIps").notNullable();
t.timestamps(true, true, true);
t.uuid("identityId").notNullable().unique();
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
t.string("type").notNullable();
t.string("allowedArns").notNullable();
});
}
await createOnUpdateTrigger(knex, TableName.IdentityAliCloudAuth);
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTableIfExists(TableName.IdentityAliCloudAuth);
await dropOnUpdateTrigger(knex, TableName.IdentityAliCloudAuth);
}
@@ -0,0 +1,25 @@
// Code generated by automation script, DO NOT EDIT.
// Automated by pulling database and generating zod schema
// To update. Just run npm run generate:schema
// Written by akhilmhdh.
import { z } from "zod";
import { TImmutableDBKeys } from "./models";
export const IdentityAlicloudAuthsSchema = z.object({
id: z.string().uuid(),
accessTokenTTL: z.coerce.number().default(7200),
accessTokenMaxTTL: z.coerce.number().default(7200),
accessTokenNumUsesLimit: z.coerce.number().default(0),
accessTokenTrustedIps: z.unknown(),
createdAt: z.date(),
updatedAt: z.date(),
identityId: z.string().uuid(),
type: z.string(),
allowedArns: z.string()
});
export type TIdentityAlicloudAuths = z.infer<typeof IdentityAlicloudAuthsSchema>;
export type TIdentityAlicloudAuthsInsert = Omit<z.input<typeof IdentityAlicloudAuthsSchema>, TImmutableDBKeys>;
export type TIdentityAlicloudAuthsUpdate = Partial<Omit<z.input<typeof IdentityAlicloudAuthsSchema>, TImmutableDBKeys>>;
+1
View File
@@ -39,6 +39,7 @@ export * from "./group-project-memberships";
export * from "./groups";
export * from "./identities";
export * from "./identity-access-tokens";
export * from "./identity-alicloud-auths";
export * from "./identity-aws-auths";
export * from "./identity-azure-auths";
export * from "./identity-gcp-auths";
+2
View File
@@ -80,6 +80,7 @@ export enum TableName {
IdentityGcpAuth = "identity_gcp_auths",
IdentityAzureAuth = "identity_azure_auths",
IdentityUaClientSecret = "identity_ua_client_secrets",
IdentityAliCloudAuth = "identity_alicloud_auths",
IdentityAwsAuth = "identity_aws_auths",
IdentityOciAuth = "identity_oci_auths",
IdentityOidcAuth = "identity_oidc_auths",
@@ -247,6 +248,7 @@ export enum IdentityAuthMethod {
UNIVERSAL_AUTH = "universal-auth",
KUBERNETES_AUTH = "kubernetes-auth",
GCP_AUTH = "gcp-auth",
ALICLOUD_AUTH = "alicloud-auth",
AWS_AUTH = "aws-auth",
AZURE_AUTH = "azure-auth",
OCI_AUTH = "oci-auth",
@@ -170,6 +170,12 @@ export enum EventType {
REVOKE_IDENTITY_GCP_AUTH = "revoke-identity-gcp-auth",
GET_IDENTITY_GCP_AUTH = "get-identity-gcp-auth",
LOGIN_IDENTITY_ALICLOUD_AUTH = "login-identity-alicloud-auth",
ADD_IDENTITY_ALICLOUD_AUTH = "add-identity-alicloud-auth",
UPDATE_IDENTITY_ALICLOUD_AUTH = "update-identity-alicloud-auth",
REVOKE_IDENTITY_ALICLOUD_AUTH = "revoke-identity-alicloud-auth",
GET_IDENTITY_ALICLOUD_AUTH = "get-identity-alicloud-auth",
LOGIN_IDENTITY_AWS_AUTH = "login-identity-aws-auth",
ADD_IDENTITY_AWS_AUTH = "add-identity-aws-auth",
UPDATE_IDENTITY_AWS_AUTH = "update-identity-aws-auth",
@@ -1060,6 +1066,53 @@ interface GetIdentityAwsAuthEvent {
};
}
interface LoginIdentityAliCloudAuthEvent {
type: EventType.LOGIN_IDENTITY_ALICLOUD_AUTH;
metadata: {
identityId: string;
identityAliCloudAuthId: string;
identityAccessTokenId: string;
};
}
interface AddIdentityAliCloudAuthEvent {
type: EventType.ADD_IDENTITY_ALICLOUD_AUTH;
metadata: {
identityId: string;
allowedArns: string;
accessTokenTTL: number;
accessTokenMaxTTL: number;
accessTokenNumUsesLimit: number;
accessTokenTrustedIps: Array<TIdentityTrustedIp>;
};
}
interface DeleteIdentityAliCloudAuthEvent {
type: EventType.REVOKE_IDENTITY_ALICLOUD_AUTH;
metadata: {
identityId: string;
};
}
interface UpdateIdentityAliCloudAuthEvent {
type: EventType.UPDATE_IDENTITY_ALICLOUD_AUTH;
metadata: {
identityId: string;
allowedArns: string;
accessTokenTTL?: number;
accessTokenMaxTTL?: number;
accessTokenNumUsesLimit?: number;
accessTokenTrustedIps?: Array<TIdentityTrustedIp>;
};
}
interface GetIdentityAliCloudAuthEvent {
type: EventType.GET_IDENTITY_ALICLOUD_AUTH;
metadata: {
identityId: string;
};
}
interface LoginIdentityOciAuthEvent {
type: EventType.LOGIN_IDENTITY_OCI_AUTH;
metadata: {
@@ -3272,6 +3325,11 @@ export type Event =
| UpdateIdentityAwsAuthEvent
| GetIdentityAwsAuthEvent
| DeleteIdentityAwsAuthEvent
| LoginIdentityAliCloudAuthEvent
| AddIdentityAliCloudAuthEvent
| UpdateIdentityAliCloudAuthEvent
| GetIdentityAliCloudAuthEvent
| DeleteIdentityAliCloudAuthEvent
| LoginIdentityOciAuthEvent
| AddIdentityOciAuthEvent
| UpdateIdentityOciAuthEvent
+38
View File
@@ -21,6 +21,7 @@ export enum ApiDocsTags {
TokenAuth = "Token Auth",
UniversalAuth = "Universal Auth",
GcpAuth = "GCP Auth",
AliCloudAuth = "Alibaba Cloud Auth",
AwsAuth = "AWS Auth",
OciAuth = "OCI Auth",
AzureAuth = "Azure Auth",
@@ -243,6 +244,43 @@ export const LDAP_AUTH = {
}
} as const;
export const ALICLOUD_AUTH = {
LOGIN: {
identityId: "The ID of the identity to login.",
Action: "The Alibaba Cloud API action. For STS GetCallerIdentity, this should be 'GetCallerIdentity'.",
Format: "The response format. For STS GetCallerIdentity, this should be 'JSON'.",
Version: "The API version. This should be in 'YYYY-MM-DD' format (e.g., '2015-04-01').",
AccessKeyId: "The AccessKey ID of the RAM user or STS token.",
SignatureMethod: "The signature algorithm. For STS GetCallerIdentity, this should be 'HMAC-SHA1'.",
Timestamp: "The timestamp of the request in UTC, formatted as 'YYYY-MM-DDTHH:mm:ssZ'.",
SignatureVersion: "The signature version. For STS GetCallerIdentity, this should be '1.0'.",
SignatureNonce: "A unique random string to prevent replay attacks.",
Signature: "The signature string calculated based on the request parameters and AccessKey Secret."
},
ATTACH: {
identityId: "The ID of the identity to attach the configuration onto.",
allowedArns: "The comma-separated list of trusted ARNs that are allowed to authenticate with Infisical.",
accessTokenTTL: "The lifetime for an access token in seconds.",
accessTokenMaxTTL: "The maximum lifetime for an access token in seconds.",
accessTokenNumUsesLimit: "The maximum number of times that an access token can be used.",
accessTokenTrustedIps: "The IPs or CIDR ranges that access tokens can be used from."
},
UPDATE: {
identityId: "The ID of the identity to update the auth method for.",
allowedArns: "The comma-separated list of trusted ARNs that are allowed to authenticate with Infisical.",
accessTokenTTL: "The new lifetime for an access token in seconds.",
accessTokenMaxTTL: "The new maximum lifetime for an access token in seconds.",
accessTokenNumUsesLimit: "The new maximum number of times that an access token can be used.",
accessTokenTrustedIps: "The new IPs or CIDR ranges that access tokens can be used from."
},
RETRIEVE: {
identityId: "The ID of the identity to retrieve the auth method for."
},
REVOKE: {
identityId: "The ID of the identity to revoke the auth method for."
}
} as const;
export const AWS_AUTH = {
LOGIN: {
identityId: "The ID of the identity to login.",
+12
View File
@@ -172,6 +172,8 @@ import { identityOrgDALFactory } from "@app/services/identity/identity-org-dal";
import { identityServiceFactory } from "@app/services/identity/identity-service";
import { identityAccessTokenDALFactory } from "@app/services/identity-access-token/identity-access-token-dal";
import { identityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
import { identityAliCloudAuthDALFactory } from "@app/services/identity-alicloud-auth/identity-alicloud-auth-dal";
import { identityAliCloudAuthServiceFactory } from "@app/services/identity-alicloud-auth/identity-alicloud-auth-service";
import { identityAwsAuthDALFactory } from "@app/services/identity-aws-auth/identity-aws-auth-dal";
import { identityAwsAuthServiceFactory } from "@app/services/identity-aws-auth/identity-aws-auth-service";
import { identityAzureAuthDALFactory } from "@app/services/identity-azure-auth/identity-azure-auth-dal";
@@ -383,6 +385,7 @@ export const registerRoutes = async (
const identityUaDAL = identityUaDALFactory(db);
const identityKubernetesAuthDAL = identityKubernetesAuthDALFactory(db);
const identityUaClientSecretDAL = identityUaClientSecretDALFactory(db);
const identityAliCloudAuthDAL = identityAliCloudAuthDALFactory(db);
const identityAwsAuthDAL = identityAwsAuthDALFactory(db);
const identityGcpAuthDAL = identityGcpAuthDALFactory(db);
const identityOciAuthDAL = identityOciAuthDALFactory(db);
@@ -1482,6 +1485,14 @@ export const registerRoutes = async (
licenseService
});
const identityAliCloudAuthService = identityAliCloudAuthServiceFactory({
identityAccessTokenDAL,
identityAliCloudAuthDAL,
identityOrgMembershipDAL,
licenseService,
permissionService
});
const identityAwsAuthService = identityAwsAuthServiceFactory({
identityAccessTokenDAL,
identityAwsAuthDAL,
@@ -1931,6 +1942,7 @@ export const registerRoutes = async (
identityUa: identityUaService,
identityKubernetesAuth: identityKubernetesAuthService,
identityGcpAuth: identityGcpAuthService,
identityAliCloudAuth: identityAliCloudAuthService,
identityAwsAuth: identityAwsAuthService,
identityAzureAuth: identityAzureAuthService,
identityOciAuth: identityOciAuthService,
@@ -0,0 +1,378 @@
import RE2 from "re2";
import { z } from "zod";
import { IdentityAlicloudAuthsSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ALICLOUD_AUTH, ApiDocsTags } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { TIdentityTrustedIp } from "@app/services/identity/identity-types";
import { validateArns } from "@app/services/identity-alicloud-auth/identity-alicloud-auth-validators";
import { isSuperAdmin } from "@app/services/super-admin/super-admin-fns";
export const registerIdentityAliCloudAuthRouter = async (server: FastifyZodProvider) => {
server.route({
method: "POST",
url: "/alicloud-auth/login",
config: {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.AliCloudAuth],
description: "Login with Alibaba Cloud Auth",
body: z.object({
identityId: z.string().trim().describe(ALICLOUD_AUTH.LOGIN.identityId),
Action: z.enum(["GetCallerIdentity"]).describe(ALICLOUD_AUTH.LOGIN.Action),
Format: z.enum(["JSON"]).describe(ALICLOUD_AUTH.LOGIN.Format),
Version: z
.string()
.refine((val) => new RE2("^\\d{4}-\\d{2}-\\d{2}$").test(val), {
message: "Version must be in YYYY-MM-DD format"
})
.describe(ALICLOUD_AUTH.LOGIN.Version),
AccessKeyId: z
.string()
.refine((val) => new RE2("^[A-Za-z0-9]+$").test(val), {
message: "AccessKeyId must be alphanumeric"
})
.describe(ALICLOUD_AUTH.LOGIN.AccessKeyId),
SignatureMethod: z.enum(["HMAC-SHA1"]).describe(ALICLOUD_AUTH.LOGIN.SignatureMethod),
Timestamp: z
.string()
.refine((val) => new RE2("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$").test(val), {
message: "Timestamp must be in YYYY-MM-DDTHH:mm:ssZ format"
})
.describe(ALICLOUD_AUTH.LOGIN.Timestamp),
SignatureVersion: z.enum(["1.0"]).describe(ALICLOUD_AUTH.LOGIN.SignatureVersion),
SignatureNonce: z
.string()
.refine((val) => new RE2("^[a-zA-Z0-9-_.]+$").test(val), {
message:
"SignatureNonce must be at least 1 character long and contain only URL-safe characters (alphanumeric, -, _, .)"
})
.describe(ALICLOUD_AUTH.LOGIN.SignatureNonce),
Signature: z
.string()
.refine((val) => new RE2("^[A-Za-z0-9+/=]+$").test(val), {
message: "Signature must be base64 characters"
})
.describe(ALICLOUD_AUTH.LOGIN.Signature)
}),
response: {
200: z.object({
accessToken: z.string(),
expiresIn: z.coerce.number(),
accessTokenMaxTTL: z.coerce.number(),
tokenType: z.literal("Bearer")
})
}
},
handler: async (req) => {
const { identityAliCloudAuth, accessToken, identityAccessToken, identityMembershipOrg } =
await server.services.identityAliCloudAuth.login(req.body);
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityMembershipOrg?.orgId,
event: {
type: EventType.LOGIN_IDENTITY_ALICLOUD_AUTH,
metadata: {
identityId: identityAliCloudAuth.identityId,
identityAccessTokenId: identityAccessToken.id,
identityAliCloudAuthId: identityAliCloudAuth.id
}
}
});
return {
accessToken,
tokenType: "Bearer" as const,
expiresIn: identityAliCloudAuth.accessTokenTTL,
accessTokenMaxTTL: identityAliCloudAuth.accessTokenMaxTTL
};
}
});
server.route({
method: "POST",
url: "/alicloud-auth/identities/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AliCloudAuth],
description: "Attach Alibaba Cloud Auth configuration onto identity",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().trim().describe(ALICLOUD_AUTH.ATTACH.identityId)
}),
body: z
.object({
allowedArns: validateArns.describe(ALICLOUD_AUTH.ATTACH.allowedArns),
accessTokenTrustedIps: z
.object({
ipAddress: z.string().trim()
})
.array()
.min(1)
.default([{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }])
.describe(ALICLOUD_AUTH.ATTACH.accessTokenTrustedIps),
accessTokenTTL: z
.number()
.int()
.min(0)
.max(315360000)
.default(2592000)
.describe(ALICLOUD_AUTH.ATTACH.accessTokenTTL),
accessTokenMaxTTL: z
.number()
.int()
.min(1)
.max(315360000)
.default(2592000)
.describe(ALICLOUD_AUTH.ATTACH.accessTokenMaxTTL),
accessTokenNumUsesLimit: z
.number()
.int()
.min(0)
.default(0)
.describe(ALICLOUD_AUTH.ATTACH.accessTokenNumUsesLimit)
})
.refine(
(val) => val.accessTokenTTL <= val.accessTokenMaxTTL,
"Access Token TTL cannot be greater than Access Token Max TTL."
),
response: {
200: z.object({
identityAliCloudAuth: IdentityAlicloudAuthsSchema
})
}
},
handler: async (req) => {
const identityAliCloudAuth = await server.services.identityAliCloudAuth.attachAliCloudAuth({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
...req.body,
identityId: req.params.identityId,
isActorSuperAdmin: isSuperAdmin(req.auth)
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityAliCloudAuth.orgId,
event: {
type: EventType.ADD_IDENTITY_ALICLOUD_AUTH,
metadata: {
identityId: identityAliCloudAuth.identityId,
allowedArns: identityAliCloudAuth.allowedArns,
accessTokenTTL: identityAliCloudAuth.accessTokenTTL,
accessTokenMaxTTL: identityAliCloudAuth.accessTokenMaxTTL,
accessTokenTrustedIps: identityAliCloudAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
accessTokenNumUsesLimit: identityAliCloudAuth.accessTokenNumUsesLimit
}
}
});
return { identityAliCloudAuth };
}
});
server.route({
method: "PATCH",
url: "/alicloud-auth/identities/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AliCloudAuth],
description: "Update Alibaba Cloud Auth configuration on identity",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().describe(ALICLOUD_AUTH.UPDATE.identityId)
}),
body: z
.object({
allowedArns: validateArns.describe(ALICLOUD_AUTH.UPDATE.allowedArns),
accessTokenTrustedIps: z
.object({
ipAddress: z.string().trim()
})
.array()
.min(1)
.optional()
.describe(ALICLOUD_AUTH.UPDATE.accessTokenTrustedIps),
accessTokenTTL: z
.number()
.int()
.min(0)
.max(315360000)
.optional()
.describe(ALICLOUD_AUTH.UPDATE.accessTokenTTL),
accessTokenNumUsesLimit: z
.number()
.int()
.min(0)
.optional()
.describe(ALICLOUD_AUTH.UPDATE.accessTokenNumUsesLimit),
accessTokenMaxTTL: z
.number()
.int()
.max(315360000)
.min(0)
.optional()
.describe(ALICLOUD_AUTH.UPDATE.accessTokenMaxTTL)
})
.refine(
(val) => (val.accessTokenMaxTTL && val.accessTokenTTL ? val.accessTokenTTL <= val.accessTokenMaxTTL : true),
"Access Token TTL cannot be greater than Access Token Max TTL."
),
response: {
200: z.object({
identityAliCloudAuth: IdentityAlicloudAuthsSchema
})
}
},
handler: async (req) => {
const identityAliCloudAuth = await server.services.identityAliCloudAuth.updateAliCloudAuth({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
...req.body,
identityId: req.params.identityId,
allowedArns: req.body.allowedArns
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityAliCloudAuth.orgId,
event: {
type: EventType.UPDATE_IDENTITY_ALICLOUD_AUTH,
metadata: {
identityId: identityAliCloudAuth.identityId,
allowedArns: identityAliCloudAuth.allowedArns,
accessTokenTTL: identityAliCloudAuth.accessTokenTTL,
accessTokenMaxTTL: identityAliCloudAuth.accessTokenMaxTTL,
accessTokenTrustedIps: identityAliCloudAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
accessTokenNumUsesLimit: identityAliCloudAuth.accessTokenNumUsesLimit
}
}
});
return { identityAliCloudAuth };
}
});
server.route({
method: "GET",
url: "/alicloud-auth/identities/:identityId",
config: {
rateLimit: readLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AliCloudAuth],
description: "Retrieve Alibaba Cloud Auth configuration on identity",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().describe(ALICLOUD_AUTH.RETRIEVE.identityId)
}),
response: {
200: z.object({
identityAliCloudAuth: IdentityAlicloudAuthsSchema
})
}
},
handler: async (req) => {
const identityAliCloudAuth = await server.services.identityAliCloudAuth.getAliCloudAuth({
identityId: req.params.identityId,
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityAliCloudAuth.orgId,
event: {
type: EventType.GET_IDENTITY_ALICLOUD_AUTH,
metadata: {
identityId: identityAliCloudAuth.identityId
}
}
});
return { identityAliCloudAuth };
}
});
server.route({
method: "DELETE",
url: "/alicloud-auth/identities/:identityId",
config: {
rateLimit: writeLimit
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
schema: {
hide: false,
tags: [ApiDocsTags.AliCloudAuth],
description: "Delete Alibaba Cloud Auth configuration on identity",
security: [
{
bearerAuth: []
}
],
params: z.object({
identityId: z.string().describe(ALICLOUD_AUTH.REVOKE.identityId)
}),
response: {
200: z.object({
identityAliCloudAuth: IdentityAlicloudAuthsSchema
})
}
},
handler: async (req) => {
const identityAliCloudAuth = await server.services.identityAliCloudAuth.revokeIdentityAliCloudAuth({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
identityId: req.params.identityId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
orgId: identityAliCloudAuth.orgId,
event: {
type: EventType.REVOKE_IDENTITY_ALICLOUD_AUTH,
metadata: {
identityId: identityAliCloudAuth.identityId
}
}
});
return { identityAliCloudAuth };
}
});
};
+2
View File
@@ -15,6 +15,7 @@ import { registerCertRouter } from "./certificate-router";
import { registerCertificateTemplateRouter } from "./certificate-template-router";
import { registerExternalGroupOrgRoleMappingRouter } from "./external-group-org-role-mapping-router";
import { registerIdentityAccessTokenRouter } from "./identity-access-token-router";
import { registerIdentityAliCloudAuthRouter } from "./identity-alicloud-auth-router";
import { registerIdentityAwsAuthRouter } from "./identity-aws-iam-auth-router";
import { registerIdentityAzureAuthRouter } from "./identity-azure-auth-router";
import { registerIdentityGcpAuthRouter } from "./identity-gcp-auth-router";
@@ -63,6 +64,7 @@ export const registerV1Routes = async (server: FastifyZodProvider) => {
await authRouter.register(registerIdentityKubernetesRouter);
await authRouter.register(registerIdentityGcpAuthRouter);
await authRouter.register(registerIdentityAccessTokenRouter);
await authRouter.register(registerIdentityAliCloudAuthRouter);
await authRouter.register(registerIdentityAwsAuthRouter);
await authRouter.register(registerIdentityAzureAuthRouter);
await authRouter.register(registerIdentityOciAuthRouter);
@@ -28,6 +28,11 @@ export const identityAccessTokenDALFactory = (db: TDbClient) => {
`${TableName.IdentityUniversalAuth}.id`
)
.leftJoin(TableName.IdentityGcpAuth, `${TableName.Identity}.id`, `${TableName.IdentityGcpAuth}.identityId`)
.leftJoin(
TableName.IdentityAliCloudAuth,
`${TableName.Identity}.id`,
`${TableName.IdentityAliCloudAuth}.identityId`
)
.leftJoin(TableName.IdentityAwsAuth, `${TableName.Identity}.id`, `${TableName.IdentityAwsAuth}.identityId`)
.leftJoin(TableName.IdentityAzureAuth, `${TableName.Identity}.id`, `${TableName.IdentityAzureAuth}.identityId`)
.leftJoin(TableName.IdentityLdapAuth, `${TableName.Identity}.id`, `${TableName.IdentityLdapAuth}.identityId`)
@@ -44,6 +49,10 @@ export const identityAccessTokenDALFactory = (db: TDbClient) => {
.select(
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityUniversalAuth).as("accessTokenTrustedIpsUa"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityGcpAuth).as("accessTokenTrustedIpsGcp"),
db
.ref("accessTokenTrustedIps")
.withSchema(TableName.IdentityAliCloudAuth)
.as("accessTokenTrustedIpsAliCloud"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityAwsAuth).as("accessTokenTrustedIpsAws"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityAzureAuth).as("accessTokenTrustedIpsAzure"),
db.ref("accessTokenTrustedIps").withSchema(TableName.IdentityKubernetesAuth).as("accessTokenTrustedIpsK8s"),
@@ -62,6 +71,7 @@ export const identityAccessTokenDALFactory = (db: TDbClient) => {
...doc,
trustedIpsUniversalAuth: doc.accessTokenTrustedIpsUa,
trustedIpsGcpAuth: doc.accessTokenTrustedIpsGcp,
trustedIpsAliCloudAuth: doc.accessTokenTrustedIpsAliCloud,
trustedIpsAwsAuth: doc.accessTokenTrustedIpsAws,
trustedIpsAzureAuth: doc.accessTokenTrustedIpsAzure,
trustedIpsKubernetesAuth: doc.accessTokenTrustedIpsK8s,
@@ -193,6 +193,7 @@ export const identityAccessTokenServiceFactory = ({
const trustedIpsMap: Record<IdentityAuthMethod, unknown> = {
[IdentityAuthMethod.UNIVERSAL_AUTH]: identityAccessToken.trustedIpsUniversalAuth,
[IdentityAuthMethod.GCP_AUTH]: identityAccessToken.trustedIpsGcpAuth,
[IdentityAuthMethod.ALICLOUD_AUTH]: identityAccessToken.trustedIpsAliCloudAuth,
[IdentityAuthMethod.AWS_AUTH]: identityAccessToken.trustedIpsAwsAuth,
[IdentityAuthMethod.OCI_AUTH]: identityAccessToken.trustedIpsOciAuth,
[IdentityAuthMethod.AZURE_AUTH]: identityAccessToken.trustedIpsAzureAuth,
@@ -0,0 +1,9 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex";
export type TIdentityAliCloudAuthDALFactory = ReturnType<typeof identityAliCloudAuthDALFactory>;
export const identityAliCloudAuthDALFactory = (db: TDbClient) => {
return ormify(db, TableName.IdentityAliCloudAuth);
};
@@ -0,0 +1,361 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { ForbiddenError } from "@casl/ability";
import { AxiosError } from "axios";
import jwt from "jsonwebtoken";
import { IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import { OrgPermissionIdentityActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import {
constructPermissionErrorMessage,
validatePrivilegeChangeOperation
} from "@app/ee/services/permission/permission-fns";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { request } from "@app/lib/config/request";
import { BadRequestError, NotFoundError, PermissionBoundaryError, UnauthorizedError } from "@app/lib/errors";
import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
import { logger } from "@app/lib/logger";
import { ActorType, AuthTokenType } from "../auth/auth-type";
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";
import { validateIdentityUpdateForSuperAdminPrivileges } from "../super-admin/super-admin-fns";
import { TIdentityAliCloudAuthDALFactory } from "./identity-alicloud-auth-dal";
import {
TAliCloudGetUserResponse,
TAttachAliCloudAuthDTO,
TGetAliCloudAuthDTO,
TLoginAliCloudAuthDTO,
TRevokeAliCloudAuthDTO,
TUpdateAliCloudAuthDTO
} from "./identity-alicloud-auth-types";
type TIdentityAliCloudAuthServiceFactoryDep = {
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "delete">;
identityAliCloudAuthDAL: Pick<
TIdentityAliCloudAuthDALFactory,
"findOne" | "transaction" | "create" | "updateById" | "delete"
>;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
};
export type TIdentityAliCloudAuthServiceFactory = ReturnType<typeof identityAliCloudAuthServiceFactory>;
export const identityAliCloudAuthServiceFactory = ({
identityAccessTokenDAL,
identityAliCloudAuthDAL,
identityOrgMembershipDAL,
licenseService,
permissionService
}: TIdentityAliCloudAuthServiceFactoryDep) => {
const login = async ({ identityId, ...params }: TLoginAliCloudAuthDTO) => {
const identityAliCloudAuth = await identityAliCloudAuthDAL.findOne({ identityId });
if (!identityAliCloudAuth) {
throw new NotFoundError({
message: "Alibaba Cloud auth method not found for identity, did you configure Alibaba Cloud auth?"
});
}
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({
identityId: identityAliCloudAuth.identityId
});
const queryString = Object.keys(params)
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent((params as Record<string, string>)[key])}`)
.join("&");
const { data } = await request
.get<TAliCloudGetUserResponse>(`https://sts.aliyuncs.com/?${queryString}`)
.catch((err: AxiosError) => {
logger.error(err.response, "AliCloudIdentityLogin: Failed to authenticate with Alibaba Cloud");
throw err;
});
if (identityAliCloudAuth.allowedArns) {
// In the future we could do partial checks for role ARNs
const isAccountAllowed = identityAliCloudAuth.allowedArns.split(",").some((arn) => arn.trim() === data.Arn);
if (!isAccountAllowed)
throw new UnauthorizedError({
message: "Access denied: Alibaba Cloud account ARN not allowed."
});
}
// Generate the token
const identityAccessToken = await identityAliCloudAuthDAL.transaction(async (tx) => {
const newToken = await identityAccessTokenDAL.create(
{
identityId: identityAliCloudAuth.identityId,
isAccessTokenRevoked: false,
accessTokenTTL: identityAliCloudAuth.accessTokenTTL,
accessTokenMaxTTL: identityAliCloudAuth.accessTokenMaxTTL,
accessTokenNumUses: 0,
accessTokenNumUsesLimit: identityAliCloudAuth.accessTokenNumUsesLimit,
authMethod: IdentityAuthMethod.ALICLOUD_AUTH
},
tx
);
return newToken;
});
const appCfg = getConfig();
const accessToken = jwt.sign(
{
identityId: identityAliCloudAuth.identityId,
identityAccessTokenId: identityAccessToken.id,
authTokenType: AuthTokenType.IDENTITY_ACCESS_TOKEN
} as TIdentityAccessTokenJwtPayload,
appCfg.AUTH_SECRET,
Number(identityAccessToken.accessTokenTTL) === 0
? undefined
: {
expiresIn: Number(identityAccessToken.accessTokenTTL)
}
);
return {
identityAliCloudAuth,
accessToken,
identityAccessToken,
identityMembershipOrg
};
};
const attachAliCloudAuth = async ({
identityId,
allowedArns,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps,
actorId,
actorAuthMethod,
actor,
actorOrgId,
isActorSuperAdmin
}: TAttachAliCloudAuthDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new BadRequestError({
message: "Failed to add Alibaba Cloud Auth to already configured identity"
});
}
if (accessTokenMaxTTL > 0 && accessTokenTTL > accessTokenMaxTTL) {
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
}
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" &&
accessTokenTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({
message:
"Failed to add IP access range to access token due to plan restriction. Upgrade plan to add IP access range."
});
if (!isValidIpOrCidr(accessTokenTrustedIp.ipAddress))
throw new BadRequestError({
message: "The IP is not a valid IPv4, IPv6, or CIDR block"
});
return extractIPDetails(accessTokenTrustedIp.ipAddress);
});
const identityAliCloudAuth = await identityAliCloudAuthDAL.transaction(async (tx) => {
const doc = await identityAliCloudAuthDAL.create(
{
identityId: identityMembershipOrg.identityId,
type: "iam",
allowedArns,
accessTokenMaxTTL,
accessTokenTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps: JSON.stringify(reformattedAccessTokenTrustedIps)
},
tx
);
return doc;
});
return { ...identityAliCloudAuth, orgId: identityMembershipOrg.orgId };
};
const updateAliCloudAuth = async ({
identityId,
allowedArns,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps,
actorId,
actorAuthMethod,
actor,
actorOrgId
}: TUpdateAliCloudAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new NotFoundError({
message: "The identity does not have Alibaba Cloud Auth attached"
});
}
const identityAliCloudAuth = await identityAliCloudAuthDAL.findOne({ identityId });
if (
(accessTokenMaxTTL || identityAliCloudAuth.accessTokenMaxTTL) > 0 &&
(accessTokenTTL || identityAliCloudAuth.accessTokenTTL) >
(accessTokenMaxTTL || identityAliCloudAuth.accessTokenMaxTTL)
) {
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
}
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" &&
accessTokenTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({
message:
"Failed to add IP access range to access token due to plan restriction. Upgrade plan to add IP access range."
});
if (!isValidIpOrCidr(accessTokenTrustedIp.ipAddress))
throw new BadRequestError({
message: "The IP is not a valid IPv4, IPv6, or CIDR block"
});
return extractIPDetails(accessTokenTrustedIp.ipAddress);
});
const updatedAliCloudAuth = await identityAliCloudAuthDAL.updateById(identityAliCloudAuth.id, {
allowedArns,
accessTokenMaxTTL,
accessTokenTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps: reformattedAccessTokenTrustedIps
? JSON.stringify(reformattedAccessTokenTrustedIps)
: undefined
});
return { ...updatedAliCloudAuth, orgId: identityMembershipOrg.orgId };
};
const getAliCloudAuth = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId }: TGetAliCloudAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new BadRequestError({
message: "The identity does not have Alibaba Cloud Auth attached"
});
}
const alicloudIdentityAuth = await identityAliCloudAuthDAL.findOne({ identityId });
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Read, OrgPermissionSubjects.Identity);
return { ...alicloudIdentityAuth, orgId: identityMembershipOrg.orgId };
};
const revokeIdentityAliCloudAuth = async ({
identityId,
actorId,
actor,
actorAuthMethod,
actorOrgId
}: TRevokeAliCloudAuthDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new NotFoundError({ message: `Failed to find identity with ID ${identityId}` });
if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.ALICLOUD_AUTH)) {
throw new BadRequestError({
message: "The identity does not have Alibaba Cloud auth"
});
}
const { permission, membership } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Edit, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
identityMembershipOrg.identityId,
identityMembershipOrg.orgId,
actorAuthMethod,
actorOrgId
);
const permissionBoundary = validatePrivilegeChangeOperation(
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity,
permission,
rolePermission
);
if (!permissionBoundary.isValid)
throw new PermissionBoundaryError({
message: constructPermissionErrorMessage(
"Failed to revoke Alibaba Cloud auth of identity with more privileged role",
membership.shouldUseNewPrivilegeSystem,
OrgPermissionIdentityActions.RevokeAuth,
OrgPermissionSubjects.Identity
),
details: { missingPermissions: permissionBoundary.missingPermissions }
});
const revokedIdentityAliCloudAuth = await identityAliCloudAuthDAL.transaction(async (tx) => {
const deletedAliCloudAuth = await identityAliCloudAuthDAL.delete({ identityId }, tx);
await identityAccessTokenDAL.delete({ identityId, authMethod: IdentityAuthMethod.ALICLOUD_AUTH }, tx);
return { ...deletedAliCloudAuth?.[0], orgId: identityMembershipOrg.orgId };
});
return revokedIdentityAliCloudAuth;
};
return {
login,
attachAliCloudAuth,
updateAliCloudAuth,
getAliCloudAuth,
revokeIdentityAliCloudAuth
};
};
@@ -0,0 +1,45 @@
import { TProjectPermission } from "@app/lib/types";
export type TLoginAliCloudAuthDTO = {
identityId: string;
Action: string;
Format: string;
Version: string;
AccessKeyId: string;
SignatureMethod: string;
Timestamp: string;
SignatureVersion: string;
SignatureNonce: string;
Signature: string;
};
export type TAttachAliCloudAuthDTO = {
identityId: string;
allowedArns: string;
accessTokenTTL: number;
accessTokenMaxTTL: number;
accessTokenNumUsesLimit: number;
accessTokenTrustedIps: { ipAddress: string }[];
isActorSuperAdmin?: boolean;
} & Omit<TProjectPermission, "projectId">;
export type TUpdateAliCloudAuthDTO = {
identityId: string;
allowedArns: string;
accessTokenTTL?: number;
accessTokenMaxTTL?: number;
accessTokenNumUsesLimit?: number;
accessTokenTrustedIps?: { ipAddress: string }[];
} & Omit<TProjectPermission, "projectId">;
export type TGetAliCloudAuthDTO = {
identityId: string;
} & Omit<TProjectPermission, "projectId">;
export type TRevokeAliCloudAuthDTO = {
identityId: string;
} & Omit<TProjectPermission, "projectId">;
export type TAliCloudGetUserResponse = {
Arn: string;
};
@@ -0,0 +1,25 @@
import RE2 from "re2";
import { z } from "zod";
const arnSchema = z
.string()
.refine(
(val) => new RE2("^acs:ram::[0-9]{16}:(user|role)/.*$").test(val),
"Invalid ARN format. Expected format: acs:ram::[0-9]{16}:(user|role)/*"
);
export const validateArns = z
.string()
.trim()
.min(1, "Allowed ARNs required")
.max(500, "Input exceeds the maximum limit of 500 characters")
.transform((val) => {
if (!val) return [];
return val
.split(",")
.map((s) => s.trim())
.filter(Boolean);
})
.refine((arr) => arr.every((name) => arnSchema.safeParse(name).success), {
message: "One or more ARNs are invalid"
})
.transform((arr) => arr.join(", "));
@@ -4,6 +4,7 @@ import { TDbClient } from "@app/db";
import {
TableName,
TIdentities,
TIdentityAlicloudAuths,
TIdentityAwsAuths,
TIdentityAzureAuths,
TIdentityGcpAuths,
@@ -57,6 +58,11 @@ export const identityProjectDALFactory = (db: TDbClient) => {
`${TableName.IdentityProjectMembership}.identityId`,
`${TableName.IdentityGcpAuth}.identityId`
)
.leftJoin(
TableName.IdentityAliCloudAuth,
`${TableName.IdentityProjectMembership}.identityId`,
`${TableName.IdentityAliCloudAuth}.identityId`
)
.leftJoin(
TableName.IdentityAwsAuth,
`${TableName.IdentityProjectMembership}.identityId`,
@@ -111,6 +117,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
db.ref("type").as("projectType").withSchema(TableName.Project),
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
db.ref("id").as("alicloudId").withSchema(TableName.IdentityAliCloudAuth),
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
db.ref("id").as("ociId").withSchema(TableName.IdentityOciAuth),
@@ -267,6 +274,11 @@ export const identityProjectDALFactory = (db: TDbClient) => {
`${TableName.Identity}.id`,
`${TableName.IdentityGcpAuth}.identityId`
)
.leftJoin<TIdentityAlicloudAuths>(
TableName.IdentityAliCloudAuth,
`${TableName.Identity}.id`,
`${TableName.IdentityAliCloudAuth}.identityId`
)
.leftJoin<TIdentityAwsAuths>(
TableName.IdentityAwsAuth,
`${TableName.Identity}.id`,
@@ -319,6 +331,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
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("alicloudId").withSchema(TableName.IdentityAliCloudAuth),
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
db.ref("id").as("ociId").withSchema(TableName.IdentityOciAuth),
@@ -346,6 +359,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
identityId,
identityName,
uaId,
alicloudId,
awsId,
gcpId,
kubernetesId,
@@ -367,6 +381,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
name: identityName,
authMethods: buildAuthMethods({
uaId,
alicloudId,
awsId,
gcpId,
kubernetesId,
@@ -3,6 +3,7 @@ import { IdentityAuthMethod } from "@app/db/schemas";
export const buildAuthMethods = ({
uaId,
gcpId,
alicloudId,
awsId,
kubernetesId,
ociId,
@@ -14,6 +15,7 @@ export const buildAuthMethods = ({
}: {
uaId?: string;
gcpId?: string;
alicloudId?: string;
awsId?: string;
kubernetesId?: string;
ociId?: string;
@@ -26,6 +28,7 @@ export const buildAuthMethods = ({
return [
...[uaId ? IdentityAuthMethod.UNIVERSAL_AUTH : null],
...[gcpId ? IdentityAuthMethod.GCP_AUTH : null],
...[alicloudId ? IdentityAuthMethod.ALICLOUD_AUTH : null],
...[awsId ? IdentityAuthMethod.AWS_AUTH : null],
...[kubernetesId ? IdentityAuthMethod.KUBERNETES_AUTH : null],
...[ociId ? IdentityAuthMethod.OCI_AUTH : null],
@@ -3,6 +3,7 @@ import { Knex } from "knex";
import { TDbClient } from "@app/db";
import {
TableName,
TIdentityAlicloudAuths,
TIdentityAwsAuths,
TIdentityAzureAuths,
TIdentityGcpAuths,
@@ -53,6 +54,11 @@ export const identityOrgDALFactory = (db: TDbClient) => {
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityGcpAuth}.identityId`
)
.leftJoin<TIdentityAlicloudAuths>(
TableName.IdentityAliCloudAuth,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.IdentityAliCloudAuth}.identityId`
)
.leftJoin<TIdentityAwsAuths>(
TableName.IdentityAwsAuth,
`${TableName.IdentityOrgMembership}.identityId`,
@@ -99,6 +105,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
db.ref("id").as("alicloudId").withSchema(TableName.IdentityAliCloudAuth),
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
db.ref("id").as("ociId").withSchema(TableName.IdentityOciAuth),
@@ -183,6 +190,11 @@ export const identityOrgDALFactory = (db: TDbClient) => {
"paginatedIdentity.identityId",
`${TableName.IdentityGcpAuth}.identityId`
)
.leftJoin<TIdentityAlicloudAuths>(
TableName.IdentityAliCloudAuth,
"paginatedIdentity.identityId",
`${TableName.IdentityAliCloudAuth}.identityId`
)
.leftJoin<TIdentityAwsAuths>(
TableName.IdentityAwsAuth,
"paginatedIdentity.identityId",
@@ -236,6 +248,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
db.ref("id").as("alicloudId").withSchema(TableName.IdentityAliCloudAuth),
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
db.ref("id").as("ociId").withSchema(TableName.IdentityOciAuth),
@@ -278,6 +291,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
id,
orgId,
uaId,
alicloudId,
awsId,
gcpId,
jwtId,
@@ -312,6 +326,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
name: identityName,
authMethods: buildAuthMethods({
uaId,
alicloudId,
awsId,
gcpId,
kubernetesId,
@@ -459,6 +474,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
db.ref("id").as("alicloudId").withSchema(TableName.IdentityAliCloudAuth),
db.ref("id").as("awsId").withSchema(TableName.IdentityAwsAuth),
db.ref("id").as("kubernetesId").withSchema(TableName.IdentityKubernetesAuth),
db.ref("id").as("ociId").withSchema(TableName.IdentityOciAuth),
@@ -502,6 +518,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
total_count,
id,
uaId,
alicloudId,
awsId,
gcpId,
jwtId,
@@ -536,6 +553,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
name: identityName,
authMethods: buildAuthMethods({
uaId,
alicloudId,
awsId,
gcpId,
kubernetesId,