├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── deployment
├── CFN-templates
│ ├── aws-cloud-migration-factory-solution-automation.template
│ ├── aws-cloud-migration-factory-solution-credentialmanager.template
│ ├── aws-cloud-migration-factory-solution-mgh.template
│ ├── aws-cloud-migration-factory-solution-mgn.template
│ ├── aws-cloud-migration-factory-solution-replatform.template
│ ├── aws-cloud-migration-factory-solution-target-account.template
│ ├── aws-cloud-migration-factory-solution-tracker.template
│ ├── aws-cloud-migration-factory-solution-waf-be.template
│ ├── aws-cloud-migration-factory-solution-waf-fe.template
│ └── aws-cloud-migration-factory-solution.template
├── build-s3-dist.sh
├── run-unit-tests.sh
├── run_integration_unit_tests.sh
└── run_lambda_unit_test.sh
├── solution-manifest.yaml
└── source
├── backend
├── lambda_functions
│ ├── helper
│ │ └── helper.py
│ ├── lambda_auth
│ │ └── lambda_auth.py
│ ├── lambda_build
│ │ └── lambda_build.py
│ ├── lambda_cognito_group_update
│ │ └── lambda_cognito_group_update.py
│ ├── lambda_cognito_user_update
│ │ └── lambda_cognito_user_update.py
│ ├── lambda_cognitogroups
│ │ └── lambda_cognitogroups.py
│ ├── lambda_defaultschema
│ │ ├── default_pipeline_templates_import.json
│ │ ├── default_policies.json
│ │ ├── default_roles.json
│ │ ├── default_schema.json
│ │ ├── default_tasks.json
│ │ └── lambda_defaultschema.py
│ ├── lambda_gfbuild
│ │ ├── lambda_gfbuild.py
│ │ ├── poetry.lock
│ │ └── pyproject.toml
│ ├── lambda_gfdeploy
│ │ └── lambda_gfdeploy.py
│ ├── lambda_gfvalidation
│ │ └── lambda_gfvalidation.py
│ ├── lambda_import_export_pipeline_templates
│ │ ├── lambda_import_export_pipeline_templates.py
│ │ └── models.py
│ ├── lambda_item
│ │ └── lambda_item.py
│ ├── lambda_items
│ │ └── lambda_items.py
│ ├── lambda_login
│ │ └── lambda_login.py
│ ├── lambda_migrationtracker_glue_execute
│ │ └── lambda_migrationtracker_glue_execute.py
│ ├── lambda_migrationtracker_glue_scriptcopy
│ │ └── lambda_migrationtracker_glue_scriptcopy.py
│ ├── lambda_notifications
│ │ └── lambda_notifications.py
│ ├── lambda_pipeline_stream
│ │ └── lambda_pipeline_stream.py
│ ├── lambda_pipeline_task_execution_output
│ │ └── lambda_pipeline_task_execution_output.py
│ ├── lambda_policy
│ │ └── lambda_policy.py
│ ├── lambda_policy_attr
│ │ └── lambda_policy_attr.py
│ ├── lambda_replatformec2schema
│ │ ├── __init__.py
│ │ ├── factory.py
│ │ └── lambda_replatformec2schema.py
│ ├── lambda_reset
│ │ └── lambda_reset.py
│ ├── lambda_role
│ │ └── lambda_role.py
│ ├── lambda_role_item
│ │ └── lambda_role_item.py
│ ├── lambda_run_athena_savedquery
│ │ └── lambda_run_athena_savedquery.py
│ ├── lambda_schema
│ │ └── lambda_schema.py
│ ├── lambda_server_stream
│ │ └── lambda_server_stream.py
│ ├── lambda_service_account
│ │ └── lambda_service_account.py
│ ├── lambda_ssm
│ │ └── lambda_ssm.py
│ ├── lambda_ssm_jobs
│ │ └── lambda_ssm_jobs.py
│ ├── lambda_ssm_load_scripts
│ │ ├── lambda_ssm_load_scripts.py
│ │ ├── poetry.lock
│ │ └── pyproject.toml
│ ├── lambda_ssm_output
│ │ └── lambda_ssm_output.py
│ ├── lambda_ssm_scripts
│ │ ├── lambda_ssm_scripts.py
│ │ ├── poetry.lock
│ │ └── pyproject.toml
│ ├── lambda_ssm_socket
│ │ ├── lambda_ssm_socket.py
│ │ ├── poetry.lock
│ │ └── pyproject.toml
│ ├── lambda_task_orchestrator
│ │ └── lambda_task_orchestrator.py
│ ├── lambda_user_admin
│ │ └── lambda_user_admin.py
│ └── lambda_wave_stream
│ │ └── lambda_wave_stream.py
├── lambda_layers
│ ├── lambda_layer_items
│ │ └── python
│ │ │ ├── item_validation.py
│ │ │ ├── query_comparator_operations.py
│ │ │ └── query_conditions.py
│ ├── lambda_layer_policy
│ │ └── python
│ │ │ ├── poetry.lock
│ │ │ ├── policy.py
│ │ │ └── pyproject.toml
│ ├── lambda_layer_py_pkgs
│ │ └── python
│ │ │ ├── poetry.lock
│ │ │ └── pyproject.toml
│ └── lambda_layer_utils
│ │ └── python
│ │ ├── cmf_boto.py
│ │ ├── cmf_logger.py
│ │ ├── cmf_pipeline.py
│ │ └── cmf_utils.py
└── lambda_unit_test
│ ├── poetry.lock
│ ├── pyproject.toml
│ ├── sample_data
│ ├── CFN_Template_1_Wordpress.yaml
│ ├── CFN_Template_2_OFBiz.yaml
│ ├── Migration_Tracker_All_Extract_Script.py
│ ├── apps.json
│ ├── connection_ids.json
│ ├── jwtRS256.key
│ ├── jwtRS256.key.pub
│ ├── pipeline_template_tasks.json
│ ├── pipeline_templates.json
│ ├── pipeline_templates_import.json
│ ├── pipelines.json
│ ├── policies.json
│ ├── roles.json
│ ├── schema_server_replatform_create_ec2.json
│ ├── schema_server_replatform_create_server.json
│ ├── schema_server_replatform_create_server_attrs.json
│ ├── schema_server_replatform_delete_server.json
│ ├── schema_server_replatform_delete_server_attrs.json
│ ├── schema_server_replatform_update_server.json
│ ├── schemas.json
│ ├── schemas_modified_TS.json
│ ├── schemas_no_app.json
│ ├── schemas_no_server.json
│ ├── schemas_no_wave.json
│ ├── schemas_server_replatform_with_attrs.json
│ ├── servers.json
│ ├── ssm_jobs.json
│ ├── ssm_load_scripts
│ │ ├── README.md
│ │ ├── invalid_zip_file.zip
│ │ ├── package_incorrect_yaml_contents
│ │ │ ├── Package-Structure.yml
│ │ │ └── hello_world.py
│ │ ├── package_invalid_attributes
│ │ │ ├── Package-Structure.yml
│ │ │ └── hello_world.py
│ │ ├── package_invalid_yaml
│ │ │ ├── Package-Structure.yml
│ │ │ └── hello_world.py
│ │ ├── package_missing_dependencies
│ │ │ ├── Package-Structure.yml
│ │ │ └── hello_world.py
│ │ ├── package_no_master_file
│ │ │ └── Package-Structure.yml
│ │ ├── package_no_yaml
│ │ │ └── hello_world.py
│ │ ├── package_schema_extensions
│ │ │ ├── Package-Structure.yml
│ │ │ └── hello_world.py
│ │ ├── package_valid
│ │ │ ├── Package-Structure.yml
│ │ │ └── hello_world.py
│ │ ├── package_valid_with_dependencies
│ │ │ ├── Package-Structure.yml
│ │ │ ├── hello_world.py
│ │ │ └── lib1.py
│ │ ├── sample_ssm_script_1.json
│ │ ├── sample_ssm_script_2.json
│ │ └── sample_ssm_scripts.zip
│ ├── ssm_scripts.json
│ ├── ssm_socket_cognito_jwks.json
│ ├── ssm_socket_cognito_jwks_error.json
│ ├── tasks.json
│ └── waves.json
│ ├── test_cmf_pipeline.py
│ ├── test_common_utils.py
│ ├── test_helper.py
│ ├── test_item_validation.py
│ ├── test_lambda_auth.py
│ ├── test_lambda_build.py
│ ├── test_lambda_cognito_base.py
│ ├── test_lambda_cognito_group_update.py
│ ├── test_lambda_cognito_user_update.py
│ ├── test_lambda_cognitogroups.py
│ ├── test_lambda_defaultschema.py
│ ├── test_lambda_export_pipeline_templates.py
│ ├── test_lambda_gfbuild.py
│ ├── test_lambda_gfcommon.py
│ ├── test_lambda_gfdeploy.py
│ ├── test_lambda_gfvalidation.py
│ ├── test_lambda_import_pipeline_templates.py
│ ├── test_lambda_item.py
│ ├── test_lambda_item_common.py
│ ├── test_lambda_items.py
│ ├── test_lambda_login.py
│ ├── test_lambda_login_common.py
│ ├── test_lambda_migrationtracker_glue_base.py
│ ├── test_lambda_migrationtracker_glue_execute.py
│ ├── test_lambda_migrationtracker_glue_scriptcopy.py
│ ├── test_lambda_notifications.py
│ ├── test_lambda_pipeline_stream.py
│ ├── test_lambda_pipeline_task_execution_output.py
│ ├── test_lambda_policy.py
│ ├── test_lambda_policy_attr.py
│ ├── test_lambda_replatformec2schema.py
│ ├── test_lambda_reset.py
│ ├── test_lambda_role.py
│ ├── test_lambda_role_item.py
│ ├── test_lambda_run_athena_savedquery.py
│ ├── test_lambda_schema.py
│ ├── test_lambda_server_stream.py
│ ├── test_lambda_service_account.py
│ ├── test_lambda_ssm.py
│ ├── test_lambda_ssm_base.py
│ ├── test_lambda_ssm_jobs.py
│ ├── test_lambda_ssm_load_scripts.py
│ ├── test_lambda_ssm_output.py
│ ├── test_lambda_ssm_scripts.py
│ ├── test_lambda_ssm_socket.py
│ ├── test_lambda_task_orchestrator.py
│ ├── test_lambda_user_admin.py
│ ├── test_lambda_wave_stream.py
│ ├── test_policy.py
│ └── tox.ini
├── frontend
├── .babelrc
├── .gitignore
├── .prettierignore
├── .prettierrc
├── README.md
├── index.html
├── index.prod.html
├── layout
│ └── main.css
├── package.json
├── public
│ ├── .well-known
│ │ └── security.txt
│ ├── env.js
│ ├── favicon.ico
│ └── manifest.json
├── src
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── AuthenticatedRoutes.tsx
│ ├── PreAuthRoutes.tsx
│ ├── __tests__
│ │ ├── TestUtils.ts
│ │ ├── amplify_test_config.ts
│ │ └── mocks
│ │ │ ├── admin_api.ts
│ │ │ ├── app_api.ts
│ │ │ ├── credentialmanager_api.ts
│ │ │ ├── login_api.ts
│ │ │ ├── ssm_api.ts
│ │ │ ├── tools_api.ts
│ │ │ ├── user_api.ts
│ │ │ └── wave_api.ts
│ ├── actions
│ │ ├── AdminPermissionsHook.ts
│ │ ├── ApplicationsHook.ts
│ │ ├── AutomationJobsHook.ts
│ │ ├── AutomationScriptsHook.ts
│ │ ├── CredentialManagerHook.ts
│ │ ├── DatabasesHook.ts
│ │ ├── PipelineTemplateTasksHook.ts
│ │ ├── PipelineTemplatesHook.ts
│ │ ├── PipelinesHook.ts
│ │ ├── SchemaHook.ts
│ │ ├── ServersHook.ts
│ │ ├── TaskExecutionsHook.ts
│ │ ├── ValueListsHook.ts
│ │ └── WavesHook.ts
│ ├── api_clients
│ │ ├── adminApiClient.ts
│ │ ├── loginApiClient.ts
│ │ ├── toolsApiClient.ts
│ │ └── userApiClient.ts
│ ├── components
│ │ ├── AmendItemModal.tsx
│ │ ├── ApplicationView.tsx
│ │ ├── AutomationJobView.tsx
│ │ ├── AutomationScriptImport.tsx
│ │ ├── AutomationScriptView.tsx
│ │ ├── AutomationScriptsTable.tsx
│ │ ├── AutomationTools.tsx
│ │ ├── CMFTopNavigation.tsx
│ │ ├── CredentialManagerModal.tsx
│ │ ├── CredentialManagerTable.tsx
│ │ ├── DatabaseView.tsx
│ │ ├── IntakeFormTable.test.tsx
│ │ ├── IntakeFormTable.tsx
│ │ ├── ItemAmend.test.tsx
│ │ ├── ItemAmend.tsx
│ │ ├── ItemAmendModal.tsx
│ │ ├── ItemTable.tsx
│ │ ├── Modal.tsx
│ │ ├── PermissionsView.tsx
│ │ ├── PipelineTemplateJsonFileImport.tsx
│ │ ├── PipelineTemplateView.tsx
│ │ ├── PipelineView.tsx
│ │ ├── SchemaAttributeAmendModal.tsx
│ │ ├── SchemaAttributeConditionsEdit.tsx
│ │ ├── SchemaAttributesTable.tsx
│ │ ├── ServerView.tsx
│ │ ├── TableHeader.tsx
│ │ ├── TaskExecutionView.tsx
│ │ ├── ToolHelp.tsx
│ │ ├── ToolHelpEdit.tsx
│ │ ├── UserGroupsModal.tsx
│ │ ├── UserPipelineTemplateVisualEditor.test.tsx
│ │ ├── UserPipelineTemplateVisualEditor.tsx
│ │ ├── UserPipelineVisualManager.tsx
│ │ ├── ViewTaskExecution.test.tsx
│ │ ├── WaveView.tsx
│ │ ├── dashboard
│ │ │ ├── ChartOSTypes.tsx
│ │ │ ├── ChartServerEnvTypes.tsx
│ │ │ ├── MFOverview.tsx
│ │ │ ├── ServerRepStatus.tsx
│ │ │ ├── ServersByMonth.tsx
│ │ │ └── WaveStatus.tsx
│ │ ├── import
│ │ │ ├── ImportCompletion.tsx
│ │ │ ├── ImportIntakeWizard.tsx
│ │ │ └── ImportOverview.tsx
│ │ ├── servicenavigation.tsx
│ │ └── ui_attributes
│ │ │ ├── AllAttributes.tsx
│ │ │ ├── AllViewerAttributes.tsx
│ │ │ ├── Audit.tsx
│ │ │ ├── CheckboxAttribute.tsx
│ │ │ ├── DateAttribute.tsx
│ │ │ ├── EmbeddedEntityAttribute.tsx
│ │ │ ├── GroupsAttribute.tsx
│ │ │ ├── JsonAttribute.tsx
│ │ │ ├── ListAttribute.tsx
│ │ │ ├── MultiValueStringAttribute.tsx
│ │ │ ├── PoliciesAttribute.tsx
│ │ │ ├── RelatedRecordPopover.tsx
│ │ │ ├── RelationshipAttribute.tsx
│ │ │ ├── TagAttribute.tsx
│ │ │ ├── TextAttribute.tsx
│ │ │ └── ValueWithLabel.tsx
│ ├── containers
│ │ ├── AdminPermissions.Groups.test.tsx
│ │ ├── AdminPermissions.Policies.test.tsx
│ │ ├── AdminPermissions.Roles.test.tsx
│ │ ├── AdminPermissions.Users.test.tsx
│ │ ├── AdminPermissions.test.tsx
│ │ ├── AdminPermissions.tsx
│ │ ├── AdminSchemaManagement.test.tsx
│ │ ├── AdminSchemaMgmt.tsx
│ │ ├── ChangePassword.test.tsx
│ │ ├── ChangePassword.tsx
│ │ ├── CredentialManager.test.tsx
│ │ ├── CredentialManager.tsx
│ │ ├── ForgotPassword.test.tsx
│ │ ├── ForgotPassword.tsx
│ │ ├── Login.test.tsx
│ │ ├── Login.tsx
│ │ ├── PipelineTemplatesImport.test.tsx
│ │ ├── PipelineTemplatesImport.tsx
│ │ ├── UserAutomationJobs.test.tsx
│ │ ├── UserAutomationJobs.tsx
│ │ ├── UserAutomationScripts.test.tsx
│ │ ├── UserAutomationScripts.tsx
│ │ ├── UserDashboard.test.tsx
│ │ ├── UserDashboard.tsx
│ │ ├── UserExport.test.tsx
│ │ ├── UserExport.tsx
│ │ ├── UserImport.test.tsx
│ │ ├── UserImport.tsx
│ │ ├── UserTableApps.test.tsx
│ │ ├── UserTableApps.tsx
│ │ ├── UserTableDatabases.test.tsx
│ │ ├── UserTableDatabases.tsx
│ │ ├── UserTablePipelineTemplates.test.tsx
│ │ ├── UserTablePipelineTemplates.tsx
│ │ ├── UserTablePipelines.test.tsx
│ │ ├── UserTablePipelines.tsx
│ │ ├── UserTableServers.test.tsx
│ │ ├── UserTableServers.tsx
│ │ ├── UserTableWaves.test.tsx
│ │ └── UserTableWaves.tsx
│ ├── contexts
│ │ ├── NotificationContext.tsx
│ │ ├── SessionContext.test.tsx
│ │ ├── SessionContext.tsx
│ │ ├── SplitPanelContext.tsx
│ │ └── ToolsContext.tsx
│ ├── index.tsx
│ ├── models
│ │ ├── AppChildProps.ts
│ │ ├── Application.ts
│ │ ├── CompletionNotification.ts
│ │ ├── Database.ts
│ │ ├── EntitySchema.ts
│ │ ├── Events.ts
│ │ ├── HelpContent.ts
│ │ ├── Pipeline.ts
│ │ ├── PipelineTemplate.ts
│ │ ├── PipelineTemplateTask.ts
│ │ ├── Server.ts
│ │ ├── UserAccess.ts
│ │ └── Wave.ts
│ ├── resources
│ │ ├── ItemTableConfig.tsx
│ │ ├── auto-script-table-config.tsx
│ │ ├── credential-table-config.ts
│ │ ├── intakeform-table-config.tsx
│ │ ├── main.test.ts
│ │ ├── main.ts
│ │ ├── permissionsReducer.ts
│ │ ├── recordFunctions.ts
│ │ ├── reducer.ts
│ │ ├── schemaReducer.ts
│ │ └── schemaattr-table-config.tsx
│ ├── setupTests.ts
│ └── utils
│ │ ├── OptionDefinition.ts
│ │ ├── entity-access-from-permissions.ts
│ │ ├── entity-access-from-premissions.test.ts
│ │ ├── import-utils.test.ts
│ │ ├── import-utils.ts
│ │ ├── table-utils.ts
│ │ ├── xlsx-export.test.ts
│ │ └── xlsx-export.ts
├── test_data
│ ├── __mocks__
│ │ ├── fileMock.js
│ │ └── styleMock.js
│ ├── default_access_policy.json
│ ├── default_groups.json
│ ├── default_policies.json
│ ├── default_roles.json
│ ├── default_schema.ts
│ ├── default_users.json
│ ├── test_invalid.csv
│ ├── test_invalid.xlsx
│ ├── test_pipeline_template_import.json
│ ├── test_valid.csv
│ └── test_valid.xlsx
├── tsconfig.json
├── tsconfig.node.json
├── vendor
│ └── xlsx-0.20.2.tgz
└── vite.config.ts
└── integrations
├── automation_packages
└── ADS
│ ├── 0-ADS-AgentInstall
│ ├── 0-ADS-AgentInstall.py
│ ├── 1-ADS-Install-Linux.py
│ ├── 1-Install-Windows.ps1
│ └── Package-Structure.yml
│ └── 1-ADS-AgentUninstall
│ ├── 1-ADS-AgentUninstall.py
│ ├── 1-ADS-Uninstall-Linux.py
│ ├── 1-Uninstall-Windows.ps1
│ └── Package-Structure.yml
├── common
└── mfcommon.py
├── credential_manager
└── lambdas
│ ├── CreateKeyValueSecret.py
│ ├── CreateOsSecret.py
│ ├── CreatePlainTextSecret.py
│ ├── CredentialManager.py
│ ├── DeleteSecret.py
│ ├── GetSecret.py
│ ├── ListSecret.py
│ └── UpdateSecret.py
├── integration_unit_tests
├── FactoryEndpoints.json
├── __init__.py
├── automation_packages
│ ├── __init__.py
│ └── ads
│ │ ├── __init__.py
│ │ ├── test_ADS_AgentInstall.py
│ │ ├── test_ADS_AgentUninstall.py
│ │ ├── test_ADS_InstallLinux.py
│ │ └── test_ads_common.py
├── common
│ ├── __init__.py
│ ├── test_cmf_get_credentials.py
│ ├── test_cmf_get_servers.py
│ ├── test_cmf_user_login.py
│ ├── test_get_factory_databases.py
│ ├── test_mfcommon.py
│ └── test_mfcommon_util.py
├── credential_manager
│ ├── __init__.py
│ ├── test_credential_manager.py
│ ├── test_credential_manager_base.py
│ ├── test_credential_manager_exceptions.py
│ └── test_credential_manager_lambda_handler.py
├── mgh
│ ├── __init__.py
│ ├── test_lambda_mgh.py
│ └── test_lambda_mgh_common_util.py
├── mgn
│ ├── __init__.py
│ ├── test_0_prerequisites_checks.py
│ ├── test_1_FileCopy.py
│ ├── test_2_AddUser.py
│ ├── test_2_RemoveUser.py
│ ├── test_2_Verify_replication.py
│ ├── test_3_Shutdown_all_servers.py
│ ├── test_3_Verify_instance_status.py
│ ├── test_4_Get_instance_IP.py
│ ├── test_4_Verify_server_connection.py
│ ├── test_5_post_cutover_validations.py
│ ├── test_AgentInstall.py
│ ├── test_InstallLinux.py
│ ├── test_lambda_mgn.py
│ ├── test_lambda_mgn_common_util.py
│ ├── test_lambda_mgn_template.py
│ ├── test_lambda_mgn_utils.py
│ └── test_mgn_common.py
├── poetry.lock
├── pyproject.toml
├── test_util.py
└── tox.ini
├── mgh
└── lambdas
│ ├── lambda_mgh.py
│ ├── poetry.lock
│ ├── pyproject.toml
│ └── recommendation-preferences.json
├── mgn
├── MGN-automation-scripts
│ ├── 0-Prerequisites-checks
│ │ ├── 0-Prerequisites-Windows.ps1
│ │ ├── 0-Prerequisites-checks.py
│ │ └── Package-Structure.yml
│ ├── 1-AgentInstall
│ │ ├── 1-AgentInstall.py
│ │ ├── 1-Install-Linux.py
│ │ ├── 1-Install-Windows.ps1
│ │ └── Package-Structure.yml
│ ├── 1-FileCopy
│ │ ├── 1-FileCopy.py
│ │ └── Package-Structure.yml
│ ├── 2-AddUser
│ │ ├── 2-AddUser.py
│ │ └── Package-Structure.yml
│ ├── 2-RemoveUser
│ │ ├── 2-RemoveUser.py
│ │ └── Package-Structure.yml
│ ├── 2-Verify-replication
│ │ ├── 2-Verify-replication.py
│ │ └── Package-Structure.yml
│ ├── 3-Shutdown-all-servers
│ │ ├── 3-Shutdown-all-servers.py
│ │ └── Package-Structure.yml
│ ├── 3-Verify-instance-status
│ │ ├── 3-Verify-instance-status.py
│ │ └── Package-Structure.yml
│ ├── 4-Get-instance-IP
│ │ ├── 4-Get-instance-IP.py
│ │ └── Package-Structure.yml
│ ├── 4-Verify-server-connection
│ │ ├── 4-Verify-server-connection.py
│ │ └── Package-Structure.yml
│ ├── 5-Post-Cutover-Validations
│ │ ├── 5-post_cutover_validations.py
│ │ ├── Package-Structure.yml
│ │ └── Software-Validation-Windows.ps1
│ ├── FactoryEndpoints.json
│ └── server-list.csv
└── lambdas
│ ├── lambda_mgn.py
│ ├── lambda_mgn_launch.py
│ ├── lambda_mgn_template.py
│ └── lambda_mgn_utils.py
└── migration-tracker
└── GlueScript
├── Migration_Tracker_App_Extract_Script.py
├── Migration_Tracker_Database_Extract_Script.py
├── Migration_Tracker_Server_Extract_Script.py
└── Migration_Tracker_Wave_Extract_Script.py
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior.
15 |
16 | **Expected behavior**
17 | A clear and concise description of what you expected to happen.
18 |
19 | **Please complete the following information about the solution:**
20 | - [ ] Version: [e.g. v1.1.0]
21 |
22 | To get the version of the solution, you can look at the description of the created CloudFormation stack. For example, "_(SO0097) - AWS CloudEndure Migration Factory Solution. Version **v1.1.0**_".
23 |
24 | - [ ] Region: [e.g. us-east-1]
25 | - [ ] Was the solution modified from the version published on this repository?
26 | - [ ] If the answer to the previous question was yes, are the changes available on GitHub?
27 | - [ ] Have you checked your [service quotas](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html) for the sevices this solution uses?
28 | - [ ] Were there any errors in the CloudWatch Logs?
29 |
30 | **Screenshots**
31 | If applicable, add screenshots to help explain your problem (please **DO NOT include sensitive information**).
32 |
33 | **Additional context**
34 | Add any other context about the problem here.
35 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this solution
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the feature you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | *Issue #, if available:*
2 |
3 | *Description of changes:*
4 |
5 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node - Logs
2 | *.log
3 | npm-debug.log*
4 |
5 | # Node - Dependencies
6 | node_modules
7 |
8 | # Temporary folder
9 | /tmp
10 |
11 | # OS - OSX
12 | .DS_Store
13 |
14 | # OS - Windows
15 | Thumbs.db
16 | ehthumbs.db
17 |
18 | # OS - Linux (KDE directory preferences)
19 | .directory
20 | # Webstorm IDE files
21 | /.idea/*
22 | /source/frontend/test-report.xml
23 | /source/frontend/dist
24 |
25 | # Frontend configuration file for local development
26 | /source/frontend/public/env_dev.js
27 |
28 | # Local build output
29 | /deployment/global-s3-assets/*
30 | /deployment/regional-s3-assets/*
31 | /source/backend/lambda_layers/lambda_layer_py_pkgs/.build
32 |
33 | #SonarQube
34 | /.scannerwork/*
35 |
36 | # Testing environment
37 | testing-venv
38 |
39 | **/**/.coverage
40 | **/**/coverage/
41 |
42 | # Python
43 | __pycache__
44 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/deployment/run_integration_unit_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 |
7 | # This script must be executed from the package root directory
8 |
9 | set -e
10 |
11 | if [ ! -d "testing-venv" ]; then
12 | echo "Creating testing-venv..."
13 | python3 -m venv testing-venv
14 | fi
15 |
16 |
17 | echo " ---- Rebuilding package locally before testing..."
18 | source testing-venv/bin/activate
19 | echo " ---- Using python: `type python3`"
20 | echo " ---- Python version: `python3 --version`"
21 | echo " ---- Installing pip"
22 | pip3 install --quiet -U pip
23 | echo " ---- Installing dependency"
24 | source_code="$PWD"
25 | echo " ---- Changing working directory to the test directory"
26 | cd source/integrations/integration_unit_tests/
27 | "$POETRY_HOME"/bin/poetry install
28 | echo "Updating source path $source_code"
29 | replace="s#%%SOURCE_PATH%%#$source_code#g"
30 | tox_path="$PWD/tox.ini"
31 | echo "tox.ini path: $tox_path"
32 | if [[ "$OSTYPE" == "darwin"* ]]; then
33 | sed -i '' -e $replace $tox_path
34 | else
35 | sed -i -e $replace $tox_path
36 | fi
37 |
38 | echo " ---- Running tests..."
39 | if [ -z "$1" ]; then
40 | echo " ---- Running all tests..."
41 | test_scope="test_*.py"
42 | else
43 | echo " ---- Running tests based on the pattern $1..."
44 | test_scope="$1"
45 | fi
46 | coverage run -m unittest discover -p "$test_scope"
47 | echo " ---- Please make sure all the test cases above pass"
48 | echo
49 | echo
50 | echo " ---- Waiting for 1 minutes for coverage journaling to complete."
51 | sleep 60
52 | echo
53 | echo " ---- Combining coverage file for multiprocessing..."
54 | coverage combine
55 | echo " ---- Unit test Coverage report"
56 | coverage report
57 | coverage xml -o./coverage/coverage.xml
58 | deactivate
59 | echo "Removing source path $source_code"
60 | replace="s#$source_code#%%SOURCE_PATH%%#g"
61 | if [[ "$OSTYPE" == "darwin"* ]]; then
62 | sed -i '' -e $replace $tox_path
63 | else
64 | sed -i -e $replace $tox_path
65 | fi
66 | echo "------------------------------------------------------------------------------"
67 | echo "[Unit Tests] Integrations Unit Tests Complete"
68 | echo "------------------------------------------------------------------------------"
--------------------------------------------------------------------------------
/deployment/run_lambda_unit_test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | # SPDX-License-Identifier: Apache-2.0
5 | #
6 |
7 | # This script must be executed from the package root directory
8 | #
9 | # To run unittests against a subset of the tests for development testing,
10 | # the script accepts a single optional argument, this is string pattern
11 | # for the tests required to be run i.e. test_lambda_ssm*
12 | # If not provided all tests will be run.
13 |
14 | set -e
15 |
16 | if [ ! -d "testing-venv" ]; then
17 | echo "Creating testing-venv..."
18 | python3 -m venv testing-venv
19 | fi
20 |
21 |
22 | echo " ---- Rebuilding package locally before testing..."
23 | source testing-venv/bin/activate
24 | echo " ---- Using python: `type python3`"
25 | echo " ---- Python version: `python3 --version`"
26 | echo " ---- Installing pip"
27 | pip3 install --quiet -U pip
28 | echo " ---- Installing dependency"
29 | source_code="$PWD"
30 | echo " ---- Changing working directory to the test directory"
31 | cd source/backend/lambda_unit_test/
32 | "$POETRY_HOME"/bin/poetry install
33 | echo "Updating source path $source_code"
34 | replace="s#%%SOURCE_PATH%%#$source_code#g"
35 | tox_path="$PWD/tox.ini"
36 | echo "tox.ini path: $tox_path"
37 | if [[ "$OSTYPE" == "darwin"* ]]; then
38 | sed -i '' -e $replace $tox_path
39 | else
40 | sed -i -e $replace $tox_path
41 | fi
42 |
43 | if [ -z "$1" ]; then
44 | echo " ---- Running all tests..."
45 | test_scope=discover
46 | else
47 | echo " ---- Running tests based on the pattern $1..."
48 | test_scope=$1
49 | fi
50 | coverage run --data-file=./coverage/.coverage -m unittest $test_scope
51 | echo " ---- Please make sure all the test cases above pass"
52 | echo
53 | echo
54 | echo " ---- Unit test Coverage report"
55 | coverage report --data-file=./coverage/.coverage
56 | coverage xml --data-file=./coverage/.coverage -o./coverage/coverage.xml
57 | deactivate
58 | echo "Removing source path $source_code"
59 | replace="s#$source_code#%%SOURCE_PATH%%#g"
60 | if [[ "$OSTYPE" == "darwin"* ]]; then
61 | sed -i '' -e $replace $tox_path
62 | else
63 | sed -i -e $replace $tox_path
64 | fi
65 |
66 | echo "------------------------------------------------------------------------------"
67 | echo "[Unit Tests] Backend Unit Tests Complete"
68 | echo "------------------------------------------------------------------------------"
--------------------------------------------------------------------------------
/solution-manifest.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | id: SO0097 # Solution Id
3 | name: cloud-migration-factory-on-aws # trademarked name
4 | version: v4.0.3 # current version of the solution. Used to verify template headers
5 | cloudformation_templates: # This list should match with AWS CloudFormation templates section of IG
6 | - template: aws-cloud-migration-factory-solution.template
7 | main_template: true
8 | - template: aws-cloud-migration-factory-solution-target-account.template
9 | main_template: true
10 | build_environment:
11 | build_image: "aws/codebuild/standard:7.0" # Options include: 'aws/codebuild/standard:5.0','aws/codebuild/standard:6.0','aws/codebuild/standard:7.0','aws/codebuild/amazonlinux2-x86_64-standard:4.0','aws/codebuild/amazonlinux2-x86_64-standard:5.0'
12 |
--------------------------------------------------------------------------------
/source/backend/lambda_functions/helper/helper.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | import json
6 | import uuid
7 |
8 | from urllib import request
9 | from cmf_logger import logger
10 |
11 |
12 | # Send response function
13 | def send_response(event, context, response_status, response_data):
14 | try:
15 | response_body = json.dumps({
16 | "Status": response_status,
17 | "PhysicalResourceId": context.log_stream_name,
18 | "StackId": event['StackId'],
19 | "RequestId": event['RequestId'],
20 | "LogicalResourceId": event['LogicalResourceId'],
21 | "Data": response_data
22 | })
23 |
24 | logger.info('Response URL: {}'.format(event['ResponseURL']))
25 | logger.info('Response Body: {}'.format(response_body))
26 |
27 | data = response_body.encode('utf-8')
28 | req = request.Request(event['ResponseURL'], data=data, method='PUT')
29 | req.add_header('Content-Type', '')
30 | req.add_header('Content-Length', len(response_body))
31 | response = request.urlopen(req) # nosec B310 URL is provided by CloudFormation
32 |
33 | logger.info('Status code: {}'.format(response.getcode()))
34 | logger.info('Status message: {}'.format(response.msg))
35 | except Exception as e:
36 | logger.error('Custom resource send_response error: {}'.format(e))
37 |
38 |
39 | def lambda_handler(event, context):
40 | logger.info('Received event: {}'.format(json.dumps(event)))
41 | response_data = {
42 | "Message": "Return UUID"
43 | }
44 |
45 | try:
46 | if event['RequestType'] == 'Create':
47 | response_data = {
48 | "UUID": str(uuid.uuid4())
49 | }
50 |
51 | send_response(event, context, 'SUCCESS', response_data)
52 | except Exception as e:
53 | logger.error('Error: {}'.format(e))
54 | response_data = {
55 | 'Error': e
56 | }
57 | send_response(event, context, 'FAILED', response_data)
58 |
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_auth/lambda_auth.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from policy import MFAuth
5 | from cmf_logger import logger, log_event_received
6 |
7 |
8 | def lambda_handler(event, _):
9 | log_event_received(event)
10 | if 'methodArn' in event:
11 | logger.info('Authenticating API Gateway request' + event['methodArn'])
12 | else:
13 | logger.info('Authenticating non-API Gateway request')
14 | auth = MFAuth()
15 | auth_response = auth.get_admin_resource_policy(event)
16 | logger.info(auth_response)
17 | return auth_response
18 |
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_cognitogroups/lambda_cognitogroups.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | import json
6 | import os
7 |
8 | import cmf_boto
9 | from cmf_logger import logger, log_event_received
10 | from cmf_utils import cors
11 |
12 | default_http_headers = {
13 | 'Access-Control-Allow-Origin': cors,
14 | 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload',
15 | 'Content-Security-Policy' : "base-uri 'self'; upgrade-insecure-requests; default-src 'none'; object-src 'none'; connect-src none; img-src 'self' data:; script-src blob: 'self'; style-src 'self'; font-src 'self' data:; form-action 'self';"
16 | }
17 |
18 |
19 | def lambda_handler(event, _):
20 | log_event_received(event)
21 |
22 | client = cmf_boto.client('cognito-idp')
23 | response = client.list_groups(
24 | UserPoolId=os.environ['userpool_id']
25 | )
26 | groups = []
27 | for group in response['Groups']:
28 | groups.append(group['GroupName'])
29 | return {'headers': {**default_http_headers},
30 | 'statusCode': 200,
31 | 'body': json.dumps(groups)
32 | }
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_defaultschema/default_roles.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "groups": {
4 | "L": [
5 | {
6 | "M": {
7 | "group_name": {
8 | "S": "admin"
9 | }
10 | }
11 | }
12 | ]
13 | },
14 | "role_id": {
15 | "S": "1"
16 | },
17 | "role_name": {
18 | "S": "FactoryAdmin"
19 | },
20 | "policies": {
21 | "L": [
22 | {
23 | "M": {
24 | "policy_id": {
25 | "S": "1"
26 | }
27 | }
28 | }
29 | ]
30 | }
31 | },
32 | {
33 | "groups": {
34 | "L": [
35 | {
36 | "M": {
37 | "group_name": {
38 | "S": "readonly"
39 | }
40 | }
41 | }
42 | ]
43 | },
44 | "role_id": {
45 | "S": "2"
46 | },
47 | "role_name": {
48 | "S": "FactoryReadOnly"
49 | },
50 | "policies": {
51 | "L": [
52 | {
53 | "M": {
54 | "policy_id": {
55 | "S": "2"
56 | }
57 | }
58 | }
59 | ]
60 | }
61 | },
62 | {
63 | "groups": {
64 | "L": [
65 | {
66 | "M": {
67 | "group_name": {
68 | "S": "orchestrator"
69 | }
70 | }
71 | }
72 | ]
73 | },
74 | "role_id": {
75 | "S": "3"
76 | },
77 | "role_name": {
78 | "S": "FactoryAutomationTaskOrchestrator"
79 | },
80 | "policies": {
81 | "L": [
82 | {
83 | "M": {
84 | "policy_id": {
85 | "S": "3"
86 | }
87 | }
88 | }
89 | ]
90 | }
91 | }
92 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_gfbuild/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "cloud-migration-factory-on-aws"
3 | package-mode = false
4 |
5 | [tool.poetry.dependencies]
6 | python = "^3.11"
7 | troposphere = "==4.9.0"
8 |
9 | [build-system]
10 | requires = ["poetry-core"]
11 | build-backend = "poetry.core.masonry.api"
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_import_export_pipeline_templates/models.py:
--------------------------------------------------------------------------------
1 | from typing import TypedDict, Optional, List
2 |
3 |
4 | class PipelineTemplateTask(TypedDict):
5 | pipeline_template_task_id: str
6 | pipeline_template_task_name: str
7 | pipeline_template_id: str
8 | task_id: Optional[str]
9 | task_name: Optional[str]
10 | task_successors: List[str]
11 | _history: dict
12 |
13 |
14 | class PipelineTemplate(TypedDict):
15 | pipeline_template_id: str
16 | pipeline_template_description: str
17 | pipeline_template_name: str
18 | pipeline_template_tasks: Optional[List[PipelineTemplateTask]]
19 | _history: dict
20 |
21 |
22 | class ClientException(Exception):
23 | def __init__(self, error: str, message: str, status_code: int = 400):
24 | self.error = error
25 | self.message = message
26 | self.status_code = status_code
27 |
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_login/lambda_login.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | import json
6 | import os
7 |
8 | import cmf_boto
9 | from cmf_logger import logger, log_event_received
10 | from cmf_utils import cors, default_http_headers
11 |
12 |
13 | def lambda_handler(event, _):
14 | response = {}
15 | log_event_received(event)
16 |
17 | try:
18 | body = json.loads(event['body'])
19 | client = cmf_boto.client('cognito-idp')
20 |
21 | if 'mfacode' in body:
22 | # This is a response to MFA request on previous login attempt.
23 | userid = body['username']
24 | mfacode = body['mfacode']
25 | session = body['session']
26 | response = client.respond_to_auth_challenge(
27 | ClientId=os.environ['clientId'],
28 | ChallengeName='SMS_MFA',
29 | Session=session,
30 | ChallengeResponses={
31 | 'SMS_MFA_CODE': mfacode,
32 | 'USERNAME': userid
33 | }
34 | )
35 | else:
36 | userid = body['username']
37 | password = body['password']
38 | response = client.initiate_auth(
39 | ClientId=os.environ['clientId'],
40 | AuthFlow='USER_PASSWORD_AUTH',
41 | AuthParameters={
42 | 'USERNAME': userid,
43 | 'PASSWORD': password
44 | }
45 | )
46 | except Exception as e:
47 | if "NotAuthorizedException" in str(e) or "UserNotFoundException" in str(e):
48 | logger.error('Incorrect username or password: %s', userid)
49 | return {'headers': {**default_http_headers},
50 | 'statusCode': 400,
51 | 'body': 'Incorrect username or password'
52 | }
53 | else:
54 | logger.error(e)
55 |
56 | if 'AuthenticationResult' in response:
57 | logger.info('User authenticated: %s', userid)
58 | return {'headers': {**default_http_headers},
59 | 'statusCode': 200,
60 | 'body': json.dumps(response['AuthenticationResult']['IdToken'])
61 | }
62 | elif 'ChallengeName' in response:
63 | logger.info('User challenge requested: %s', userid)
64 | return {'headers': {**default_http_headers},
65 | 'statusCode': 200,
66 | 'body': json.dumps(response)
67 | }
68 |
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_pipeline_task_execution_output/lambda_pipeline_task_execution_output.py:
--------------------------------------------------------------------------------
1 | import gzip
2 | import json
3 | import base64
4 | import re
5 | import os
6 | from datetime import datetime
7 | import time
8 |
9 | import cmf_boto
10 | from cmf_logger import logger
11 | import cmf_pipeline
12 |
13 | ddb_client = cmf_boto.resource("dynamodb")
14 | application = os.environ["application"]
15 | environment = os.environ["environment"]
16 | task_executions_table_name = '{}-{}-task_executions'.format(application, environment)
17 | task_executions_table = ddb_client.Table(task_executions_table_name)
18 |
19 |
20 | def update_log(task_execution_id, status, message):
21 | logger.info(f'Writing log for task execution ID: {task_execution_id}')
22 | resp = task_executions_table.get_item(Key={'task_execution_id': task_execution_id})
23 | if "Item" not in resp:
24 | logger.warn("Task execution ID not found")
25 | return
26 | task_execution_data = resp["Item"]
27 |
28 | message = "[" + time.strftime("%H:%M:%S") + "] " + "\n" + message + "\n"
29 | output = task_execution_data.get("output", "") + message
30 | last_output_message = message.split(f'[{status}]',1)[1]
31 |
32 | cmf_pipeline.update_task_execution_output(task_execution_id, last_output_message, output)
33 | cmf_pipeline.update_task_execution_status(task_execution_id, cmf_pipeline.TaskExecutionStatus(status))
34 |
35 |
36 | def lambda_handler(event, _):
37 | # parse Cloudwatch Log
38 | cw_data = event['awslogs']['data']
39 | compressed_payload = base64.b64decode(cw_data)
40 | uncompressed_payload = gzip.decompress(compressed_payload)
41 | payload = json.loads(uncompressed_payload)
42 | for log_event in payload['logEvents']:
43 | message = log_event["message"]
44 |
45 | logger.info('Processing Cloudwatch event.')
46 |
47 | # Expected log format to be "[task_execution_id][status] message"
48 | message_metadata = re.findall(r"\[(.*?)\]", message)
49 | if (len(message_metadata) < 2):
50 | logger.debug(f"Can't process message format: {message}")
51 | continue
52 |
53 | update_log(message_metadata[0], message_metadata[1], message)
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_replatformec2schema/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from . import factory
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_reset/lambda_reset.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | import json
6 | import os
7 |
8 | import cmf_boto
9 | from cmf_utils import cors, default_http_headers
10 | from cmf_logger import logger, log_event_received
11 |
12 |
13 | def lambda_handler(event, _):
14 | log_event_received(event)
15 |
16 | body = json.loads(event['body'])
17 | userid = body['username']
18 | oldpassword = body['oldpassword']
19 | newpassword = body['newpassword']
20 | client = cmf_boto.client('cognito-idp')
21 | try:
22 | response = client.initiate_auth(
23 | ClientId=os.environ['clientId'],
24 | AuthFlow='USER_PASSWORD_AUTH',
25 | AuthParameters={
26 | 'USERNAME': userid,
27 | 'PASSWORD': oldpassword
28 | }
29 | )
30 | except Exception as e:
31 | if "NotAuthorizedException" in str(e) or "UserNotFoundException" in str(e):
32 | return {'headers': {**default_http_headers},
33 | 'statusCode': 400,
34 | 'body': 'Incorrect old username or password'
35 | }
36 |
37 | challenge_name = response['ChallengeName']
38 | if challenge_name == "NEW_PASSWORD_REQUIRED":
39 | response = client.respond_to_auth_challenge(
40 | ClientId=os.environ['clientId'],
41 | ChallengeName='NEW_PASSWORD_REQUIRED',
42 | Session=response['Session'],
43 | ChallengeResponses={
44 | 'NEW_PASSWORD': newpassword,
45 | 'USERNAME' : userid
46 |
47 | }
48 | )
49 |
50 | return {
51 | 'headers': {**default_http_headers},
52 | 'statusCode': 200,
53 | 'body': json.dumps(response)
54 | }
55 |
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_ssm_load_scripts/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "cloud-migration-factory-on-aws"
3 | package-mode = false
4 |
5 | [tool.poetry.dependencies]
6 | python = "^3.11"
7 | PyYAML = "^6.0.2"
8 |
9 | [build-system]
10 | requires = ["poetry-core"]
11 | build-backend = "poetry.core.masonry.api"
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_ssm_scripts/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "cloud-migration-factory-on-aws"
3 | package-mode = false
4 |
5 | [tool.poetry.dependencies]
6 | python = "^3.11"
7 | PyYAML = "^6.0.2"
8 |
9 | [build-system]
10 | requires = ["poetry-core"]
11 | build-backend = "poetry.core.masonry.api"
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_ssm_socket/poetry.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
2 |
3 | [[package]]
4 | name = "pyjwt"
5 | version = "2.10.1"
6 | description = "JSON Web Token implementation in Python"
7 | optional = false
8 | python-versions = ">=3.9"
9 | groups = ["main"]
10 | files = [
11 | {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"},
12 | {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"},
13 | ]
14 |
15 | [package.extras]
16 | crypto = ["cryptography (>=3.4.0)"]
17 | dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"]
18 | docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
19 | tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
20 |
21 | [metadata]
22 | lock-version = "2.1"
23 | python-versions = "^3.11"
24 | content-hash = "0b979cc021881b0dd9dbc97614dcc0a16d1ffc8698f60e1e926fa2ed9f859f8c"
25 |
--------------------------------------------------------------------------------
/source/backend/lambda_functions/lambda_ssm_socket/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "cloud-migration-factory-on-aws"
3 | package-mode = false
4 |
5 | [tool.poetry.dependencies]
6 | python = "^3.11"
7 | PyJWT= "2.10.1"
8 |
9 | [build-system]
10 | requires = ["poetry-core"]
11 | build-backend = "poetry.core.masonry.api"
--------------------------------------------------------------------------------
/source/backend/lambda_layers/lambda_layer_items/python/query_comparator_operations.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | import query_conditions
5 |
6 | # list of operation names as constants
7 | EQUAL_COMPARATOR = "="
8 | NOT_EQUAL_COMPARATOR = "!="
9 | EMPTY_COMPARATOR = "empty"
10 | NOT_EMPTY_COMPARATOR = "!empty"
11 |
12 | query_comparator_operations_dictionary = {
13 | EQUAL_COMPARATOR: query_conditions.equal_query_condition,
14 | NOT_EQUAL_COMPARATOR: query_conditions.not_equal_query_condition,
15 | EMPTY_COMPARATOR: query_conditions.empty_query_condition,
16 | NOT_EMPTY_COMPARATOR: query_conditions.not_empty_query_condition
17 | }
--------------------------------------------------------------------------------
/source/backend/lambda_layers/lambda_layer_items/python/query_conditions.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | def equal_query_condition(item, query, query_result):
6 | if query['attribute'] in item and query['value']:
7 | if item[query['attribute']] == query['value']:
8 | query_result = True if query_result != False else query_result
9 | return query_result
10 |
11 | return False
12 |
13 |
14 | def not_equal_query_condition(item, query, query_result):
15 | if query['attribute'] in item and query['value']:
16 | if item[query['attribute']] != query['value']:
17 | query_result = True if query_result != False else query_result
18 | return query_result
19 |
20 | return False
21 |
22 |
23 | def empty_query_condition(item, query, query_result):
24 | if query['attribute'] in item:
25 | query_result = non_list_type_attribute_for_empty_comparator(item, query, query_result)
26 | elif query['attribute'] not in item and 'comparator' in query:
27 | query_result = True if query_result != False else query_result
28 |
29 | return query_result
30 |
31 |
32 | def not_empty_query_condition(item, query, query_result):
33 | if query['attribute'] in item:
34 | query_result = non_list_type_attribute_for_not_empty_comparator(item, query, query_result)
35 |
36 | return query_result
37 |
38 |
39 | def non_list_type_attribute_for_empty_comparator(item, query, query_result):
40 | if item[query['attribute']] == '':
41 | query_result = True if query_result != False else query_result
42 | return query_result
43 |
44 | return False
45 |
46 |
47 | def non_list_type_attribute_for_not_empty_comparator(item, query, query_result):
48 | if item[query['attribute']] != '':
49 | query_result = True if query_result != False else query_result
50 | return query_result
51 |
52 | return False
53 |
54 |
55 | def parse_outcomes(outcomes):
56 | return_required = False
57 | return_hidden = False
58 |
59 | for outcome in outcomes:
60 | if outcome == 'required':
61 | return_required = True
62 | elif outcome == 'not_required':
63 | return_required = False
64 | elif outcome == 'hidden':
65 | return_hidden = True
66 | elif outcome == 'not_hidden':
67 | return_hidden = False
68 |
69 | return return_required, return_hidden
--------------------------------------------------------------------------------
/source/backend/lambda_layers/lambda_layer_policy/python/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "cloud-migration-factory-on-aws"
3 | package-mode = false
4 |
5 | [tool.poetry.dependencies]
6 | python = "^3.11"
7 | urllib3 = ">=2.3.0"
8 | requests = "==2.32.3"
9 | PyJWT = {extras = ["crypto"], version = "2.10.1"}
10 | simplejson = "==3.20.1"
11 |
12 | [build-system]
13 | requires = ["poetry-core"]
14 | build-backend = "poetry.core.masonry.api"
--------------------------------------------------------------------------------
/source/backend/lambda_layers/lambda_layer_py_pkgs/python/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "cloud-migration-factory-on-aws"
3 | package-mode = false
4 |
5 | [tool.poetry.dependencies]
6 | python = "^3.11"
7 | urllib3 = ">=2.3.0"
8 | requests = "==2.32.3"
9 | simplejson = "==3.20.1"
10 | boto3 = "^1.37.6"
11 | botocore = "^1.37.6"
12 | aws-lambda-powertools = ">=3.7.0"
13 | mypy-boto3-dynamodb = ">=1.37.0"
14 |
15 | [build-system]
16 | requires = ["poetry-core"]
17 | build-backend = "poetry.core.masonry.api"
--------------------------------------------------------------------------------
/source/backend/lambda_layers/lambda_layer_utils/python/cmf_boto.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from botocore.config import Config
5 | import boto3
6 | import os
7 |
8 |
9 | def client(*args, **kwargs):
10 | """
11 | returns a boto client instrumented with a user agent
12 | """
13 | _add_user_agent(kwargs)
14 | return boto3.client(*args, **kwargs)
15 |
16 |
17 | def resource(*args, **kwargs):
18 | """
19 | returns a boto resource instrumented with a user agent
20 | """
21 | _add_user_agent(kwargs)
22 | return boto3.resource(*args, **kwargs)
23 |
24 |
25 | def session_client(session, *args, **kwargs):
26 | """
27 | returns a boto session_client instrumented with a user agent
28 | """
29 | _add_user_agent(kwargs)
30 | return session.client(*args, **kwargs)
31 |
32 |
33 | def _add_user_agent(kwargs):
34 | """
35 | adds a user agent to the kwargs if there isn't none
36 | """
37 | solution_id = os.getenv('SOLUTION_ID', 'SO0097')
38 | solution_version = os.getenv('SOLUTION_VERSION', 'unknown')
39 | user_agent = f'AwsSolution/{solution_id}/{solution_version}'
40 | if 'config' not in kwargs:
41 | boto_config = Config(user_agent_extra=user_agent)
42 | kwargs['config'] = boto_config
43 | else:
44 | kwargs['config'] = kwargs['config'].merge(Config(user_agent_extra=user_agent))
45 |
--------------------------------------------------------------------------------
/source/backend/lambda_layers/lambda_layer_utils/python/cmf_logger.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | from importlib import reload
5 | import logging
6 | import os
7 |
8 | LOGGER_LEVELS = {
9 | 'DEBUG': logging.DEBUG,
10 | 'INFO': logging.INFO,
11 | 'WARNING': logging.WARNING,
12 | 'ERROR': logging.ERROR,
13 | }
14 |
15 | LOGLEVEL = os.getenv('LOGLEVEL', 'INFO').upper()
16 | # This will not take effect if a basicConfig has already been set for the process
17 | logging.basicConfig(format='%(asctime)s | %(levelname)s | %(message)s', level=LOGLEVEL) # //NOSONAR Basic configuration doesn't pose security risk
18 | logger = logging.getLogger()
19 | logger.setLevel(LOGGER_LEVELS[LOGLEVEL])
20 |
21 |
22 | def get_logger(name=None):
23 | return logging.getLogger(name)
24 |
25 |
26 | def init_task_execution_logger(filter):
27 | reload(logging)
28 | task_execution_logger = logging.getLogger()
29 | logging.basicConfig(format='[%(task_execution_id)s][%(status)s] %(message)s', level=logging.INFO)
30 | task_execution_logger.setLevel(logging.INFO)
31 | task_execution_logger.addFilter(filter)
32 | return task_execution_logger
33 |
34 | def log_event_received(event):
35 | logger.info(f'RequestId: {event.get("requestContext", {}).get("requestId", "{not provided}")}, '
36 | f'ExtendedRequestId: {event.get("requestContext", {}).get("extendedRequestId", "{not provided}")}')
--------------------------------------------------------------------------------
/source/backend/lambda_layers/lambda_layer_utils/python/cmf_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 | from datetime import datetime, timezone
4 | import os
5 | import requests
6 | import json
7 |
8 | # System-wide data format for logging and notifications.
9 | CONST_DT_FORMAT = '%Y-%m-%dT%H:%M:%S.%f%z'
10 | CONST_DT_FORMAT_V3 = '%Y-%m-%dT%H:%M:%S.%f'
11 |
12 | REQUESTS_DEFAULT_TIMEOUT = 60
13 |
14 | if 'cors' in os.environ:
15 | cors = os.environ['cors']
16 | else:
17 | cors = '*'
18 |
19 | default_http_headers = {
20 | 'Access-Control-Allow-Origin': cors,
21 | 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload',
22 | 'Content-Security-Policy': "base-uri 'self'; upgrade-insecure-requests; default-src 'none'; object-src 'none'; connect-src none; img-src 'self' data:; script-src blob: 'self'; style-src 'self'; font-src 'self' data:; form-action 'self';"
23 | }
24 |
25 | # anonymous_usage_data settings.
26 | anonymous_usage_data = os.environ.get('AnonymousUsageData', 'Yes')
27 | s_uuid = os.environ.get('solutionUUID', '')
28 | region = os.environ.get('region','unknown')
29 | if region == 'unknown':
30 | region = os.environ.get('REGION', 'unknown')
31 | anonymous_usage_data_url = 'https://metrics.awssolutionsbuilder.com/generic'
32 | solution_id = os.getenv('SOLUTION_ID', 'SO0097')
33 |
34 |
35 | def send_anonymous_usage_data(status):
36 | if anonymous_usage_data == "Yes":
37 | usage_data = {"Solution": solution_id,
38 | "UUID": s_uuid,
39 | "Status": status,
40 | "TimeStamp": str(datetime.now()),
41 | "Region": region
42 | }
43 | requests.post(anonymous_usage_data_url,
44 | data=json.dumps(usage_data),
45 | headers={'content-type': 'application/json'},
46 | timeout=REQUESTS_DEFAULT_TIMEOUT)
47 |
48 |
49 | def get_date_from_string(str_date):
50 | try:
51 | created_timestamp = datetime.strptime(str_date, CONST_DT_FORMAT)
52 | except Exception as _:
53 | # try old pre v4 format for backward compatibility.
54 | created_timestamp = datetime.strptime(str_date, CONST_DT_FORMAT_V3)
55 |
56 | created_timestamp = created_timestamp.replace(tzinfo=timezone.utc)
57 |
58 | return created_timestamp
59 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "cloud-migration-factory-on-aws"
3 | package-mode = false
4 |
5 | [tool.poetry.dependencies]
6 | python = "^3.11"
7 | urllib3 = ">=2.3.0"
8 | requests = "==2.32.3"
9 | simplejson = "==3.20.1"
10 | boto3 = "^1.37.6"
11 | botocore = "^1.37.6"
12 | moto = "==5.1.1"
13 | coverage = "==7.6.12"
14 | troposphere = "==4.9.0"
15 | PyYAML = "==6.0.2"
16 | pyparsing = "==3.2.1"
17 | docker = "==7.1.0"
18 | aws-lambda-powertools = {extras = ["aws-sdk"], version = ">=3.7.0"}
19 | PyJWT = {extras = ["crypto"], version = "2.10.1"}
20 | joserfc = "~=1.0.4"
21 | mypy-boto3-dynamodb = ">=1.37.0"
22 |
23 | [tool.poetry.group.dev.dependencies]
24 |
25 | [build-system]
26 | requires = ["poetry-core"]
27 | build-backend = "poetry.core.masonry.api"
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/Migration_Tracker_All_Extract_Script.py:
--------------------------------------------------------------------------------
1 | # sample file for testing
2 | # used by test_lambda_migrationtracker_glue_base.py, the lambda lambda_migrationtracker_glue_base.py copies the file
3 | # to a specified S3 bucket. So the tests verify that the file is copied regardless of the content
4 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/apps.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "app_id": {
4 | "S": "1"
5 | },
6 | "app_name": {
7 | "S": "Wordpress"
8 | },
9 | "aws_accountid": {
10 | "S": "111111111111"
11 | },
12 | "aws_region": {
13 | "S": "us-east-1"
14 | },
15 | "wave_id": {
16 | "S": "1"
17 | },
18 | "tags": {
19 | "L": [
20 | {
21 | "S": "tag1"
22 | },
23 | {
24 | "S": "tag2"
25 | }
26 | ]
27 | },
28 | "description":{
29 | "S": "The amazing wordpress"
30 | }
31 | },
32 | {
33 | "app_id": {
34 | "S": "2"
35 | },
36 | "app_name": {
37 | "S": "OFBiz"
38 | },
39 | "aws_accountid": {
40 | "S": "111111111111"
41 | },
42 | "aws_region": {
43 | "S": "us-east-1"
44 | },
45 | "wave_id": {
46 | "S": "1"
47 | }
48 | }
49 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/connection_ids.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "connectionId": {
4 | "S": "1"
5 | }
6 | },
7 | {
8 | "connectionId": {
9 | "S": "2"
10 | }
11 | }
12 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/jwtRS256.key.pub:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAx363yFGiUUD0M3zy4G7Y
3 | 6cjTm+k9BYaTbaXYJe7l/coCJg0KK+xkRtWFGqftDiRM1qAbHrLrLolfF2HwWaMp
4 | 9sya6cYNnj+z64cJ1YwPXO8ATX5pD2vNQHFgwWYp20McpNADxrJ908kCrGav9Qws
5 | yZb5AICPJ6zY6mPBSkJkSbY+Gxp/Lkf+EGVTifCIr1Ob7SfVrS7NMXcwqhh3iAF7
6 | n83DCU9QHrIYY1A/2E96NIx1y+CcaWLd7XB20atC7vNnrh06rL/fg12OrfDAfIb/
7 | Ln6EeYDmDMOgHX9i0UhInIGd2LSF2+sIIO+W94Wrcz7EtotruBvDCL4O2cuW3qPY
8 | B4OX3ARI0/octMCBb373gTRzjVFE5X4DeHAXWo9ljq3FeA9GlcNfekTNvZ//HbuL
9 | oJM3w5kA4zptkHEAWcEFIe87VgdVBXnHASyN9XFcaWhenPBxtr33+Yxsw6o9SNCU
10 | iGrHu7O5ZLcLE9BuONoawOv3oHpuUupNJlUBKe5uocXV2neAyysD0dmIZQ8lVVfc
11 | eaM14GI8ozImlEpLkyZ3uocXqS4RoQ7kmneSXxa0Mc3jVSyJ/lNEdTGNK+e80hC7
12 | ZD4FyyIvB8zNtFROwUj8cSOWEy2E/Hd5dMQsSBDAEr2MEfGOf6D7G/ziPG8wU1XO
13 | kFMvemw6dqq4ju3+FE1Yvz8CAwEAAQ==
14 | -----END PUBLIC KEY-----
15 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/pipeline_templates.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pipeline_template_id": {
4 | "S": "1"
5 | },
6 | "pipeline_template_description": {
7 | "S": "Imports Application Discovery Service (ADS) inventory data and EC2 recommendations"
8 | },
9 | "pipeline_template_name": {
10 | "S": "Migration Hub Import"
11 | },
12 | "_history": {
13 | "M": {
14 | "createdBy": {
15 | "M": {
16 | "email": {
17 | "S": "someone@example.com"
18 | },
19 | "userRef": {
20 | "S": "0468d488-50a1-706b-dfb1-4a977a1e105b"
21 | }
22 | }
23 | },
24 | "createdTimestamp": {
25 | "S": "2024-09-17T11:00:37.943349+00:00"
26 | }
27 | }
28 | }
29 | },
30 | {
31 | "pipeline_template_id": {
32 | "S": "2"
33 | },
34 | "pipeline_template_description": {
35 | "S": "Facilitates server replications via Application Migration Service (MGN) for the selected wave"
36 | },
37 | "pipeline_template_name": {
38 | "S": "Rehost with Application Migration Service (MGN)"
39 | },
40 | "_history": {
41 | "M": {
42 | "createdBy": {
43 | "M": {
44 | "email": {
45 | "S": "someone@example.com"
46 | },
47 | "userRef": {
48 | "S": "0468d488-50a1-706b-dfb1-4a977a1e105b"
49 | }
50 | }
51 | },
52 | "createdTimestamp": {
53 | "S": "2024-09-17T11:00:43.603504+00:00"
54 | }
55 | }
56 | }
57 | }
58 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/pipelines.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "pipeline_id": {
4 | "S": "1"
5 | },
6 | "pipeline_name": {
7 | "S": "Pipeline1"
8 | },
9 | "pipeline_status": {
10 | "S": "Not Started"
11 | },
12 | "_history": {
13 | "M": {
14 | "lastModifiedTimestamp": {
15 | "S": "test"
16 | },
17 | "lastModifiedBy": {
18 | "S": "test"
19 | }
20 | },
21 | "M": {
22 | "createdByTimestamp": {
23 | "S": "test"
24 | },
25 | "createdBy": {
26 | "M": {
27 | "email": {
28 | "S": "test"
29 | },
30 | "userRef": {
31 | "S": "test"
32 | }
33 | }
34 | }
35 | }
36 | }
37 | },
38 | {
39 | "pipeline_id": {
40 | "S": "2"
41 | },
42 | "pipeline_name": {
43 | "S": "Pipeline2"
44 | },
45 | "pipeline_status": {
46 | "S": "In Progress"
47 | },
48 | "_history": {
49 | "M": {
50 | "lastModifiedTimestamp": {
51 | "S": "test"
52 | },
53 | "lastModifiedBy": {
54 | "S": "test"
55 | }
56 | },
57 | "M": {
58 | "createdByTimestamp": {
59 | "S": "test"
60 | },
61 | "createdBy": {
62 | "M": {
63 | "email": {
64 | "S": "test"
65 | },
66 | "userRef": {
67 | "S": "test"
68 | }
69 | }
70 | }
71 | }
72 | }
73 | },
74 | {
75 | "pipeline_id": {
76 | "S": "2"
77 | },
78 | "pipeline_name": {
79 | "S": "Pipeline2"
80 | },
81 | "pipeline_status": {
82 | "S": "In Progress"
83 | },
84 | "_history": {
85 | "M": {
86 | "lastModifiedTimestamp": {
87 | "S": "test"
88 | },
89 | "lastModifiedBy": {
90 | "S": "test"
91 | }
92 | },
93 | "M": {
94 | "createdByTimestamp": {
95 | "S": "test"
96 | },
97 | "createdBy": {
98 | "M": {
99 | "email": {
100 | "S": "test"
101 | },
102 | "userRef": {
103 | "S": "test"
104 | }
105 | }
106 | }
107 | }
108 | }
109 | }
110 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/policies.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "policy_id": {
4 | "S": "1"
5 | },
6 | "policy_name": {
7 | "S": "Administrator"
8 | }
9 | },
10 | {
11 | "policy_id": {
12 | "S": "2"
13 | },
14 | "policy_name": {
15 | "S": "ReadOnly"
16 | }
17 | },
18 | {
19 | "policy_id": {
20 | "S": "3"
21 | },
22 | "policy_name": {
23 | "S": "CustomPolicy"
24 | }
25 | }
26 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/roles.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "role_id": {
4 | "S": "1"
5 | },
6 | "groups": {
7 | "L": [
8 | {
9 | "M": {
10 | "group_name": {
11 | "S": "admin"
12 | }
13 | }
14 | }
15 | ]
16 | },
17 | "policies": {
18 | "L": [
19 | {
20 | "M": {
21 | "policy_id": {
22 | "S": "1"
23 | }
24 | }
25 | }
26 | ]
27 | },
28 | "role_name": {
29 | "S": "FactoryAdmin"
30 | }
31 | },
32 | {
33 | "role_id": {
34 | "S": "2"
35 | },
36 | "groups": {
37 | "L": [
38 | {
39 | "M": {
40 | "group_name": {
41 | "S": "readonly"
42 | }
43 | }
44 | }
45 | ]
46 | },
47 | "policies": {
48 | "L": [
49 | {
50 | "M": {
51 | "policy_id": {
52 | "S": "2"
53 | }
54 | }
55 | }
56 | ]
57 | },
58 | "role_name": {
59 | "S": "FactoryReadOnly"
60 | }
61 | },
62 | {
63 | "role_id": {
64 | "S": "3"
65 | },
66 | "groups": {
67 | "L": [
68 | {
69 | "M": {
70 | "group_name": {
71 | "S": "orchestrator"
72 | }
73 | }
74 | }
75 | ]
76 | },
77 | "policies": {
78 | "L": [
79 | {
80 | "M": {
81 | "policy_id": {
82 | "S": "3"
83 | }
84 | }
85 | }
86 | ]
87 | },
88 | "role_name": {
89 | "S": "FactoryAutomationTaskOrchestrator"
90 | }
91 | }
92 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schema_server_replatform_create_ec2.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema_name": "EC2",
3 | "schema_type": "automation",
4 | "friendly_name": "EC2",
5 | "attributes": [
6 | {
7 | "rel_display_attribute": "aws_accountid",
8 | "system": true,
9 | "validation_regex": "^(?!\\s*$).+",
10 | "rel_key": "aws_accountid",
11 | "name": "accountid",
12 | "description": "AWS account ID",
13 | "rel_entity": "application",
14 | "validation_regex_msg": "AWS account ID must be provided.",
15 | "type": "relationship"
16 | },
17 | {
18 | "rel_display_attribute": "wave_name",
19 | "system": true,
20 | "validation_regex": "^(?!\\s*$).+",
21 | "rel_key": "wave_id",
22 | "name": "waveid",
23 | "description": "Wave",
24 | "rel_entity": "wave",
25 | "validation_regex_msg": "Wave must be provided.",
26 | "type": "relationship"
27 | }
28 | ],
29 | "group": "RePlatform",
30 | "description": "New EC2 Build",
31 | "actions": [
32 | {
33 | "name": "EC2 Input Validation",
34 | "apiMethod": "post",
35 | "id": "EC2 Input Validation",
36 | "awsuistyle": "primary",
37 | "apiPath": "/gfvalidate"
38 | },
39 | {
40 | "name": "EC2 Generate CF Template",
41 | "apiMethod": "post",
42 | "id": "EC2 Generate CF Template",
43 | "awsuistyle": "primary",
44 | "apiPath": "/gfbuild"
45 | },
46 | {
47 | "name": "EC2 Deployment",
48 | "apiMethod": "post",
49 | "id": "EC2 Deployment",
50 | "awsuistyle": "primary",
51 | "apiPath": "/gfdeploy"
52 | }
53 | ]
54 | }
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schema_server_replatform_delete_server.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema_name": "server",
3 | "schema_type": "user",
4 | "attributes": [
5 | {
6 | "description": "Server Id",
7 | "hidden": true,
8 | "name": "server_id",
9 | "required": true,
10 | "system": true,
11 | "type": "string"
12 | },
13 | {
14 | "description": "Application",
15 | "group_order": "-998",
16 | "name": "app_id",
17 | "rel_display_attribute": "app_name",
18 | "rel_entity": "application",
19 | "rel_key": "app_id",
20 | "required": true,
21 | "system": true,
22 | "type": "relationship"
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schema_server_replatform_delete_server_attrs.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema_name": "server",
3 | "schema_type": "user",
4 | "attributes": [
5 | {
6 | "description": "Server Id",
7 | "hidden": true,
8 | "name": "server_id",
9 | "required": true,
10 | "system": true,
11 | "type": "string"
12 | },
13 | {
14 | "description": "Application",
15 | "group_order": "-998",
16 | "name": "app_id",
17 | "rel_display_attribute": "app_name",
18 | "rel_entity": "application",
19 | "rel_key": "app_id",
20 | "required": true,
21 | "system": true,
22 | "type": "relationship"
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schema_server_replatform_update_server.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema_name": "server",
3 | "schema_type": "user",
4 | "attributes": [
5 | {
6 | "description": "Server Id",
7 | "hidden": true,
8 | "name": "server_id",
9 | "required": true,
10 | "system": true,
11 | "type": "string"
12 | },
13 | {
14 | "description": "Application",
15 | "group_order": "-998",
16 | "name": "app_id",
17 | "rel_display_attribute": "app_name",
18 | "rel_entity": "application",
19 | "rel_key": "app_id",
20 | "required": true,
21 | "system": true,
22 | "type": "relationship"
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schemas.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "schema_name": {
4 | "S": "server"
5 | },
6 | "schema_type": {
7 | "S": "user"
8 | },
9 | "attributes": {
10 | "L": [
11 | {
12 | "M": {
13 | "description": {
14 | "S": "Server Id"
15 | },
16 | "hidden": {
17 | "BOOL": true
18 | },
19 | "name": {
20 | "S": "server_id"
21 | },
22 | "required": {
23 | "BOOL": true
24 | },
25 | "system": {
26 | "BOOL": true
27 | },
28 | "type": {
29 | "S": "string"
30 | }
31 | }
32 | },
33 | {
34 | "M": {
35 | "description": {
36 | "S": "Application"
37 | },
38 | "group_order": {
39 | "S": "-998"
40 | },
41 | "name": {
42 | "S": "app_id"
43 | },
44 | "rel_display_attribute": {
45 | "S": "app_name"
46 | },
47 | "rel_entity": {
48 | "S": "application"
49 | },
50 | "rel_key": {
51 | "S": "app_id"
52 | },
53 | "required": {
54 | "BOOL": true
55 | },
56 | "system": {
57 | "BOOL": true
58 | },
59 | "type": {
60 | "S": "relationship"
61 | }
62 | }
63 | }
64 | ]
65 | }
66 | },
67 | {
68 | "schema_name": {
69 | "S": "wave"
70 | },
71 | "schema_type": {
72 | "S": "user"
73 | }
74 | },
75 | {
76 | "schema_name": {
77 | "S": "app"
78 | },
79 | "schema_type": {
80 | "S": "user"
81 | },
82 | "attributes": {
83 | "L": [
84 | {
85 | "M": {
86 | "name": {
87 | "S": "app_id"
88 | },
89 | "type": {
90 | "S": "string"
91 | }
92 | }
93 | },
94 | {
95 | "M": {
96 | "name": {
97 | "S": "app_name"
98 | },
99 | "type": {
100 | "S": "string"
101 | }
102 | }
103 | }
104 | ]
105 | }
106 | },
107 | {
108 | "schema_name": {
109 | "S": "automation"
110 | },
111 | "schema_type": {
112 | "S": "automation"
113 | }
114 | }
115 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schemas_modified_TS.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "schema_name": {
4 | "S": "server"
5 | },
6 | "lastModifiedTimestamp": {
7 | "S": "2023-04-28T15:27:12.991773+00:00"
8 | },
9 | "schema_type": {
10 | "S": "user"
11 | }
12 | },
13 | {
14 | "schema_name": {
15 | "S": "wave"
16 | },
17 | "lastModifiedTimestamp": {
18 | "S": "2023-04-28T15:27:12.991773+00:00"
19 | },
20 | "schema_type": {
21 | "S": "user"
22 | }
23 | },
24 | {
25 | "schema_name": {
26 | "S": "app"
27 | },
28 | "lastModifiedTimestamp": {
29 | "S": "2023-04-25T18:53:25.915746+00:00"
30 | },
31 | "schema_type": {
32 | "S": "user"
33 | }
34 | }
35 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schemas_no_app.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "schema_name": {
4 | "S": "server"
5 | },
6 | "schema_type": {
7 | "S": "user"
8 | }
9 | },
10 | {
11 | "schema_name": {
12 | "S": "wave"
13 | },
14 | "schema_type": {
15 | "S": "user"
16 | }
17 | }
18 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schemas_no_server.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "schema_name": {
4 | "S": "wave"
5 | },
6 | "schema_type": {
7 | "S": "user"
8 | }
9 | },
10 | {
11 | "schema_name": {
12 | "S": "app"
13 | },
14 | "schema_type": {
15 | "S": "user"
16 | }
17 | }
18 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/schemas_no_wave.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "schema_name": {
4 | "S": "server"
5 | },
6 | "schema_type": {
7 | "S": "user"
8 | }
9 | },
10 | {
11 | "schema_name": {
12 | "S": "app"
13 | },
14 | "schema_type": {
15 | "S": "user"
16 | }
17 | }
18 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/README.md:
--------------------------------------------------------------------------------
1 | This folder contains test data for the lambdas
2 | - lambda_ssm_load_scripts
3 | - lambda_ssm_scripts
4 |
5 | ### lambda_ssm_load_scripts
6 | The tests expect a zip file with scripts.
7 | - sample_ssm_scripts.zip, the zip file containing sample_ssm_script_1.json and sample_ssm_script_2.json
8 | - sample_ssm_script_1.json and sample_ssm_script_2.json are the sample json files included for the convenience of checking the contents without unzipping
9 |
10 | ### lambda_ssm_scripts
11 | - invalid_zip_file.zip - a single python source file renamed with .zip extension to be used as invalid zip in the tests
12 |
13 |
14 | - package_valid consists of
15 | - hello_world.py
16 | - mfcommon.py
17 | - Package-Structure.yml
18 |
19 | The test then creates a zip file containing the above files on the fly
20 |
21 | Similarly, the following packages are used in the tests
22 | - package_invalid_yaml
23 | - package_no_yaml
24 | - package_incorrect_yaml_contents
25 | - package_no_master_file
26 | - package_valid_with_dependencies
27 | - package_missing_dependencies
28 | - package_schema_extensions
29 | - package_invalid_attributes
30 |
31 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_incorrect_yaml_contents/Package-Structure.yml:
--------------------------------------------------------------------------------
1 | Name1: "Hello World"
2 | Description1: "This script will output the text provided in the argument."
3 | MasterFileName1: "hello_world.py"
4 | Arguments1:
5 | -
6 | name: "MyMessage"
7 | long_desc: "Message to output."
8 | description: "Message that will be output from python and powershell,"
9 | type: "sting"
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_incorrect_yaml_contents/hello_world.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_invalid_attributes/Package-Structure.yml:
--------------------------------------------------------------------------------
1 | Name: "Hello World"
2 | Description: "This script will output the text provided in the argument."
3 | MasterFileName: "hello_world.py"
4 | Arguments:
5 | -
6 | name: ""
7 | long_desc1: "Message to output."
8 | description1: "Message that will be output from python and powershell,"
9 | type1: "sting"
10 | - name: "MyMessage 2"
11 | long_desc: "Message to output 2."
12 | description: "Message that will be output from python and powershell 2,"
13 | type: "list"
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_invalid_attributes/hello_world.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_invalid_yaml/Package-Structure.yml:
--------------------------------------------------------------------------------
1 | Name: "Hello World"
2 | Description: "This script will output the text provided in the argument."
3 | MasterFileName: "hello_world.py"
4 | Arguments:
5 | -
6 | name: "MyMessage"
7 | long_desc: "Message to output."
8 | description: "Message that will be output from python and powershell,"
9 | type: "sting"
10 | INVALID LINE
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_invalid_yaml/hello_world.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_missing_dependencies/Package-Structure.yml:
--------------------------------------------------------------------------------
1 | Name: "Hello World"
2 | Description: "This script will output the text provided in the argument."
3 | MasterFileName: "hello_world.py"
4 | Arguments:
5 | -
6 | name: "MyMessage"
7 | long_desc: "Message to output."
8 | description: "Message that will be output from python and powershell,"
9 | type: "sting"
10 | Dependencies:
11 | - lib1.py
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_missing_dependencies/hello_world.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_no_master_file/Package-Structure.yml:
--------------------------------------------------------------------------------
1 | Name: "Hello World"
2 | Description: "This script will output the text provided in the argument."
3 | MasterFileName: "hello_world.py"
4 | Arguments:
5 | -
6 | name: "MyMessage"
7 | long_desc: "Message to output."
8 | description: "Message that will be output from python and powershell,"
9 | type: "sting"
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_no_yaml/hello_world.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_schema_extensions/Package-Structure.yml:
--------------------------------------------------------------------------------
1 | Name: "Hello World"
2 | Description: "This script will output the text provided in the argument."
3 | MasterFileName: "hello_world.py"
4 | Arguments:
5 | -
6 | name: "MyMessage"
7 | long_desc: "Message to output."
8 | description: "Message that will be output from python and powershell,"
9 | type: "sting"
10 | SchemaExtensions:
11 | -
12 | name: "extension_script_1"
13 | schema: "extension_schema_1"
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_schema_extensions/hello_world.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_valid/Package-Structure.yml:
--------------------------------------------------------------------------------
1 | Name: "Hello World"
2 | Description: "This script will output the text provided in the argument."
3 | MasterFileName: "hello_world.py"
4 | Arguments:
5 | -
6 | name: "MyMessage"
7 | long_desc: "Message to output."
8 | description: "Message that will be output from python and powershell,"
9 | type: "sting"
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_valid/hello_world.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_valid_with_dependencies/Package-Structure.yml:
--------------------------------------------------------------------------------
1 | Name: "Hello World"
2 | Description: "This script will output the text provided in the argument."
3 | MasterFileName: "hello_world.py"
4 | Arguments:
5 | -
6 | name: "MyMessage"
7 | long_desc: "Message to output."
8 | description: "Message that will be output from python and powershell,"
9 | type: "sting"
10 | Dependencies:
11 | - lib1.py
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_valid_with_dependencies/hello_world.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/package_valid_with_dependencies/lib1.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 | # no content, test only expects the presence of the file
5 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/sample_ssm_script_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample ssm script 1 for testing lambda_ssm_scripts.py",
3 | "comment": "sample_ssm_script_1.json and sample_ssm_script_2.json are zipped in sample_ssm_scripts.zip. The test expects only sample_ssm_scripts.zip. The json files included for for the convenience of checking the contents without unzipping"
4 | }
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/sample_ssm_script_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample ssm script 1 for testing lambda_ssm_scripts.py",
3 | "comment": "sample_ssm_script_1.json and sample_ssm_script_2.json are zipped in sample_ssm_scripts.zip. The test expects only sample_ssm_scripts.zip. The json files included for for the convenience of checking the contents without unzipping"
4 | }
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/sample_ssm_scripts.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-solutions/cloud-migration-factory-on-aws/f151fc4eb1195021be7170e7075c8e924073c3c5/source/backend/lambda_unit_test/sample_data/ssm_load_scripts/sample_ssm_scripts.zip
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_socket_cognito_jwks.json:
--------------------------------------------------------------------------------
1 | {
2 | "keys": [
3 | {
4 | "alg": "RS256",
5 | "e": "AQAB",
6 | "kid": "UPSZ26EORotKU88HFmnKO6Z1NgTVteSRMVwvIfqmpKA=",
7 | "kty": "RSA",
8 | "n": "x363yFGiUUD0M3zy4G7Y6cjTm-k9BYaTbaXYJe7l_coCJg0KK-xkRtWFGqftDiRM1qAbHrLrLolfF2HwWaMp9sya6cYNnj-z64cJ1YwPXO8ATX5pD2vNQHFgwWYp20McpNADxrJ908kCrGav9QwsyZb5AICPJ6zY6mPBSkJkSbY-Gxp_Lkf-EGVTifCIr1Ob7SfVrS7NMXcwqhh3iAF7n83DCU9QHrIYY1A_2E96NIx1y-CcaWLd7XB20atC7vNnrh06rL_fg12OrfDAfIb_Ln6EeYDmDMOgHX9i0UhInIGd2LSF2-sIIO-W94Wrcz7EtotruBvDCL4O2cuW3qPYB4OX3ARI0_octMCBb373gTRzjVFE5X4DeHAXWo9ljq3FeA9GlcNfekTNvZ__HbuLoJM3w5kA4zptkHEAWcEFIe87VgdVBXnHASyN9XFcaWhenPBxtr33-Yxsw6o9SNCUiGrHu7O5ZLcLE9BuONoawOv3oHpuUupNJlUBKe5uocXV2neAyysD0dmIZQ8lVVfceaM14GI8ozImlEpLkyZ3uocXqS4RoQ7kmneSXxa0Mc3jVSyJ_lNEdTGNK-e80hC7ZD4FyyIvB8zNtFROwUj8cSOWEy2E_Hd5dMQsSBDAEr2MEfGOf6D7G_ziPG8wU1XOkFMvemw6dqq4ju3-FE1Yvz8",
9 | "use": "sig"
10 | },
11 | {
12 | "alg": "RS256",
13 | "e": "AQAB",
14 | "kid": "as27v9YhmOD4TTdky8xvFHCjZ+ZqKKEjhi7eAeBGBhE=",
15 | "kty": "RSA",
16 | "n": "zQGdp6Mp4opT5WGS8vzdrTJjxipxNLrUDMX4TLZ76JxzgMdyK5btlmyCVdg7k13fo_n3tKtjEuZ1c7ukxMpLf_Pfo5k9Bdz9YoGuawv1VNzpKGQKPbK9W1JTynbhYsWKYc6XdQ0LsB4rNa1KkKfJCLVloReqPbLBFC5WylZrTrIpXRTR5FdXk6UD3dbEifuxEj6EUC6Z9IqJ8p79yoDR20Cwv3cYBPrZZbjESFcokqQSlpsScMnA8L5Xxli8hUHXPJdQkKlW_19D6xwHk54OoUk8EZTWVZ3KheTwr-8qHh8-i1D2yj8iGbF68yn5PiSQS2Ku12kTpUmTw9iQIGZdaw",
17 | "use": "sig"
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/ssm_socket_cognito_jwks_error.json:
--------------------------------------------------------------------------------
1 | {
2 | "keys": [
3 | {
4 | "alg": "RS256",
5 | "e": "AQAB",
6 | "kid": "UPSZ26EORotKU88HFmnKO6Z1NgTVteSRMVwvIfqmpKA=",
7 | "kty": "RSA",
8 | "n": "errorx363yFGiUUD0M3zy4G7Y6cjTm-k9BYaTbaXYJe7l_coCJg0KK-xkRtWFGqftDiRM1qAbHrLrLolfF2HwWaMp9sya6cYNnj-z64cJ1YwPXO8ATX5pD2vNQHFgwWYp20McpNADxrJ908kCrGav9QwsyZb5AICPJ6zY6mPBSkJkSbY-Gxp_Lkf-EGVTifCIr1Ob7SfVrS7NMXcwqhh3iAF7n83DCU9QHrIYY1A_2E96NIx1y-CcaWLd7XB20atC7vNnrh06rL_fg12OrfDAfIb_Ln6EeYDmDMOgHX9i0UhInIGd2LSF2-sIIO-W94Wrcz7EtotruBvDCL4O2cuW3qPYB4OX3ARI0_octMCBb373gTRzjVFE5X4DeHAXWo9ljq3FeA9GlcNfekTNvZ__HbuLoJM3w5kA4zptkHEAWcEFIe87VgdVBXnHASyN9XFcaWhenPBxtr33-Yxsw6o9SNCUiGrHu7O5ZLcLE9BuONoawOv3oHpuUupNJlUBKe5uocXV2neAyysD0dmIZQ8lVVfceaM14GI8ozImlEpLkyZ3uocXqS4RoQ7kmneSXxa0Mc3jVSyJ_lNEdTGNK-e80hC7ZD4FyyIvB8zNtFROwUj8cSOWEy2E_Hd5dMQsSBDAEr2MEfGOf6D7G_ziPG8wU1XOkFMvemw6dqq4ju3-FE1Yvz8",
9 | "use": "sig"
10 | },
11 | {
12 | "alg": "RS256",
13 | "e": "AQAB",
14 | "kid": "as27v9YhmOD4TTdky8xvFHCjZ+ZqKKEjhi7eAeBGBhE=",
15 | "kty": "RSA",
16 | "n": "zQGdp6Mp4opT5WGS8vzdrTJjxipxNLrUDMX4TLZ76JxzgMdyK5btlmyCVdg7k13fo_n3tKtjEuZ1c7ukxMpLf_Pfo5k9Bdz9YoGuawv1VNzpKGQKPbK9W1JTynbhYsWKYc6XdQ0LsB4rNa1KkKfJCLVloReqPbLBFC5WylZrTrIpXRTR5FdXk6UD3dbEifuxEj6EUC6Z9IqJ8p79yoDR20Cwv3cYBPrZZbjESFcokqQSlpsScMnA8L5Xxli8hUHXPJdQkKlW_19D6xwHk54OoUk8EZTWVZ3KheTwr-8qHh8-i1D2yj8iGbF68yn5PiSQS2Ku12kTpUmTw9iQIGZdaw",
17 | "use": "sig"
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/sample_data/waves.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "wave_id": {
4 | "S": "1"
5 | },
6 | "wave_name": {
7 | "S": "Wave 1"
8 | }
9 | },
10 | {
11 | "wave_id": {
12 | "S": "2"
13 | },
14 | "wave_name": {
15 | "S": "Wave 2"
16 | }
17 | }
18 | ]
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/test_lambda_cognitogroups.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | import json
6 | import os
7 | import unittest
8 | from unittest import mock
9 |
10 | from moto import mock_aws
11 | import boto3
12 |
13 | import test_common_utils
14 |
15 | @mock.patch.dict('os.environ', test_common_utils.default_mock_os_environ)
16 | class LambdaCognitoGroupsTest(unittest.TestCase):
17 |
18 | @mock_aws
19 | def assert_lambda_handler(self):
20 | import lambda_cognitogroups
21 | test_client = boto3.client('cognito-idp')
22 | user_pool_id = test_client.create_user_pool(PoolName='testPool')['UserPool']['Id']
23 | test_group_name = 'testUserGroup'
24 | test_client.create_group(
25 | GroupName=test_group_name,
26 | UserPoolId=user_pool_id,
27 | )
28 | os.environ['userpool_id'] = user_pool_id
29 | response = lambda_cognitogroups.lambda_handler({}, {})
30 | self.assertEqual(200, response['statusCode'])
31 | self.assertEqual(json.dumps([test_group_name]), response['body'])
32 |
33 | def test_lambda_handler(self):
34 | self.assert_lambda_handler()
35 |
36 | def test_lambda_handler_with_cors_set(self):
37 | import os
38 | os.environ['cors'] = '*'
39 | self.assert_lambda_handler()
40 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/test_lambda_item_common.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | import os
6 | import unittest
7 | from unittest import mock
8 |
9 | import boto3
10 | from moto import mock_aws
11 | from mypy_boto3_dynamodb.service_resource import Table
12 |
13 | import test_common_utils
14 | from test_common_utils import logger, default_mock_os_environ as mock_os_environ
15 |
16 |
17 | def mock_item_check_valid_item_create_valid(item, schema, related_items=None):
18 | logger.debug(f'mock_item_check_valid_item_create({item}, {schema}, {related_items})')
19 | return None
20 |
21 |
22 | def mock_item_check_valid_item_create_in_valid(item, schema, related_items=None):
23 | logger.debug(f'mock_item_check_valid_item_create({item}, {schema}, {related_items})')
24 | return ['Simulated error, attribute x is required']
25 |
26 | @mock.patch.dict('os.environ', mock_os_environ)
27 | @mock_aws
28 | class LambdaItemCommonTest(unittest.TestCase):
29 |
30 | def setUp(self) -> None:
31 | os.environ['AWS_DEFAULT_REGION'] = 'us-east-1'
32 | self.ddb_client = boto3.client('dynamodb')
33 | self.schema_table_name = f'{os.environ["application"]}-{os.environ["environment"]}-schema'
34 | self.apps_table_name = f'{os.environ["application"]}-{os.environ["environment"]}-apps'
35 | self.pipeline_templates_table_name = \
36 | f'{os.environ["application"]}-{os.environ["environment"]}-pipeline_templates'
37 | self.pipeline_template_tasks_table_name = \
38 | f'{os.environ["application"]}-{os.environ["environment"]}-pipeline_template_tasks'
39 | test_common_utils.create_and_populate_schemas(self.ddb_client, self.schema_table_name)
40 | test_common_utils.create_and_populate_apps(self.ddb_client, self.apps_table_name)
41 | self.apps_table = boto3.resource('dynamodb').Table(self.apps_table_name)
42 | self.pipeline_templates_table: Table = boto3.resource('dynamodb').Table(self.pipeline_templates_table_name)
43 | self.pipeline_templates_tasks_table: Table = boto3.resource('dynamodb').Table(
44 | self.pipeline_template_tasks_table_name)
45 |
46 | self.event_schema_no_exist = {
47 | 'httpMethod': 'GET',
48 | 'pathParameters': {
49 | 'schema': 'NO_EXIST'
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/test_lambda_login_common.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | from test_common_utils import logger
6 | import botocore
7 |
8 | model = botocore.session.get_session().get_service_model('cognito-idp')
9 | factory = botocore.errorfactory.ClientExceptionsFactory()
10 | exceptions = factory.create_client_exceptions(model)
11 |
12 |
13 | def mock_boto_api_call_success(client, operation_name, kwarg):
14 | logger.info(f'client = {client}, operation_name = {operation_name}, kwarg = {kwarg}')
15 | if operation_name == 'InitiateAuth':
16 | return {
17 | 'ChallengeName': 'NEW_PASSWORD_REQUIRED',
18 | 'Session': 'TEST_SESSION'
19 | }
20 | if operation_name == 'RespondToAuthChallenge':
21 | return {
22 | 'AuthenticationResult': {
23 | 'IdToken': 'TOKEN_123'
24 | }
25 | }
26 |
27 |
28 | def mock_boto_api_call_incorrect_chanllenge(client, operation_name, kwarg):
29 | logger.info(f'client = {client}, operation_name = {operation_name}, kwarg = {kwarg}')
30 | if operation_name == 'InitiateAuth':
31 | return {
32 | 'ChallengeName': 'NEW_PASSWORD_REQUIRED_INCORRECT',
33 | 'Session': 'TEST_SESSION'
34 | }
35 |
36 |
37 | def mock_boto_api_call_exception(client, operation_name, kwarg):
38 | logger.info(f'client = {client}, operation_name = {operation_name}, kwarg = {kwarg}')
39 | if operation_name == 'InitiateAuth':
40 | raise exceptions.ClientError({'Error': {'Code': 'NotAuthorizedException'}},
41 | 'test-op')
42 |
43 |
44 | def mock_boto_api_call_exception_unexpected(client, operation_name, kwarg):
45 | logger.info(f'client = {client}, operation_name = {operation_name}, kwarg = {kwarg}')
46 | if operation_name == 'InitiateAuth':
47 | raise exceptions.ClientError({'Error': {'Code': 'UnExpectedException'}},
48 | 'test-op')
49 |
50 |
51 | def mock_boto_api_call_next_challenge(client, operation_name, kwarg):
52 | logger.info(f'client = {client}, operation_name = {operation_name}, kwarg = {kwarg}')
53 | if operation_name == 'InitiateAuth':
54 | return {
55 | 'ChallengeName': 'NEW_PASSWORD_REQUIRED',
56 | 'Session': 'TEST_SESSION'
57 | }
58 | if operation_name == 'RespondToAuthChallenge':
59 | return {
60 | 'AuthenticationResult': {
61 | 'IdToken': 'TOKEN_123'
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/test_lambda_run_athena_savedquery.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | import os
6 | import unittest
7 | from unittest import mock
8 | import time
9 |
10 | import boto3
11 | from moto import mock_aws
12 | from test_common_utils import LambdaContextFnArn, test_account_id
13 | from test_common_utils import logger, default_mock_os_environ
14 |
15 |
16 | mock_os_environ = {
17 | **default_mock_os_environ,
18 | 'database': 'cmf_db',
19 | 'workgroup': 'cmf_workgroup'
20 | }
21 |
22 |
23 | @mock.patch.dict('os.environ', mock_os_environ)
24 | @mock_aws
25 | class LambdaRunAthenaSavedQueryTest(unittest.TestCase):
26 |
27 | @mock.patch.dict('os.environ', mock_os_environ)
28 | def setUp(self) -> None:
29 | self.athena_client = boto3.client('athena')
30 | self.athena_client.create_work_group(Name=os.getenv('workgroup'), Configuration={})
31 | # add sleep to make sure that the resource is created
32 | time.sleep(5)
33 | logger.info(f'{os.getenv("workgroup")} athena work group created')
34 |
35 | def test_lambda_handler(self):
36 | import lambda_run_athena_savedquery
37 | context = LambdaContextFnArn(
38 | 'arn:aws:lambda:us-east-1:' + test_account_id + ':function:migration-factory-lab-test')
39 | workgroup = self.athena_client.get_work_group(WorkGroup=os.getenv('workgroup'))
40 | logger.info(f'In test_lambda_handler, retrieved workgroup - {workgroup}')
41 | response = lambda_run_athena_savedquery.lambda_handler(None, context)
42 | # the function doesn't return anything, so no validation with moto
43 | # can add test with patch that validate arguments called with
44 | self.assertIsNone(response)
45 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/test_lambda_ssm_base.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: Apache-2.0
3 |
4 |
5 | import unittest
6 | import uuid
7 | from datetime import datetime
8 | from datetime import timedelta
9 | from unittest import mock
10 |
11 | from moto import mock_aws
12 |
13 | from test_common_utils import default_mock_os_environ
14 |
15 |
16 | @mock.patch.dict('os.environ', default_mock_os_environ)
17 | @mock_aws
18 | class LambdaSSMBaseTest(unittest.TestCase):
19 | def put_recent_job(self, table_obj, job_id, num_hours):
20 | current_time = datetime.utcnow()
21 | current_time = current_time + timedelta(hours=-num_hours)
22 | current_time_str = current_time.isoformat(sep='T')
23 | ssm_uuid = str(uuid.uuid4())
24 | instance_id = 'i-00000000000000000'
25 | ssm_id = instance_id + '+' + ssm_uuid + '+' + current_time_str
26 | item = {
27 | 'SSMId': ssm_id,
28 | 'uuid': ssm_uuid,
29 | 'jobname': 'Test job ' + str(job_id),
30 | 'status': 'RUNNING',
31 | 'SSMData': {
32 | 'status': 'RUNNING',
33 | },
34 | 'output': 'job output 123',
35 | '_history': {
36 | 'createdTimestamp': current_time_str
37 | }
38 | }
39 | table_obj.put_item(Item=item)
40 | return ssm_id
41 |
--------------------------------------------------------------------------------
/source/backend/lambda_unit_test/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | envlist = py39
3 | skipsdist = True
4 |
5 | [coverage:run]
6 | relative_files = True
7 | branch = True
8 | source = %%SOURCE_PATH%%
9 |
--------------------------------------------------------------------------------
/source/frontend/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-typescript",
5 | [
6 | "@babel/preset-react",
7 | {
8 | "runtime": "automatic"
9 | }
10 | ]
11 | ]
12 | }
--------------------------------------------------------------------------------
/source/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 | /vite.config.d.ts
23 | /vite.config.js
24 |
--------------------------------------------------------------------------------
/source/frontend/.prettierignore:
--------------------------------------------------------------------------------
1 | build
2 | coverage
3 | *.svg
4 | Config
--------------------------------------------------------------------------------
/source/frontend/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": true,
6 | "singleQuote": false,
7 | "trailingComma": "es5",
8 | "bracketSpacing": true,
9 | "bracketSameLine": false,
10 | "arrowParens": "always"
11 | }
12 |
--------------------------------------------------------------------------------
/source/frontend/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | To install the project, you can run:
6 |
7 | ### `npm install`
8 |
9 | To run the project, you can run:
10 |
11 | ### `npm start`
12 |
13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
15 |
16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console.
18 |
19 | ### `npm test`
20 |
21 | Launches the test runner in the interactive watch mode.
22 | See the section about [running tests](#running-tests) for more information.
23 |
24 | ### `npm run build`
25 |
26 | Builds the app for production to the `build` folder.
27 | It correctly bundles React in production mode and optimizes the build for the best performance.
28 |
--------------------------------------------------------------------------------
/source/frontend/index.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
51 | {JSON.stringify(props.taskExecution.task_execution_inputs, null, " ")}
52 |
53 |