Skip to content

Commit

Permalink
fix: limit query parameter parsing in auth admin api (#13512)
Browse files Browse the repository at this point in the history
* fix: limit query parameter parsing in auth admin api

* try this

* pr feedback
sobolk authored Jan 3, 2024
1 parent 9034f86 commit 2480681
Showing 6 changed files with 537 additions and 407 deletions.
9 changes: 0 additions & 9 deletions codebuild_specs/e2e_workflow_base.yml
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ env:
AWS_REGION: us-east-1
CDK_DEFAULT_REGION: us-east-1
CLI_REGION: us-east-1
TEST_SUITE: src/__tests__/auth_2b.test.ts
AMPLIFY_DIR: '$CODEBUILD_SRC_DIR/out'
AMPLIFY_PATH: '$CODEBUILD_SRC_DIR/out/amplify-pkg-linux-x64'

@@ -102,14 +101,10 @@ batch:
compute-type: BUILD_GENERAL1_LARGE
- identifier: amplify_sudo_install_test
buildspec: codebuild_specs/amplify_sudo_install_test.yml
env:
compute-type: BUILD_GENERAL1_MEDIUM
depend-on:
- upb
- identifier: amplify_install_test
buildspec: codebuild_specs/amplify_install_test.yml
env:
compute-type: BUILD_GENERAL1_MEDIUM
depend-on:
- upb
- identifier: amplify_console_integration_tests
@@ -120,14 +115,10 @@ batch:
- upb
- identifier: amplify_migration_tests_non_multi_env_layers
buildspec: codebuild_specs/amplify_migration_tests_non_multi_env_layers.yml
env:
compute-type: BUILD_GENERAL1_MEDIUM
depend-on:
- upb
- identifier: amplify_migration_tests_multi_env_layers
buildspec: codebuild_specs/amplify_migration_tests_multi_env_layers.yml
env:
compute-type: BUILD_GENERAL1_MEDIUM
depend-on:
- upb
- identifier: amplify_general_config_tests
606 changes: 298 additions & 308 deletions codebuild_specs/e2e_workflow_generated.yml

Large diffs are not rendered by default.

104 changes: 52 additions & 52 deletions codebuild_specs/wait_for_ids.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
[
"l_S3server_api_8_function_8",
"l_amplify_app",
"l_amplify_configure_env_2_init_d",
"l_analytics_kinesis_analytics_pinpoint_flutter_analytics_pinpoint_js",
"l_android_notifications_pinpoint_config_flutter_analytics_pinpoint_config_flutter_notifications_pinpoint_config",
"l_android_analytics_pinpoint_config_android_notifications_pinpoint_config_flutter_analytics_pinpoint_config",
"l_api_2b_api_6c_api_9a",
"l_api_3_api_6b_api_1",
"l_api_4_containers_api_secrets_storage_4",
"l_api_6a_auth_7b_export_pull_b",
"l_api_6b_api_1_layer_1",
"l_api_7_export_pull_a_function_9a",
"l_api_graphql_v2_migration_v10",
"l_api_key_migration1_schema_auth_14_api_3",
"l_api_key_migration4_schema_iterative_update_4_function_1",
"l_api_key_migration_2_v8",
"l_api_key_migration_v8",
"l_api_lambda_auth_1_api_key_migration2_schema_searchable",
"l_api_rest_basic_migration_v10",
"l_api_rest_lambda_migration_v10",
"l_api_rest_serverless_migration_v10",
"l_apigw_api_lambda_auth_1_api_key_migration2",
"l_auth_12_auth_2g_auth_2h",
"l_auth_1a_auth_trigger_custom_policies_function",
"l_auth_1b_delete_geo_add_c",
@@ -28,8 +26,7 @@
"l_auth_3a_auth_3b_auth_4a",
"l_auth_4b_auth_8a_export_pull_d",
"l_auth_4c_auth_5a_auth_5c",
"l_auth_5g_hosted_ui_user_groups_s3_access",
"l_auth_6_function_2a_schema_connection_2",
"l_auth_5g_admin_api_hosted_ui",
"l_auth_7a_auth_8c_feature_flags",
"l_auth_9_custom_resources_env_5",
"l_auth_add_all_migration_v10",
@@ -42,26 +39,29 @@
"l_auth_migration_v12",
"l_auth_oauth_lambda_migration_v12",
"l_auth_override_migration_v10",
"l_build_function_custom_resource_with_storage_dynamodb_simulator",
"l_container_hosting_init_b_notifications_apns",
"l_containers_api_1",
"l_containers_api_2",
"l_containers_api_secrets_storage_4_schema_auth_10",
"l_custom_resource_with_storage_dynamodb_simulator_export_pull_c",
"l_custom_policies_container_function_9b_schema_iterative_update_2",
"l_custom_stack_migration_v10",
"l_datastore_modelgen",
"l_diagnose_hooks_a_mock_api",
"l_env_1_geo_add_a_init_a",
"l_env_3",
"l_env_4_frontend_config_drift_schema_auth_4d",
"l_export_pull_c_function_12_function_13",
"l_flutter_notifications_pinpoint_config_ios_analytics_pinpoint_config_ios_notifications_pinpoint_config",
"l_function_10_function_9c_function_permissions",
"l_function_12_function_13_function_14",
"l_function_15_function_2d_general_config_headless_init",
"l_function_14_function_15_function_2d",
"l_function_1_storage_5",
"l_function_2b_function_7_api_connection_migration2",
"l_function_2c_function_3b_function_4",
"l_function_3a_init_special_case_http_migration",
"l_function_6_storage_2_export",
"l_function_7_api_connection_migration2_api_4",
"l_function_9b_schema_iterative_update_2_storage_1a",
"l_function_8_schema_iterative_update_locking_api_lambda_auth_2",
"l_function_migration_update_v8",
"l_general_config_headless_init_help_hooks_c",
"l_geo_add_b_s3_sse_schema_auth_4a",
"l_geo_add_d_geo_import_3_hosting",
"l_geo_add_e",
@@ -70,15 +70,13 @@
"l_geo_import_1a_geo_import_2_global_sandbox_b",
"l_geo_import_1b_global_sandbox_a_init_e",
"l_geo_migration_v10",
"l_geo_multi_env_searchable_datastore_resolvers",
"l_geo_remove_1",
"l_geo_remove_2",
"l_geo_remove_3",
"l_geo_update_1",
"l_geo_update_2",
"l_git_clone_attach_init_c_layer_4",
"l_git_clone_migration_tests_v10",
"l_help_hooks_c_init_force_push",
"l_hooks_b_notifications_analytics_compatibility_sms_1_plugin",
"l_hostingPROD",
"l_iam_permissions_boundary_node_function_notifications_sms",
@@ -97,11 +95,13 @@
"l_import_s3_2c",
"l_import_s3_3",
"l_init_f_auth_5d_configure_project",
"l_interactions_1_interactions_2_minify_cloudformation",
"l_init_force_push_interactions_1_interactions_2",
"l_interactions_schema_model_a_tags",
"l_ios_analytics_pinpoint_config_ios_notifications_pinpoint_config_javascript_analytics_pinpoint_config",
"l_javascript_notifications_pinpoint_config_pr_previews_multi_env_1_pull_2",
"l_javascript_analytics_pinpoint_config_javascript_notifications_pinpoint_config_pr_previews_multi_env_1",
"l_layer_1_api_key_migration4_schema_iterative_update_4",
"l_layer_2_schema_auth_13_function_5",
"l_layer_3_api_connection_migration_api_key_migration3",
"l_minify_cloudformation_notifications_multi_env_notifications_sms_update",
"l_notifications_analytics_compatibility_in_app_2_schema_auth_11_c_schema_auth_2b",
"l_notifications_analytics_compatibility_sms_2_analytics_2_global_sandbox_c",
"l_notifications_fcm_notifications_in_app_messaging_env_2_with_babel_config",
@@ -110,16 +110,16 @@
"l_notifications_migration_3_v8",
"l_notifications_migration_4_v8",
"l_notifications_migration_v8",
"l_notifications_multi_env_notifications_sms_update_opensearch_simulator",
"l_notifications_sms_pull_pull_auth_10",
"l_parameter_store_1_parameter_store_2_android_analytics_pinpoint_config",
"l_opensearch_simulator_parameter_store_1_parameter_store_2",
"l_pinpoint_region_migration_v10",
"l_predictions_schema_auth_11_b_schema_auth_1b",
"l_push_smoketest_ios_smoketest",
"l_pull_2_push_smoketest_ios",
"l_resolvers_schema_key_api_5",
"l_scaffold_v10",
"l_schema_auth_10_geo_multi_env_searchable_datastore",
"l_schema_auth_11_a",
"l_schema_auth_12_schema_auth_3_schema_function_2",
"l_schema_auth_13_function_5_schema_iterative_update_1",
"l_schema_auth_15",
"l_schema_auth_2a_schema_auth_7a_schema_auth_7b",
"l_schema_auth_4b_schema_model_e_schema_versioned",
@@ -133,30 +133,31 @@
"l_schema_auth_9_b_schema_iterative_rollback_1_predictions_migration",
"l_schema_auth_9_c_storage_3_auth_11",
"l_schema_connection_1",
"l_schema_function_1_api_9b_custom_policies_container",
"l_schema_iterative_update_locking_api_lambda_auth_2_layer_2",
"l_schema_key_api_5_apigw",
"l_schema_connection_2_schema_function_1_api_9b",
"l_schema_iterative_update_1_auth_6_function_2a",
"l_schema_model_b_schema_model_d_auth_5f",
"l_schema_predictions_model_migration_auth_3c",
"l_schema_searchable_api_key_migration1_schema_auth_14",
"l_searchable_migration",
"l_smoketest_S3server_api_8",
"l_smoketest_amplify_app",
"l_storage_1b_function_11_function_2b",
"l_storage_5",
"l_storage_1a_storage_1b_function_11",
"l_storage_migration_v10",
"l_studio_modelgen_custom_transformers_notifications_in_app_messaging_env_1",
"l_uibuilder",
"l_user_groups_js_frontend_config_build_function",
"l_user_groups_s3_access_user_groups_js_frontend_config",
"w_admin_api_hosted_ui_user_groups_s3_access",
"w_analytics_kinesis_analytics_pinpoint_flutter_analytics_pinpoint_js",
"w_api_10_api_7_export_pull_a",
"w_api_1_layer_1_api_key_migration4",
"w_api_2a_api_2b_api_6c",
"w_api_5_apigw_api_lambda_auth_1",
"w_api_6a_auth_7b_export_pull_b",
"w_api_8_schema_iterative_update_locking_api_lambda_auth_2",
"w_api_6b_api_1_layer_1",
"w_api_9a_auth_2h_auth_5g",
"w_api_connection_migration2_api_4_containers_api_secrets",
"w_api_key_migration2_schema_searchable_api_key_migration1",
"w_api_key_migration1_schema_auth_14_api_3",
"w_api_key_migration3_predictions_schema_auth_11_b",
"w_api_key_migration4_schema_iterative_update_4_function_1",
"w_api_lambda_auth_1_api_key_migration2_schema_searchable",
"w_api_lambda_auth_2_schema_auth_13_function_5",
"w_auth_11_auth_1b_delete",
"w_auth_2a_auth_2b_auth_2d",
"w_auth_2c",
@@ -165,29 +166,30 @@
"w_auth_4a_auth_7a_auth_8c",
"w_auth_5a_auth_5c_env_1",
"w_auth_5e_auth_8b_geo_add_b",
"w_auth_6_function_2a_schema_connection_2",
"w_auth_8a_export_pull_d_schema_auth_5a",
"w_configure_project_init_c_layer_4",
"w_containers_api_1",
"w_containers_api_2",
"w_containers_api_secrets_storage_4_schema_auth_10",
"w_custom_policies_container_function_9b_schema_iterative_update_2",
"w_custom_policies_function_storage_2_iam_permissions_boundary",
"w_dynamodb_simulator_export_pull_c_function_12",
"w_env_3",
"w_env_5_function_10_function_9c",
"w_export_pull_c_function_12_function_13",
"w_feature_flags_geo_import_1b_global_sandbox_a",
"w_frontend_config_drift_schema_auth_4d_schema_auth_6a",
"w_function_14_function_2d_general_config_headless_init",
"w_function_13_function_14_function_2d",
"w_function_2b_api_connection_migration2_api_4",
"w_function_2c_interactions_schema_model_a",
"w_function_9a_geo_headless_api_key_migration5",
"w_function_9b_schema_iterative_update_2_storage_1a",
"w_function_permissions_geo_import_1a_geo_import_2",
"w_general_config_headless_init_help_init_force_push",
"w_geo_add_a_init_a_schema_auth_4c",
"w_geo_add_c_geo_add_d_geo_import_3",
"w_geo_multi_env_searchable_datastore_resolvers",
"w_geo_remove_1",
"w_global_sandbox_b_schema_auth_5d_schema_auth_6b",
"w_help_init_force_push_interactions_1",
"w_hooks_b_notifications_analytics_compatibility_sms_1_plugin",
"w_hosted_ui_user_groups_s3_access_user_groups",
"w_hostingPROD",
"w_hosting_layer_3_api_connection_migration",
"w_import_dynamodb_1",
@@ -197,20 +199,17 @@
"w_init_d_init_f_auth_5d",
"w_init_e_notifications_analytics_compatibility_in_app_2_schema_auth_11_c",
"w_init_special_case_http_migration_schema_auth_12",
"w_interactions_2_minify_cloudformation_notifications_multi_env",
"w_js_frontend_config_build_function_dynamodb_simulator",
"w_interactions_1_interactions_2_minify_cloudformation",
"w_model_migration_auth_3c_auth_4c",
"w_node_function_notifications_sms_schema_auth_4b",
"w_notifications_analytics_compatibility_sms_2_analytics_2_global_sandbox_c",
"w_notifications_in_app_messaging",
"w_notifications_in_app_messaging_env_2_with_babel_config_amplify_configure",
"w_notifications_multi_env_notifications_sms_update_parameter_store_1",
"w_notifications_sms_pull_auth_10_container_hosting",
"w_notifications_sms_update_parameter_store_1_parameter_store_2",
"w_push_smoketest_ios_smoketest",
"w_parameter_store_2_push_smoketest_ios",
"w_s3_sse_schema_auth_4a_schema_model_b",
"w_schema_auth_11_a",
"w_schema_auth_13_function_5_schema_iterative_update_1",
"w_schema_auth_14_api_3_api_6b",
"w_schema_auth_15",
"w_schema_auth_1a_schema_auth_5b_schema_auth_8b",
"w_schema_auth_1b_schema_auth_2a_schema_auth_7a",
@@ -222,16 +221,17 @@
"w_schema_auth_8c_auth_3a_auth_3b",
"w_schema_auth_9_a_schema_auth_9_c_storage_3",
"w_schema_connection_1",
"w_schema_connection_2_schema_function_1_api_9b",
"w_schema_data_access_patterns_schema_model_c_schema_predictions",
"w_schema_function_1_api_9b_custom_policies_container",
"w_schema_iterative_update_1_auth_6_function_2a",
"w_schema_iterative_update_3_auth_migration_amplify_remove",
"w_schema_iterative_update_4_function_1",
"w_schema_key_api_5_apigw",
"w_schema_model_d_auth_5f_env_4",
"w_schema_model_e_schema_versioned_auth_1c",
"w_searchable_datastore_resolvers_schema_key",
"w_searchable_migration",
"w_storage_1b_function_11_function_2b",
"w_storage_4_schema_auth_10_geo_multi_env",
"w_smoketest_api_8_schema_iterative_update_locking",
"w_storage_1a_storage_1b_function_11",
"w_studio_modelgen_custom_transformers_notifications_in_app_messaging_env_1",
"w_tags_auth_1a_auth_trigger"
"w_tags_auth_1a_auth_trigger",
"w_user_groups_js_frontend_config_build_function"
]
Original file line number Diff line number Diff line change
@@ -162,14 +162,8 @@ app.get('/getUser', async (req, res, next) => {

app.get('/listUsers', async (req, res, next) => {
try {
let response;
if (req.query.token) {
response = await listUsers(req.query.limit || 25, req.query.token);
} else if (req.query.limit) {
response = await listUsers((Limit = req.query.limit));
} else {
response = await listUsers();
}
const limit = req.query.limit ? parseInt(req.query.limit) : 25;
const response = await listUsers(limit, req.query.token);
res.status(200).json(response);
} catch (err) {
next(err);
@@ -178,14 +172,8 @@ app.get('/listUsers', async (req, res, next) => {

app.get('/listGroups', async (req, res, next) => {
try {
let response;
if (req.query.token) {
response = await listGroups(req.query.limit || 25, req.query.token);
} else if (req.query.limit) {
response = await listGroups((Limit = req.query.limit));
} else {
response = await listGroups();
}
const limit = req.query.limit ? parseInt(req.query.limit) : 25;
const response = await listGroups(limit, req.query.token);
res.status(200).json(response);
} catch (err) {
next(err);
@@ -200,14 +188,8 @@ app.get('/listGroupsForUser', async (req, res, next) => {
}

try {
let response;
if (req.query.token) {
response = await listGroupsForUser(req.query.username, req.query.limit || 25, req.query.token);
} else if (req.query.limit) {
response = await listGroupsForUser(req.query.username, (Limit = req.query.limit));
} else {
response = await listGroupsForUser(req.query.username);
}
const limit = req.query.limit ? parseInt(req.query.limit) : 25;
const response = await listGroupsForUser(req.query.username, limit, req.query.token);
res.status(200).json(response);
} catch (err) {
next(err);
@@ -222,14 +204,8 @@ app.get('/listUsersInGroup', async (req, res, next) => {
}

try {
let response;
if (req.query.token) {
response = await listUsersInGroup(req.query.groupname, req.query.limit || 25, req.query.token);
} else if (req.query.limit) {
response = await listUsersInGroup(req.query.groupname, (Limit = req.query.limit));
} else {
response = await listUsersInGroup(req.query.groupname);
}
const limit = req.query.limit ? parseInt(req.query.limit) : 25;
const response = await listUsersInGroup(req.query.groupname, limit, req.query.token);
res.status(200).json(response);
} catch (err) {
next(err);
8 changes: 2 additions & 6 deletions packages/amplify-e2e-core/src/utils/auth-utils.ts
Original file line number Diff line number Diff line change
@@ -42,12 +42,8 @@ export async function setupUser(
}
}

export async function addUserToGroup(
cognitoClient: CognitoIdentityServiceProvider,
userPoolId: string,
username: string,
groupName?: string,
): Promise<void> {
export async function addUserToGroup(userPoolId: string, username: string, groupName: string, region?: string): Promise<void> {
const cognitoClient = getConfiguredCognitoClient(region);
await cognitoClient
.adminAddUserToGroup({
UserPoolId: userPoolId,
177 changes: 177 additions & 0 deletions packages/amplify-e2e-tests/src/__tests__/auth/admin-api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import {
addAuthWithGroupsAndAdminAPI,
addUserToGroup,
amplifyPushAuth,
configureAmplify,
createNewProjectDir,
deleteProject,
deleteProjectDir,
getProjectMeta,
getUserPoolId,
initJSProjectWithProfile,
invokeFunction,
setupUser,
} from '@aws-amplify/amplify-e2e-core';
import { $TSAny } from '@aws-amplify/amplify-cli-core';

describe('auth admin api tests', () => {
let projRoot: string;
let adminLambdaName: string;
let adminLambdaRegion: string;

const callAdminLambda = async (request: $TSAny): Promise<$TSAny> => {
if (!request.requestContext) {
// Mock authorization necessary for admin API
request.requestContext = {
authorizer: {
claims: {
'cognito:groups': 'Admins',
},
},
};
}
const lambdaResponse = await invokeFunction(adminLambdaName, JSON.stringify(request), adminLambdaRegion);
return JSON.parse(lambdaResponse.Payload.toString());
};

beforeAll(async () => {
projRoot = await createNewProjectDir('auth');
await initJSProjectWithProfile(projRoot);
await addAuthWithGroupsAndAdminAPI(projRoot);
await amplifyPushAuth(projRoot);

const meta = getProjectMeta(projRoot);
const adminLambdaOutputs = Object.keys(meta.function).map((key) => meta.function[key])[0].output;
adminLambdaName = adminLambdaOutputs.Name;
adminLambdaRegion = adminLambdaOutputs.Region;

const userPoolId = getUserPoolId(projRoot);
await configureAmplify(projRoot);

for (let i = 0; i < 5; i++) {
const username = `testUser${i}`;
const password = `Password12#${i}`;
await setupUser(userPoolId, username, password, 'Users', adminLambdaRegion);
}

for (let i = 0; i < 5; i++) {
const username = `testAdminUser${i}`;
const password = `Password12#${i}`;
await setupUser(userPoolId, username, password, 'Admins', adminLambdaRegion);
await addUserToGroup(userPoolId, username, 'Users', adminLambdaRegion);
}
});

afterAll(async () => {
await deleteProject(projRoot);
deleteProjectDir(projRoot);
});

it('can list groups', async () => {
const request = {
path: '/listGroups',
httpMethod: 'GET',
};
const response = await callAdminLambda(request);
expect(response.statusCode).toBe(200);
const responseBody = JSON.parse(response.body);
expect(responseBody.Groups.length).toBe(2);
});

it('can list groups with limit', async () => {
const request = {
path: '/listGroups',
httpMethod: 'GET',
queryStringParameters: {
limit: '1',
},
};
const response = await callAdminLambda(request);
expect(response.statusCode).toBe(200);
const responseBody = JSON.parse(response.body);
expect(responseBody.Groups.length).toBe(1);
});

it('can list users', async () => {
const request = {
path: '/listUsers',
httpMethod: 'GET',
};
const response = await callAdminLambda(request);
expect(response.statusCode).toBe(200);
const responseBody = JSON.parse(response.body);
expect(responseBody.Users.length).toBe(10);
});

it('can list users with limit', async () => {
const request = {
path: '/listUsers',
httpMethod: 'GET',
queryStringParameters: {
limit: '1',
},
};
const response = await callAdminLambda(request);
expect(response.statusCode).toBe(200);
const responseBody = JSON.parse(response.body);
expect(responseBody.Users.length).toBe(1);
});

it('can list users in group', async () => {
const request = {
path: '/listUsersInGroup',
httpMethod: 'GET',
queryStringParameters: {
groupname: 'Admins',
},
};
const response = await callAdminLambda(request);
expect(response.statusCode).toBe(200);
const responseBody = JSON.parse(response.body);
expect(responseBody.Users.length).toBe(5);
});

it('can list users in group with limit', async () => {
const request = {
path: '/listUsersInGroup',
httpMethod: 'GET',
queryStringParameters: {
limit: '1',
groupname: 'Admins',
},
};
const response = await callAdminLambda(request);
expect(response.statusCode).toBe(200);
const responseBody = JSON.parse(response.body);
expect(responseBody.Users.length).toBe(1);
});

it('can list groups for user', async () => {
const request = {
path: '/listGroupsForUser',
httpMethod: 'GET',
queryStringParameters: {
username: 'testAdminUser1',
},
};
const response = await callAdminLambda(request);
expect(response.statusCode).toBe(200);
const responseBody = JSON.parse(response.body);
expect(responseBody.Groups.length).toBe(2);
});

it('can list groups for user with limit', async () => {
const request = {
path: '/listGroupsForUser',
httpMethod: 'GET',
queryStringParameters: {
limit: '1',
username: 'testAdminUser1',
},
};
const response = await callAdminLambda(request);
expect(response.statusCode).toBe(200);
const responseBody = JSON.parse(response.body);
expect(responseBody.Groups.length).toBe(1);
});
});

0 comments on commit 2480681

Please sign in to comment.