feat(api): add Cognito user pools to the cloud explorer
Adds a userpools catalog entry, schema and AwsUserPoolsAdapter, verified against Floci core: - list/get/create/delete user pools; create can set email or username sign-in, a relaxed password policy for local test users, and a public app client (on by default) whose id is surfaced in the pool metadata - users as the pool's child items: list (paged), get, create and delete; passwords are set permanent by default so users can sign in at once - map Cognito's HTTP-400 error names (UserNotFoundException, UsernameExistsException, AliasExistsException, InvalidPasswordException) - link Floci's cognito-idp service to the new page on the diagnostics page
This commit is contained in:
@@ -239,6 +239,13 @@ export const SERVICE_CATALOG = {
|
||||
// AWS retains its dedicated page while Azure and GCP use Cloud Explorer.
|
||||
routeByCloud: {aws: '/secretsmanager'},
|
||||
},
|
||||
userpools: {
|
||||
displayName: 'User Directories',
|
||||
displayNameByCloud: {aws: 'Cognito'},
|
||||
iconKey: 'userpools',
|
||||
group: 'Security',
|
||||
order: 7,
|
||||
},
|
||||
iac: {
|
||||
displayName: 'Infrastructure as Code',
|
||||
displayNameByCloud: {aws: 'CloudFormation'},
|
||||
|
||||
@@ -230,7 +230,7 @@ export type KnownResourceType =
|
||||
| 'instance' | 'image' | 'vpc' | 'lambda' | 'azure-function' | 'gcp-function'
|
||||
| 'secret' | 'iam-user' | 'servicebus-namespace' | 'queue' | 'fifo-queue'
|
||||
| 'topic' | 'event-bus' | 'rest-api' | 'stack' | 'email' | 'sql-server'
|
||||
| 'postgres-flexible-server' | 'load-balancer' | 'state-machine' | 'scheduler-job' | 'key' | 'parameter' | 'cloud-run-service' | 'log-group'
|
||||
| 'postgres-flexible-server' | 'load-balancer' | 'state-machine' | 'scheduler-job' | 'key' | 'parameter' | 'cloud-run-service' | 'log-group' | 'user-pool'
|
||||
|
||||
export interface CloudResource {
|
||||
id: string
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import type {CloudProvider, FieldSchema, ServiceSchema, TableColumnSchema} from './types'
|
||||
|
||||
/** Cognito's own limit and character set for user pool names. */
|
||||
export const USER_POOL_NAME_PATTERN = '^[\\w\\s+=,.@-]{1,128}$'
|
||||
export const USER_POOL_SIGN_IN = ['email', 'username'] as const
|
||||
export const USER_POOL_PASSWORD_POLICIES = ['default', 'relaxed'] as const
|
||||
|
||||
const userPoolColumns: TableColumnSchema[] = [
|
||||
{name: 'name', label: 'Name'},
|
||||
{name: 'id', label: 'Pool ID', format: 'code'},
|
||||
{name: 'status', label: 'Status', format: 'badge'},
|
||||
{name: 'createdAt', label: 'Created', format: 'datetime'},
|
||||
]
|
||||
|
||||
const userPoolFilters: FieldSchema[] = [{name: 'search', label: 'Search', type: 'text', required: false}]
|
||||
|
||||
export function awsUserPoolsSchema(): ServiceSchema {
|
||||
return {
|
||||
cloud: 'aws',
|
||||
service: 'userpools',
|
||||
displayName: 'Amazon Cognito user pools',
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Pool name',
|
||||
type: 'text',
|
||||
required: true,
|
||||
validation: {pattern: USER_POOL_NAME_PATTERN, message: 'Use up to 128 letters, digits, spaces or + = , . @ _ -'},
|
||||
},
|
||||
{
|
||||
name: 'signInWith',
|
||||
label: 'Sign in with',
|
||||
type: 'select',
|
||||
required: false,
|
||||
defaultValue: 'email',
|
||||
description: 'Email makes the address the sign-in name; username keeps a separate user name.',
|
||||
options: [{label: 'Email address', value: 'email'}, {label: 'Username', value: 'username'}],
|
||||
},
|
||||
{
|
||||
name: 'passwordPolicy',
|
||||
label: 'Password policy',
|
||||
type: 'select',
|
||||
required: false,
|
||||
defaultValue: 'default',
|
||||
description: 'Relaxed only requires 8 characters, which keeps local test users quick to create.',
|
||||
options: [
|
||||
{label: 'AWS default (upper, lower, number, symbol)', value: 'default'},
|
||||
{label: 'Relaxed (8+ characters)', value: 'relaxed'},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'createAppClient',
|
||||
label: 'App client',
|
||||
type: 'select',
|
||||
required: false,
|
||||
defaultValue: 'yes',
|
||||
description: 'A public client (no secret) with username/password and refresh-token sign-in, named <pool>-client.',
|
||||
options: [{label: 'Create an app client', value: 'yes'}, {label: 'No app client', value: 'no'}],
|
||||
},
|
||||
],
|
||||
actions: ['list', 'create', 'delete', 'inspect'],
|
||||
capabilities: {
|
||||
resourceActions: [
|
||||
{name: 'list', label: 'List user pools', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'create', label: 'Create user pool', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete user pool', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'inspect', label: 'Inspect user pool', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
itemActions: [
|
||||
{name: 'list', label: 'List users', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'get', label: 'Get user', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'put', label: 'Create user', enabled: true, status: 'available', runtimeRequired: true},
|
||||
{name: 'delete', label: 'Delete user', enabled: true, status: 'available', runtimeRequired: true},
|
||||
],
|
||||
},
|
||||
filters: userPoolFilters,
|
||||
columns: userPoolColumns,
|
||||
}
|
||||
}
|
||||
|
||||
export function userPoolsSchemaFor(cloud: CloudProvider): ServiceSchema | null {
|
||||
return cloud === 'aws' ? awsUserPoolsSchema() : null
|
||||
}
|
||||
Reference in New Issue
Block a user