Files
simstudioai--sim/apps/sim/app/api/tools/identity-center/utils.ts
T
wehub-resource-sync d25d482dc2
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

305 lines
9.3 KiB
TypeScript

import {
DescribeGroupCommand,
DescribeUserCommand,
GetGroupIdCommand,
GetUserIdCommand,
IdentitystoreClient,
ListGroupsCommand,
} from '@aws-sdk/client-identitystore'
import {
DescribeAccountCommand,
ListAccountsCommand,
OrganizationsClient,
} from '@aws-sdk/client-organizations'
import {
type AccountAssignmentOperationStatus,
DescribeAccountAssignmentCreationStatusCommand,
DescribeAccountAssignmentDeletionStatusCommand,
DescribePermissionSetCommand,
ListAccountAssignmentsForPrincipalCommand,
ListInstancesCommand,
ListPermissionSetsCommand,
type PrincipalType,
SSOAdminClient,
} from '@aws-sdk/client-sso-admin'
import type { IdentityCenterConnectionConfig } from '@/tools/identity_center/types'
export function createSSOAdminClient(config: IdentityCenterConnectionConfig): SSOAdminClient {
return new SSOAdminClient({
region: config.region,
credentials: {
accessKeyId: config.accessKeyId,
secretAccessKey: config.secretAccessKey,
},
})
}
export function createIdentityStoreClient(
config: IdentityCenterConnectionConfig
): IdentitystoreClient {
return new IdentitystoreClient({
region: config.region,
credentials: {
accessKeyId: config.accessKeyId,
secretAccessKey: config.secretAccessKey,
},
})
}
export function createOrganizationsClient(config: IdentityCenterConnectionConfig) {
return new OrganizationsClient({
region: 'us-east-1', // Organizations API only available in us-east-1
credentials: {
accessKeyId: config.accessKeyId,
secretAccessKey: config.secretAccessKey,
},
})
}
export async function listInstances(
client: SSOAdminClient,
maxResults?: number | null,
nextToken?: string | null
) {
const command = new ListInstancesCommand({
...(maxResults ? { MaxResults: maxResults } : {}),
...(nextToken ? { NextToken: nextToken } : {}),
})
const response = await client.send(command)
const instances = (response.Instances ?? []).map((instance) => ({
instanceArn: instance.InstanceArn ?? '',
identityStoreId: instance.IdentityStoreId ?? '',
name: instance.Name ?? null,
status: instance.Status ?? '',
statusReason: instance.StatusReason ?? null,
ownerAccountId: instance.OwnerAccountId ?? null,
createdDate: instance.CreatedDate?.toISOString() ?? null,
}))
return { instances, nextToken: response.NextToken ?? null, count: instances.length }
}
export async function listAccounts(
client: OrganizationsClient,
maxResults?: number | null,
nextToken?: string | null
) {
const command = new ListAccountsCommand({
...(maxResults ? { MaxResults: maxResults } : {}),
...(nextToken ? { NextToken: nextToken } : {}),
})
const response = await client.send(command)
const accounts = (response.Accounts ?? []).map((account) => ({
id: account.Id ?? '',
arn: account.Arn ?? '',
name: account.Name ?? '',
email: account.Email ?? '',
status: account.State ?? '',
joinedTimestamp: account.JoinedTimestamp?.toISOString() ?? null,
}))
return { accounts, nextToken: response.NextToken ?? null, count: accounts.length }
}
export async function listPermissionSets(
client: SSOAdminClient,
instanceArn: string,
maxResults?: number | null,
nextToken?: string | null
) {
const listCommand = new ListPermissionSetsCommand({
InstanceArn: instanceArn,
...(maxResults ? { MaxResults: maxResults } : {}),
...(nextToken ? { NextToken: nextToken } : {}),
})
const listResponse = await client.send(listCommand)
const permissionSetArns = listResponse.PermissionSets ?? []
const permissionSets = await Promise.all(
permissionSetArns.map(async (arn) => {
const describeCommand = new DescribePermissionSetCommand({
InstanceArn: instanceArn,
PermissionSetArn: arn,
})
const describeResponse = await client.send(describeCommand)
const ps = describeResponse.PermissionSet
return {
permissionSetArn: ps?.PermissionSetArn ?? arn,
name: ps?.Name ?? '',
description: ps?.Description ?? null,
sessionDuration: ps?.SessionDuration ?? null,
createdDate: ps?.CreatedDate?.toISOString() ?? null,
}
})
)
return {
permissionSets,
nextToken: listResponse.NextToken ?? null,
count: permissionSets.length,
}
}
export async function getUserByEmail(
ssoClient: IdentitystoreClient,
identityStoreId: string,
email: string
) {
const getUserIdCommand = new GetUserIdCommand({
IdentityStoreId: identityStoreId,
AlternateIdentifier: {
UniqueAttribute: {
AttributePath: 'emails.value',
AttributeValue: email,
},
},
})
const getUserIdResponse = await ssoClient.send(getUserIdCommand)
const userId = getUserIdResponse.UserId ?? ''
const describeCommand = new DescribeUserCommand({
IdentityStoreId: identityStoreId,
UserId: userId,
})
const describeResponse = await ssoClient.send(describeCommand)
const primaryEmail =
describeResponse.Emails?.find((e) => e.Primary)?.Value ??
describeResponse.Emails?.[0]?.Value ??
null
return {
userId,
userName: describeResponse.UserName ?? '',
displayName: describeResponse.DisplayName ?? null,
email: primaryEmail,
}
}
export function mapAssignmentStatus(status: AccountAssignmentOperationStatus) {
return {
status: status.Status ?? '',
requestId: status.RequestId ?? '',
accountId: status.TargetId ?? null,
permissionSetArn: status.PermissionSetArn ?? null,
principalType: status.PrincipalType ?? null,
principalId: status.PrincipalId ?? null,
failureReason: status.FailureReason ?? null,
createdDate: status.CreatedDate?.toISOString() ?? null,
}
}
export async function checkAssignmentCreationStatus(
client: SSOAdminClient,
instanceArn: string,
requestId: string
) {
const command = new DescribeAccountAssignmentCreationStatusCommand({
InstanceArn: instanceArn,
AccountAssignmentCreationRequestId: requestId,
})
const response = await client.send(command)
return mapAssignmentStatus(response.AccountAssignmentCreationStatus ?? {})
}
export async function checkAssignmentDeletionStatus(
client: SSOAdminClient,
instanceArn: string,
requestId: string
) {
const command = new DescribeAccountAssignmentDeletionStatusCommand({
InstanceArn: instanceArn,
AccountAssignmentDeletionRequestId: requestId,
})
const response = await client.send(command)
return mapAssignmentStatus(response.AccountAssignmentDeletionStatus ?? {})
}
export async function listGroups(
client: IdentitystoreClient,
identityStoreId: string,
maxResults?: number | null,
nextToken?: string | null
) {
const command = new ListGroupsCommand({
IdentityStoreId: identityStoreId,
...(maxResults ? { MaxResults: maxResults } : {}),
...(nextToken ? { NextToken: nextToken } : {}),
})
const response = await client.send(command)
const groups = (response.Groups ?? []).map((group) => ({
groupId: group.GroupId ?? '',
displayName: group.DisplayName ?? null,
description: group.Description ?? null,
externalIds: group.ExternalIds?.map((e) => ({ issuer: e.Issuer ?? '', id: e.Id ?? '' })) ?? [],
}))
return { groups, nextToken: response.NextToken ?? null, count: groups.length }
}
export async function getGroupByDisplayName(
client: IdentitystoreClient,
identityStoreId: string,
displayName: string
) {
const getGroupIdCommand = new GetGroupIdCommand({
IdentityStoreId: identityStoreId,
AlternateIdentifier: {
UniqueAttribute: {
AttributePath: 'displayName',
AttributeValue: displayName,
},
},
})
const getGroupIdResponse = await client.send(getGroupIdCommand)
const groupId = getGroupIdResponse.GroupId ?? ''
const describeCommand = new DescribeGroupCommand({
IdentityStoreId: identityStoreId,
GroupId: groupId,
})
const describeResponse = await client.send(describeCommand)
return {
groupId,
displayName: describeResponse.DisplayName ?? null,
description: describeResponse.Description ?? null,
}
}
export async function describeAccount(client: OrganizationsClient, accountId: string) {
const command = new DescribeAccountCommand({ AccountId: accountId })
const response = await client.send(command)
const account = response.Account
return {
id: account?.Id ?? '',
arn: account?.Arn ?? '',
name: account?.Name ?? '',
email: account?.Email ?? '',
status: account?.State ?? '',
joinedTimestamp: account?.JoinedTimestamp?.toISOString() ?? null,
}
}
export async function listAccountAssignmentsForPrincipal(
client: SSOAdminClient,
instanceArn: string,
principalId: string,
principalType: string,
maxResults?: number | null,
nextToken?: string | null
) {
const command = new ListAccountAssignmentsForPrincipalCommand({
InstanceArn: instanceArn,
PrincipalId: principalId,
PrincipalType: principalType as PrincipalType,
...(maxResults ? { MaxResults: maxResults } : {}),
...(nextToken ? { NextToken: nextToken } : {}),
})
const response = await client.send(command)
const assignments = (response.AccountAssignments ?? []).map((a) => ({
accountId: a.AccountId ?? '',
permissionSetArn: a.PermissionSetArn ?? '',
principalType: a.PrincipalType ?? '',
principalId: a.PrincipalId ?? '',
}))
return { assignments, nextToken: response.NextToken ?? null, count: assignments.length }
}