diff --git a/.gitignore b/.gitignore index 0a24fe476..0282e3caf 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ python_env .ropeproject/ .pytest_cache/ venv/ +env/ .python-version .vscode/ tests/file.tmp diff --git a/.travis.yml b/.travis.yml index 5bc9779f3..77dd2ae55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,36 +2,56 @@ dist: xenial language: python sudo: false services: - - docker +- docker python: - - 2.7 - - 3.6 - - 3.7 +- 2.7 +- 3.6 +- 3.7 env: - - TEST_SERVER_MODE=false - - TEST_SERVER_MODE=true +- TEST_SERVER_MODE=false +- TEST_SERVER_MODE=true before_install: - - export BOTO_CONFIG=/dev/null +- export BOTO_CONFIG=/dev/null install: - # We build moto first so the docker container doesn't try to compile it as well, also note we don't use - # -d for docker run so the logs show up in travis - # Python images come from here: https://hub.docker.com/_/python/ - - | - python setup.py sdist +- | + python setup.py sdist - if [ "$TEST_SERVER_MODE" = "true" ]; then - docker run --rm -t --name motoserver -e TEST_SERVER_MODE=true -e AWS_SECRET_ACCESS_KEY=server_secret -e AWS_ACCESS_KEY_ID=server_key -v `pwd`:/moto -p 5000:5000 -v /var/run/docker.sock:/var/run/docker.sock python:${TRAVIS_PYTHON_VERSION}-stretch /moto/travis_moto_server.sh & - fi - travis_retry pip install boto==2.45.0 - travis_retry pip install boto3 - travis_retry pip install dist/moto*.gz - travis_retry pip install coveralls==1.1 - travis_retry pip install -r requirements-dev.txt + if [ "$TEST_SERVER_MODE" = "true" ]; then + docker run --rm -t --name motoserver -e TEST_SERVER_MODE=true -e AWS_SECRET_ACCESS_KEY=server_secret -e AWS_ACCESS_KEY_ID=server_key -v `pwd`:/moto -p 5000:5000 -v /var/run/docker.sock:/var/run/docker.sock python:${TRAVIS_PYTHON_VERSION}-stretch /moto/travis_moto_server.sh & + fi + travis_retry pip install boto==2.45.0 + travis_retry pip install boto3 + travis_retry pip install dist/moto*.gz + travis_retry pip install coveralls==1.1 + travis_retry pip install -r requirements-dev.txt - if [ "$TEST_SERVER_MODE" = "true" ]; then - python wait_for.py - fi + if [ "$TEST_SERVER_MODE" = "true" ]; then + python wait_for.py + fi script: - - make test +- make test after_success: - - coveralls +- coveralls +before_deploy: +- git checkout $TRAVIS_BRANCH +- git fetch --unshallow +- python update_version_from_git.py +deploy: + - provider: pypi + distributions: sdist bdist_wheel + user: spulec + password: + secure: NxnPylnTfekJmGyoufCw0lMoYRskSMJzvAIyAlJJVYKwEhmiCPOrdy5qV8i8mRZ1AkUsqU3jBZ/PD56n96clHW0E3d080UleRDj6JpyALVdeLfMqZl9kLmZ8bqakWzYq3VSJKw2zGP/L4tPGf8wTK1SUv9yl/YNDsBdCkjDverw= + on: + branch: + - master + skip_cleanup: true + skip_existing: true + # - provider: pypi + # distributions: sdist bdist_wheel + # user: spulec + # password: + # secure: NxnPylnTfekJmGyoufCw0lMoYRskSMJzvAIyAlJJVYKwEhmiCPOrdy5qV8i8mRZ1AkUsqU3jBZ/PD56n96clHW0E3d080UleRDj6JpyALVdeLfMqZl9kLmZ8bqakWzYq3VSJKw2zGP/L4tPGf8wTK1SUv9yl/YNDsBdCkjDverw= + # on: + # tags: true + # skip_existing: true diff --git a/AUTHORS.md b/AUTHORS.md index fbca08368..01b000182 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -54,5 +54,6 @@ Moto is written by Steve Pulec with contributions from: * [William Richard](https://github.com/william-richard) * [Alex Casalboni](https://github.com/alexcasalboni) * [Jon Beilke](https://github.com/jrbeilke) +* [Bendeguz Acs](https://github.com/acsbendi) * [Craig Anderson](https://github.com/craiga) * [Robert Lewis](https://github.com/ralewis85) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f28083221..40da55ccf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,10 @@ Moto has a [Code of Conduct](https://github.com/spulec/moto/blob/master/CODE_OF_CONDUCT.md), you can expect to be treated with respect at all times when interacting with this project. +## Running the tests locally + +Moto has a Makefile which has some helpful commands for getting setup. You should be able to run `make init` to install the dependencies and then `make test` to run the tests. + ## Is there a missing feature? Moto is easier to contribute to than you probably think. There's [a list of which endpoints have been implemented](https://github.com/spulec/moto/blob/master/IMPLEMENTATION_COVERAGE.md) and we invite you to add new endpoints to existing services or to add new services. diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md index e03eaabe1..d149b0dd8 100644 --- a/IMPLEMENTATION_COVERAGE.md +++ b/IMPLEMENTATION_COVERAGE.md @@ -1,5 +1,6 @@ -## acm - 41% implemented +## acm +38% implemented - [X] add_tags_to_certificate - [X] delete_certificate - [ ] describe_certificate @@ -9,14 +10,18 @@ - [ ] list_certificates - [ ] list_tags_for_certificate - [X] remove_tags_from_certificate +- [ ] renew_certificate - [X] request_certificate - [ ] resend_validation_email - [ ] update_certificate_options -## acm-pca - 0% implemented +## acm-pca +0% implemented - [ ] create_certificate_authority - [ ] create_certificate_authority_audit_report +- [ ] create_permission - [ ] delete_certificate_authority +- [ ] delete_permission - [ ] describe_certificate_authority - [ ] describe_certificate_authority_audit_report - [ ] get_certificate @@ -25,63 +30,145 @@ - [ ] import_certificate_authority_certificate - [ ] issue_certificate - [ ] list_certificate_authorities +- [ ] list_permissions - [ ] list_tags +- [ ] restore_certificate_authority - [ ] revoke_certificate - [ ] tag_certificate_authority - [ ] untag_certificate_authority - [ ] update_certificate_authority -## alexaforbusiness - 0% implemented +## alexaforbusiness +0% implemented +- [ ] approve_skill - [ ] associate_contact_with_address_book +- [ ] associate_device_with_network_profile - [ ] associate_device_with_room - [ ] associate_skill_group_with_room +- [ ] associate_skill_with_skill_group +- [ ] associate_skill_with_users - [ ] create_address_book +- [ ] create_business_report_schedule +- [ ] create_conference_provider - [ ] create_contact +- [ ] create_gateway_group +- [ ] create_network_profile - [ ] create_profile - [ ] create_room - [ ] create_skill_group - [ ] create_user - [ ] delete_address_book +- [ ] delete_business_report_schedule +- [ ] delete_conference_provider - [ ] delete_contact +- [ ] delete_device +- [ ] delete_device_usage_data +- [ ] delete_gateway_group +- [ ] delete_network_profile - [ ] delete_profile - [ ] delete_room - [ ] delete_room_skill_parameter +- [ ] delete_skill_authorization - [ ] delete_skill_group - [ ] delete_user - [ ] disassociate_contact_from_address_book - [ ] disassociate_device_from_room +- [ ] disassociate_skill_from_skill_group +- [ ] disassociate_skill_from_users - [ ] disassociate_skill_group_from_room +- [ ] forget_smart_home_appliances - [ ] get_address_book +- [ ] get_conference_preference +- [ ] get_conference_provider - [ ] get_contact - [ ] get_device +- [ ] get_gateway +- [ ] get_gateway_group +- [ ] get_invitation_configuration +- [ ] get_network_profile - [ ] get_profile - [ ] get_room - [ ] get_room_skill_parameter - [ ] get_skill_group +- [ ] list_business_report_schedules +- [ ] list_conference_providers +- [ ] list_device_events +- [ ] list_gateway_groups +- [ ] list_gateways - [ ] list_skills +- [ ] list_skills_store_categories +- [ ] list_skills_store_skills_by_category +- [ ] list_smart_home_appliances - [ ] list_tags +- [ ] put_conference_preference +- [ ] put_invitation_configuration - [ ] put_room_skill_parameter +- [ ] put_skill_authorization +- [ ] register_avs_device +- [ ] reject_skill - [ ] resolve_room - [ ] revoke_invitation - [ ] search_address_books - [ ] search_contacts - [ ] search_devices +- [ ] search_network_profiles - [ ] search_profiles - [ ] search_rooms - [ ] search_skill_groups - [ ] search_users +- [ ] send_announcement - [ ] send_invitation - [ ] start_device_sync +- [ ] start_smart_home_appliance_discovery - [ ] tag_resource - [ ] untag_resource - [ ] update_address_book +- [ ] update_business_report_schedule +- [ ] update_conference_provider - [ ] update_contact - [ ] update_device +- [ ] update_gateway +- [ ] update_gateway_group +- [ ] update_network_profile - [ ] update_profile - [ ] update_room - [ ] update_skill_group -## apigateway - 24% implemented +## amplify +0% implemented +- [ ] create_app +- [ ] create_branch +- [ ] create_deployment +- [ ] create_domain_association +- [ ] create_webhook +- [ ] delete_app +- [ ] delete_branch +- [ ] delete_domain_association +- [ ] delete_job +- [ ] delete_webhook +- [ ] get_app +- [ ] get_branch +- [ ] get_domain_association +- [ ] get_job +- [ ] get_webhook +- [ ] list_apps +- [ ] list_branches +- [ ] list_domain_associations +- [ ] list_jobs +- [ ] list_tags_for_resource +- [ ] list_webhooks +- [ ] start_deployment +- [ ] start_job +- [ ] stop_job +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_app +- [ ] update_branch +- [ ] update_domain_association +- [ ] update_webhook + +## apigateway +24% implemented - [ ] create_api_key - [ ] create_authorizer - [ ] create_base_path_mapping @@ -203,7 +290,74 @@ - [ ] update_usage_plan - [ ] update_vpc_link -## application-autoscaling - 0% implemented +## apigatewaymanagementapi +0% implemented +- [ ] post_to_connection + +## apigatewayv2 +0% implemented +- [ ] create_api +- [ ] create_api_mapping +- [ ] create_authorizer +- [ ] create_deployment +- [ ] create_domain_name +- [ ] create_integration +- [ ] create_integration_response +- [ ] create_model +- [ ] create_route +- [ ] create_route_response +- [ ] create_stage +- [ ] delete_api +- [ ] delete_api_mapping +- [ ] delete_authorizer +- [ ] delete_deployment +- [ ] delete_domain_name +- [ ] delete_integration +- [ ] delete_integration_response +- [ ] delete_model +- [ ] delete_route +- [ ] delete_route_response +- [ ] delete_stage +- [ ] get_api +- [ ] get_api_mapping +- [ ] get_api_mappings +- [ ] get_apis +- [ ] get_authorizer +- [ ] get_authorizers +- [ ] get_deployment +- [ ] get_deployments +- [ ] get_domain_name +- [ ] get_domain_names +- [ ] get_integration +- [ ] get_integration_response +- [ ] get_integration_responses +- [ ] get_integrations +- [ ] get_model +- [ ] get_model_template +- [ ] get_models +- [ ] get_route +- [ ] get_route_response +- [ ] get_route_responses +- [ ] get_routes +- [ ] get_stage +- [ ] get_stages +- [ ] get_tags +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_api +- [ ] update_api_mapping +- [ ] update_authorizer +- [ ] update_deployment +- [ ] update_domain_name +- [ ] update_integration +- [ ] update_integration_response +- [ ] update_model +- [ ] update_route +- [ ] update_route_response +- [ ] update_stage + +## application-autoscaling +0% implemented - [ ] delete_scaling_policy - [ ] delete_scheduled_action - [ ] deregister_scalable_target @@ -215,8 +369,61 @@ - [ ] put_scheduled_action - [ ] register_scalable_target -## appstream - 0% implemented +## application-insights +0% implemented +- [ ] create_application +- [ ] create_component +- [ ] delete_application +- [ ] delete_component +- [ ] describe_application +- [ ] describe_component +- [ ] describe_component_configuration +- [ ] describe_component_configuration_recommendation +- [ ] describe_observation +- [ ] describe_problem +- [ ] describe_problem_observations +- [ ] list_applications +- [ ] list_components +- [ ] list_problems +- [ ] update_component +- [ ] update_component_configuration + +## appmesh +0% implemented +- [ ] create_mesh +- [ ] create_route +- [ ] create_virtual_node +- [ ] create_virtual_router +- [ ] create_virtual_service +- [ ] delete_mesh +- [ ] delete_route +- [ ] delete_virtual_node +- [ ] delete_virtual_router +- [ ] delete_virtual_service +- [ ] describe_mesh +- [ ] describe_route +- [ ] describe_virtual_node +- [ ] describe_virtual_router +- [ ] describe_virtual_service +- [ ] list_meshes +- [ ] list_routes +- [ ] list_tags_for_resource +- [ ] list_virtual_nodes +- [ ] list_virtual_routers +- [ ] list_virtual_services +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_mesh +- [ ] update_route +- [ ] update_virtual_node +- [ ] update_virtual_router +- [ ] update_virtual_service + +## appstream +0% implemented - [ ] associate_fleet +- [ ] batch_associate_user_stack +- [ ] batch_disassociate_user_stack - [ ] copy_image - [ ] create_directory_config - [ ] create_fleet @@ -224,18 +431,29 @@ - [ ] create_image_builder_streaming_url - [ ] create_stack - [ ] create_streaming_url +- [ ] create_usage_report_subscription +- [ ] create_user - [ ] delete_directory_config - [ ] delete_fleet - [ ] delete_image - [ ] delete_image_builder +- [ ] delete_image_permissions - [ ] delete_stack +- [ ] delete_usage_report_subscription +- [ ] delete_user - [ ] describe_directory_configs - [ ] describe_fleets - [ ] describe_image_builders +- [ ] describe_image_permissions - [ ] describe_images - [ ] describe_sessions - [ ] describe_stacks +- [ ] describe_usage_report_subscriptions +- [ ] describe_user_stack_associations +- [ ] describe_users +- [ ] disable_user - [ ] disassociate_fleet +- [ ] enable_user - [ ] expire_session - [ ] list_associated_fleets - [ ] list_associated_stacks @@ -248,20 +466,25 @@ - [ ] untag_resource - [ ] update_directory_config - [ ] update_fleet +- [ ] update_image_permissions - [ ] update_stack -## appsync - 0% implemented +## appsync +0% implemented - [ ] create_api_key - [ ] create_data_source +- [ ] create_function - [ ] create_graphql_api - [ ] create_resolver - [ ] create_type - [ ] delete_api_key - [ ] delete_data_source +- [ ] delete_function - [ ] delete_graphql_api - [ ] delete_resolver - [ ] delete_type - [ ] get_data_source +- [ ] get_function - [ ] get_graphql_api - [ ] get_introspection_schema - [ ] get_resolver @@ -269,33 +492,51 @@ - [ ] get_type - [ ] list_api_keys - [ ] list_data_sources +- [ ] list_functions - [ ] list_graphql_apis - [ ] list_resolvers +- [ ] list_resolvers_by_function +- [ ] list_tags_for_resource - [ ] list_types - [ ] start_schema_creation +- [ ] tag_resource +- [ ] untag_resource - [ ] update_api_key - [ ] update_data_source +- [ ] update_function - [ ] update_graphql_api - [ ] update_resolver - [ ] update_type -## athena - 0% implemented +## athena +0% implemented - [ ] batch_get_named_query - [ ] batch_get_query_execution - [ ] create_named_query +- [ ] create_work_group - [ ] delete_named_query +- [ ] delete_work_group - [ ] get_named_query - [ ] get_query_execution - [ ] get_query_results +- [ ] get_work_group - [ ] list_named_queries - [ ] list_query_executions +- [ ] list_tags_for_resource +- [ ] list_work_groups - [ ] start_query_execution - [ ] stop_query_execution +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_work_group -## autoscaling - 44% implemented +## autoscaling +44% implemented - [X] attach_instances - [X] attach_load_balancer_target_groups - [X] attach_load_balancers +- [ ] batch_delete_scheduled_action +- [ ] batch_put_scheduled_update_group_action - [ ] complete_lifecycle_action - [X] create_auto_scaling_group - [X] create_launch_configuration @@ -341,18 +582,68 @@ - [ ] resume_processes - [X] set_desired_capacity - [X] set_instance_health -- [ ] set_instance_protection +- [X] set_instance_protection - [X] suspend_processes - [ ] terminate_instance_in_auto_scaling_group - [X] update_auto_scaling_group -## autoscaling-plans - 0% implemented +## autoscaling-plans +0% implemented - [ ] create_scaling_plan - [ ] delete_scaling_plan - [ ] describe_scaling_plan_resources - [ ] describe_scaling_plans +- [ ] get_scaling_plan_resource_forecast_data +- [ ] update_scaling_plan -## batch - 93% implemented +## backup +0% implemented +- [ ] create_backup_plan +- [ ] create_backup_selection +- [ ] create_backup_vault +- [ ] delete_backup_plan +- [ ] delete_backup_selection +- [ ] delete_backup_vault +- [ ] delete_backup_vault_access_policy +- [ ] delete_backup_vault_notifications +- [ ] delete_recovery_point +- [ ] describe_backup_job +- [ ] describe_backup_vault +- [ ] describe_protected_resource +- [ ] describe_recovery_point +- [ ] describe_restore_job +- [ ] export_backup_plan_template +- [ ] get_backup_plan +- [ ] get_backup_plan_from_json +- [ ] get_backup_plan_from_template +- [ ] get_backup_selection +- [ ] get_backup_vault_access_policy +- [ ] get_backup_vault_notifications +- [ ] get_recovery_point_restore_metadata +- [ ] get_supported_resource_types +- [ ] list_backup_jobs +- [ ] list_backup_plan_templates +- [ ] list_backup_plan_versions +- [ ] list_backup_plans +- [ ] list_backup_selections +- [ ] list_backup_vaults +- [ ] list_protected_resources +- [ ] list_recovery_points_by_backup_vault +- [ ] list_recovery_points_by_resource +- [ ] list_restore_jobs +- [ ] list_tags +- [ ] put_backup_vault_access_policy +- [ ] put_backup_vault_notifications +- [ ] start_backup_job +- [ ] start_restore_job +- [ ] stop_backup_job +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_backup_plan +- [ ] update_recovery_point_lifecycle + +## batch +93% implemented - [ ] cancel_job - [X] create_compute_environment - [X] create_job_queue @@ -370,7 +661,8 @@ - [X] update_compute_environment - [X] update_job_queue -## budgets - 0% implemented +## budgets +0% implemented - [ ] create_budget - [ ] create_notification - [ ] create_subscriber @@ -378,6 +670,7 @@ - [ ] delete_notification - [ ] delete_subscriber - [ ] describe_budget +- [ ] describe_budget_performance_history - [ ] describe_budgets - [ ] describe_notifications_for_budget - [ ] describe_subscribers_for_notification @@ -385,15 +678,81 @@ - [ ] update_notification - [ ] update_subscriber -## ce - 0% implemented +## ce +0% implemented - [ ] get_cost_and_usage +- [ ] get_cost_forecast - [ ] get_dimension_values - [ ] get_reservation_coverage - [ ] get_reservation_purchase_recommendation - [ ] get_reservation_utilization +- [ ] get_rightsizing_recommendation - [ ] get_tags +- [ ] get_usage_forecast -## cloud9 - 0% implemented +## chime +0% implemented +- [ ] associate_phone_number_with_user +- [ ] associate_phone_numbers_with_voice_connector +- [ ] batch_delete_phone_number +- [ ] batch_suspend_user +- [ ] batch_unsuspend_user +- [ ] batch_update_phone_number +- [ ] batch_update_user +- [ ] create_account +- [ ] create_bot +- [ ] create_phone_number_order +- [ ] create_voice_connector +- [ ] delete_account +- [ ] delete_events_configuration +- [ ] delete_phone_number +- [ ] delete_voice_connector +- [ ] delete_voice_connector_origination +- [ ] delete_voice_connector_termination +- [ ] delete_voice_connector_termination_credentials +- [ ] disassociate_phone_number_from_user +- [ ] disassociate_phone_numbers_from_voice_connector +- [ ] get_account +- [ ] get_account_settings +- [ ] get_bot +- [ ] get_events_configuration +- [ ] get_global_settings +- [ ] get_phone_number +- [ ] get_phone_number_order +- [ ] get_user +- [ ] get_user_settings +- [ ] get_voice_connector +- [ ] get_voice_connector_origination +- [ ] get_voice_connector_termination +- [ ] get_voice_connector_termination_health +- [ ] invite_users +- [ ] list_accounts +- [ ] list_bots +- [ ] list_phone_number_orders +- [ ] list_phone_numbers +- [ ] list_users +- [ ] list_voice_connector_termination_credentials +- [ ] list_voice_connectors +- [ ] logout_user +- [ ] put_events_configuration +- [ ] put_voice_connector_origination +- [ ] put_voice_connector_termination +- [ ] put_voice_connector_termination_credentials +- [ ] regenerate_security_token +- [ ] reset_personal_pin +- [ ] restore_phone_number +- [ ] search_available_phone_numbers +- [ ] update_account +- [ ] update_account_settings +- [ ] update_bot +- [ ] update_global_settings +- [ ] update_phone_number +- [ ] update_user +- [ ] update_user_settings +- [ ] update_voice_connector + +## cloud9 +0% implemented - [ ] create_environment_ec2 - [ ] create_environment_membership - [ ] delete_environment @@ -405,7 +764,8 @@ - [ ] update_environment - [ ] update_environment_membership -## clouddirectory - 0% implemented +## clouddirectory +0% implemented - [ ] add_facet_to_object - [ ] apply_schema - [ ] attach_object @@ -434,6 +794,7 @@ - [ ] get_applied_schema_version - [ ] get_directory - [ ] get_facet +- [ ] get_link_attributes - [ ] get_object_attributes - [ ] get_object_information - [ ] get_schema_as_json @@ -446,6 +807,7 @@ - [ ] list_facet_names - [ ] list_incoming_typed_links - [ ] list_index +- [ ] list_managed_schema_arns - [ ] list_object_attributes - [ ] list_object_children - [ ] list_object_parent_paths @@ -464,13 +826,15 @@ - [ ] tag_resource - [ ] untag_resource - [ ] update_facet +- [ ] update_link_attributes - [ ] update_object_attributes - [ ] update_schema - [ ] update_typed_link_facet - [ ] upgrade_applied_schema - [ ] upgrade_published_schema -## cloudformation - 65% implemented +## cloudformation +40% implemented - [ ] cancel_update_stack - [ ] continue_update_rollback - [X] create_change_set @@ -481,46 +845,44 @@ - [X] delete_stack - [X] delete_stack_instances - [X] delete_stack_set -- [ ] deploy - [ ] describe_account_limits - [X] describe_change_set - [ ] describe_stack_drift_detection_status -- [X] describe_stack_events -- [X] describe_stack_instance -- [X] describe_stack_resource +- [ ] describe_stack_events +- [ ] describe_stack_instance +- [ ] describe_stack_resource - [ ] describe_stack_resource_drifts -- [X] describe_stack_resources -- [X] describe_stack_set -- [X] describe_stack_set_operation +- [ ] describe_stack_resources +- [ ] describe_stack_set +- [ ] describe_stack_set_operation - [X] describe_stacks - [ ] detect_stack_drift - [ ] detect_stack_resource_drift - [ ] estimate_template_cost - [X] execute_change_set - [ ] get_stack_policy -- [X] get_template +- [ ] get_template - [ ] get_template_summary - [X] list_change_sets - [X] list_exports - [ ] list_imports -- [X] list_stack_instances +- [ ] list_stack_instances - [X] list_stack_resources -- [X] list_stack_set_operation_results -- [X] list_stack_set_operations -- [X] list_stack_sets +- [ ] list_stack_set_operation_results +- [ ] list_stack_set_operations +- [ ] list_stack_sets - [X] list_stacks -- [ ] package - [ ] set_stack_policy - [ ] signal_resource -- [X] stop_stack_set_operation +- [ ] stop_stack_set_operation - [X] update_stack -- [X] update_stack_instances +- [ ] update_stack_instances - [X] update_stack_set - [ ] update_termination_protection - [X] validate_template -- [ ] wait -## cloudfront - 0% implemented +## cloudfront +0% implemented - [ ] create_cloud_front_origin_access_identity - [ ] create_distribution - [ ] create_distribution_with_tags @@ -535,7 +897,6 @@ - [ ] delete_field_level_encryption_config - [ ] delete_field_level_encryption_profile - [ ] delete_public_key -- [ ] delete_service_linked_role - [ ] delete_streaming_distribution - [ ] get_cloud_front_origin_access_identity - [ ] get_cloud_front_origin_access_identity_config @@ -568,7 +929,8 @@ - [ ] update_public_key - [ ] update_streaming_distribution -## cloudhsm - 0% implemented +## cloudhsm +0% implemented - [ ] add_tags_to_resource - [ ] create_hapg - [ ] create_hsm @@ -590,19 +952,24 @@ - [ ] modify_luna_client - [ ] remove_tags_from_resource -## cloudhsmv2 - 0% implemented +## cloudhsmv2 +0% implemented +- [ ] copy_backup_to_region - [ ] create_cluster - [ ] create_hsm +- [ ] delete_backup - [ ] delete_cluster - [ ] delete_hsm - [ ] describe_backups - [ ] describe_clusters - [ ] initialize_cluster - [ ] list_tags +- [ ] restore_backup - [ ] tag_resource - [ ] untag_resource -## cloudsearch - 0% implemented +## cloudsearch +0% implemented - [ ] build_suggesters - [ ] create_domain - [ ] define_analysis_scheme @@ -628,12 +995,14 @@ - [ ] update_scaling_parameters - [ ] update_service_access_policies -## cloudsearchdomain - 0% implemented +## cloudsearchdomain +0% implemented - [ ] search - [ ] suggest - [ ] upload_documents -## cloudtrail - 0% implemented +## cloudtrail +0% implemented - [ ] add_tags - [ ] create_trail - [ ] delete_trail @@ -649,50 +1018,68 @@ - [ ] stop_logging - [ ] update_trail -## cloudwatch - 56% implemented +## cloudwatch +39% implemented - [X] delete_alarms +- [ ] delete_anomaly_detector - [X] delete_dashboards - [ ] describe_alarm_history - [ ] describe_alarms - [ ] describe_alarms_for_metric +- [ ] describe_anomaly_detectors - [ ] disable_alarm_actions - [ ] enable_alarm_actions - [X] get_dashboard - [ ] get_metric_data - [X] get_metric_statistics +- [ ] get_metric_widget_image - [X] list_dashboards - [ ] list_metrics +- [ ] list_tags_for_resource +- [ ] put_anomaly_detector - [X] put_dashboard - [X] put_metric_alarm - [X] put_metric_data - [X] set_alarm_state +- [ ] tag_resource +- [ ] untag_resource -## codebuild - 0% implemented +## codebuild +0% implemented - [ ] batch_delete_builds - [ ] batch_get_builds - [ ] batch_get_projects - [ ] create_project - [ ] create_webhook - [ ] delete_project +- [ ] delete_source_credentials - [ ] delete_webhook +- [ ] import_source_credentials - [ ] invalidate_project_cache - [ ] list_builds - [ ] list_builds_for_project - [ ] list_curated_environment_images - [ ] list_projects +- [ ] list_source_credentials - [ ] start_build - [ ] stop_build - [ ] update_project - [ ] update_webhook -## codecommit - 0% implemented +## codecommit +0% implemented +- [ ] batch_describe_merge_conflicts - [ ] batch_get_repositories - [ ] create_branch +- [ ] create_commit - [ ] create_pull_request - [ ] create_repository +- [ ] create_unreferenced_merge_commit - [ ] delete_branch - [ ] delete_comment_content +- [ ] delete_file - [ ] delete_repository +- [ ] describe_merge_conflicts - [ ] describe_pull_request_events - [ ] get_blob - [ ] get_branch @@ -701,20 +1088,32 @@ - [ ] get_comments_for_pull_request - [ ] get_commit - [ ] get_differences +- [ ] get_file +- [ ] get_folder +- [ ] get_merge_commit - [ ] get_merge_conflicts +- [ ] get_merge_options - [ ] get_pull_request - [ ] get_repository - [ ] get_repository_triggers - [ ] list_branches - [ ] list_pull_requests - [ ] list_repositories +- [ ] list_tags_for_resource +- [ ] merge_branches_by_fast_forward +- [ ] merge_branches_by_squash +- [ ] merge_branches_by_three_way - [ ] merge_pull_request_by_fast_forward +- [ ] merge_pull_request_by_squash +- [ ] merge_pull_request_by_three_way - [ ] post_comment_for_compared_commit - [ ] post_comment_for_pull_request - [ ] post_comment_reply - [ ] put_file - [ ] put_repository_triggers +- [ ] tag_resource - [ ] test_repository_triggers +- [ ] untag_resource - [ ] update_comment - [ ] update_default_branch - [ ] update_pull_request_description @@ -723,12 +1122,14 @@ - [ ] update_repository_description - [ ] update_repository_name -## codedeploy - 0% implemented +## codedeploy +0% implemented - [ ] add_tags_to_on_premises_instances - [ ] batch_get_application_revisions - [ ] batch_get_applications - [ ] batch_get_deployment_groups - [ ] batch_get_deployment_instances +- [ ] batch_get_deployment_targets - [ ] batch_get_deployments - [ ] batch_get_on_premises_instances - [ ] continue_deployment @@ -747,31 +1148,39 @@ - [ ] get_deployment_config - [ ] get_deployment_group - [ ] get_deployment_instance +- [ ] get_deployment_target - [ ] get_on_premises_instance - [ ] list_application_revisions - [ ] list_applications - [ ] list_deployment_configs - [ ] list_deployment_groups - [ ] list_deployment_instances +- [ ] list_deployment_targets - [ ] list_deployments - [ ] list_git_hub_account_token_names - [ ] list_on_premises_instances +- [ ] list_tags_for_resource - [ ] put_lifecycle_event_hook_execution_status - [ ] register_application_revision - [ ] register_on_premises_instance - [ ] remove_tags_from_on_premises_instances - [ ] skip_wait_time_for_instance_termination - [ ] stop_deployment +- [ ] tag_resource +- [ ] untag_resource - [ ] update_application - [ ] update_deployment_group -## codepipeline - 0% implemented +## codepipeline +0% implemented - [ ] acknowledge_job - [ ] acknowledge_third_party_job - [ ] create_custom_action_type - [ ] create_pipeline - [ ] delete_custom_action_type - [ ] delete_pipeline +- [ ] delete_webhook +- [ ] deregister_webhook_with_third_party - [ ] disable_stage_transition - [ ] enable_stage_transition - [ ] get_job_details @@ -779,9 +1188,12 @@ - [ ] get_pipeline_execution - [ ] get_pipeline_state - [ ] get_third_party_job_details +- [ ] list_action_executions - [ ] list_action_types - [ ] list_pipeline_executions - [ ] list_pipelines +- [ ] list_tags_for_resource +- [ ] list_webhooks - [ ] poll_for_jobs - [ ] poll_for_third_party_jobs - [ ] put_action_revision @@ -790,11 +1202,16 @@ - [ ] put_job_success_result - [ ] put_third_party_job_failure_result - [ ] put_third_party_job_success_result +- [ ] put_webhook +- [ ] register_webhook_with_third_party - [ ] retry_stage_execution - [ ] start_pipeline_execution +- [ ] tag_resource +- [ ] untag_resource - [ ] update_pipeline -## codestar - 0% implemented +## codestar +0% implemented - [ ] associate_team_member - [ ] create_project - [ ] create_user_profile @@ -814,27 +1231,32 @@ - [ ] update_team_member - [ ] update_user_profile -## cognito-identity - 0% implemented -- [ ] create_identity_pool +## cognito-identity +23% implemented +- [X] create_identity_pool - [ ] delete_identities - [ ] delete_identity_pool - [ ] describe_identity - [ ] describe_identity_pool -- [ ] get_credentials_for_identity -- [ ] get_id +- [X] get_credentials_for_identity +- [X] get_id - [ ] get_identity_pool_roles -- [ ] get_open_id_token -- [ ] get_open_id_token_for_developer_identity +- [X] get_open_id_token +- [X] get_open_id_token_for_developer_identity - [ ] list_identities - [ ] list_identity_pools +- [ ] list_tags_for_resource - [ ] lookup_developer_identity - [ ] merge_developer_identities - [ ] set_identity_pool_roles +- [ ] tag_resource - [ ] unlink_developer_identity - [ ] unlink_identity +- [ ] untag_resource - [ ] update_identity_pool -## cognito-idp - 34% implemented +## cognito-idp +37% implemented - [ ] add_custom_attributes - [X] admin_add_user_to_group - [ ] admin_confirm_sign_up @@ -856,6 +1278,7 @@ - [ ] admin_reset_user_password - [ ] admin_respond_to_auth_challenge - [ ] admin_set_user_mfa_preference +- [ ] admin_set_user_password - [ ] admin_set_user_settings - [ ] admin_update_auth_event_feedback - [ ] admin_update_device_status @@ -905,6 +1328,7 @@ - [X] list_groups - [X] list_identity_providers - [ ] list_resource_servers +- [ ] list_tags_for_resource - [ ] list_user_import_jobs - [X] list_user_pool_clients - [X] list_user_pools @@ -920,18 +1344,22 @@ - [ ] sign_up - [ ] start_user_import_job - [ ] stop_user_import_job +- [ ] tag_resource +- [ ] untag_resource - [ ] update_auth_event_feedback - [ ] update_device_status - [ ] update_group -- [x] update_identity_provider +- [X] update_identity_provider - [ ] update_resource_server - [ ] update_user_attributes - [ ] update_user_pool - [X] update_user_pool_client +- [X] update_user_pool_domain - [ ] verify_software_token - [ ] verify_user_attribute -## cognito-sync - 0% implemented +## cognito-sync +0% implemented - [ ] bulk_publish - [ ] delete_dataset - [ ] describe_dataset @@ -950,71 +1378,155 @@ - [ ] unsubscribe_from_dataset - [ ] update_records -## comprehend - 0% implemented +## comprehend +0% implemented - [ ] batch_detect_dominant_language - [ ] batch_detect_entities - [ ] batch_detect_key_phrases - [ ] batch_detect_sentiment +- [ ] batch_detect_syntax +- [ ] create_document_classifier +- [ ] create_entity_recognizer +- [ ] delete_document_classifier +- [ ] delete_entity_recognizer +- [ ] describe_document_classification_job +- [ ] describe_document_classifier +- [ ] describe_dominant_language_detection_job +- [ ] describe_entities_detection_job +- [ ] describe_entity_recognizer +- [ ] describe_key_phrases_detection_job +- [ ] describe_sentiment_detection_job - [ ] describe_topics_detection_job - [ ] detect_dominant_language - [ ] detect_entities - [ ] detect_key_phrases - [ ] detect_sentiment +- [ ] detect_syntax +- [ ] list_document_classification_jobs +- [ ] list_document_classifiers +- [ ] list_dominant_language_detection_jobs +- [ ] list_entities_detection_jobs +- [ ] list_entity_recognizers +- [ ] list_key_phrases_detection_jobs +- [ ] list_sentiment_detection_jobs +- [ ] list_tags_for_resource - [ ] list_topics_detection_jobs +- [ ] start_document_classification_job +- [ ] start_dominant_language_detection_job +- [ ] start_entities_detection_job +- [ ] start_key_phrases_detection_job +- [ ] start_sentiment_detection_job - [ ] start_topics_detection_job +- [ ] stop_dominant_language_detection_job +- [ ] stop_entities_detection_job +- [ ] stop_key_phrases_detection_job +- [ ] stop_sentiment_detection_job +- [ ] stop_training_document_classifier +- [ ] stop_training_entity_recognizer +- [ ] tag_resource +- [ ] untag_resource -## config - 0% implemented +## comprehendmedical +0% implemented +- [ ] detect_entities +- [ ] detect_phi + +## config +24% implemented +- [ ] batch_get_aggregate_resource_config - [ ] batch_get_resource_config -- [ ] delete_aggregation_authorization +- [X] delete_aggregation_authorization - [ ] delete_config_rule -- [ ] delete_configuration_aggregator -- [ ] delete_configuration_recorder -- [ ] delete_delivery_channel +- [X] delete_configuration_aggregator +- [X] delete_configuration_recorder +- [X] delete_delivery_channel - [ ] delete_evaluation_results +- [ ] delete_organization_config_rule - [ ] delete_pending_aggregation_request +- [ ] delete_remediation_configuration +- [ ] delete_retention_configuration - [ ] deliver_config_snapshot - [ ] describe_aggregate_compliance_by_config_rules -- [ ] describe_aggregation_authorizations +- [X] describe_aggregation_authorizations - [ ] describe_compliance_by_config_rule - [ ] describe_compliance_by_resource - [ ] describe_config_rule_evaluation_status - [ ] describe_config_rules - [ ] describe_configuration_aggregator_sources_status -- [ ] describe_configuration_aggregators -- [ ] describe_configuration_recorder_status -- [ ] describe_configuration_recorders +- [X] describe_configuration_aggregators +- [X] describe_configuration_recorder_status +- [X] describe_configuration_recorders - [ ] describe_delivery_channel_status -- [ ] describe_delivery_channels +- [X] describe_delivery_channels +- [ ] describe_organization_config_rule_statuses +- [ ] describe_organization_config_rules - [ ] describe_pending_aggregation_requests +- [ ] describe_remediation_configurations +- [ ] describe_remediation_execution_status +- [ ] describe_retention_configurations - [ ] get_aggregate_compliance_details_by_config_rule - [ ] get_aggregate_config_rule_compliance_summary +- [ ] get_aggregate_discovered_resource_counts +- [ ] get_aggregate_resource_config - [ ] get_compliance_details_by_config_rule - [ ] get_compliance_details_by_resource - [ ] get_compliance_summary_by_config_rule - [ ] get_compliance_summary_by_resource_type - [ ] get_discovered_resource_counts +- [ ] get_organization_config_rule_detailed_status - [ ] get_resource_config_history +- [ ] list_aggregate_discovered_resources - [ ] list_discovered_resources -- [ ] put_aggregation_authorization +- [ ] list_tags_for_resource +- [X] put_aggregation_authorization - [ ] put_config_rule -- [ ] put_configuration_aggregator -- [ ] put_configuration_recorder -- [ ] put_delivery_channel +- [X] put_configuration_aggregator +- [X] put_configuration_recorder +- [X] put_delivery_channel - [ ] put_evaluations +- [ ] put_organization_config_rule +- [ ] put_remediation_configurations +- [ ] put_retention_configuration +- [ ] select_resource_config - [ ] start_config_rules_evaluation -- [ ] start_configuration_recorder -- [ ] stop_configuration_recorder +- [X] start_configuration_recorder +- [ ] start_remediation_execution +- [X] stop_configuration_recorder +- [ ] tag_resource +- [ ] untag_resource -## connect - 0% implemented +## connect +0% implemented +- [ ] create_user +- [ ] delete_user +- [ ] describe_user +- [ ] describe_user_hierarchy_group +- [ ] describe_user_hierarchy_structure +- [ ] get_contact_attributes +- [ ] get_current_metric_data +- [ ] get_federation_token +- [ ] get_metric_data +- [ ] list_routing_profiles +- [ ] list_security_profiles +- [ ] list_user_hierarchy_groups +- [ ] list_users - [ ] start_outbound_voice_contact - [ ] stop_contact +- [ ] update_contact_attributes +- [ ] update_user_hierarchy +- [ ] update_user_identity_info +- [ ] update_user_phone_config +- [ ] update_user_routing_profile +- [ ] update_user_security_profiles -## cur - 0% implemented +## cur +0% implemented - [ ] delete_report_definition - [ ] describe_report_definitions - [ ] put_report_definition -## datapipeline - 42% implemented +## datapipeline +42% implemented - [X] activate_pipeline - [ ] add_tags - [X] create_pipeline @@ -1035,7 +1547,36 @@ - [ ] set_task_status - [ ] validate_pipeline_definition -## dax - 0% implemented +## datasync +0% implemented +- [ ] cancel_task_execution +- [ ] create_agent +- [ ] create_location_efs +- [ ] create_location_nfs +- [ ] create_location_s3 +- [ ] create_task +- [ ] delete_agent +- [ ] delete_location +- [ ] delete_task +- [ ] describe_agent +- [ ] describe_location_efs +- [ ] describe_location_nfs +- [ ] describe_location_s3 +- [ ] describe_task +- [ ] describe_task_execution +- [ ] list_agents +- [ ] list_locations +- [ ] list_tags_for_resource +- [ ] list_task_executions +- [ ] list_tasks +- [ ] start_task_execution +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_agent +- [ ] update_task + +## dax +0% implemented - [ ] create_cluster - [ ] create_parameter_group - [ ] create_subnet_group @@ -1058,13 +1599,15 @@ - [ ] update_parameter_group - [ ] update_subnet_group -## devicefarm - 0% implemented +## devicefarm +0% implemented - [ ] create_device_pool - [ ] create_instance_profile - [ ] create_network_profile - [ ] create_project - [ ] create_remote_access_session - [ ] create_upload +- [ ] create_vpce_configuration - [ ] delete_device_pool - [ ] delete_instance_profile - [ ] delete_network_profile @@ -1072,6 +1615,7 @@ - [ ] delete_remote_access_session - [ ] delete_run - [ ] delete_upload +- [ ] delete_vpce_configuration - [ ] get_account_settings - [ ] get_device - [ ] get_device_instance @@ -1087,6 +1631,7 @@ - [ ] get_suite - [ ] get_test - [ ] get_upload +- [ ] get_vpce_configuration - [ ] install_to_remote_access_session - [ ] list_artifacts - [ ] list_device_instances @@ -1103,49 +1648,64 @@ - [ ] list_runs - [ ] list_samples - [ ] list_suites +- [ ] list_tags_for_resource - [ ] list_tests - [ ] list_unique_problems - [ ] list_uploads +- [ ] list_vpce_configurations - [ ] purchase_offering - [ ] renew_offering - [ ] schedule_run +- [ ] stop_job - [ ] stop_remote_access_session - [ ] stop_run +- [ ] tag_resource +- [ ] untag_resource - [ ] update_device_instance - [ ] update_device_pool - [ ] update_instance_profile - [ ] update_network_profile - [ ] update_project +- [ ] update_upload +- [ ] update_vpce_configuration -## directconnect - 0% implemented +## directconnect +0% implemented +- [ ] accept_direct_connect_gateway_association_proposal - [ ] allocate_connection_on_interconnect - [ ] allocate_hosted_connection - [ ] allocate_private_virtual_interface - [ ] allocate_public_virtual_interface +- [ ] allocate_transit_virtual_interface - [ ] associate_connection_with_lag - [ ] associate_hosted_connection - [ ] associate_virtual_interface - [ ] confirm_connection - [ ] confirm_private_virtual_interface - [ ] confirm_public_virtual_interface +- [ ] confirm_transit_virtual_interface - [ ] create_bgp_peer - [ ] create_connection - [ ] create_direct_connect_gateway - [ ] create_direct_connect_gateway_association +- [ ] create_direct_connect_gateway_association_proposal - [ ] create_interconnect - [ ] create_lag - [ ] create_private_virtual_interface - [ ] create_public_virtual_interface +- [ ] create_transit_virtual_interface - [ ] delete_bgp_peer - [ ] delete_connection - [ ] delete_direct_connect_gateway - [ ] delete_direct_connect_gateway_association +- [ ] delete_direct_connect_gateway_association_proposal - [ ] delete_interconnect - [ ] delete_lag - [ ] delete_virtual_interface - [ ] describe_connection_loa - [ ] describe_connections - [ ] describe_connections_on_interconnect +- [ ] describe_direct_connect_gateway_association_proposals - [ ] describe_direct_connect_gateway_associations - [ ] describe_direct_connect_gateway_attachments - [ ] describe_direct_connect_gateways @@ -1161,31 +1721,50 @@ - [ ] disassociate_connection_from_lag - [ ] tag_resource - [ ] untag_resource +- [ ] update_direct_connect_gateway_association - [ ] update_lag +- [ ] update_virtual_interface_attributes -## discovery - 0% implemented +## discovery +0% implemented - [ ] associate_configuration_items_to_application +- [ ] batch_delete_import_data - [ ] create_application - [ ] create_tags - [ ] delete_applications - [ ] delete_tags - [ ] describe_agents - [ ] describe_configurations +- [ ] describe_continuous_exports - [ ] describe_export_configurations - [ ] describe_export_tasks +- [ ] describe_import_tasks - [ ] describe_tags - [ ] disassociate_configuration_items_from_application - [ ] export_configurations - [ ] get_discovery_summary - [ ] list_configurations - [ ] list_server_neighbors +- [ ] start_continuous_export - [ ] start_data_collection_by_agent_ids - [ ] start_export_task +- [ ] start_import_task +- [ ] stop_continuous_export - [ ] stop_data_collection_by_agent_ids - [ ] update_application -## dms - 0% implemented +## dlm +0% implemented +- [ ] create_lifecycle_policy +- [ ] delete_lifecycle_policy +- [ ] get_lifecycle_policies +- [ ] get_lifecycle_policy +- [ ] update_lifecycle_policy + +## dms +0% implemented - [ ] add_tags_to_resource +- [ ] apply_pending_maintenance_action - [ ] create_endpoint - [ ] create_event_subscription - [ ] create_replication_instance @@ -1206,6 +1785,7 @@ - [ ] describe_event_subscriptions - [ ] describe_events - [ ] describe_orderable_replication_instances +- [ ] describe_pending_maintenance_actions - [ ] describe_refresh_schemas_status - [ ] describe_replication_instance_task_logs - [ ] describe_replication_instances @@ -1230,7 +1810,53 @@ - [ ] stop_replication_task - [ ] test_connection -## ds - 0% implemented +## docdb +0% implemented +- [ ] add_tags_to_resource +- [ ] apply_pending_maintenance_action +- [ ] copy_db_cluster_parameter_group +- [ ] copy_db_cluster_snapshot +- [ ] create_db_cluster +- [ ] create_db_cluster_parameter_group +- [ ] create_db_cluster_snapshot +- [ ] create_db_instance +- [ ] create_db_subnet_group +- [ ] delete_db_cluster +- [ ] delete_db_cluster_parameter_group +- [ ] delete_db_cluster_snapshot +- [ ] delete_db_instance +- [ ] delete_db_subnet_group +- [ ] describe_db_cluster_parameter_groups +- [ ] describe_db_cluster_parameters +- [ ] describe_db_cluster_snapshot_attributes +- [ ] describe_db_cluster_snapshots +- [ ] describe_db_clusters +- [ ] describe_db_engine_versions +- [ ] describe_db_instances +- [ ] describe_db_subnet_groups +- [ ] describe_engine_default_cluster_parameters +- [ ] describe_event_categories +- [ ] describe_events +- [ ] describe_orderable_db_instance_options +- [ ] describe_pending_maintenance_actions +- [ ] failover_db_cluster +- [ ] list_tags_for_resource +- [ ] modify_db_cluster +- [ ] modify_db_cluster_parameter_group +- [ ] modify_db_cluster_snapshot_attribute +- [ ] modify_db_instance +- [ ] modify_db_subnet_group +- [ ] reboot_db_instance +- [ ] remove_tags_from_resource +- [ ] reset_db_cluster_parameter_group +- [ ] restore_db_cluster_from_snapshot +- [ ] restore_db_cluster_to_point_in_time +- [ ] start_db_cluster +- [ ] stop_db_cluster + +## ds +0% implemented +- [ ] accept_shared_directory - [ ] add_ip_routes - [ ] add_tags_to_resource - [ ] cancel_schema_extension @@ -1239,11 +1865,13 @@ - [ ] create_computer - [ ] create_conditional_forwarder - [ ] create_directory +- [ ] create_log_subscription - [ ] create_microsoft_ad - [ ] create_snapshot - [ ] create_trust - [ ] delete_conditional_forwarder - [ ] delete_directory +- [ ] delete_log_subscription - [ ] delete_snapshot - [ ] delete_trust - [ ] deregister_event_topic @@ -1251,6 +1879,7 @@ - [ ] describe_directories - [ ] describe_domain_controllers - [ ] describe_event_topics +- [ ] describe_shared_directories - [ ] describe_snapshots - [ ] describe_trusts - [ ] disable_radius @@ -1260,19 +1889,26 @@ - [ ] get_directory_limits - [ ] get_snapshot_limits - [ ] list_ip_routes +- [ ] list_log_subscriptions - [ ] list_schema_extensions - [ ] list_tags_for_resource - [ ] register_event_topic +- [ ] reject_shared_directory - [ ] remove_ip_routes - [ ] remove_tags_from_resource +- [ ] reset_user_password - [ ] restore_from_snapshot +- [ ] share_directory - [ ] start_schema_extension +- [ ] unshare_directory - [ ] update_conditional_forwarder - [ ] update_number_of_domain_controllers - [ ] update_radius +- [ ] update_trust - [ ] verify_trust -## dynamodb - 22% implemented +## dynamodb +19% implemented - [ ] batch_get_item - [ ] batch_write_item - [ ] create_backup @@ -1283,7 +1919,9 @@ - [X] delete_table - [ ] describe_backup - [ ] describe_continuous_backups +- [ ] describe_endpoints - [ ] describe_global_table +- [ ] describe_global_table_settings - [ ] describe_limits - [ ] describe_table - [ ] describe_time_to_live @@ -1298,42 +1936,54 @@ - [ ] restore_table_to_point_in_time - [X] scan - [ ] tag_resource +- [ ] transact_get_items +- [ ] transact_write_items - [ ] untag_resource - [ ] update_continuous_backups - [ ] update_global_table +- [ ] update_global_table_settings - [ ] update_item - [ ] update_table - [ ] update_time_to_live -## dynamodbstreams - 0% implemented -- [ ] describe_stream -- [ ] get_records -- [ ] get_shard_iterator -- [ ] list_streams +## dynamodbstreams +100% implemented +- [X] describe_stream +- [X] get_records +- [X] get_shard_iterator +- [X] list_streams -## ec2 - 37% implemented +## ec2 +28% implemented - [ ] accept_reserved_instances_exchange_quote +- [ ] accept_transit_gateway_vpc_attachment - [ ] accept_vpc_endpoint_connections - [X] accept_vpc_peering_connection +- [ ] advertise_byoip_cidr - [X] allocate_address - [ ] allocate_hosts +- [ ] apply_security_groups_to_client_vpn_target_network - [ ] assign_ipv6_addresses - [ ] assign_private_ip_addresses - [X] associate_address +- [ ] associate_client_vpn_target_network - [X] associate_dhcp_options - [ ] associate_iam_instance_profile - [X] associate_route_table - [ ] associate_subnet_cidr_block +- [ ] associate_transit_gateway_route_table - [X] associate_vpc_cidr_block - [ ] attach_classic_link_vpc - [X] attach_internet_gateway - [X] attach_network_interface - [X] attach_volume - [X] attach_vpn_gateway +- [ ] authorize_client_vpn_ingress - [X] authorize_security_group_egress - [X] authorize_security_group_ingress - [ ] bundle_instance - [ ] cancel_bundle_task +- [ ] cancel_capacity_reservation - [ ] cancel_conversion_task - [ ] cancel_export_task - [ ] cancel_import_task @@ -1344,18 +1994,22 @@ - [ ] copy_fpga_image - [X] copy_image - [X] copy_snapshot +- [ ] create_capacity_reservation +- [ ] create_client_vpn_endpoint +- [ ] create_client_vpn_route - [X] create_customer_gateway - [ ] create_default_subnet - [ ] create_default_vpc - [X] create_dhcp_options - [ ] create_egress_only_internet_gateway +- [ ] create_fleet - [ ] create_flow_logs - [ ] create_fpga_image - [X] create_image - [ ] create_instance_export_task - [X] create_internet_gateway - [X] create_key_pair -- [ ] create_launch_template +- [X] create_launch_template - [ ] create_launch_template_version - [X] create_nat_gateway - [X] create_network_acl @@ -1368,9 +2022,18 @@ - [X] create_route_table - [X] create_security_group - [X] create_snapshot +- [ ] create_snapshots - [ ] create_spot_datafeed_subscription - [X] create_subnet - [X] create_tags +- [ ] create_traffic_mirror_filter +- [ ] create_traffic_mirror_filter_rule +- [ ] create_traffic_mirror_session +- [ ] create_traffic_mirror_target +- [ ] create_transit_gateway +- [ ] create_transit_gateway_route +- [ ] create_transit_gateway_route_table +- [ ] create_transit_gateway_vpc_attachment - [X] create_volume - [X] create_vpc - [ ] create_vpc_endpoint @@ -1380,9 +2043,12 @@ - [X] create_vpn_connection - [ ] create_vpn_connection_route - [X] create_vpn_gateway +- [ ] delete_client_vpn_endpoint +- [ ] delete_client_vpn_route - [X] delete_customer_gateway - [ ] delete_dhcp_options - [ ] delete_egress_only_internet_gateway +- [ ] delete_fleets - [ ] delete_flow_logs - [ ] delete_fpga_image - [X] delete_internet_gateway @@ -1402,6 +2068,14 @@ - [ ] delete_spot_datafeed_subscription - [X] delete_subnet - [X] delete_tags +- [ ] delete_traffic_mirror_filter +- [ ] delete_traffic_mirror_filter_rule +- [ ] delete_traffic_mirror_session +- [ ] delete_traffic_mirror_target +- [ ] delete_transit_gateway +- [ ] delete_transit_gateway_route +- [ ] delete_transit_gateway_route_table +- [ ] delete_transit_gateway_vpc_attachment - [X] delete_volume - [X] delete_vpc - [ ] delete_vpc_endpoint_connection_notifications @@ -1411,19 +2085,30 @@ - [X] delete_vpn_connection - [ ] delete_vpn_connection_route - [X] delete_vpn_gateway +- [ ] deprovision_byoip_cidr - [X] deregister_image - [ ] describe_account_attributes - [X] describe_addresses - [ ] describe_aggregate_id_format - [X] describe_availability_zones - [ ] describe_bundle_tasks +- [ ] describe_byoip_cidrs +- [ ] describe_capacity_reservations - [ ] describe_classic_link_instances +- [ ] describe_client_vpn_authorization_rules +- [ ] describe_client_vpn_connections +- [ ] describe_client_vpn_endpoints +- [ ] describe_client_vpn_routes +- [ ] describe_client_vpn_target_networks - [ ] describe_conversion_tasks - [ ] describe_customer_gateways - [X] describe_dhcp_options - [ ] describe_egress_only_internet_gateways - [ ] describe_elastic_gpus - [ ] describe_export_tasks +- [ ] describe_fleet_history +- [ ] describe_fleet_instances +- [ ] describe_fleets - [ ] describe_flow_logs - [ ] describe_fpga_image_attribute - [ ] describe_fpga_images @@ -1454,6 +2139,7 @@ - [ ] describe_placement_groups - [ ] describe_prefix_lists - [ ] describe_principal_id_format +- [ ] describe_public_ipv4_pools - [X] describe_regions - [ ] describe_reserved_instances - [ ] describe_reserved_instances_listings @@ -1475,6 +2161,13 @@ - [ ] describe_stale_security_groups - [ ] describe_subnets - [X] describe_tags +- [ ] describe_traffic_mirror_filters +- [ ] describe_traffic_mirror_sessions +- [ ] describe_traffic_mirror_targets +- [ ] describe_transit_gateway_attachments +- [ ] describe_transit_gateway_route_tables +- [ ] describe_transit_gateway_vpc_attachments +- [ ] describe_transit_gateways - [ ] describe_volume_attribute - [ ] describe_volume_status - [X] describe_volumes @@ -1497,36 +2190,58 @@ - [X] detach_network_interface - [X] detach_volume - [X] detach_vpn_gateway +- [ ] disable_ebs_encryption_by_default +- [ ] disable_transit_gateway_route_table_propagation - [ ] disable_vgw_route_propagation - [ ] disable_vpc_classic_link - [ ] disable_vpc_classic_link_dns_support - [X] disassociate_address +- [ ] disassociate_client_vpn_target_network - [ ] disassociate_iam_instance_profile - [X] disassociate_route_table - [ ] disassociate_subnet_cidr_block +- [ ] disassociate_transit_gateway_route_table - [X] disassociate_vpc_cidr_block +- [ ] enable_ebs_encryption_by_default +- [ ] enable_transit_gateway_route_table_propagation - [ ] enable_vgw_route_propagation - [ ] enable_volume_io - [ ] enable_vpc_classic_link - [ ] enable_vpc_classic_link_dns_support +- [ ] export_client_vpn_client_certificate_revocation_list +- [ ] export_client_vpn_client_configuration +- [ ] export_transit_gateway_routes +- [ ] get_capacity_reservation_usage - [ ] get_console_output - [ ] get_console_screenshot +- [ ] get_ebs_default_kms_key_id +- [ ] get_ebs_encryption_by_default - [ ] get_host_reservation_purchase_preview - [ ] get_launch_template_data - [ ] get_password_data - [ ] get_reserved_instances_exchange_quote +- [ ] get_transit_gateway_attachment_propagations +- [ ] get_transit_gateway_route_table_associations +- [ ] get_transit_gateway_route_table_propagations +- [ ] import_client_vpn_client_certificate_revocation_list - [ ] import_image - [ ] import_instance - [X] import_key_pair - [ ] import_snapshot - [ ] import_volume +- [ ] modify_capacity_reservation +- [ ] modify_client_vpn_endpoint +- [ ] modify_ebs_default_kms_key_id +- [ ] modify_fleet - [ ] modify_fpga_image_attribute - [ ] modify_hosts - [ ] modify_id_format - [ ] modify_identity_id_format - [ ] modify_image_attribute - [X] modify_instance_attribute +- [ ] modify_instance_capacity_reservation_attributes - [ ] modify_instance_credit_specification +- [ ] modify_instance_event_start_time - [ ] modify_instance_placement - [ ] modify_launch_template - [X] modify_network_interface_attribute @@ -1534,6 +2249,10 @@ - [ ] modify_snapshot_attribute - [X] modify_spot_fleet_request - [X] modify_subnet_attribute +- [ ] modify_traffic_mirror_filter_network_services +- [ ] modify_traffic_mirror_filter_rule +- [ ] modify_traffic_mirror_session +- [ ] modify_transit_gateway_vpc_attachment - [ ] modify_volume - [ ] modify_volume_attribute - [X] modify_vpc_attribute @@ -1543,13 +2262,16 @@ - [ ] modify_vpc_endpoint_service_permissions - [ ] modify_vpc_peering_connection_options - [ ] modify_vpc_tenancy +- [ ] modify_vpn_connection - [ ] monitor_instances - [ ] move_address_to_vpc +- [ ] provision_byoip_cidr - [ ] purchase_host_reservation - [ ] purchase_reserved_instances_offering - [ ] purchase_scheduled_instances - [X] reboot_instances - [ ] register_image +- [ ] reject_transit_gateway_vpc_attachment - [ ] reject_vpc_endpoint_connections - [X] reject_vpc_peering_connection - [X] release_address @@ -1559,31 +2281,42 @@ - [X] replace_network_acl_entry - [X] replace_route - [X] replace_route_table_association +- [ ] replace_transit_gateway_route - [ ] report_instance_status - [X] request_spot_fleet - [X] request_spot_instances +- [ ] reset_ebs_default_kms_key_id - [ ] reset_fpga_image_attribute - [ ] reset_image_attribute - [ ] reset_instance_attribute - [ ] reset_network_interface_attribute - [ ] reset_snapshot_attribute - [ ] restore_address_to_classic +- [ ] revoke_client_vpn_ingress - [X] revoke_security_group_egress - [X] revoke_security_group_ingress - [ ] run_instances - [ ] run_scheduled_instances +- [ ] search_transit_gateway_routes - [X] start_instances - [X] stop_instances +- [ ] terminate_client_vpn_connections - [X] terminate_instances - [ ] unassign_ipv6_addresses - [ ] unassign_private_ip_addresses - [ ] unmonitor_instances - [ ] update_security_group_rule_descriptions_egress - [ ] update_security_group_rule_descriptions_ingress +- [ ] withdraw_byoip_cidr -## ecr - 31% implemented +## ec2-instance-connect +0% implemented +- [ ] send_ssh_public_key + +## ecr +30% implemented - [ ] batch_check_layer_availability -- [ ] batch_delete_image +- [X] batch_delete_image - [X] batch_get_image - [ ] complete_layer_upload - [X] create_repository @@ -1599,46 +2332,65 @@ - [ ] get_repository_policy - [ ] initiate_layer_upload - [X] list_images +- [ ] list_tags_for_resource - [X] put_image +- [ ] put_image_tag_mutability - [ ] put_lifecycle_policy - [ ] set_repository_policy - [ ] start_lifecycle_policy_preview +- [ ] tag_resource +- [ ] untag_resource - [ ] upload_layer_part -## ecs - 87% implemented +## ecs +63% implemented - [X] create_cluster - [X] create_service +- [ ] create_task_set +- [ ] delete_account_setting - [X] delete_attributes - [X] delete_cluster - [X] delete_service +- [ ] delete_task_set - [X] deregister_container_instance - [X] deregister_task_definition - [X] describe_clusters - [X] describe_container_instances - [X] describe_services - [X] describe_task_definition +- [ ] describe_task_sets - [X] describe_tasks - [ ] discover_poll_endpoint +- [ ] list_account_settings - [X] list_attributes - [X] list_clusters - [X] list_container_instances - [X] list_services +- [X] list_tags_for_resource - [X] list_task_definition_families - [X] list_task_definitions - [X] list_tasks +- [ ] put_account_setting +- [ ] put_account_setting_default - [X] put_attributes - [X] register_container_instance - [X] register_task_definition - [X] run_task - [X] start_task - [X] stop_task +- [ ] submit_attachment_state_changes - [ ] submit_container_state_change - [ ] submit_task_state_change +- [ ] tag_resource +- [ ] untag_resource - [ ] update_container_agent - [X] update_container_instances_state - [X] update_service +- [ ] update_service_primary_task_set +- [ ] update_task_set -## efs - 0% implemented +## efs +0% implemented - [ ] create_file_system - [ ] create_mount_target - [ ] create_tags @@ -1646,14 +2398,31 @@ - [ ] delete_mount_target - [ ] delete_tags - [ ] describe_file_systems +- [ ] describe_lifecycle_configuration - [ ] describe_mount_target_security_groups - [ ] describe_mount_targets - [ ] describe_tags - [ ] modify_mount_target_security_groups +- [ ] put_lifecycle_configuration +- [ ] update_file_system -## elasticache - 0% implemented +## eks +0% implemented +- [ ] create_cluster +- [ ] delete_cluster +- [ ] describe_cluster +- [ ] describe_update +- [ ] list_clusters +- [ ] list_updates +- [ ] update_cluster_config +- [ ] update_cluster_version + +## elasticache +0% implemented - [ ] add_tags_to_resource - [ ] authorize_cache_security_group_ingress +- [ ] batch_apply_update_action +- [ ] batch_stop_update_action - [ ] copy_snapshot - [ ] create_cache_cluster - [ ] create_cache_parameter_group @@ -1661,6 +2430,7 @@ - [ ] create_cache_subnet_group - [ ] create_replication_group - [ ] create_snapshot +- [ ] decrease_replica_count - [ ] delete_cache_cluster - [ ] delete_cache_parameter_group - [ ] delete_cache_security_group @@ -1678,7 +2448,10 @@ - [ ] describe_replication_groups - [ ] describe_reserved_cache_nodes - [ ] describe_reserved_cache_nodes_offerings +- [ ] describe_service_updates - [ ] describe_snapshots +- [ ] describe_update_actions +- [ ] increase_replica_count - [ ] list_allowed_node_type_modifications - [ ] list_tags_for_resource - [ ] modify_cache_cluster @@ -1693,7 +2466,8 @@ - [ ] revoke_cache_security_group_ingress - [ ] test_failover -## elasticbeanstalk - 0% implemented +## elasticbeanstalk +0% implemented - [ ] abort_environment_update - [ ] apply_environment_managed_action - [ ] check_dns_availability @@ -1739,7 +2513,8 @@ - [ ] update_tags_for_resource - [ ] validate_configuration_settings -## elastictranscoder - 0% implemented +## elastictranscoder +0% implemented - [ ] cancel_job - [ ] create_job - [ ] create_pipeline @@ -1758,7 +2533,8 @@ - [ ] update_pipeline_notifications - [ ] update_pipeline_status -## elb - 34% implemented +## elb +34% implemented - [ ] add_tags - [X] apply_security_groups_to_load_balancer - [ ] attach_load_balancer_to_subnets @@ -1789,7 +2565,8 @@ - [ ] set_load_balancer_policies_for_backend_server - [X] set_load_balancer_policies_of_listener -## elbv2 - 70% implemented +## elbv2 +70% implemented - [ ] add_listener_certificates - [ ] add_tags - [X] create_listener @@ -1825,7 +2602,8 @@ - [X] set_security_groups - [X] set_subnets -## emr - 55% implemented +## emr +55% implemented - [ ] add_instance_fleet - [X] add_instance_groups - [X] add_job_flow_steps @@ -1854,8 +2632,10 @@ - [X] set_visible_to_all_users - [X] terminate_job_flows -## es - 0% implemented +## es +0% implemented - [ ] add_tags +- [ ] cancel_elasticsearch_service_software_update - [ ] create_elasticsearch_domain - [ ] delete_elasticsearch_domain - [ ] delete_elasticsearch_service_role @@ -1863,40 +2643,72 @@ - [ ] describe_elasticsearch_domain_config - [ ] describe_elasticsearch_domains - [ ] describe_elasticsearch_instance_type_limits +- [ ] describe_reserved_elasticsearch_instance_offerings +- [ ] describe_reserved_elasticsearch_instances +- [ ] get_compatible_elasticsearch_versions +- [ ] get_upgrade_history +- [ ] get_upgrade_status - [ ] list_domain_names - [ ] list_elasticsearch_instance_types - [ ] list_elasticsearch_versions - [ ] list_tags +- [ ] purchase_reserved_elasticsearch_instance_offering - [ ] remove_tags +- [ ] start_elasticsearch_service_software_update - [ ] update_elasticsearch_domain_config +- [ ] upgrade_elasticsearch_domain -## events - 100% implemented +## events +48% implemented +- [ ] activate_event_source +- [ ] create_event_bus +- [ ] create_partner_event_source +- [ ] deactivate_event_source +- [ ] delete_event_bus +- [ ] delete_partner_event_source - [X] delete_rule - [X] describe_event_bus +- [ ] describe_event_source +- [ ] describe_partner_event_source - [X] describe_rule - [X] disable_rule - [X] enable_rule +- [ ] list_event_buses +- [ ] list_event_sources +- [ ] list_partner_event_source_accounts +- [ ] list_partner_event_sources - [X] list_rule_names_by_target - [X] list_rules +- [ ] list_tags_for_resource - [X] list_targets_by_rule - [X] put_events +- [ ] put_partner_events - [X] put_permission - [X] put_rule - [X] put_targets - [X] remove_permission - [X] remove_targets +- [ ] tag_resource - [X] test_event_pattern +- [ ] untag_resource -## firehose - 0% implemented +## firehose +0% implemented - [ ] create_delivery_stream - [ ] delete_delivery_stream - [ ] describe_delivery_stream - [ ] list_delivery_streams +- [ ] list_tags_for_delivery_stream - [ ] put_record - [ ] put_record_batch +- [ ] start_delivery_stream_encryption +- [ ] stop_delivery_stream_encryption +- [ ] tag_delivery_stream +- [ ] untag_delivery_stream - [ ] update_destination -## fms - 0% implemented +## fms +0% implemented - [ ] associate_admin_account - [ ] delete_notification_channel - [ ] delete_policy @@ -1905,12 +2717,29 @@ - [ ] get_compliance_detail - [ ] get_notification_channel - [ ] get_policy +- [ ] get_protection_status - [ ] list_compliance_status +- [ ] list_member_accounts - [ ] list_policies - [ ] put_notification_channel - [ ] put_policy -## gamelift - 0% implemented +## fsx +0% implemented +- [ ] create_backup +- [ ] create_file_system +- [ ] create_file_system_from_backup +- [ ] delete_backup +- [ ] delete_file_system +- [ ] describe_backups +- [ ] describe_file_systems +- [ ] list_tags_for_resource +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_file_system + +## gamelift +0% implemented - [ ] accept_match - [ ] create_alias - [ ] create_build @@ -1921,6 +2750,7 @@ - [ ] create_matchmaking_rule_set - [ ] create_player_session - [ ] create_player_sessions +- [ ] create_script - [ ] create_vpc_peering_authorization - [ ] create_vpc_peering_connection - [ ] delete_alias @@ -1928,7 +2758,9 @@ - [ ] delete_fleet - [ ] delete_game_session_queue - [ ] delete_matchmaking_configuration +- [ ] delete_matchmaking_rule_set - [ ] delete_scaling_policy +- [ ] delete_script - [ ] delete_vpc_peering_authorization - [ ] delete_vpc_peering_connection - [ ] describe_alias @@ -1950,6 +2782,7 @@ - [ ] describe_player_sessions - [ ] describe_runtime_configuration - [ ] describe_scaling_policies +- [ ] describe_script - [ ] describe_vpc_peering_authorizations - [ ] describe_vpc_peering_connections - [ ] get_game_session_log_url @@ -1957,13 +2790,16 @@ - [ ] list_aliases - [ ] list_builds - [ ] list_fleets +- [ ] list_scripts - [ ] put_scaling_policy - [ ] request_upload_credentials - [ ] resolve_alias - [ ] search_game_sessions +- [ ] start_fleet_actions - [ ] start_game_session_placement - [ ] start_match_backfill - [ ] start_matchmaking +- [ ] stop_fleet_actions - [ ] stop_game_session_placement - [ ] stop_matchmaking - [ ] update_alias @@ -1975,9 +2811,11 @@ - [ ] update_game_session_queue - [ ] update_matchmaking_configuration - [ ] update_runtime_configuration +- [ ] update_script - [ ] validate_matchmaking_rule_set -## glacier - 12% implemented +## glacier +12% implemented - [ ] abort_multipart_upload - [ ] abort_vault_lock - [ ] add_tags_to_vault @@ -2012,25 +2850,53 @@ - [ ] upload_archive - [ ] upload_multipart_part -## glue - 0% implemented +## globalaccelerator +0% implemented +- [ ] create_accelerator +- [ ] create_endpoint_group +- [ ] create_listener +- [ ] delete_accelerator +- [ ] delete_endpoint_group +- [ ] delete_listener +- [ ] describe_accelerator +- [ ] describe_accelerator_attributes +- [ ] describe_endpoint_group +- [ ] describe_listener +- [ ] list_accelerators +- [ ] list_endpoint_groups +- [ ] list_listeners +- [ ] update_accelerator +- [ ] update_accelerator_attributes +- [ ] update_endpoint_group +- [ ] update_listener + +## glue +5% implemented - [ ] batch_create_partition - [ ] batch_delete_connection - [ ] batch_delete_partition - [ ] batch_delete_table - [ ] batch_delete_table_version +- [ ] batch_get_crawlers +- [ ] batch_get_dev_endpoints +- [ ] batch_get_jobs - [ ] batch_get_partition +- [ ] batch_get_triggers +- [ ] batch_get_workflows - [ ] batch_stop_job_run - [ ] create_classifier - [ ] create_connection - [ ] create_crawler -- [ ] create_database +- [X] create_database - [ ] create_dev_endpoint - [ ] create_job - [ ] create_partition - [ ] create_script -- [ ] create_table +- [ ] create_security_configuration +- [X] create_table - [ ] create_trigger - [ ] create_user_defined_function +- [ ] create_workflow - [ ] delete_classifier - [ ] delete_connection - [ ] delete_crawler @@ -2038,10 +2904,13 @@ - [ ] delete_dev_endpoint - [ ] delete_job - [ ] delete_partition -- [ ] delete_table +- [ ] delete_resource_policy +- [ ] delete_security_configuration +- [X] delete_table - [ ] delete_table_version - [ ] delete_trigger - [ ] delete_user_defined_function +- [ ] delete_workflow - [ ] get_catalog_import_status - [ ] get_classifier - [ ] get_classifiers @@ -2050,12 +2919,15 @@ - [ ] get_crawler - [ ] get_crawler_metrics - [ ] get_crawlers -- [ ] get_database +- [ ] get_data_catalog_encryption_settings +- [X] get_database - [ ] get_databases - [ ] get_dataflow_graph - [ ] get_dev_endpoint - [ ] get_dev_endpoints - [ ] get_job +- [ ] get_job_bookmark +- [ ] get_job_bookmarks - [ ] get_job_run - [ ] get_job_runs - [ ] get_jobs @@ -2063,23 +2935,42 @@ - [ ] get_partition - [ ] get_partitions - [ ] get_plan -- [ ] get_table +- [ ] get_resource_policy +- [ ] get_security_configuration +- [ ] get_security_configurations +- [X] get_table - [ ] get_table_version - [ ] get_table_versions -- [ ] get_tables +- [X] get_tables +- [ ] get_tags - [ ] get_trigger - [ ] get_triggers - [ ] get_user_defined_function - [ ] get_user_defined_functions +- [ ] get_workflow +- [ ] get_workflow_run +- [ ] get_workflow_run_properties +- [ ] get_workflow_runs - [ ] import_catalog_to_glue +- [ ] list_crawlers +- [ ] list_dev_endpoints +- [ ] list_jobs +- [ ] list_triggers +- [ ] list_workflows +- [ ] put_data_catalog_encryption_settings +- [ ] put_resource_policy +- [ ] put_workflow_run_properties - [ ] reset_job_bookmark - [ ] start_crawler - [ ] start_crawler_schedule - [ ] start_job_run - [ ] start_trigger +- [ ] start_workflow_run - [ ] stop_crawler - [ ] stop_crawler_schedule - [ ] stop_trigger +- [ ] tag_resource +- [ ] untag_resource - [ ] update_classifier - [ ] update_connection - [ ] update_crawler @@ -2091,10 +2982,14 @@ - [ ] update_table - [ ] update_trigger - [ ] update_user_defined_function +- [ ] update_workflow -## greengrass - 0% implemented +## greengrass +0% implemented - [ ] associate_role_to_group - [ ] associate_service_role_to_account +- [ ] create_connector_definition +- [ ] create_connector_definition_version - [ ] create_core_definition - [ ] create_core_definition_version - [ ] create_deployment @@ -2112,6 +3007,7 @@ - [ ] create_software_update_job - [ ] create_subscription_definition - [ ] create_subscription_definition_version +- [ ] delete_connector_definition - [ ] delete_core_definition - [ ] delete_device_definition - [ ] delete_function_definition @@ -2122,7 +3018,10 @@ - [ ] disassociate_role_from_group - [ ] disassociate_service_role_from_account - [ ] get_associated_role +- [ ] get_bulk_deployment_status - [ ] get_connectivity_info +- [ ] get_connector_definition +- [ ] get_connector_definition_version - [ ] get_core_definition - [ ] get_core_definition_version - [ ] get_deployment_status @@ -2141,6 +3040,10 @@ - [ ] get_service_role_for_account - [ ] get_subscription_definition - [ ] get_subscription_definition_version +- [ ] list_bulk_deployment_detailed_reports +- [ ] list_bulk_deployments +- [ ] list_connector_definition_versions +- [ ] list_connector_definitions - [ ] list_core_definition_versions - [ ] list_core_definitions - [ ] list_deployments @@ -2157,8 +3060,14 @@ - [ ] list_resource_definitions - [ ] list_subscription_definition_versions - [ ] list_subscription_definitions +- [ ] list_tags_for_resource - [ ] reset_deployments +- [ ] start_bulk_deployment +- [ ] stop_bulk_deployment +- [ ] tag_resource +- [ ] untag_resource - [ ] update_connectivity_info +- [ ] update_connector_definition - [ ] update_core_definition - [ ] update_device_definition - [ ] update_function_definition @@ -2168,16 +3077,47 @@ - [ ] update_resource_definition - [ ] update_subscription_definition -## guardduty - 0% implemented +## groundstation +0% implemented +- [ ] cancel_contact +- [ ] create_config +- [ ] create_dataflow_endpoint_group +- [ ] create_mission_profile +- [ ] delete_config +- [ ] delete_dataflow_endpoint_group +- [ ] delete_mission_profile +- [ ] describe_contact +- [ ] get_config +- [ ] get_dataflow_endpoint_group +- [ ] get_minute_usage +- [ ] get_mission_profile +- [ ] get_satellite +- [ ] list_configs +- [ ] list_contacts +- [ ] list_dataflow_endpoint_groups +- [ ] list_ground_stations +- [ ] list_mission_profiles +- [ ] list_satellites +- [ ] list_tags_for_resource +- [ ] reserve_contact +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_config +- [ ] update_mission_profile + +## guardduty +0% implemented - [ ] accept_invitation - [ ] archive_findings - [ ] create_detector +- [ ] create_filter - [ ] create_ip_set - [ ] create_members - [ ] create_sample_findings - [ ] create_threat_intel_set - [ ] decline_invitations - [ ] delete_detector +- [ ] delete_filter - [ ] delete_invitations - [ ] delete_ip_set - [ ] delete_members @@ -2185,6 +3125,7 @@ - [ ] disassociate_from_master_account - [ ] disassociate_members - [ ] get_detector +- [ ] get_filter - [ ] get_findings - [ ] get_findings_statistics - [ ] get_invitations_count @@ -2194,20 +3135,26 @@ - [ ] get_threat_intel_set - [ ] invite_members - [ ] list_detectors +- [ ] list_filters - [ ] list_findings - [ ] list_invitations - [ ] list_ip_sets - [ ] list_members +- [ ] list_tags_for_resource - [ ] list_threat_intel_sets - [ ] start_monitoring_members - [ ] stop_monitoring_members +- [ ] tag_resource - [ ] unarchive_findings +- [ ] untag_resource - [ ] update_detector +- [ ] update_filter - [ ] update_findings_feedback - [ ] update_ip_set - [ ] update_threat_intel_set -## health - 0% implemented +## health +0% implemented - [ ] describe_affected_entities - [ ] describe_entity_aggregates - [ ] describe_event_aggregates @@ -2215,7 +3162,8 @@ - [ ] describe_event_types - [ ] describe_events -## iam - 62% implemented +## iam +55% implemented - [ ] add_client_id_to_open_id_connect_provider - [X] add_role_to_instance_profile - [X] add_user_to_group @@ -2249,6 +3197,7 @@ - [ ] delete_policy - [X] delete_policy_version - [X] delete_role +- [ ] delete_role_permissions_boundary - [X] delete_role_policy - [X] delete_saml_provider - [X] delete_server_certificate @@ -2257,6 +3206,7 @@ - [X] delete_signing_certificate - [ ] delete_ssh_public_key - [X] delete_user +- [ ] delete_user_permissions_boundary - [X] delete_user_policy - [ ] delete_virtual_mfa_device - [X] detach_group_policy @@ -2264,6 +3214,8 @@ - [X] detach_user_policy - [X] enable_mfa_device - [ ] generate_credential_report +- [ ] generate_organizations_access_report +- [ ] generate_service_last_accessed_details - [X] get_access_key_last_used - [X] get_account_authorization_details - [ ] get_account_password_policy @@ -2276,17 +3228,20 @@ - [X] get_instance_profile - [X] get_login_profile - [ ] get_open_id_connect_provider +- [ ] get_organizations_access_report - [X] get_policy - [X] get_policy_version - [X] get_role - [X] get_role_policy - [X] get_saml_provider - [X] get_server_certificate +- [ ] get_service_last_accessed_details +- [ ] get_service_last_accessed_details_with_entities - [ ] get_service_linked_role_deletion_status - [ ] get_ssh_public_key - [X] get_user - [X] get_user_policy -- [X] list_access_keys +- [ ] list_access_keys - [X] list_account_aliases - [X] list_attached_group_policies - [X] list_attached_role_policies @@ -2294,27 +3249,30 @@ - [ ] list_entities_for_policy - [X] list_group_policies - [X] list_groups -- [X] list_groups_for_user -- [X] list_instance_profiles -- [X] list_instance_profiles_for_role +- [ ] list_groups_for_user +- [ ] list_instance_profiles +- [ ] list_instance_profiles_for_role - [X] list_mfa_devices - [ ] list_open_id_connect_providers - [X] list_policies +- [ ] list_policies_granting_service_access - [X] list_policy_versions - [X] list_role_policies -- [X] list_roles - [X] list_role_tags -- [ ] list_user_tags +- [X] list_roles - [X] list_saml_providers -- [X] list_server_certificates +- [ ] list_server_certificates - [ ] list_service_specific_credentials - [X] list_signing_certificates - [ ] list_ssh_public_keys - [X] list_user_policies +- [ ] list_user_tags - [X] list_users - [ ] list_virtual_mfa_devices - [X] put_group_policy +- [ ] put_role_permissions_boundary - [X] put_role_policy +- [ ] put_user_permissions_boundary - [X] put_user_policy - [ ] remove_client_id_from_open_id_connect_provider - [X] remove_role_from_instance_profile @@ -2322,6 +3280,7 @@ - [ ] reset_service_specific_credential - [ ] resync_mfa_device - [ ] set_default_policy_version +- [ ] set_security_token_service_preferences - [ ] simulate_custom_policy - [ ] simulate_principal_policy - [X] tag_role @@ -2334,19 +3293,20 @@ - [ ] update_group - [X] update_login_profile - [ ] update_open_id_connect_provider_thumbprint -- [ ] update_role -- [ ] update_role_description +- [X] update_role +- [X] update_role_description - [X] update_saml_provider - [ ] update_server_certificate - [ ] update_service_specific_credential - [X] update_signing_certificate - [ ] update_ssh_public_key - [X] update_user -- [X] upload_server_certificate +- [ ] upload_server_certificate - [X] upload_signing_certificate - [ ] upload_ssh_public_key -## importexport - 0% implemented +## importexport +0% implemented - [ ] cancel_job - [ ] create_job - [ ] get_shipping_label @@ -2354,10 +3314,12 @@ - [ ] list_jobs - [ ] update_job -## inspector - 0% implemented +## inspector +0% implemented - [ ] add_attributes_to_findings - [ ] create_assessment_target - [ ] create_assessment_template +- [ ] create_exclusions_preview - [ ] create_resource_group - [ ] delete_assessment_run - [ ] delete_assessment_target @@ -2366,16 +3328,19 @@ - [ ] describe_assessment_targets - [ ] describe_assessment_templates - [ ] describe_cross_account_access_role +- [ ] describe_exclusions - [ ] describe_findings - [ ] describe_resource_groups - [ ] describe_rules_packages - [ ] get_assessment_report +- [ ] get_exclusions_preview - [ ] get_telemetry_metadata - [ ] list_assessment_run_agents - [ ] list_assessment_runs - [ ] list_assessment_targets - [ ] list_assessment_templates - [ ] list_event_subscriptions +- [ ] list_exclusions - [ ] list_findings - [ ] list_rules_packages - [ ] list_tags_for_resource @@ -2389,37 +3354,53 @@ - [ ] unsubscribe_from_event - [ ] update_assessment_target -## iot - 33% implemented +## iot +24% implemented - [ ] accept_certificate_transfer +- [ ] add_thing_to_billing_group - [X] add_thing_to_thing_group - [ ] associate_targets_with_job - [X] attach_policy - [X] attach_principal_policy +- [ ] attach_security_profile - [X] attach_thing_principal +- [ ] cancel_audit_task - [ ] cancel_certificate_transfer - [ ] cancel_job +- [ ] cancel_job_execution - [ ] clear_default_authorizer - [ ] create_authorizer +- [ ] create_billing_group - [ ] create_certificate_from_csr +- [ ] create_dynamic_thing_group - [X] create_job - [X] create_keys_and_certificate - [ ] create_ota_update - [X] create_policy - [ ] create_policy_version - [ ] create_role_alias +- [ ] create_scheduled_audit +- [ ] create_security_profile - [ ] create_stream - [X] create_thing - [X] create_thing_group - [X] create_thing_type - [ ] create_topic_rule +- [ ] delete_account_audit_configuration - [ ] delete_authorizer +- [ ] delete_billing_group - [ ] delete_ca_certificate - [X] delete_certificate +- [ ] delete_dynamic_thing_group +- [ ] delete_job +- [ ] delete_job_execution - [ ] delete_ota_update - [X] delete_policy - [ ] delete_policy_version - [ ] delete_registration_code - [ ] delete_role_alias +- [ ] delete_scheduled_audit +- [ ] delete_security_profile - [ ] delete_stream - [X] delete_thing - [X] delete_thing_group @@ -2427,7 +3408,10 @@ - [ ] delete_topic_rule - [ ] delete_v2_logging_level - [ ] deprecate_thing_type +- [ ] describe_account_audit_configuration +- [ ] describe_audit_task - [ ] describe_authorizer +- [ ] describe_billing_group - [ ] describe_ca_certificate - [X] describe_certificate - [ ] describe_default_authorizer @@ -2437,6 +3421,8 @@ - [X] describe_job - [ ] describe_job_execution - [ ] describe_role_alias +- [ ] describe_scheduled_audit +- [ ] describe_security_profile - [ ] describe_stream - [X] describe_thing - [X] describe_thing_group @@ -2444,6 +3430,7 @@ - [X] describe_thing_type - [X] detach_policy - [X] detach_principal_policy +- [ ] detach_security_profile - [X] detach_thing_principal - [ ] disable_topic_rule - [ ] enable_topic_rule @@ -2455,10 +3442,15 @@ - [X] get_policy - [ ] get_policy_version - [ ] get_registration_code +- [ ] get_statistics - [ ] get_topic_rule - [ ] get_v2_logging_options +- [ ] list_active_violations - [ ] list_attached_policies +- [ ] list_audit_findings +- [ ] list_audit_tasks - [ ] list_authorizers +- [ ] list_billing_groups - [ ] list_ca_certificates - [X] list_certificates - [ ] list_certificates_by_ca @@ -2474,8 +3466,13 @@ - [X] list_principal_policies - [X] list_principal_things - [ ] list_role_aliases +- [ ] list_scheduled_audits +- [ ] list_security_profiles +- [ ] list_security_profiles_for_target - [ ] list_streams +- [ ] list_tags_for_resource - [ ] list_targets_for_policy +- [ ] list_targets_for_security_profile - [X] list_thing_groups - [X] list_thing_groups_for_thing - [X] list_thing_principals @@ -2483,13 +3480,16 @@ - [ ] list_thing_registration_tasks - [X] list_thing_types - [X] list_things +- [ ] list_things_in_billing_group - [X] list_things_in_thing_group - [ ] list_topic_rules - [ ] list_v2_logging_levels +- [ ] list_violation_events - [ ] register_ca_certificate - [X] register_certificate - [ ] register_thing - [ ] reject_certificate_transfer +- [ ] remove_thing_from_billing_group - [X] remove_thing_from_thing_group - [ ] replace_topic_rule - [ ] search_index @@ -2498,41 +3498,213 @@ - [ ] set_logging_options - [ ] set_v2_logging_level - [ ] set_v2_logging_options +- [ ] start_on_demand_audit_task - [ ] start_thing_registration_task - [ ] stop_thing_registration_task +- [ ] tag_resource - [ ] test_authorization - [ ] test_invoke_authorizer - [ ] transfer_certificate +- [ ] untag_resource +- [ ] update_account_audit_configuration - [ ] update_authorizer +- [ ] update_billing_group - [ ] update_ca_certificate - [X] update_certificate +- [ ] update_dynamic_thing_group - [ ] update_event_configurations - [ ] update_indexing_configuration +- [ ] update_job - [ ] update_role_alias +- [ ] update_scheduled_audit +- [ ] update_security_profile - [ ] update_stream - [X] update_thing - [X] update_thing_group - [X] update_thing_groups_for_thing +- [ ] validate_security_profile_behaviors -## iot-data - 0% implemented -- [ ] delete_thing_shadow -- [ ] get_thing_shadow -- [ ] publish -- [ ] update_thing_shadow +## iot-data +100% implemented +- [X] delete_thing_shadow +- [X] get_thing_shadow +- [X] publish +- [X] update_thing_shadow -## iot-jobs-data - 0% implemented +## iot-jobs-data +0% implemented - [ ] describe_job_execution - [ ] get_pending_job_executions - [ ] start_next_pending_job_execution - [ ] update_job_execution -## kinesis - 61% implemented +## iot1click-devices +0% implemented +- [ ] claim_devices_by_claim_code +- [ ] describe_device +- [ ] finalize_device_claim +- [ ] get_device_methods +- [ ] initiate_device_claim +- [ ] invoke_device_method +- [ ] list_device_events +- [ ] list_devices +- [ ] list_tags_for_resource +- [ ] tag_resource +- [ ] unclaim_device +- [ ] untag_resource +- [ ] update_device_state + +## iot1click-projects +0% implemented +- [ ] associate_device_with_placement +- [ ] create_placement +- [ ] create_project +- [ ] delete_placement +- [ ] delete_project +- [ ] describe_placement +- [ ] describe_project +- [ ] disassociate_device_from_placement +- [ ] get_devices_in_placement +- [ ] list_placements +- [ ] list_projects +- [ ] list_tags_for_resource +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_placement +- [ ] update_project + +## iotanalytics +0% implemented +- [ ] batch_put_message +- [ ] cancel_pipeline_reprocessing +- [ ] create_channel +- [ ] create_dataset +- [ ] create_dataset_content +- [ ] create_datastore +- [ ] create_pipeline +- [ ] delete_channel +- [ ] delete_dataset +- [ ] delete_dataset_content +- [ ] delete_datastore +- [ ] delete_pipeline +- [ ] describe_channel +- [ ] describe_dataset +- [ ] describe_datastore +- [ ] describe_logging_options +- [ ] describe_pipeline +- [ ] get_dataset_content +- [ ] list_channels +- [ ] list_dataset_contents +- [ ] list_datasets +- [ ] list_datastores +- [ ] list_pipelines +- [ ] list_tags_for_resource +- [ ] put_logging_options +- [ ] run_pipeline_activity +- [ ] sample_channel_data +- [ ] start_pipeline_reprocessing +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_channel +- [ ] update_dataset +- [ ] update_datastore +- [ ] update_pipeline + +## iotevents +0% implemented +- [ ] create_detector_model +- [ ] create_input +- [ ] delete_detector_model +- [ ] delete_input +- [ ] describe_detector_model +- [ ] describe_input +- [ ] describe_logging_options +- [ ] list_detector_model_versions +- [ ] list_detector_models +- [ ] list_inputs +- [ ] list_tags_for_resource +- [ ] put_logging_options +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_detector_model +- [ ] update_input + +## iotevents-data +0% implemented +- [ ] batch_put_message +- [ ] batch_update_detector +- [ ] describe_detector +- [ ] list_detectors + +## iotthingsgraph +0% implemented +- [ ] associate_entity_to_thing +- [ ] create_flow_template +- [ ] create_system_instance +- [ ] create_system_template +- [ ] delete_flow_template +- [ ] delete_namespace +- [ ] delete_system_instance +- [ ] delete_system_template +- [ ] deploy_system_instance +- [ ] deprecate_flow_template +- [ ] deprecate_system_template +- [ ] describe_namespace +- [ ] dissociate_entity_from_thing +- [ ] get_entities +- [ ] get_flow_template +- [ ] get_flow_template_revisions +- [ ] get_namespace_deletion_status +- [ ] get_system_instance +- [ ] get_system_template +- [ ] get_system_template_revisions +- [ ] get_upload_status +- [ ] list_flow_execution_messages +- [ ] list_tags_for_resource +- [ ] search_entities +- [ ] search_flow_executions +- [ ] search_flow_templates +- [ ] search_system_instances +- [ ] search_system_templates +- [ ] search_things +- [ ] tag_resource +- [ ] undeploy_system_instance +- [ ] untag_resource +- [ ] update_flow_template +- [ ] update_system_template +- [ ] upload_entity_definitions + +## kafka +0% implemented +- [ ] create_cluster +- [ ] create_configuration +- [ ] delete_cluster +- [ ] describe_cluster +- [ ] describe_cluster_operation +- [ ] describe_configuration +- [ ] describe_configuration_revision +- [ ] get_bootstrap_brokers +- [ ] list_cluster_operations +- [ ] list_clusters +- [ ] list_configuration_revisions +- [ ] list_configurations +- [ ] list_nodes +- [ ] list_tags_for_resource +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_broker_storage +- [ ] update_cluster_configuration + +## kinesis +50% implemented - [X] add_tags_to_stream - [X] create_stream - [ ] decrease_stream_retention_period - [X] delete_stream +- [ ] deregister_stream_consumer - [ ] describe_limits - [X] describe_stream +- [ ] describe_stream_consumer - [X] describe_stream_summary - [ ] disable_enhanced_monitoring - [ ] enable_enhanced_monitoring @@ -2540,25 +3712,33 @@ - [X] get_shard_iterator - [ ] increase_stream_retention_period - [ ] list_shards +- [ ] list_stream_consumers - [X] list_streams - [X] list_tags_for_stream - [X] merge_shards - [X] put_record - [X] put_records +- [ ] register_stream_consumer - [X] remove_tags_from_stream - [X] split_shard - [ ] start_stream_encryption - [ ] stop_stream_encryption +- [ ] subscribe_to_shard - [ ] update_shard_count -## kinesis-video-archived-media - 0% implemented +## kinesis-video-archived-media +0% implemented +- [ ] get_dash_streaming_session_url +- [ ] get_hls_streaming_session_url - [ ] get_media_for_fragment_list - [ ] list_fragments -## kinesis-video-media - 0% implemented +## kinesis-video-media +0% implemented - [ ] get_media -## kinesisanalytics - 0% implemented +## kinesisanalytics +0% implemented - [ ] add_application_cloud_watch_logging_option - [ ] add_application_input - [ ] add_application_input_processing_configuration @@ -2573,11 +3753,42 @@ - [ ] describe_application - [ ] discover_input_schema - [ ] list_applications +- [ ] list_tags_for_resource - [ ] start_application - [ ] stop_application +- [ ] tag_resource +- [ ] untag_resource - [ ] update_application -## kinesisvideo - 0% implemented +## kinesisanalyticsv2 +0% implemented +- [ ] add_application_cloud_watch_logging_option +- [ ] add_application_input +- [ ] add_application_input_processing_configuration +- [ ] add_application_output +- [ ] add_application_reference_data_source +- [ ] create_application +- [ ] create_application_snapshot +- [ ] delete_application +- [ ] delete_application_cloud_watch_logging_option +- [ ] delete_application_input_processing_configuration +- [ ] delete_application_output +- [ ] delete_application_reference_data_source +- [ ] delete_application_snapshot +- [ ] describe_application +- [ ] describe_application_snapshot +- [ ] discover_input_schema +- [ ] list_application_snapshots +- [ ] list_applications +- [ ] list_tags_for_resource +- [ ] start_application +- [ ] stop_application +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_application + +## kinesisvideo +0% implemented - [ ] create_stream - [ ] delete_stream - [ ] describe_stream @@ -2589,21 +3800,27 @@ - [ ] update_data_retention - [ ] update_stream -## kms - 25% implemented -- [ ] cancel_key_deletion +## kms +41% implemented +- [X] cancel_key_deletion +- [ ] connect_custom_key_store - [ ] create_alias +- [ ] create_custom_key_store - [ ] create_grant - [X] create_key - [ ] decrypt - [X] delete_alias +- [ ] delete_custom_key_store - [ ] delete_imported_key_material +- [ ] describe_custom_key_stores - [X] describe_key -- [ ] disable_key +- [X] disable_key - [X] disable_key_rotation -- [ ] enable_key +- [ ] disconnect_custom_key_store +- [X] enable_key - [X] enable_key_rotation - [ ] encrypt -- [ ] generate_data_key +- [X] generate_data_key - [ ] generate_data_key_without_plaintext - [ ] generate_random - [X] get_key_policy @@ -2614,19 +3831,22 @@ - [ ] list_grants - [ ] list_key_policies - [X] list_keys -- [ ] list_resource_tags +- [X] list_resource_tags - [ ] list_retirable_grants - [X] put_key_policy - [ ] re_encrypt - [ ] retire_grant - [ ] revoke_grant -- [ ] schedule_key_deletion -- [ ] tag_resource +- [X] schedule_key_deletion +- [X] tag_resource - [ ] untag_resource - [ ] update_alias -- [ ] update_key_description +- [ ] update_custom_key_store +- [X] update_key_description -## lambda - 0% implemented +## lambda +0% implemented +- [ ] add_layer_version_permission - [ ] add_permission - [ ] create_alias - [ ] create_event_source_mapping @@ -2635,21 +3855,29 @@ - [ ] delete_event_source_mapping - [ ] delete_function - [ ] delete_function_concurrency +- [ ] delete_layer_version - [ ] get_account_settings - [ ] get_alias - [ ] get_event_source_mapping - [ ] get_function - [ ] get_function_configuration +- [ ] get_layer_version +- [ ] get_layer_version_by_arn +- [ ] get_layer_version_policy - [ ] get_policy - [ ] invoke - [ ] invoke_async - [ ] list_aliases - [ ] list_event_source_mappings - [ ] list_functions +- [ ] list_layer_versions +- [ ] list_layers - [ ] list_tags - [ ] list_versions_by_function +- [ ] publish_layer_version - [ ] publish_version - [ ] put_function_concurrency +- [ ] remove_layer_version_permission - [ ] remove_permission - [ ] tag_resource - [ ] untag_resource @@ -2658,7 +3886,8 @@ - [ ] update_function_code - [ ] update_function_configuration -## lex-models - 0% implemented +## lex-models +0% implemented - [ ] create_bot_version - [ ] create_intent_version - [ ] create_slot_type_version @@ -2696,17 +3925,39 @@ - [ ] put_slot_type - [ ] start_import -## lex-runtime - 0% implemented +## lex-runtime +0% implemented - [ ] post_content - [ ] post_text -## lightsail - 0% implemented +## license-manager +0% implemented +- [ ] create_license_configuration +- [ ] delete_license_configuration +- [ ] get_license_configuration +- [ ] get_service_settings +- [ ] list_associations_for_license_configuration +- [ ] list_license_configurations +- [ ] list_license_specifications_for_resource +- [ ] list_resource_inventory +- [ ] list_tags_for_resource +- [ ] list_usage_for_license_configuration +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_license_configuration +- [ ] update_license_specifications_for_resource +- [ ] update_service_settings + +## lightsail +0% implemented - [ ] allocate_static_ip - [ ] attach_disk - [ ] attach_instances_to_load_balancer - [ ] attach_load_balancer_tls_certificate - [ ] attach_static_ip - [ ] close_instance_public_ports +- [ ] copy_snapshot +- [ ] create_cloud_formation_stack - [ ] create_disk - [ ] create_disk_from_snapshot - [ ] create_disk_snapshot @@ -2718,6 +3969,9 @@ - [ ] create_key_pair - [ ] create_load_balancer - [ ] create_load_balancer_tls_certificate +- [ ] create_relational_database +- [ ] create_relational_database_from_snapshot +- [ ] create_relational_database_snapshot - [ ] delete_disk - [ ] delete_disk_snapshot - [ ] delete_domain @@ -2725,21 +3979,27 @@ - [ ] delete_instance - [ ] delete_instance_snapshot - [ ] delete_key_pair +- [ ] delete_known_host_keys - [ ] delete_load_balancer - [ ] delete_load_balancer_tls_certificate +- [ ] delete_relational_database +- [ ] delete_relational_database_snapshot - [ ] detach_disk - [ ] detach_instances_from_load_balancer - [ ] detach_static_ip - [ ] download_default_key_pair +- [ ] export_snapshot - [ ] get_active_names - [ ] get_blueprints - [ ] get_bundles +- [ ] get_cloud_formation_stack_records - [ ] get_disk - [ ] get_disk_snapshot - [ ] get_disk_snapshots - [ ] get_disks - [ ] get_domain - [ ] get_domains +- [ ] get_export_snapshot_records - [ ] get_instance - [ ] get_instance_access_details - [ ] get_instance_metric_data @@ -2758,6 +4018,18 @@ - [ ] get_operations - [ ] get_operations_for_resource - [ ] get_regions +- [ ] get_relational_database +- [ ] get_relational_database_blueprints +- [ ] get_relational_database_bundles +- [ ] get_relational_database_events +- [ ] get_relational_database_log_events +- [ ] get_relational_database_log_streams +- [ ] get_relational_database_master_user_password +- [ ] get_relational_database_metric_data +- [ ] get_relational_database_parameters +- [ ] get_relational_database_snapshot +- [ ] get_relational_database_snapshots +- [ ] get_relational_databases - [ ] get_static_ip - [ ] get_static_ips - [ ] import_key_pair @@ -2766,14 +4038,22 @@ - [ ] peer_vpc - [ ] put_instance_public_ports - [ ] reboot_instance +- [ ] reboot_relational_database - [ ] release_static_ip - [ ] start_instance +- [ ] start_relational_database - [ ] stop_instance +- [ ] stop_relational_database +- [ ] tag_resource - [ ] unpeer_vpc +- [ ] untag_resource - [ ] update_domain_entry - [ ] update_load_balancer_attribute +- [ ] update_relational_database +- [ ] update_relational_database_parameters -## logs - 27% implemented +## logs +28% implemented - [ ] associate_kms_key - [ ] cancel_export_task - [ ] create_export_task @@ -2784,31 +4064,38 @@ - [X] delete_log_stream - [ ] delete_metric_filter - [ ] delete_resource_policy -- [ ] delete_retention_policy +- [X] delete_retention_policy - [ ] delete_subscription_filter - [ ] describe_destinations - [ ] describe_export_tasks - [X] describe_log_groups - [X] describe_log_streams - [ ] describe_metric_filters +- [ ] describe_queries - [ ] describe_resource_policies - [ ] describe_subscription_filters - [ ] disassociate_kms_key - [X] filter_log_events - [X] get_log_events +- [ ] get_log_group_fields +- [ ] get_log_record +- [ ] get_query_results - [ ] list_tags_log_group - [ ] put_destination - [ ] put_destination_policy - [X] put_log_events - [ ] put_metric_filter - [ ] put_resource_policy -- [ ] put_retention_policy +- [X] put_retention_policy - [ ] put_subscription_filter +- [ ] start_query +- [ ] stop_query - [ ] tag_log_group - [ ] test_metric_filter - [ ] untag_log_group -## machinelearning - 0% implemented +## machinelearning +0% implemented - [ ] add_tags - [ ] create_batch_prediction - [ ] create_data_source_from_rds @@ -2838,14 +4125,69 @@ - [ ] update_evaluation - [ ] update_ml_model -## marketplace-entitlement - 0% implemented +## macie +0% implemented +- [ ] associate_member_account +- [ ] associate_s3_resources +- [ ] disassociate_member_account +- [ ] disassociate_s3_resources +- [ ] list_member_accounts +- [ ] list_s3_resources +- [ ] update_s3_resources + +## managedblockchain +0% implemented +- [ ] create_member +- [ ] create_network +- [ ] create_node +- [ ] create_proposal +- [ ] delete_member +- [ ] delete_node +- [ ] get_member +- [ ] get_network +- [ ] get_node +- [ ] get_proposal +- [ ] list_invitations +- [ ] list_members +- [ ] list_networks +- [ ] list_nodes +- [ ] list_proposal_votes +- [ ] list_proposals +- [ ] reject_invitation +- [ ] vote_on_proposal + +## marketplace-entitlement +0% implemented - [ ] get_entitlements -## marketplacecommerceanalytics - 0% implemented +## marketplacecommerceanalytics +0% implemented - [ ] generate_data_set - [ ] start_support_data_export -## mediaconvert - 0% implemented +## mediaconnect +0% implemented +- [ ] add_flow_outputs +- [ ] create_flow +- [ ] delete_flow +- [ ] describe_flow +- [ ] grant_flow_entitlements +- [ ] list_entitlements +- [ ] list_flows +- [ ] list_tags_for_resource +- [ ] remove_flow_output +- [ ] revoke_flow_entitlement +- [ ] start_flow +- [ ] stop_flow +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_flow_entitlement +- [ ] update_flow_output +- [ ] update_flow_source + +## mediaconvert +0% implemented +- [ ] associate_certificate - [ ] cancel_job - [ ] create_job - [ ] create_job_template @@ -2855,6 +4197,7 @@ - [ ] delete_preset - [ ] delete_queue - [ ] describe_endpoints +- [ ] disassociate_certificate - [ ] get_job - [ ] get_job_template - [ ] get_preset @@ -2863,30 +4206,49 @@ - [ ] list_jobs - [ ] list_presets - [ ] list_queues +- [ ] list_tags_for_resource +- [ ] tag_resource +- [ ] untag_resource - [ ] update_job_template - [ ] update_preset - [ ] update_queue -## medialive - 0% implemented +## medialive +0% implemented +- [ ] batch_update_schedule - [ ] create_channel - [ ] create_input - [ ] create_input_security_group +- [ ] create_tags - [ ] delete_channel - [ ] delete_input - [ ] delete_input_security_group +- [ ] delete_reservation +- [ ] delete_schedule +- [ ] delete_tags - [ ] describe_channel - [ ] describe_input - [ ] describe_input_security_group +- [ ] describe_offering +- [ ] describe_reservation +- [ ] describe_schedule - [ ] list_channels - [ ] list_input_security_groups - [ ] list_inputs +- [ ] list_offerings +- [ ] list_reservations +- [ ] list_tags_for_resource +- [ ] purchase_offering - [ ] start_channel - [ ] stop_channel - [ ] update_channel +- [ ] update_channel_class - [ ] update_input - [ ] update_input_security_group +- [ ] update_reservation -## mediapackage - 0% implemented +## mediapackage +0% implemented - [ ] create_channel - [ ] create_origin_endpoint - [ ] delete_channel @@ -2895,35 +4257,77 @@ - [ ] describe_origin_endpoint - [ ] list_channels - [ ] list_origin_endpoints +- [ ] list_tags_for_resource - [ ] rotate_channel_credentials +- [ ] rotate_ingest_endpoint_credentials +- [ ] tag_resource +- [ ] untag_resource - [ ] update_channel - [ ] update_origin_endpoint -## mediastore - 0% implemented +## mediapackage-vod +0% implemented +- [ ] create_asset +- [ ] create_packaging_configuration +- [ ] create_packaging_group +- [ ] delete_asset +- [ ] delete_packaging_configuration +- [ ] delete_packaging_group +- [ ] describe_asset +- [ ] describe_packaging_configuration +- [ ] describe_packaging_group +- [ ] list_assets +- [ ] list_packaging_configurations +- [ ] list_packaging_groups + +## mediastore +0% implemented - [ ] create_container - [ ] delete_container - [ ] delete_container_policy - [ ] delete_cors_policy +- [ ] delete_lifecycle_policy - [ ] describe_container - [ ] get_container_policy - [ ] get_cors_policy +- [ ] get_lifecycle_policy - [ ] list_containers +- [ ] list_tags_for_resource - [ ] put_container_policy - [ ] put_cors_policy +- [ ] put_lifecycle_policy +- [ ] start_access_logging +- [ ] stop_access_logging +- [ ] tag_resource +- [ ] untag_resource -## mediastore-data - 0% implemented +## mediastore-data +0% implemented - [ ] delete_object - [ ] describe_object - [ ] get_object - [ ] list_items - [ ] put_object -## meteringmarketplace - 0% implemented +## mediatailor +0% implemented +- [ ] delete_playback_configuration +- [ ] get_playback_configuration +- [ ] list_playback_configurations +- [ ] list_tags_for_resource +- [ ] put_playback_configuration +- [ ] tag_resource +- [ ] untag_resource + +## meteringmarketplace +0% implemented - [ ] batch_meter_usage - [ ] meter_usage +- [ ] register_usage - [ ] resolve_customer -## mgh - 0% implemented +## mgh +0% implemented - [ ] associate_created_artifact - [ ] associate_discovered_resource - [ ] create_progress_update_stream @@ -2941,7 +4345,8 @@ - [ ] notify_migration_task_state - [ ] put_resource_attributes -## mobile - 0% implemented +## mobile +0% implemented - [ ] create_project - [ ] delete_project - [ ] describe_bundle @@ -2952,26 +4357,33 @@ - [ ] list_projects - [ ] update_project -## mq - 0% implemented +## mq +0% implemented - [ ] create_broker - [ ] create_configuration +- [ ] create_tags - [ ] create_user - [ ] delete_broker +- [ ] delete_tags - [ ] delete_user - [ ] describe_broker +- [ ] describe_broker_engine_types +- [ ] describe_broker_instance_options - [ ] describe_configuration - [ ] describe_configuration_revision - [ ] describe_user - [ ] list_brokers - [ ] list_configuration_revisions - [ ] list_configurations +- [ ] list_tags - [ ] list_users - [ ] reboot_broker - [ ] update_broker - [ ] update_configuration - [ ] update_user -## mturk - 0% implemented +## mturk +0% implemented - [ ] accept_qualification_request - [ ] approve_assignment - [ ] associate_qualification_with_worker @@ -3012,7 +4424,68 @@ - [ ] update_notification_settings - [ ] update_qualification_type -## opsworks - 12% implemented +## neptune +0% implemented +- [ ] add_role_to_db_cluster +- [ ] add_source_identifier_to_subscription +- [ ] add_tags_to_resource +- [ ] apply_pending_maintenance_action +- [ ] copy_db_cluster_parameter_group +- [ ] copy_db_cluster_snapshot +- [ ] copy_db_parameter_group +- [ ] create_db_cluster +- [ ] create_db_cluster_parameter_group +- [ ] create_db_cluster_snapshot +- [ ] create_db_instance +- [ ] create_db_parameter_group +- [ ] create_db_subnet_group +- [ ] create_event_subscription +- [ ] delete_db_cluster +- [ ] delete_db_cluster_parameter_group +- [ ] delete_db_cluster_snapshot +- [ ] delete_db_instance +- [ ] delete_db_parameter_group +- [ ] delete_db_subnet_group +- [ ] delete_event_subscription +- [ ] describe_db_cluster_parameter_groups +- [ ] describe_db_cluster_parameters +- [ ] describe_db_cluster_snapshot_attributes +- [ ] describe_db_cluster_snapshots +- [ ] describe_db_clusters +- [ ] describe_db_engine_versions +- [ ] describe_db_instances +- [ ] describe_db_parameter_groups +- [ ] describe_db_parameters +- [ ] describe_db_subnet_groups +- [ ] describe_engine_default_cluster_parameters +- [ ] describe_engine_default_parameters +- [ ] describe_event_categories +- [ ] describe_event_subscriptions +- [ ] describe_events +- [ ] describe_orderable_db_instance_options +- [ ] describe_pending_maintenance_actions +- [ ] describe_valid_db_instance_modifications +- [ ] failover_db_cluster +- [ ] list_tags_for_resource +- [ ] modify_db_cluster +- [ ] modify_db_cluster_parameter_group +- [ ] modify_db_cluster_snapshot_attribute +- [ ] modify_db_instance +- [ ] modify_db_parameter_group +- [ ] modify_db_subnet_group +- [ ] modify_event_subscription +- [ ] promote_read_replica_db_cluster +- [ ] reboot_db_instance +- [ ] remove_role_from_db_cluster +- [ ] remove_source_identifier_from_subscription +- [ ] remove_tags_from_resource +- [ ] reset_db_cluster_parameter_group +- [ ] reset_db_parameter_group +- [ ] restore_db_cluster_from_snapshot +- [ ] restore_db_cluster_to_point_in_time + +## opsworks +12% implemented - [ ] assign_instance - [ ] assign_volume - [ ] associate_elastic_ip @@ -3088,7 +4561,8 @@ - [ ] update_user_profile - [ ] update_volume -## opsworkscm - 0% implemented +## opsworkscm +0% implemented - [ ] associate_node - [ ] create_backup - [ ] create_server @@ -3100,16 +4574,19 @@ - [ ] describe_node_association_status - [ ] describe_servers - [ ] disassociate_node +- [ ] export_server_engine_attribute - [ ] restore_server - [ ] start_maintenance - [ ] update_server - [ ] update_server_engine_attributes -## organizations - 47% implemented +## organizations +41% implemented - [ ] accept_handshake - [X] attach_policy - [ ] cancel_handshake - [X] create_account +- [ ] create_gov_cloud_account - [X] create_organization - [X] create_organizational_unit - [X] create_policy @@ -3143,13 +4620,70 @@ - [X] list_policies - [X] list_policies_for_target - [X] list_roots +- [ ] list_tags_for_resource - [X] list_targets_for_policy - [X] move_account - [ ] remove_account_from_organization +- [ ] tag_resource +- [ ] untag_resource - [ ] update_organizational_unit - [ ] update_policy -## pinpoint - 0% implemented +## personalize +0% implemented +- [ ] create_campaign +- [ ] create_dataset +- [ ] create_dataset_group +- [ ] create_dataset_import_job +- [ ] create_event_tracker +- [ ] create_schema +- [ ] create_solution +- [ ] create_solution_version +- [ ] delete_campaign +- [ ] delete_dataset +- [ ] delete_dataset_group +- [ ] delete_event_tracker +- [ ] delete_schema +- [ ] delete_solution +- [ ] describe_algorithm +- [ ] describe_campaign +- [ ] describe_dataset +- [ ] describe_dataset_group +- [ ] describe_dataset_import_job +- [ ] describe_event_tracker +- [ ] describe_feature_transformation +- [ ] describe_recipe +- [ ] describe_schema +- [ ] describe_solution +- [ ] describe_solution_version +- [ ] get_solution_metrics +- [ ] list_campaigns +- [ ] list_dataset_groups +- [ ] list_dataset_import_jobs +- [ ] list_datasets +- [ ] list_event_trackers +- [ ] list_recipes +- [ ] list_schemas +- [ ] list_solution_versions +- [ ] list_solutions +- [ ] update_campaign + +## personalize-events +0% implemented +- [ ] put_events + +## personalize-runtime +0% implemented +- [ ] get_personalized_ranking +- [ ] get_recommendations + +## pi +0% implemented +- [ ] describe_dimension_keys +- [ ] get_resource_metrics + +## pinpoint +0% implemented - [ ] create_app - [ ] create_campaign - [ ] create_export_job @@ -3169,20 +4703,25 @@ - [ ] delete_gcm_channel - [ ] delete_segment - [ ] delete_sms_channel +- [ ] delete_user_endpoints +- [ ] delete_voice_channel - [ ] get_adm_channel - [ ] get_apns_channel - [ ] get_apns_sandbox_channel - [ ] get_apns_voip_channel - [ ] get_apns_voip_sandbox_channel - [ ] get_app +- [ ] get_application_date_range_kpi - [ ] get_application_settings - [ ] get_apps - [ ] get_baidu_channel - [ ] get_campaign - [ ] get_campaign_activities +- [ ] get_campaign_date_range_kpi - [ ] get_campaign_version - [ ] get_campaign_versions - [ ] get_campaigns +- [ ] get_channels - [ ] get_email_channel - [ ] get_endpoint - [ ] get_event_stream @@ -3198,9 +4737,17 @@ - [ ] get_segment_versions - [ ] get_segments - [ ] get_sms_channel +- [ ] get_user_endpoints +- [ ] get_voice_channel +- [ ] list_tags_for_resource +- [ ] phone_number_validate - [ ] put_event_stream +- [ ] put_events +- [ ] remove_attributes - [ ] send_messages - [ ] send_users_messages +- [ ] tag_resource +- [ ] untag_resource - [ ] update_adm_channel - [ ] update_apns_channel - [ ] update_apns_sandbox_channel @@ -3215,32 +4762,135 @@ - [ ] update_gcm_channel - [ ] update_segment - [ ] update_sms_channel +- [ ] update_voice_channel -## polly - 83% implemented +## pinpoint-email +0% implemented +- [ ] create_configuration_set +- [ ] create_configuration_set_event_destination +- [ ] create_dedicated_ip_pool +- [ ] create_deliverability_test_report +- [ ] create_email_identity +- [ ] delete_configuration_set +- [ ] delete_configuration_set_event_destination +- [ ] delete_dedicated_ip_pool +- [ ] delete_email_identity +- [ ] get_account +- [ ] get_blacklist_reports +- [ ] get_configuration_set +- [ ] get_configuration_set_event_destinations +- [ ] get_dedicated_ip +- [ ] get_dedicated_ips +- [ ] get_deliverability_dashboard_options +- [ ] get_deliverability_test_report +- [ ] get_domain_deliverability_campaign +- [ ] get_domain_statistics_report +- [ ] get_email_identity +- [ ] list_configuration_sets +- [ ] list_dedicated_ip_pools +- [ ] list_deliverability_test_reports +- [ ] list_domain_deliverability_campaigns +- [ ] list_email_identities +- [ ] list_tags_for_resource +- [ ] put_account_dedicated_ip_warmup_attributes +- [ ] put_account_sending_attributes +- [ ] put_configuration_set_delivery_options +- [ ] put_configuration_set_reputation_options +- [ ] put_configuration_set_sending_options +- [ ] put_configuration_set_tracking_options +- [ ] put_dedicated_ip_in_pool +- [ ] put_dedicated_ip_warmup_attributes +- [ ] put_deliverability_dashboard_option +- [ ] put_email_identity_dkim_attributes +- [ ] put_email_identity_feedback_attributes +- [ ] put_email_identity_mail_from_attributes +- [ ] send_email +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_configuration_set_event_destination + +## pinpoint-sms-voice +0% implemented +- [ ] create_configuration_set +- [ ] create_configuration_set_event_destination +- [ ] delete_configuration_set +- [ ] delete_configuration_set_event_destination +- [ ] get_configuration_set_event_destinations +- [ ] send_voice_message +- [ ] update_configuration_set_event_destination + +## polly +55% implemented - [X] delete_lexicon - [X] describe_voices - [X] get_lexicon +- [ ] get_speech_synthesis_task - [X] list_lexicons +- [ ] list_speech_synthesis_tasks - [X] put_lexicon +- [ ] start_speech_synthesis_task - [ ] synthesize_speech -## pricing - 0% implemented +## pricing +0% implemented - [ ] describe_services - [ ] get_attribute_values - [ ] get_products -## rds - 0% implemented +## quicksight +0% implemented +- [ ] create_group +- [ ] create_group_membership +- [ ] delete_group +- [ ] delete_group_membership +- [ ] delete_user +- [ ] delete_user_by_principal_id +- [ ] describe_group +- [ ] describe_user +- [ ] get_dashboard_embed_url +- [ ] list_group_memberships +- [ ] list_groups +- [ ] list_user_groups +- [ ] list_users +- [ ] register_user +- [ ] update_group +- [ ] update_user + +## ram +0% implemented +- [ ] accept_resource_share_invitation +- [ ] associate_resource_share +- [ ] create_resource_share +- [ ] delete_resource_share +- [ ] disassociate_resource_share +- [ ] enable_sharing_with_aws_organization +- [ ] get_resource_policies +- [ ] get_resource_share_associations +- [ ] get_resource_share_invitations +- [ ] get_resource_shares +- [ ] list_principals +- [ ] list_resources +- [ ] reject_resource_share_invitation +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_resource_share + +## rds +0% implemented - [ ] add_role_to_db_cluster +- [ ] add_role_to_db_instance - [ ] add_source_identifier_to_subscription - [ ] add_tags_to_resource - [ ] apply_pending_maintenance_action - [ ] authorize_db_security_group_ingress +- [ ] backtrack_db_cluster - [ ] copy_db_cluster_parameter_group - [ ] copy_db_cluster_snapshot - [ ] copy_db_parameter_group - [ ] copy_db_snapshot - [ ] copy_option_group - [ ] create_db_cluster +- [ ] create_db_cluster_endpoint - [ ] create_db_cluster_parameter_group - [ ] create_db_cluster_snapshot - [ ] create_db_instance @@ -3250,25 +4900,32 @@ - [ ] create_db_snapshot - [ ] create_db_subnet_group - [ ] create_event_subscription +- [ ] create_global_cluster - [ ] create_option_group - [ ] delete_db_cluster +- [ ] delete_db_cluster_endpoint - [ ] delete_db_cluster_parameter_group - [ ] delete_db_cluster_snapshot - [ ] delete_db_instance +- [ ] delete_db_instance_automated_backup - [ ] delete_db_parameter_group - [ ] delete_db_security_group - [ ] delete_db_snapshot - [ ] delete_db_subnet_group - [ ] delete_event_subscription +- [ ] delete_global_cluster - [ ] delete_option_group - [ ] describe_account_attributes - [ ] describe_certificates +- [ ] describe_db_cluster_backtracks +- [ ] describe_db_cluster_endpoints - [ ] describe_db_cluster_parameter_groups - [ ] describe_db_cluster_parameters - [ ] describe_db_cluster_snapshot_attributes - [ ] describe_db_cluster_snapshots - [ ] describe_db_clusters - [ ] describe_db_engine_versions +- [ ] describe_db_instance_automated_backups - [ ] describe_db_instances - [ ] describe_db_log_files - [ ] describe_db_parameter_groups @@ -3282,6 +4939,7 @@ - [ ] describe_event_categories - [ ] describe_event_subscriptions - [ ] describe_events +- [ ] describe_global_clusters - [ ] describe_option_group_options - [ ] describe_option_groups - [ ] describe_orderable_db_instance_options @@ -3293,7 +4951,9 @@ - [ ] download_db_log_file_portion - [ ] failover_db_cluster - [ ] list_tags_for_resource +- [ ] modify_current_db_cluster_capacity - [ ] modify_db_cluster +- [ ] modify_db_cluster_endpoint - [ ] modify_db_cluster_parameter_group - [ ] modify_db_cluster_snapshot_attribute - [ ] modify_db_instance @@ -3302,12 +4962,15 @@ - [ ] modify_db_snapshot_attribute - [ ] modify_db_subnet_group - [ ] modify_event_subscription +- [ ] modify_global_cluster - [ ] modify_option_group - [ ] promote_read_replica - [ ] promote_read_replica_db_cluster - [ ] purchase_reserved_db_instances_offering - [ ] reboot_db_instance +- [ ] remove_from_global_cluster - [ ] remove_role_from_db_cluster +- [ ] remove_role_from_db_instance - [ ] remove_source_identifier_from_subscription - [ ] remove_tags_from_resource - [ ] reset_db_cluster_parameter_group @@ -3319,12 +4982,30 @@ - [ ] restore_db_instance_from_s3 - [ ] restore_db_instance_to_point_in_time - [ ] revoke_db_security_group_ingress +- [ ] start_activity_stream +- [ ] start_db_cluster - [ ] start_db_instance +- [ ] stop_activity_stream +- [ ] stop_db_cluster - [ ] stop_db_instance -## redshift - 41% implemented +## rds-data +0% implemented +- [ ] batch_execute_statement +- [ ] begin_transaction +- [ ] commit_transaction +- [ ] execute_sql +- [ ] execute_statement +- [ ] rollback_transaction + +## redshift +32% implemented +- [ ] accept_reserved_node_exchange - [ ] authorize_cluster_security_group_ingress - [ ] authorize_snapshot_access +- [ ] batch_delete_cluster_snapshots +- [ ] batch_modify_cluster_snapshots +- [ ] cancel_resize - [ ] copy_cluster_snapshot - [X] create_cluster - [X] create_cluster_parameter_group @@ -3335,6 +5016,7 @@ - [ ] create_hsm_client_certificate - [ ] create_hsm_configuration - [X] create_snapshot_copy_grant +- [ ] create_snapshot_schedule - [X] create_tags - [X] delete_cluster - [X] delete_cluster_parameter_group @@ -3345,12 +5027,16 @@ - [ ] delete_hsm_client_certificate - [ ] delete_hsm_configuration - [X] delete_snapshot_copy_grant +- [ ] delete_snapshot_schedule - [X] delete_tags +- [ ] describe_account_attributes +- [ ] describe_cluster_db_revisions - [X] describe_cluster_parameter_groups - [ ] describe_cluster_parameters - [X] describe_cluster_security_groups - [X] describe_cluster_snapshots - [X] describe_cluster_subnet_groups +- [ ] describe_cluster_tracks - [ ] describe_cluster_versions - [X] describe_clusters - [ ] describe_default_cluster_parameters @@ -3365,6 +5051,8 @@ - [ ] describe_reserved_nodes - [ ] describe_resize - [X] describe_snapshot_copy_grants +- [ ] describe_snapshot_schedules +- [ ] describe_storage - [ ] describe_table_restore_status - [X] describe_tags - [ ] disable_logging @@ -3372,28 +5060,37 @@ - [ ] enable_logging - [X] enable_snapshot_copy - [ ] get_cluster_credentials +- [ ] get_reserved_node_exchange_offerings - [X] modify_cluster +- [ ] modify_cluster_db_revision - [ ] modify_cluster_iam_roles +- [ ] modify_cluster_maintenance - [ ] modify_cluster_parameter_group +- [ ] modify_cluster_snapshot +- [ ] modify_cluster_snapshot_schedule - [ ] modify_cluster_subnet_group - [ ] modify_event_subscription - [X] modify_snapshot_copy_retention_period +- [ ] modify_snapshot_schedule - [ ] purchase_reserved_node_offering - [ ] reboot_cluster - [ ] reset_cluster_parameter_group +- [ ] resize_cluster - [X] restore_from_cluster_snapshot - [ ] restore_table_from_cluster_snapshot - [ ] revoke_cluster_security_group_ingress - [ ] revoke_snapshot_access - [ ] rotate_encryption_key -## rekognition - 0% implemented +## rekognition +0% implemented - [ ] compare_faces - [ ] create_collection - [ ] create_stream_processor - [ ] delete_collection - [ ] delete_faces - [ ] delete_stream_processor +- [ ] describe_collection - [ ] describe_stream_processor - [ ] detect_faces - [ ] detect_labels @@ -3422,28 +5119,70 @@ - [ ] start_stream_processor - [ ] stop_stream_processor -## resource-groups - 62% implemented +## resource-groups +75% implemented - [X] create_group - [X] delete_group - [X] get_group -- [X] get_group_query -- [ ] get_tags +- [ ] get_group_query +- [X] get_tags - [ ] list_group_resources - [X] list_groups - [ ] search_resources -- [ ] tag -- [ ] untag +- [X] tag +- [X] untag - [X] update_group - [X] update_group_query -## resourcegroupstaggingapi - 60% implemented +## resourcegroupstaggingapi +60% implemented - [X] get_resources - [X] get_tag_keys - [X] get_tag_values - [ ] tag_resources - [ ] untag_resources -## route53 - 12% implemented +## robomaker +0% implemented +- [ ] batch_describe_simulation_job +- [ ] cancel_deployment_job +- [ ] cancel_simulation_job +- [ ] create_deployment_job +- [ ] create_fleet +- [ ] create_robot +- [ ] create_robot_application +- [ ] create_robot_application_version +- [ ] create_simulation_application +- [ ] create_simulation_application_version +- [ ] create_simulation_job +- [ ] delete_fleet +- [ ] delete_robot +- [ ] delete_robot_application +- [ ] delete_simulation_application +- [ ] deregister_robot +- [ ] describe_deployment_job +- [ ] describe_fleet +- [ ] describe_robot +- [ ] describe_robot_application +- [ ] describe_simulation_application +- [ ] describe_simulation_job +- [ ] list_deployment_jobs +- [ ] list_fleets +- [ ] list_robot_applications +- [ ] list_robots +- [ ] list_simulation_applications +- [ ] list_simulation_jobs +- [ ] list_tags_for_resource +- [ ] register_robot +- [ ] restart_simulation_job +- [ ] sync_deployment_job +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_robot_application +- [ ] update_simulation_application + +## route53 +12% implemented - [ ] associate_vpc_with_hosted_zone - [ ] change_resource_record_sets - [X] change_tags_for_resource @@ -3501,7 +5240,8 @@ - [ ] update_traffic_policy_comment - [ ] update_traffic_policy_instance -## route53domains - 0% implemented +## route53domains +0% implemented - [ ] check_domain_availability - [ ] check_domain_transferability - [ ] delete_tags_for_domain @@ -3527,7 +5267,33 @@ - [ ] update_tags_for_domain - [ ] view_billing -## s3 - 15% implemented +## route53resolver +0% implemented +- [ ] associate_resolver_endpoint_ip_address +- [ ] associate_resolver_rule +- [ ] create_resolver_endpoint +- [ ] create_resolver_rule +- [ ] delete_resolver_endpoint +- [ ] delete_resolver_rule +- [ ] disassociate_resolver_endpoint_ip_address +- [ ] disassociate_resolver_rule +- [ ] get_resolver_endpoint +- [ ] get_resolver_rule +- [ ] get_resolver_rule_association +- [ ] get_resolver_rule_policy +- [ ] list_resolver_endpoint_ip_addresses +- [ ] list_resolver_endpoints +- [ ] list_resolver_rule_associations +- [ ] list_resolver_rules +- [ ] list_tags_for_resource +- [ ] put_resolver_rule_policy +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_resolver_endpoint +- [ ] update_resolver_rule + +## s3 +14% implemented - [ ] abort_multipart_upload - [ ] complete_multipart_upload - [ ] copy_object @@ -3547,7 +5313,8 @@ - [ ] delete_object - [ ] delete_object_tagging - [ ] delete_objects -- [X] get_bucket_accelerate_configuration +- [ ] delete_public_access_block +- [ ] get_bucket_accelerate_configuration - [X] get_bucket_acl - [ ] get_bucket_analytics_configuration - [ ] get_bucket_cors @@ -3555,12 +5322,13 @@ - [ ] get_bucket_inventory_configuration - [ ] get_bucket_lifecycle - [ ] get_bucket_lifecycle_configuration -- [X] get_bucket_location +- [ ] get_bucket_location - [ ] get_bucket_logging - [ ] get_bucket_metrics_configuration - [ ] get_bucket_notification - [ ] get_bucket_notification_configuration - [X] get_bucket_policy +- [ ] get_bucket_policy_status - [ ] get_bucket_replication - [ ] get_bucket_request_payment - [ ] get_bucket_tagging @@ -3568,8 +5336,12 @@ - [ ] get_bucket_website - [ ] get_object - [ ] get_object_acl +- [ ] get_object_legal_hold +- [ ] get_object_lock_configuration +- [ ] get_object_retention - [ ] get_object_tagging - [ ] get_object_torrent +- [ ] get_public_access_block - [ ] head_bucket - [ ] head_object - [ ] list_bucket_analytics_configurations @@ -3601,52 +5373,111 @@ - [ ] put_bucket_website - [ ] put_object - [ ] put_object_acl +- [ ] put_object_legal_hold +- [ ] put_object_lock_configuration +- [ ] put_object_retention - [ ] put_object_tagging +- [ ] put_public_access_block - [ ] restore_object - [ ] select_object_content - [ ] upload_part - [ ] upload_part_copy -## sagemaker - 0% implemented +## s3control +0% implemented +- [ ] create_job +- [ ] delete_public_access_block +- [ ] describe_job +- [ ] get_public_access_block +- [ ] list_jobs +- [ ] put_public_access_block +- [ ] update_job_priority +- [ ] update_job_status + +## sagemaker +0% implemented - [ ] add_tags +- [ ] create_algorithm +- [ ] create_code_repository +- [ ] create_compilation_job - [ ] create_endpoint - [ ] create_endpoint_config +- [ ] create_hyper_parameter_tuning_job +- [ ] create_labeling_job - [ ] create_model +- [ ] create_model_package - [ ] create_notebook_instance - [ ] create_notebook_instance_lifecycle_config - [ ] create_presigned_notebook_instance_url - [ ] create_training_job +- [ ] create_transform_job +- [ ] create_workteam +- [ ] delete_algorithm +- [ ] delete_code_repository - [ ] delete_endpoint - [ ] delete_endpoint_config - [ ] delete_model +- [ ] delete_model_package - [ ] delete_notebook_instance - [ ] delete_notebook_instance_lifecycle_config - [ ] delete_tags +- [ ] delete_workteam +- [ ] describe_algorithm +- [ ] describe_code_repository +- [ ] describe_compilation_job - [ ] describe_endpoint - [ ] describe_endpoint_config +- [ ] describe_hyper_parameter_tuning_job +- [ ] describe_labeling_job - [ ] describe_model +- [ ] describe_model_package - [ ] describe_notebook_instance - [ ] describe_notebook_instance_lifecycle_config +- [ ] describe_subscribed_workteam - [ ] describe_training_job +- [ ] describe_transform_job +- [ ] describe_workteam +- [ ] get_search_suggestions +- [ ] list_algorithms +- [ ] list_code_repositories +- [ ] list_compilation_jobs - [ ] list_endpoint_configs - [ ] list_endpoints +- [ ] list_hyper_parameter_tuning_jobs +- [ ] list_labeling_jobs +- [ ] list_labeling_jobs_for_workteam +- [ ] list_model_packages - [ ] list_models - [ ] list_notebook_instance_lifecycle_configs - [ ] list_notebook_instances +- [ ] list_subscribed_workteams - [ ] list_tags - [ ] list_training_jobs +- [ ] list_training_jobs_for_hyper_parameter_tuning_job +- [ ] list_transform_jobs +- [ ] list_workteams +- [ ] render_ui_template +- [ ] search - [ ] start_notebook_instance +- [ ] stop_compilation_job +- [ ] stop_hyper_parameter_tuning_job +- [ ] stop_labeling_job - [ ] stop_notebook_instance - [ ] stop_training_job +- [ ] stop_transform_job +- [ ] update_code_repository - [ ] update_endpoint - [ ] update_endpoint_weights_and_capacities - [ ] update_notebook_instance - [ ] update_notebook_instance_lifecycle_config +- [ ] update_workteam -## sagemaker-runtime - 0% implemented +## sagemaker-runtime +0% implemented - [ ] invoke_endpoint -## sdb - 0% implemented +## sdb +0% implemented - [ ] batch_delete_attributes - [ ] batch_put_attributes - [ ] create_domain @@ -3658,15 +5489,19 @@ - [ ] put_attributes - [ ] select -## secretsmanager - 33% implemented +## secretsmanager +55% implemented - [ ] cancel_rotate_secret - [X] create_secret +- [ ] delete_resource_policy - [X] delete_secret - [X] describe_secret - [X] get_random_password +- [ ] get_resource_policy - [X] get_secret_value - [X] list_secret_version_ids - [X] list_secrets +- [ ] put_resource_policy - [X] put_secret_value - [X] restore_secret - [X] rotate_secret @@ -3675,23 +5510,92 @@ - [ ] update_secret - [ ] update_secret_version_stage -## serverlessrepo - 0% implemented +## securityhub +0% implemented +- [ ] accept_invitation +- [ ] batch_disable_standards +- [ ] batch_enable_standards +- [ ] batch_import_findings +- [ ] create_action_target +- [ ] create_insight +- [ ] create_members +- [ ] decline_invitations +- [ ] delete_action_target +- [ ] delete_insight +- [ ] delete_invitations +- [ ] delete_members +- [ ] describe_action_targets +- [ ] describe_hub +- [ ] describe_products +- [ ] disable_import_findings_for_product +- [ ] disable_security_hub +- [ ] disassociate_from_master_account +- [ ] disassociate_members +- [ ] enable_import_findings_for_product +- [ ] enable_security_hub +- [ ] get_enabled_standards +- [ ] get_findings +- [ ] get_insight_results +- [ ] get_insights +- [ ] get_invitations_count +- [ ] get_master_account +- [ ] get_members +- [ ] invite_members +- [ ] list_enabled_products_for_import +- [ ] list_invitations +- [ ] list_members +- [ ] list_tags_for_resource +- [ ] tag_resource +- [ ] untag_resource +- [ ] update_action_target +- [ ] update_findings +- [ ] update_insight + +## serverlessrepo +0% implemented - [ ] create_application - [ ] create_application_version - [ ] create_cloud_formation_change_set +- [ ] create_cloud_formation_template - [ ] delete_application - [ ] get_application - [ ] get_application_policy +- [ ] get_cloud_formation_template +- [ ] list_application_dependencies - [ ] list_application_versions - [ ] list_applications - [ ] put_application_policy - [ ] update_application -## servicecatalog - 0% implemented +## service-quotas +0% implemented +- [ ] associate_service_quota_template +- [ ] delete_service_quota_increase_request_from_template +- [ ] disassociate_service_quota_template +- [ ] get_association_for_service_quota_template +- [ ] get_aws_default_service_quota +- [ ] get_requested_service_quota_change +- [ ] get_service_quota +- [ ] get_service_quota_increase_request_from_template +- [ ] list_aws_default_service_quotas +- [ ] list_requested_service_quota_change_history +- [ ] list_requested_service_quota_change_history_by_quota +- [ ] list_service_quota_increase_requests_in_template +- [ ] list_service_quotas +- [ ] list_services +- [ ] put_service_quota_increase_request_into_template +- [ ] request_service_quota_increase + +## servicecatalog +0% implemented - [ ] accept_portfolio_share +- [ ] associate_budget_with_resource - [ ] associate_principal_with_portfolio - [ ] associate_product_with_portfolio +- [ ] associate_service_action_with_provisioning_artifact - [ ] associate_tag_option_with_resource +- [ ] batch_associate_service_action_with_provisioning_artifact +- [ ] batch_disassociate_service_action_from_provisioning_artifact - [ ] copy_product - [ ] create_constraint - [ ] create_portfolio @@ -3699,6 +5603,7 @@ - [ ] create_product - [ ] create_provisioned_product_plan - [ ] create_provisioning_artifact +- [ ] create_service_action - [ ] create_tag_option - [ ] delete_constraint - [ ] delete_portfolio @@ -3706,10 +5611,12 @@ - [ ] delete_product - [ ] delete_provisioned_product_plan - [ ] delete_provisioning_artifact +- [ ] delete_service_action - [ ] delete_tag_option - [ ] describe_constraint - [ ] describe_copy_product_status - [ ] describe_portfolio +- [ ] describe_portfolio_share_status - [ ] describe_product - [ ] describe_product_as_admin - [ ] describe_product_view @@ -3718,22 +5625,36 @@ - [ ] describe_provisioning_artifact - [ ] describe_provisioning_parameters - [ ] describe_record +- [ ] describe_service_action +- [ ] describe_service_action_execution_parameters - [ ] describe_tag_option +- [ ] disable_aws_organizations_access +- [ ] disassociate_budget_from_resource - [ ] disassociate_principal_from_portfolio - [ ] disassociate_product_from_portfolio +- [ ] disassociate_service_action_from_provisioning_artifact - [ ] disassociate_tag_option_from_resource +- [ ] enable_aws_organizations_access - [ ] execute_provisioned_product_plan +- [ ] execute_provisioned_product_service_action +- [ ] get_aws_organizations_access_status - [ ] list_accepted_portfolio_shares +- [ ] list_budgets_for_resource - [ ] list_constraints_for_portfolio - [ ] list_launch_paths +- [ ] list_organization_portfolio_access - [ ] list_portfolio_access - [ ] list_portfolios - [ ] list_portfolios_for_product - [ ] list_principals_for_portfolio - [ ] list_provisioned_product_plans - [ ] list_provisioning_artifacts +- [ ] list_provisioning_artifacts_for_service_action - [ ] list_record_history - [ ] list_resources_for_tag_option +- [ ] list_service_actions +- [ ] list_service_actions_for_provisioning_artifact +- [ ] list_stack_instances_for_provisioned_product - [ ] list_tag_options - [ ] provision_product - [ ] reject_portfolio_share @@ -3746,16 +5667,21 @@ - [ ] update_portfolio - [ ] update_product - [ ] update_provisioned_product +- [ ] update_provisioned_product_properties - [ ] update_provisioning_artifact +- [ ] update_service_action - [ ] update_tag_option -## servicediscovery - 0% implemented +## servicediscovery +0% implemented +- [ ] create_http_namespace - [ ] create_private_dns_namespace - [ ] create_public_dns_namespace - [ ] create_service - [ ] delete_namespace - [ ] delete_service - [ ] deregister_instance +- [ ] discover_instances - [ ] get_instance - [ ] get_instances_health_status - [ ] get_namespace @@ -3769,7 +5695,8 @@ - [ ] update_instance_custom_health_status - [ ] update_service -## ses - 11% implemented +## ses +12% implemented - [ ] clone_receipt_rule_set - [ ] create_configuration_set - [ ] create_configuration_set_event_destination @@ -3812,6 +5739,7 @@ - [ ] list_receipt_rule_sets - [ ] list_templates - [X] list_verified_email_addresses +- [ ] put_configuration_set_delivery_options - [ ] put_identity_policy - [ ] reorder_receipt_rule_set - [ ] send_bounce @@ -3825,7 +5753,7 @@ - [ ] set_identity_feedback_forwarding_enabled - [ ] set_identity_headers_in_notifications_enabled - [ ] set_identity_mail_from_domain -- [ ] set_identity_notification_topic +- [X] set_identity_notification_topic - [ ] set_receipt_rule_position - [ ] test_render_template - [ ] update_account_sending_enabled @@ -3841,32 +5769,83 @@ - [X] verify_email_address - [X] verify_email_identity -## shield - 0% implemented +## shield +0% implemented +- [ ] associate_drt_log_bucket +- [ ] associate_drt_role - [ ] create_protection - [ ] create_subscription - [ ] delete_protection - [ ] delete_subscription - [ ] describe_attack +- [ ] describe_drt_access +- [ ] describe_emergency_contact_settings - [ ] describe_protection - [ ] describe_subscription +- [ ] disassociate_drt_log_bucket +- [ ] disassociate_drt_role - [ ] get_subscription_state - [ ] list_attacks - [ ] list_protections +- [ ] update_emergency_contact_settings +- [ ] update_subscription -## sms - 0% implemented +## signer +0% implemented +- [ ] cancel_signing_profile +- [ ] describe_signing_job +- [ ] get_signing_platform +- [ ] get_signing_profile +- [ ] list_signing_jobs +- [ ] list_signing_platforms +- [ ] list_signing_profiles +- [ ] put_signing_profile +- [ ] start_signing_job + +## sms +0% implemented +- [ ] create_app - [ ] create_replication_job +- [ ] delete_app +- [ ] delete_app_launch_configuration +- [ ] delete_app_replication_configuration - [ ] delete_replication_job - [ ] delete_server_catalog - [ ] disassociate_connector +- [ ] generate_change_set +- [ ] generate_template +- [ ] get_app +- [ ] get_app_launch_configuration +- [ ] get_app_replication_configuration - [ ] get_connectors - [ ] get_replication_jobs - [ ] get_replication_runs - [ ] get_servers - [ ] import_server_catalog +- [ ] launch_app +- [ ] list_apps +- [ ] put_app_launch_configuration +- [ ] put_app_replication_configuration +- [ ] start_app_replication - [ ] start_on_demand_replication_run +- [ ] stop_app_replication +- [ ] terminate_app +- [ ] update_app - [ ] update_replication_job -## snowball - 0% implemented +## sms-voice +0% implemented +- [ ] create_configuration_set +- [ ] create_configuration_set_event_destination +- [ ] delete_configuration_set +- [ ] delete_configuration_set_event_destination +- [ ] get_configuration_set_event_destinations +- [ ] list_configuration_sets +- [ ] send_voice_message +- [ ] update_configuration_set_event_destination + +## snowball +0% implemented - [ ] cancel_cluster - [ ] cancel_job - [ ] create_address @@ -3881,11 +5860,13 @@ - [ ] get_snowball_usage - [ ] list_cluster_jobs - [ ] list_clusters +- [ ] list_compatible_images - [ ] list_jobs - [ ] update_cluster - [ ] update_job -## sns - 53% implemented +## sns +48% implemented - [ ] add_permission - [ ] check_if_phone_number_is_opted_out - [ ] confirm_subscription @@ -3905,6 +5886,7 @@ - [X] list_platform_applications - [X] list_subscriptions - [ ] list_subscriptions_by_topic +- [ ] list_tags_for_resource - [X] list_topics - [ ] opt_in_phone_number - [X] publish @@ -3915,9 +5897,12 @@ - [X] set_subscription_attributes - [ ] set_topic_attributes - [X] subscribe +- [ ] tag_resource - [X] unsubscribe +- [ ] untag_resource -## sqs - 65% implemented +## sqs +65% implemented - [X] add_permission - [X] change_message_visibility - [ ] change_message_visibility_batch @@ -3926,7 +5911,7 @@ - [ ] delete_message_batch - [X] delete_queue - [ ] get_queue_attributes -- [X] get_queue_url +- [ ] get_queue_url - [X] list_dead_letter_source_queues - [ ] list_queue_tags - [X] list_queues @@ -3939,19 +5924,23 @@ - [X] tag_queue - [X] untag_queue -## ssm - 11% implemented +## ssm +10% implemented - [X] add_tags_to_resource - [ ] cancel_command +- [ ] cancel_maintenance_window_execution - [ ] create_activation - [ ] create_association - [ ] create_association_batch - [ ] create_document - [ ] create_maintenance_window +- [ ] create_ops_item - [ ] create_patch_baseline - [ ] create_resource_data_sync - [ ] delete_activation - [ ] delete_association - [ ] delete_document +- [ ] delete_inventory - [ ] delete_maintenance_window - [X] delete_parameter - [X] delete_parameters @@ -3963,6 +5952,8 @@ - [ ] deregister_task_from_maintenance_window - [ ] describe_activations - [ ] describe_association +- [ ] describe_association_execution_targets +- [ ] describe_association_executions - [ ] describe_automation_executions - [ ] describe_automation_step_executions - [ ] describe_available_patches @@ -3975,18 +5966,25 @@ - [ ] describe_instance_patch_states - [ ] describe_instance_patch_states_for_patch_group - [ ] describe_instance_patches +- [ ] describe_inventory_deletions - [ ] describe_maintenance_window_execution_task_invocations - [ ] describe_maintenance_window_execution_tasks - [ ] describe_maintenance_window_executions +- [ ] describe_maintenance_window_schedule - [ ] describe_maintenance_window_targets - [ ] describe_maintenance_window_tasks - [ ] describe_maintenance_windows +- [ ] describe_maintenance_windows_for_target +- [ ] describe_ops_items - [ ] describe_parameters - [ ] describe_patch_baselines - [ ] describe_patch_group_state - [ ] describe_patch_groups +- [ ] describe_patch_properties +- [ ] describe_sessions - [ ] get_automation_execution -- [ ] get_command_invocation +- [X] get_command_invocation +- [ ] get_connection_status - [ ] get_default_patch_baseline - [ ] get_deployable_patch_snapshot_for_instance - [ ] get_document @@ -3997,12 +5995,16 @@ - [ ] get_maintenance_window_execution_task - [ ] get_maintenance_window_execution_task_invocation - [ ] get_maintenance_window_task +- [ ] get_ops_item +- [ ] get_ops_summary - [X] get_parameter - [ ] get_parameter_history - [X] get_parameters - [X] get_parameters_by_path - [ ] get_patch_baseline - [ ] get_patch_baseline_for_patch_group +- [ ] get_service_setting +- [ ] label_parameter_version - [ ] list_association_versions - [ ] list_associations - [ ] list_command_invocations @@ -4024,10 +6026,15 @@ - [ ] register_target_with_maintenance_window - [ ] register_task_with_maintenance_window - [X] remove_tags_from_resource +- [ ] reset_service_setting +- [ ] resume_session - [ ] send_automation_signal - [X] send_command +- [ ] start_associations_once - [ ] start_automation_execution +- [ ] start_session - [ ] stop_automation_execution +- [ ] terminate_session - [ ] update_association - [ ] update_association_status - [ ] update_document @@ -4036,9 +6043,12 @@ - [ ] update_maintenance_window_target - [ ] update_maintenance_window_task - [ ] update_managed_instance_role +- [ ] update_ops_item - [ ] update_patch_baseline +- [ ] update_service_setting -## stepfunctions - 0% implemented +## stepfunctions +0% implemented - [ ] create_activity - [ ] create_state_machine - [ ] delete_activity @@ -4052,23 +6062,30 @@ - [ ] list_activities - [ ] list_executions - [ ] list_state_machines +- [ ] list_tags_for_resource - [ ] send_task_failure - [ ] send_task_heartbeat - [ ] send_task_success - [ ] start_execution - [ ] stop_execution +- [ ] tag_resource +- [ ] untag_resource - [ ] update_state_machine -## storagegateway - 0% implemented +## storagegateway +0% implemented - [ ] activate_gateway - [ ] add_cache - [ ] add_tags_to_resource - [ ] add_upload_buffer - [ ] add_working_storage +- [ ] assign_tape_pool +- [ ] attach_volume - [ ] cancel_archival - [ ] cancel_retrieval - [ ] create_cached_iscsi_volume - [ ] create_nfs_file_share +- [ ] create_smb_file_share - [ ] create_snapshot - [ ] create_snapshot_from_volume_recovery_point - [ ] create_stored_iscsi_volume @@ -4089,6 +6106,8 @@ - [ ] describe_gateway_information - [ ] describe_maintenance_start_time - [ ] describe_nfs_file_shares +- [ ] describe_smb_file_shares +- [ ] describe_smb_settings - [ ] describe_snapshot_schedule - [ ] describe_stored_iscsi_volumes - [ ] describe_tape_archives @@ -4097,7 +6116,9 @@ - [ ] describe_upload_buffer - [ ] describe_vtl_devices - [ ] describe_working_storage +- [ ] detach_volume - [ ] disable_gateway +- [ ] join_domain - [ ] list_file_shares - [ ] list_gateways - [ ] list_local_disks @@ -4113,6 +6134,7 @@ - [ ] retrieve_tape_archive - [ ] retrieve_tape_recovery_point - [ ] set_local_console_password +- [ ] set_smb_guest_password - [ ] shutdown_gateway - [ ] start_gateway - [ ] update_bandwidth_rate_limit @@ -4121,19 +6143,24 @@ - [ ] update_gateway_software_now - [ ] update_maintenance_start_time - [ ] update_nfs_file_share +- [ ] update_smb_file_share +- [ ] update_smb_security_strategy - [ ] update_snapshot_schedule - [ ] update_vtl_device_type -## sts - 42% implemented +## sts +50% implemented - [X] assume_role - [ ] assume_role_with_saml -- [ ] assume_role_with_web_identity +- [X] assume_role_with_web_identity - [ ] decode_authorization_message +- [ ] get_access_key_info - [ ] get_caller_identity - [X] get_federation_token - [X] get_session_token -## support - 0% implemented +## support +0% implemented - [ ] add_attachments_to_set - [ ] add_communication_to_case - [ ] create_case @@ -4149,7 +6176,8 @@ - [ ] refresh_trusted_advisor_check - [ ] resolve_case -## swf - 58% implemented +## swf +48% implemented - [ ] count_closed_workflow_executions - [ ] count_open_workflow_executions - [X] count_pending_activity_tasks @@ -4166,6 +6194,7 @@ - [X] list_closed_workflow_executions - [X] list_domains - [X] list_open_workflow_executions +- [ ] list_tags_for_resource - [ ] list_workflow_types - [X] poll_for_activity_task - [X] poll_for_decision_task @@ -4180,10 +6209,26 @@ - [X] respond_decision_task_completed - [X] signal_workflow_execution - [X] start_workflow_execution +- [ ] tag_resource - [X] terminate_workflow_execution +- [ ] undeprecate_activity_type +- [ ] undeprecate_domain +- [ ] undeprecate_workflow_type +- [ ] untag_resource -## transcribe - 0% implemented +## textract +0% implemented +- [ ] analyze_document +- [ ] detect_document_text +- [ ] get_document_analysis +- [ ] get_document_text_detection +- [ ] start_document_analysis +- [ ] start_document_text_detection + +## transcribe +0% implemented - [ ] create_vocabulary +- [ ] delete_transcription_job - [ ] delete_vocabulary - [ ] get_transcription_job - [ ] get_vocabulary @@ -4192,10 +6237,37 @@ - [ ] start_transcription_job - [ ] update_vocabulary -## translate - 0% implemented +## transfer +0% implemented +- [ ] create_server +- [ ] create_user +- [ ] delete_server +- [ ] delete_ssh_public_key +- [ ] delete_user +- [ ] describe_server +- [ ] describe_user +- [ ] import_ssh_public_key +- [ ] list_servers +- [ ] list_tags_for_resource +- [ ] list_users +- [ ] start_server +- [ ] stop_server +- [ ] tag_resource +- [ ] test_identity_provider +- [ ] untag_resource +- [ ] update_server +- [ ] update_user + +## translate +0% implemented +- [ ] delete_terminology +- [ ] get_terminology +- [ ] import_terminology +- [ ] list_terminologies - [ ] translate_text -## waf - 0% implemented +## waf +0% implemented - [ ] create_byte_match_set - [ ] create_geo_match_set - [ ] create_ip_set @@ -4211,6 +6283,7 @@ - [ ] delete_byte_match_set - [ ] delete_geo_match_set - [ ] delete_ip_set +- [ ] delete_logging_configuration - [ ] delete_permission_policy - [ ] delete_rate_based_rule - [ ] delete_regex_match_set @@ -4226,6 +6299,7 @@ - [ ] get_change_token_status - [ ] get_geo_match_set - [ ] get_ip_set +- [ ] get_logging_configuration - [ ] get_permission_policy - [ ] get_rate_based_rule - [ ] get_rate_based_rule_managed_keys @@ -4242,6 +6316,7 @@ - [ ] list_byte_match_sets - [ ] list_geo_match_sets - [ ] list_ip_sets +- [ ] list_logging_configurations - [ ] list_rate_based_rules - [ ] list_regex_match_sets - [ ] list_regex_pattern_sets @@ -4250,9 +6325,13 @@ - [ ] list_size_constraint_sets - [ ] list_sql_injection_match_sets - [ ] list_subscribed_rule_groups +- [ ] list_tags_for_resource - [ ] list_web_acls - [ ] list_xss_match_sets +- [ ] put_logging_configuration - [ ] put_permission_policy +- [ ] tag_resource +- [ ] untag_resource - [ ] update_byte_match_set - [ ] update_geo_match_set - [ ] update_ip_set @@ -4266,7 +6345,8 @@ - [ ] update_web_acl - [ ] update_xss_match_set -## waf-regional - 0% implemented +## waf-regional +0% implemented - [ ] associate_web_acl - [ ] create_byte_match_set - [ ] create_geo_match_set @@ -4283,6 +6363,7 @@ - [ ] delete_byte_match_set - [ ] delete_geo_match_set - [ ] delete_ip_set +- [ ] delete_logging_configuration - [ ] delete_permission_policy - [ ] delete_rate_based_rule - [ ] delete_regex_match_set @@ -4299,6 +6380,7 @@ - [ ] get_change_token_status - [ ] get_geo_match_set - [ ] get_ip_set +- [ ] get_logging_configuration - [ ] get_permission_policy - [ ] get_rate_based_rule - [ ] get_rate_based_rule_managed_keys @@ -4316,6 +6398,7 @@ - [ ] list_byte_match_sets - [ ] list_geo_match_sets - [ ] list_ip_sets +- [ ] list_logging_configurations - [ ] list_rate_based_rules - [ ] list_regex_match_sets - [ ] list_regex_pattern_sets @@ -4325,9 +6408,13 @@ - [ ] list_size_constraint_sets - [ ] list_sql_injection_match_sets - [ ] list_subscribed_rule_groups +- [ ] list_tags_for_resource - [ ] list_web_acls - [ ] list_xss_match_sets +- [ ] put_logging_configuration - [ ] put_permission_policy +- [ ] tag_resource +- [ ] untag_resource - [ ] update_byte_match_set - [ ] update_geo_match_set - [ ] update_ip_set @@ -4341,7 +6428,8 @@ - [ ] update_web_acl - [ ] update_xss_match_set -## workdocs - 0% implemented +## workdocs +0% implemented - [ ] abort_document_version_upload - [ ] activate_user - [ ] add_resource_permissions @@ -4375,6 +6463,7 @@ - [ ] get_document_version - [ ] get_folder - [ ] get_folder_path +- [ ] get_resources - [ ] initiate_document_version_upload - [ ] remove_all_resource_permissions - [ ] remove_resource_permission @@ -4383,7 +6472,41 @@ - [ ] update_folder - [ ] update_user -## workmail - 0% implemented +## worklink +0% implemented +- [ ] associate_domain +- [ ] associate_website_authorization_provider +- [ ] associate_website_certificate_authority +- [ ] create_fleet +- [ ] delete_fleet +- [ ] describe_audit_stream_configuration +- [ ] describe_company_network_configuration +- [ ] describe_device +- [ ] describe_device_policy_configuration +- [ ] describe_domain +- [ ] describe_fleet_metadata +- [ ] describe_identity_provider_configuration +- [ ] describe_website_certificate_authority +- [ ] disassociate_domain +- [ ] disassociate_website_authorization_provider +- [ ] disassociate_website_certificate_authority +- [ ] list_devices +- [ ] list_domains +- [ ] list_fleets +- [ ] list_website_authorization_providers +- [ ] list_website_certificate_authorities +- [ ] restore_domain_access +- [ ] revoke_domain_access +- [ ] sign_out_user +- [ ] update_audit_stream_configuration +- [ ] update_company_network_configuration +- [ ] update_device_policy_configuration +- [ ] update_domain_metadata +- [ ] update_fleet_metadata +- [ ] update_identity_provider_configuration + +## workmail +0% implemented - [ ] associate_delegate_to_resource - [ ] associate_member_to_group - [ ] create_alias @@ -4402,6 +6525,7 @@ - [ ] describe_user - [ ] disassociate_delegate_from_resource - [ ] disassociate_member_from_group +- [ ] get_mailbox_details - [ ] list_aliases - [ ] list_group_members - [ ] list_groups @@ -4413,29 +6537,65 @@ - [ ] put_mailbox_permissions - [ ] register_to_work_mail - [ ] reset_password +- [ ] update_mailbox_quota - [ ] update_primary_email_address - [ ] update_resource -## workspaces - 0% implemented +## workspaces +0% implemented +- [ ] associate_ip_groups +- [ ] authorize_ip_rules +- [ ] copy_workspace_image +- [ ] create_ip_group - [ ] create_tags - [ ] create_workspaces +- [ ] delete_ip_group - [ ] delete_tags +- [ ] delete_workspace_image +- [ ] describe_account +- [ ] describe_account_modifications +- [ ] describe_client_properties +- [ ] describe_ip_groups - [ ] describe_tags - [ ] describe_workspace_bundles - [ ] describe_workspace_directories +- [ ] describe_workspace_images - [ ] describe_workspaces - [ ] describe_workspaces_connection_status +- [ ] disassociate_ip_groups +- [ ] import_workspace_image +- [ ] list_available_management_cidr_ranges +- [ ] modify_account +- [ ] modify_client_properties - [ ] modify_workspace_properties +- [ ] modify_workspace_state - [ ] reboot_workspaces - [ ] rebuild_workspaces +- [ ] revoke_ip_rules - [ ] start_workspaces - [ ] stop_workspaces - [ ] terminate_workspaces +- [ ] update_rules_of_ip_group -## xray - 0% implemented +## xray +0% implemented - [ ] batch_get_traces +- [ ] create_group +- [ ] create_sampling_rule +- [ ] delete_group +- [ ] delete_sampling_rule +- [ ] get_encryption_config +- [ ] get_group +- [ ] get_groups +- [ ] get_sampling_rules +- [ ] get_sampling_statistic_summaries +- [ ] get_sampling_targets - [ ] get_service_graph +- [ ] get_time_series_service_statistics - [ ] get_trace_graph - [ ] get_trace_summaries +- [ ] put_encryption_config - [ ] put_telemetry_records - [ ] put_trace_segments +- [ ] update_group +- [ ] update_sampling_rule diff --git a/Makefile b/Makefile index de08c6f74..2a7249760 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ endif init: @python setup.py develop - @pip install -r requirements.txt + @pip install -r requirements-dev.txt lint: flake8 moto diff --git a/README.md b/README.md index 70faee2c8..4e39ada35 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ [![Build Status](https://travis-ci.org/spulec/moto.svg?branch=master)](https://travis-ci.org/spulec/moto) [![Coverage Status](https://coveralls.io/repos/spulec/moto/badge.svg?branch=master)](https://coveralls.io/r/spulec/moto) [![Docs](https://readthedocs.org/projects/pip/badge/?version=stable)](http://docs.getmoto.org) +![PyPI](https://img.shields.io/pypi/v/moto.svg) +![PyPI - Python Version](https://img.shields.io/pypi/pyversions/moto.svg) +![PyPI - Downloads](https://img.shields.io/pypi/dw/moto.svg) # In a nutshell @@ -55,95 +58,96 @@ With the decorator wrapping the test, all the calls to s3 are automatically mock It gets even better! Moto isn't just for Python code and it isn't just for S3. Look at the [standalone server mode](https://github.com/spulec/moto#stand-alone-server-mode) for more information about running Moto with other languages. Here's the status of the other AWS services implemented: ```gherkin -|------------------------------------------------------------------------------| -| Service Name | Decorator | Development Status | -|------------------------------------------------------------------------------| -| ACM | @mock_acm | all endpoints done | -|------------------------------------------------------------------------------| -| API Gateway | @mock_apigateway | core endpoints done | -|------------------------------------------------------------------------------| -| Autoscaling | @mock_autoscaling| core endpoints done | -|------------------------------------------------------------------------------| -| Cloudformation | @mock_cloudformation| core endpoints done | -|------------------------------------------------------------------------------| -| Cloudwatch | @mock_cloudwatch | basic endpoints done | -|------------------------------------------------------------------------------| -| CloudwatchEvents | @mock_events | all endpoints done | -|------------------------------------------------------------------------------| -| Cognito Identity | @mock_cognitoidentity| basic endpoints done | -|------------------------------------------------------------------------------| -| Cognito Identity Provider | @mock_cognitoidp| basic endpoints done | -|------------------------------------------------------------------------------| -| Config | @mock_config | basic endpoints done | -|------------------------------------------------------------------------------| -| Data Pipeline | @mock_datapipeline| basic endpoints done | -|------------------------------------------------------------------------------| -| DynamoDB | @mock_dynamodb | core endpoints done | -| DynamoDB2 | @mock_dynamodb2 | all endpoints + partial indexes | -|------------------------------------------------------------------------------| -| EC2 | @mock_ec2 | core endpoints done | -| - AMI | | core endpoints done | -| - EBS | | core endpoints done | -| - Instances | | all endpoints done | -| - Security Groups | | core endpoints done | -| - Tags | | all endpoints done | -|------------------------------------------------------------------------------| -| ECR | @mock_ecr | basic endpoints done | -|------------------------------------------------------------------------------| -| ECS | @mock_ecs | basic endpoints done | -|------------------------------------------------------------------------------| -| ELB | @mock_elb | core endpoints done | -|------------------------------------------------------------------------------| -| ELBv2 | @mock_elbv2 | all endpoints done | -|------------------------------------------------------------------------------| -| EMR | @mock_emr | core endpoints done | -|------------------------------------------------------------------------------| -| Glacier | @mock_glacier | core endpoints done | -|------------------------------------------------------------------------------| -| IAM | @mock_iam | core endpoints done | -|------------------------------------------------------------------------------| -| IoT | @mock_iot | core endpoints done | -| | @mock_iotdata | core endpoints done | -|------------------------------------------------------------------------------| -| Lambda | @mock_lambda | basic endpoints done, requires | -| | | docker | -|------------------------------------------------------------------------------| -| Logs | @mock_logs | basic endpoints done | -|------------------------------------------------------------------------------| -| Kinesis | @mock_kinesis | core endpoints done | -|------------------------------------------------------------------------------| -| KMS | @mock_kms | basic endpoints done | -|------------------------------------------------------------------------------| -| Organizations | @mock_organizations | some core endpoints done | -|------------------------------------------------------------------------------| -| Polly | @mock_polly | all endpoints done | -|------------------------------------------------------------------------------| -| RDS | @mock_rds | core endpoints done | -|------------------------------------------------------------------------------| -| RDS2 | @mock_rds2 | core endpoints done | -|------------------------------------------------------------------------------| -| Redshift | @mock_redshift | core endpoints done | -|------------------------------------------------------------------------------| -| Route53 | @mock_route53 | core endpoints done | -|------------------------------------------------------------------------------| -| S3 | @mock_s3 | core endpoints done | -|------------------------------------------------------------------------------| -| SecretsManager | @mock_secretsmanager | basic endpoints done -|------------------------------------------------------------------------------| -| SES | @mock_ses | all endpoints done | -|------------------------------------------------------------------------------| -| SNS | @mock_sns | all endpoints done | -|------------------------------------------------------------------------------| -| SQS | @mock_sqs | core endpoints done | -|------------------------------------------------------------------------------| -| SSM | @mock_ssm | core endpoints done | -|------------------------------------------------------------------------------| -| STS | @mock_sts | core endpoints done | -|------------------------------------------------------------------------------| -| SWF | @mock_swf | basic endpoints done | -|------------------------------------------------------------------------------| -| X-Ray | @mock_xray | all endpoints done | -|------------------------------------------------------------------------------| +|-------------------------------------------------------------------------------------| +| Service Name | Decorator | Development Status | +|-------------------------------------------------------------------------------------| +| ACM | @mock_acm | all endpoints done | +|-------------------------------------------------------------------------------------| +| API Gateway | @mock_apigateway | core endpoints done | +|-------------------------------------------------------------------------------------| +| Autoscaling | @mock_autoscaling | core endpoints done | +|-------------------------------------------------------------------------------------| +| Cloudformation | @mock_cloudformation | core endpoints done | +|-------------------------------------------------------------------------------------| +| Cloudwatch | @mock_cloudwatch | basic endpoints done | +|-------------------------------------------------------------------------------------| +| CloudwatchEvents | @mock_events | all endpoints done | +|-------------------------------------------------------------------------------------| +| Cognito Identity | @mock_cognitoidentity | basic endpoints done | +|-------------------------------------------------------------------------------------| +| Cognito Identity Provider | @mock_cognitoidp | basic endpoints done | +|-------------------------------------------------------------------------------------| +| Config | @mock_config | basic endpoints done | +| | | core endpoints done | +|-------------------------------------------------------------------------------------| +| Data Pipeline | @mock_datapipeline | basic endpoints done | +|-------------------------------------------------------------------------------------| +| DynamoDB | @mock_dynamodb | core endpoints done | +| DynamoDB2 | @mock_dynamodb2 | all endpoints + partial indexes | +|-------------------------------------------------------------------------------------| +| EC2 | @mock_ec2 | core endpoints done | +| - AMI | | core endpoints done | +| - EBS | | core endpoints done | +| - Instances | | all endpoints done | +| - Security Groups | | core endpoints done | +| - Tags | | all endpoints done | +|-------------------------------------------------------------------------------------| +| ECR | @mock_ecr | basic endpoints done | +|-------------------------------------------------------------------------------------| +| ECS | @mock_ecs | basic endpoints done | +|-------------------------------------------------------------------------------------| +| ELB | @mock_elb | core endpoints done | +|-------------------------------------------------------------------------------------| +| ELBv2 | @mock_elbv2 | all endpoints done | +|-------------------------------------------------------------------------------------| +| EMR | @mock_emr | core endpoints done | +|-------------------------------------------------------------------------------------| +| Glacier | @mock_glacier | core endpoints done | +|-------------------------------------------------------------------------------------| +| IAM | @mock_iam | core endpoints done | +|-------------------------------------------------------------------------------------| +| IoT | @mock_iot | core endpoints done | +| | @mock_iotdata | core endpoints done | +|-------------------------------------------------------------------------------------| +| Kinesis | @mock_kinesis | core endpoints done | +|-------------------------------------------------------------------------------------| +| KMS | @mock_kms | basic endpoints done | +|-------------------------------------------------------------------------------------| +| Lambda | @mock_lambda | basic endpoints done, requires | +| | | docker | +|-------------------------------------------------------------------------------------| +| Logs | @mock_logs | basic endpoints done | +|-------------------------------------------------------------------------------------| +| Organizations | @mock_organizations | some core endpoints done | +|-------------------------------------------------------------------------------------| +| Polly | @mock_polly | all endpoints done | +|-------------------------------------------------------------------------------------| +| RDS | @mock_rds | core endpoints done | +|-------------------------------------------------------------------------------------| +| RDS2 | @mock_rds2 | core endpoints done | +|-------------------------------------------------------------------------------------| +| Redshift | @mock_redshift | core endpoints done | +|-------------------------------------------------------------------------------------| +| Route53 | @mock_route53 | core endpoints done | +|-------------------------------------------------------------------------------------| +| S3 | @mock_s3 | core endpoints done | +|-------------------------------------------------------------------------------------| +| SecretsManager | @mock_secretsmanager | basic endpoints done | +|-------------------------------------------------------------------------------------| +| SES | @mock_ses | all endpoints done | +|-------------------------------------------------------------------------------------| +| SNS | @mock_sns | all endpoints done | +|-------------------------------------------------------------------------------------| +| SQS | @mock_sqs | core endpoints done | +|-------------------------------------------------------------------------------------| +| SSM | @mock_ssm | core endpoints done | +|-------------------------------------------------------------------------------------| +| STS | @mock_sts | core endpoints done | +|-------------------------------------------------------------------------------------| +| SWF | @mock_swf | basic endpoints done | +|-------------------------------------------------------------------------------------| +| X-Ray | @mock_xray | all endpoints done | +|-------------------------------------------------------------------------------------| ``` For a full list of endpoint [implementation coverage](https://github.com/spulec/moto/blob/master/IMPLEMENTATION_COVERAGE.md) @@ -252,6 +256,137 @@ def test_my_model_save(): mock.stop() ``` +## IAM-like Access Control + +Moto also has the ability to authenticate and authorize actions, just like it's done by IAM in AWS. This functionality can be enabled by either setting the `INITIAL_NO_AUTH_ACTION_COUNT` environment variable or using the `set_initial_no_auth_action_count` decorator. Note that the current implementation is very basic, see [this file](https://github.com/spulec/moto/blob/master/moto/core/access_control.py) for more information. + +### `INITIAL_NO_AUTH_ACTION_COUNT` + +If this environment variable is set, moto will skip performing any authentication as many times as the variable's value, and only starts authenticating requests afterwards. If it is not set, it defaults to infinity, thus moto will never perform any authentication at all. + +### `set_initial_no_auth_action_count` + +This is a decorator that works similarly to the environment variable, but the settings are only valid in the function's scope. When the function returns, everything is restored. + +```python +@set_initial_no_auth_action_count(4) +@mock_ec2 +def test_describe_instances_allowed(): + policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "ec2:Describe*", + "Resource": "*" + } + ] + } + access_key = ... + # create access key for an IAM user/assumed role that has the policy above. + # this part should call __exactly__ 4 AWS actions, so that authentication and authorization starts exactly after this + + client = boto3.client('ec2', region_name='us-east-1', + aws_access_key_id=access_key['AccessKeyId'], + aws_secret_access_key=access_key['SecretAccessKey']) + + # if the IAM principal whose access key is used, does not have the permission to describe instances, this will fail + instances = client.describe_instances()['Reservations'][0]['Instances'] + assert len(instances) == 0 +``` + +See [the related test suite](https://github.com/spulec/moto/blob/master/tests/test_core/test_auth.py) for more examples. + +## Very Important -- Recommended Usage +There are some important caveats to be aware of when using moto: + +*Failure to follow these guidelines could result in your tests mutating your __REAL__ infrastructure!* + +### How do I avoid tests from mutating my real infrastructure? +You need to ensure that the mocks are actually in place. Changes made to recent versions of `botocore` +have altered some of the mock behavior. In short, you need to ensure that you _always_ do the following: + +1. Ensure that your tests have dummy environment variables set up: + + export AWS_ACCESS_KEY_ID='testing' + export AWS_SECRET_ACCESS_KEY='testing' + export AWS_SECURITY_TOKEN='testing' + export AWS_SESSION_TOKEN='testing' + +1. __VERY IMPORTANT__: ensure that you have your mocks set up __BEFORE__ your `boto3` client is established. + This can typically happen if you import a module that has a `boto3` client instantiated outside of a function. + See the pesky imports section below on how to work around this. + +### Example on usage? +If you are a user of [pytest](https://pytest.org/en/latest/), you can leverage [pytest fixtures](https://pytest.org/en/latest/fixture.html#fixture) +to help set up your mocks and other AWS resources that you would need. + +Here is an example: +```python +@pytest.fixture(scope='function') +def aws_credentials(): + """Mocked AWS Credentials for moto.""" + os.environ['AWS_ACCESS_KEY_ID'] = 'testing' + os.environ['AWS_SECRET_ACCESS_KEY'] = 'testing' + os.environ['AWS_SECURITY_TOKEN'] = 'testing' + os.environ['AWS_SESSION_TOKEN'] = 'testing' + +@pytest.fixture(scope='function') +def s3(aws_credentials): + with mock_s3(): + yield boto3.client('s3', region_name='us-east-1') + + +@pytest.fixture(scope='function') +def sts(aws_credentials): + with mock_sts(): + yield boto3.client('sts', region_name='us-east-1') + + +@pytest.fixture(scope='function') +def cloudwatch(aws_credentials): + with mock_cloudwatch(): + yield boto3.client('cloudwatch', region_name='us-east-1') + +... etc. +``` + +In the code sample above, all of the AWS/mocked fixtures take in a parameter of `aws_credentials`, +which sets the proper fake environment variables. The fake environment variables are used so that `botocore` doesn't try to locate real +credentials on your system. + +Next, once you need to do anything with the mocked AWS environment, do something like: +```python +def test_create_bucket(s3): + # s3 is a fixture defined above that yields a boto3 s3 client. + # Feel free to instantiate another boto3 S3 client -- Keep note of the region though. + s3.create_bucket(Bucket="somebucket") + + result = s3.list_buckets() + assert len(result['Buckets']) == 1 + assert result['Buckets'][0]['Name'] == 'somebucket' +``` + +### What about those pesky imports? +Recall earlier, it was mentioned that mocks should be established __BEFORE__ the clients are set up. One way +to avoid import issues is to make use of local Python imports -- i.e. import the module inside of the unit +test you want to run vs. importing at the top of the file. + +Example: +```python +def test_something(s3): + from some.package.that.does.something.with.s3 import some_func # <-- Local import for unit test + # ^^ Importing here ensures that the mock has been established. + + sume_func() # The mock has been established from the "s3" pytest fixture, so this function that uses + # a package-level S3 client will properly use the mock and not reach out to AWS. +``` + +### Other caveats +For Tox, Travis CI, and other build systems, you might need to also perform a `touch ~/.aws/credentials` +command before running the tests. As long as that file is present (empty preferably) and the environment +variables above are set, you should be good to go. + ## Stand-alone Server Mode Moto also has a stand-alone server mode. This allows you to utilize @@ -318,3 +453,11 @@ boto3.resource( ```console $ pip install moto ``` + +## Releases + +Releases are done from travisci. Fairly closely following this: +https://docs.travis-ci.com/user/deployment/pypi/ + +- Commits to `master` branch do a dev deploy to pypi. +- Commits to a tag do a real deploy to pypi. diff --git a/docs/index.rst b/docs/index.rst index 66e12e4bd..4811fb797 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,66 +17,95 @@ with ``moto`` and its usage. Currently implemented Services: ------------------------------- -+-----------------------+---------------------+-----------------------------------+ -| Service Name | Decorator | Development Status | -+=======================+=====================+===================================+ -| API Gateway | @mock_apigateway | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Autoscaling | @mock_autoscaling | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Cloudformation | @mock_cloudformation| core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Cloudwatch | @mock_cloudwatch | basic endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Data Pipeline | @mock_datapipeline | basic endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| - DynamoDB | - @mock_dynamodb | - core endpoints done | -| - DynamoDB2 | - @mock_dynamodb2 | - core endpoints + partial indexes| -+-----------------------+---------------------+-----------------------------------+ -| EC2 | @mock_ec2 | core endpoints done | -| - AMI | | - core endpoints done | -| - EBS | | - core endpoints done | -| - Instances | | - all endpoints done | -| - Security Groups | | - core endpoints done | -| - Tags | | - all endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| ECS | @mock_ecs | basic endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| ELB | @mock_elb | core endpoints done | -| | @mock_elbv2 | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| EMR | @mock_emr | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Glacier | @mock_glacier | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| IAM | @mock_iam | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Lambda | @mock_lambda | basic endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Kinesis | @mock_kinesis | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| KMS | @mock_kms | basic endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| RDS | @mock_rds | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| RDS2 | @mock_rds2 | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Redshift | @mock_redshift | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| Route53 | @mock_route53 | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| S3 | @mock_s3 | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| SES | @mock_ses | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| SNS | @mock_sns | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| SQS | @mock_sqs | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| STS | @mock_sts | core endpoints done | -+-----------------------+---------------------+-----------------------------------+ -| SWF | @mock_swf | basic endpoints done | -+-----------------------+---------------------+-----------------------------------+ ++---------------------------+-----------------------+------------------------------------+ +| Service Name | Decorator | Development Status | ++===========================+=======================+====================================+ +| ACM | @mock_acm | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| API Gateway | @mock_apigateway | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Autoscaling | @mock_autoscaling | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Cloudformation | @mock_cloudformation | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Cloudwatch | @mock_cloudwatch | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| CloudwatchEvents | @mock_events | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Cognito Identity | @mock_cognitoidentity | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Cognito Identity Provider | @mock_cognitoidp | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Config | @mock_config | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Data Pipeline | @mock_datapipeline | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| DynamoDB | - @mock_dynamodb | - core endpoints done | +| DynamoDB2 | - @mock_dynamodb2 | - core endpoints + partial indexes | ++---------------------------+-----------------------+------------------------------------+ +| EC2 | @mock_ec2 | core endpoints done | +| - AMI | | - core endpoints done | +| - EBS | | - core endpoints done | +| - Instances | | - all endpoints done | +| - Security Groups | | - core endpoints done | +| - Tags | | - all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| ECR | @mock_ecr | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| ECS | @mock_ecs | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| ELB | @mock_elb | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| ELBv2 | @mock_elbv2 | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| EMR | @mock_emr | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Glacier | @mock_glacier | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| IAM | @mock_iam | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| IoT | @mock_iot | core endpoints done | +| | @mock_iotdata | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Kinesis | @mock_kinesis | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| KMS | @mock_kms | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Lambda | @mock_lambda | basic endpoints done, | +| | | requires docker | ++---------------------------+-----------------------+------------------------------------+ +| Logs | @mock_logs | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Organizations | @mock_organizations | some core edpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Polly | @mock_polly | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| RDS | @mock_rds | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| RDS2 | @mock_rds2 | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Redshift | @mock_redshift | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| Route53 | @mock_route53 | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| S3 | @mock_s3 | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| SecretsManager | @mock_secretsmanager | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| SES | @mock_ses | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| SNS | @mock_sns | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| SQS | @mock_sqs | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| SSM | @mock_ssm | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| STS | @mock_sts | core endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| SWF | @mock_swf | basic endpoints done | ++---------------------------+-----------------------+------------------------------------+ +| X-Ray | @mock_xray | all endpoints done | ++---------------------------+-----------------------+------------------------------------+ diff --git a/moto/__init__.py b/moto/__init__.py index 8c51bab27..8594cedd2 100644 --- a/moto/__init__.py +++ b/moto/__init__.py @@ -3,7 +3,7 @@ import logging # logging.getLogger('boto').setLevel(logging.CRITICAL) __title__ = 'moto' -__version__ = '1.3.8' +__version__ = '1.3.14.dev' from .acm import mock_acm # flake8: noqa from .apigateway import mock_apigateway, mock_apigateway_deprecated # flake8: noqa diff --git a/moto/acm/models.py b/moto/acm/models.py index 15a1bd44d..b25dbcdff 100644 --- a/moto/acm/models.py +++ b/moto/acm/models.py @@ -105,7 +105,7 @@ class CertBundle(BaseModel): self.arn = arn @classmethod - def generate_cert(cls, domain_name, sans=None): + def generate_cert(cls, domain_name, region, sans=None): if sans is None: sans = set() else: @@ -152,7 +152,7 @@ class CertBundle(BaseModel): encryption_algorithm=serialization.NoEncryption() ) - return cls(cert_armored, private_key, cert_type='AMAZON_ISSUED', cert_status='PENDING_VALIDATION') + return cls(cert_armored, private_key, cert_type='AMAZON_ISSUED', cert_status='PENDING_VALIDATION', region=region) def validate_pk(self): try: @@ -325,7 +325,7 @@ class AWSCertificateManagerBackend(BaseBackend): return bundle.arn - def get_certificates_list(self): + def get_certificates_list(self, statuses): """ Get list of certificates @@ -333,7 +333,9 @@ class AWSCertificateManagerBackend(BaseBackend): :rtype: list of CertBundle """ for arn in self._certificates.keys(): - yield self.get_certificate(arn) + cert = self.get_certificate(arn) + if not statuses or cert.status in statuses: + yield cert def get_certificate(self, arn): if arn not in self._certificates: @@ -355,7 +357,7 @@ class AWSCertificateManagerBackend(BaseBackend): if arn is not None: return arn - cert = CertBundle.generate_cert(domain_name, subject_alt_names) + cert = CertBundle.generate_cert(domain_name, region=self.region, sans=subject_alt_names) if idempotency_token is not None: self._set_idempotency_token_arn(idempotency_token, cert.arn) self._certificates[cert.arn] = cert diff --git a/moto/acm/responses.py b/moto/acm/responses.py index 38ebbaaa0..0d0ac640b 100644 --- a/moto/acm/responses.py +++ b/moto/acm/responses.py @@ -132,8 +132,8 @@ class AWSCertificateManagerResponse(BaseResponse): def list_certificates(self): certs = [] - - for cert_bundle in self.acm_backend.get_certificates_list(): + statuses = self._get_param('CertificateStatuses') + for cert_bundle in self.acm_backend.get_certificates_list(statuses): certs.append({ 'CertificateArn': cert_bundle.arn, 'DomainName': cert_bundle.common_name diff --git a/moto/apigateway/models.py b/moto/apigateway/models.py index 41a49e361..6be062d7f 100644 --- a/moto/apigateway/models.py +++ b/moto/apigateway/models.py @@ -309,6 +309,25 @@ class ApiKey(BaseModel, dict): self['createdDate'] = self['lastUpdatedDate'] = int(time.time()) self['stageKeys'] = stageKeys + def update_operations(self, patch_operations): + for op in patch_operations: + if op['op'] == 'replace': + if '/name' in op['path']: + self['name'] = op['value'] + elif '/customerId' in op['path']: + self['customerId'] = op['value'] + elif '/description' in op['path']: + self['description'] = op['value'] + elif '/enabled' in op['path']: + self['enabled'] = self._str2bool(op['value']) + else: + raise Exception( + 'Patch operation "%s" not implemented' % op['op']) + return self + + def _str2bool(self, v): + return v.lower() == "true" + class UsagePlan(BaseModel, dict): @@ -599,6 +618,10 @@ class APIGatewayBackend(BaseBackend): def get_apikey(self, api_key_id): return self.keys[api_key_id] + def update_apikey(self, api_key_id, patch_operations): + key = self.keys[api_key_id] + return key.update_operations(patch_operations) + def delete_apikey(self, api_key_id): self.keys.pop(api_key_id) return {} diff --git a/moto/apigateway/responses.py b/moto/apigateway/responses.py index bc4d262cd..fa82705b1 100644 --- a/moto/apigateway/responses.py +++ b/moto/apigateway/responses.py @@ -245,6 +245,9 @@ class APIGatewayResponse(BaseResponse): if self.method == 'GET': apikey_response = self.backend.get_apikey(apikey) + elif self.method == 'PATCH': + patch_operations = self._get_param('patchOperations') + apikey_response = self.backend.update_apikey(apikey, patch_operations) elif self.method == 'DELETE': apikey_response = self.backend.delete_apikey(apikey) return 200, {}, json.dumps(apikey_response) diff --git a/moto/apigateway/utils.py b/moto/apigateway/utils.py index 6d1e6ef19..31f8060b0 100644 --- a/moto/apigateway/utils.py +++ b/moto/apigateway/utils.py @@ -1,9 +1,10 @@ from __future__ import unicode_literals import six import random +import string def create_id(): size = 10 - chars = list(range(10)) + ['A-Z'] + chars = list(range(10)) + list(string.ascii_lowercase) return ''.join(six.text_type(random.choice(chars)) for x in range(size)) diff --git a/moto/autoscaling/exceptions.py b/moto/autoscaling/exceptions.py index 7dd81e0d6..74f62241d 100644 --- a/moto/autoscaling/exceptions.py +++ b/moto/autoscaling/exceptions.py @@ -13,3 +13,12 @@ class ResourceContentionError(RESTError): super(ResourceContentionError, self).__init__( "ResourceContentionError", "You already have a pending update to an Auto Scaling resource (for example, a group, instance, or load balancer).") + + +class InvalidInstanceError(AutoscalingClientError): + + def __init__(self, instance_id): + super(InvalidInstanceError, self).__init__( + "ValidationError", + "Instance [{0}] is invalid." + .format(instance_id)) diff --git a/moto/autoscaling/models.py b/moto/autoscaling/models.py index 24811be73..422075951 100644 --- a/moto/autoscaling/models.py +++ b/moto/autoscaling/models.py @@ -3,6 +3,8 @@ from __future__ import unicode_literals import random from boto.ec2.blockdevicemapping import BlockDeviceType, BlockDeviceMapping +from moto.ec2.exceptions import InvalidInstanceIdError + from moto.compat import OrderedDict from moto.core import BaseBackend, BaseModel from moto.ec2 import ec2_backends @@ -10,7 +12,7 @@ from moto.elb import elb_backends from moto.elbv2 import elbv2_backends from moto.elb.exceptions import LoadBalancerNotFoundError from .exceptions import ( - AutoscalingClientError, ResourceContentionError, + AutoscalingClientError, ResourceContentionError, InvalidInstanceError ) # http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/AS_Concepts.html#Cooldown @@ -73,6 +75,26 @@ class FakeLaunchConfiguration(BaseModel): self.associate_public_ip_address = associate_public_ip_address self.block_device_mapping_dict = block_device_mapping_dict + @classmethod + def create_from_instance(cls, name, instance, backend): + config = backend.create_launch_configuration( + name=name, + image_id=instance.image_id, + kernel_id='', + ramdisk_id='', + key_name=instance.key_name, + security_groups=instance.security_groups, + user_data=instance.user_data, + instance_type=instance.instance_type, + instance_monitoring=False, + instance_profile_name=None, + spot_price=None, + ebs_optimized=instance.ebs_optimized, + associate_public_ip_address=instance.associate_public_ip, + block_device_mappings=instance.block_device_mapping + ) + return config + @classmethod def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): properties = cloudformation_json['Properties'] @@ -279,6 +301,12 @@ class FakeAutoScalingGroup(BaseModel): if min_size is not None: self.min_size = min_size + if desired_capacity is None: + if min_size is not None and min_size > len(self.instance_states): + desired_capacity = min_size + if max_size is not None and max_size < len(self.instance_states): + desired_capacity = max_size + if launch_config_name: self.launch_config = self.autoscaling_backend.launch_configurations[ launch_config_name] @@ -414,7 +442,8 @@ class AutoScalingBackend(BaseBackend): health_check_type, load_balancers, target_group_arns, placement_group, termination_policies, tags, - new_instances_protected_from_scale_in=False): + new_instances_protected_from_scale_in=False, + instance_id=None): def make_int(value): return int(value) if value is not None else value @@ -427,6 +456,13 @@ class AutoScalingBackend(BaseBackend): health_check_period = 300 else: health_check_period = make_int(health_check_period) + if launch_config_name is None and instance_id is not None: + try: + instance = self.ec2_backend.get_instance(instance_id) + launch_config_name = name + FakeLaunchConfiguration.create_from_instance(launch_config_name, instance, self) + except InvalidInstanceIdError: + raise InvalidInstanceError(instance_id) group = FakeAutoScalingGroup( name=name, @@ -684,6 +720,18 @@ class AutoScalingBackend(BaseBackend): for instance in protected_instances: instance.protected_from_scale_in = protected_from_scale_in + def notify_terminate_instances(self, instance_ids): + for autoscaling_group_name, autoscaling_group in self.autoscaling_groups.items(): + original_instance_count = len(autoscaling_group.instance_states) + autoscaling_group.instance_states = list(filter( + lambda i_state: i_state.instance.id not in instance_ids, + autoscaling_group.instance_states + )) + difference = original_instance_count - len(autoscaling_group.instance_states) + if difference > 0: + autoscaling_group.replace_autoscaling_group_instances(difference, autoscaling_group.get_propagated_tags()) + self.update_attached_elbs(autoscaling_group_name) + autoscaling_backends = {} for region, ec2_backend in ec2_backends.items(): diff --git a/moto/autoscaling/responses.py b/moto/autoscaling/responses.py index 985c6f852..5e409aafb 100644 --- a/moto/autoscaling/responses.py +++ b/moto/autoscaling/responses.py @@ -48,7 +48,7 @@ class AutoScalingResponse(BaseResponse): start = all_names.index(marker) + 1 else: start = 0 - max_records = self._get_param('MaxRecords', 50) # the default is 100, but using 50 to make testing easier + max_records = self._get_int_param('MaxRecords', 50) # the default is 100, but using 50 to make testing easier launch_configurations_resp = all_launch_configurations[start:start + max_records] next_token = None if len(all_launch_configurations) > start + max_records: @@ -74,6 +74,7 @@ class AutoScalingResponse(BaseResponse): desired_capacity=self._get_int_param('DesiredCapacity'), max_size=self._get_int_param('MaxSize'), min_size=self._get_int_param('MinSize'), + instance_id=self._get_param('InstanceId'), launch_config_name=self._get_param('LaunchConfigurationName'), vpc_zone_identifier=self._get_param('VPCZoneIdentifier'), default_cooldown=self._get_int_param('DefaultCooldown'), diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 8dfa4724a..acc7a5257 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import base64 +import time from collections import defaultdict import copy import datetime @@ -31,6 +32,7 @@ from moto.logs.models import logs_backends from moto.s3.exceptions import MissingBucket, MissingKey from moto import settings from .utils import make_function_arn, make_function_ver_arn +from moto.sqs import sqs_backends logger = logging.getLogger(__name__) @@ -231,6 +233,10 @@ class LambdaFunction(BaseModel): config.update({"VpcId": "vpc-123abc"}) return config + @property + def physical_resource_id(self): + return self.function_name + def __repr__(self): return json.dumps(self.get_configuration()) @@ -425,24 +431,59 @@ class LambdaFunction(BaseModel): class EventSourceMapping(BaseModel): def __init__(self, spec): # required - self.function_name = spec['FunctionName'] + self.function_arn = spec['FunctionArn'] self.event_source_arn = spec['EventSourceArn'] - self.starting_position = spec['StartingPosition'] + self.uuid = str(uuid.uuid4()) + self.last_modified = time.mktime(datetime.datetime.utcnow().timetuple()) + + # BatchSize service default/max mapping + batch_size_map = { + 'kinesis': (100, 10000), + 'dynamodb': (100, 1000), + 'sqs': (10, 10), + } + source_type = self.event_source_arn.split(":")[2].lower() + batch_size_entry = batch_size_map.get(source_type) + if batch_size_entry: + # Use service default if not provided + batch_size = int(spec.get('BatchSize', batch_size_entry[0])) + if batch_size > batch_size_entry[1]: + raise ValueError("InvalidParameterValueException", + "BatchSize {} exceeds the max of {}".format(batch_size, batch_size_entry[1])) + else: + self.batch_size = batch_size + else: + raise ValueError("InvalidParameterValueException", + "Unsupported event source type") # optional - self.batch_size = spec.get('BatchSize', 100) + self.starting_position = spec.get('StartingPosition', 'TRIM_HORIZON') self.enabled = spec.get('Enabled', True) self.starting_position_timestamp = spec.get('StartingPositionTimestamp', None) + def get_configuration(self): + return { + 'UUID': self.uuid, + 'BatchSize': self.batch_size, + 'EventSourceArn': self.event_source_arn, + 'FunctionArn': self.function_arn, + 'LastModified': self.last_modified, + 'LastProcessingResult': '', + 'State': 'Enabled' if self.enabled else 'Disabled', + 'StateTransitionReason': 'User initiated' + } + @classmethod def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): properties = cloudformation_json['Properties'] + func = lambda_backends[region_name].get_function(properties['FunctionName']) spec = { - 'FunctionName': properties['FunctionName'], + 'FunctionArn': func.function_arn, 'EventSourceArn': properties['EventSourceArn'], - 'StartingPosition': properties['StartingPosition'] + 'StartingPosition': properties['StartingPosition'], + 'BatchSize': properties.get('BatchSize', 100) } optional_properties = 'BatchSize Enabled StartingPositionTimestamp'.split() for prop in optional_properties: @@ -462,8 +503,10 @@ class LambdaVersion(BaseModel): def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): properties = cloudformation_json['Properties'] + function_name = properties['FunctionName'] + func = lambda_backends[region_name].publish_function(function_name) spec = { - 'Version': properties.get('Version') + 'Version': func.version } return LambdaVersion(spec) @@ -511,6 +554,9 @@ class LambdaStorage(object): def get_arn(self, arn): return self._arns.get(arn, None) + def get_function_by_name_or_arn(self, input): + return self.get_function(input) or self.get_arn(input) + def put_function(self, fn): """ :param fn: Function @@ -592,6 +638,7 @@ class LambdaStorage(object): class LambdaBackend(BaseBackend): def __init__(self, region_name): self._lambdas = LambdaStorage() + self._event_source_mappings = {} self.region_name = region_name def reset(self): @@ -613,6 +660,40 @@ class LambdaBackend(BaseBackend): fn.version = ver.version return fn + def create_event_source_mapping(self, spec): + required = [ + 'EventSourceArn', + 'FunctionName', + ] + for param in required: + if not spec.get(param): + raise RESTError('InvalidParameterValueException', 'Missing {}'.format(param)) + + # Validate function name + func = self._lambdas.get_function_by_name_or_arn(spec.pop('FunctionName', '')) + if not func: + raise RESTError('ResourceNotFoundException', 'Invalid FunctionName') + + # Validate queue + for queue in sqs_backends[self.region_name].queues.values(): + if queue.queue_arn == spec['EventSourceArn']: + if queue.lambda_event_source_mappings.get('func.function_arn'): + # TODO: Correct exception? + raise RESTError('ResourceConflictException', 'The resource already exists.') + if queue.fifo_queue: + raise RESTError('InvalidParameterValueException', + '{} is FIFO'.format(queue.queue_arn)) + else: + spec.update({'FunctionArn': func.function_arn}) + esm = EventSourceMapping(spec) + self._event_source_mappings[esm.uuid] = esm + + # Set backend function on queue + queue.lambda_event_source_mappings[esm.function_arn] = esm + + return esm + raise RESTError('ResourceNotFoundException', 'Invalid EventSourceArn') + def publish_function(self, function_name): return self._lambdas.publish_function(function_name) @@ -622,6 +703,33 @@ class LambdaBackend(BaseBackend): def list_versions_by_function(self, function_name): return self._lambdas.list_versions_by_function(function_name) + def get_event_source_mapping(self, uuid): + return self._event_source_mappings.get(uuid) + + def delete_event_source_mapping(self, uuid): + return self._event_source_mappings.pop(uuid) + + def update_event_source_mapping(self, uuid, spec): + esm = self.get_event_source_mapping(uuid) + if esm: + if spec.get('FunctionName'): + func = self._lambdas.get_function_by_name_or_arn(spec.get('FunctionName')) + esm.function_arn = func.function_arn + if 'BatchSize' in spec: + esm.batch_size = spec['BatchSize'] + if 'Enabled' in spec: + esm.enabled = spec['Enabled'] + return esm + return False + + def list_event_source_mappings(self, event_source_arn, function_name): + esms = list(self._event_source_mappings.values()) + if event_source_arn: + esms = list(filter(lambda x: x.event_source_arn == event_source_arn, esms)) + if function_name: + esms = list(filter(lambda x: x.function_name == function_name, esms)) + return esms + def get_function_by_arn(self, function_arn): return self._lambdas.get_arn(function_arn) @@ -631,7 +739,43 @@ class LambdaBackend(BaseBackend): def list_functions(self): return self._lambdas.all() - def send_message(self, function_name, message, subject=None, qualifier=None): + def send_sqs_batch(self, function_arn, messages, queue_arn): + success = True + for message in messages: + func = self.get_function_by_arn(function_arn) + result = self._send_sqs_message(func, message, queue_arn) + if not result: + success = False + return success + + def _send_sqs_message(self, func, message, queue_arn): + event = { + "Records": [ + { + "messageId": message.id, + "receiptHandle": message.receipt_handle, + "body": message.body, + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1545082649183", + "SenderId": "AIDAIENQZJOLO23YVJ4VO", + "ApproximateFirstReceiveTimestamp": "1545082649185" + }, + "messageAttributes": {}, + "md5OfBody": "098f6bcd4621d373cade4e832627b4f6", + "eventSource": "aws:sqs", + "eventSourceARN": queue_arn, + "awsRegion": self.region_name + } + ] + } + + request_headers = {} + response_headers = {} + func.invoke(json.dumps(event), request_headers, response_headers) + return 'x-amz-function-error' not in response_headers + + def send_sns_message(self, function_name, message, subject=None, qualifier=None): event = { "Records": [ { diff --git a/moto/awslambda/responses.py b/moto/awslambda/responses.py index c29c9acd9..1e7feb0d0 100644 --- a/moto/awslambda/responses.py +++ b/moto/awslambda/responses.py @@ -39,6 +39,31 @@ class LambdaResponse(BaseResponse): else: raise ValueError("Cannot handle request") + def event_source_mappings(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + if request.method == 'GET': + querystring = self.querystring + event_source_arn = querystring.get('EventSourceArn', [None])[0] + function_name = querystring.get('FunctionName', [None])[0] + return self._list_event_source_mappings(event_source_arn, function_name) + elif request.method == 'POST': + return self._create_event_source_mapping(request, full_url, headers) + else: + raise ValueError("Cannot handle request") + + def event_source_mapping(self, request, full_url, headers): + self.setup_class(request, full_url, headers) + path = request.path if hasattr(request, 'path') else path_url(request.url) + uuid = path.split('/')[-1] + if request.method == 'GET': + return self._get_event_source_mapping(uuid) + elif request.method == 'PUT': + return self._update_event_source_mapping(uuid) + elif request.method == 'DELETE': + return self._delete_event_source_mapping(uuid) + else: + raise ValueError("Cannot handle request") + def function(self, request, full_url, headers): self.setup_class(request, full_url, headers) if request.method == 'GET': @@ -177,6 +202,45 @@ class LambdaResponse(BaseResponse): config = fn.get_configuration() return 201, {}, json.dumps(config) + def _create_event_source_mapping(self, request, full_url, headers): + try: + fn = self.lambda_backend.create_event_source_mapping(self.json_body) + except ValueError as e: + return 400, {}, json.dumps({"Error": {"Code": e.args[0], "Message": e.args[1]}}) + else: + config = fn.get_configuration() + return 201, {}, json.dumps(config) + + def _list_event_source_mappings(self, event_source_arn, function_name): + esms = self.lambda_backend.list_event_source_mappings(event_source_arn, function_name) + result = { + 'EventSourceMappings': [esm.get_configuration() for esm in esms] + } + return 200, {}, json.dumps(result) + + def _get_event_source_mapping(self, uuid): + result = self.lambda_backend.get_event_source_mapping(uuid) + if result: + return 200, {}, json.dumps(result.get_configuration()) + else: + return 404, {}, "{}" + + def _update_event_source_mapping(self, uuid): + result = self.lambda_backend.update_event_source_mapping(uuid, self.json_body) + if result: + return 202, {}, json.dumps(result.get_configuration()) + else: + return 404, {}, "{}" + + def _delete_event_source_mapping(self, uuid): + esm = self.lambda_backend.delete_event_source_mapping(uuid) + if esm: + json_result = esm.get_configuration() + json_result.update({'State': 'Deleting'}) + return 202, {}, json.dumps(json_result) + else: + return 404, {}, "{}" + def _publish_function(self, request, full_url, headers): function_name = self.path.rsplit('/', 2)[-2] diff --git a/moto/awslambda/urls.py b/moto/awslambda/urls.py index 7c4d064dc..fb2c6ee7e 100644 --- a/moto/awslambda/urls.py +++ b/moto/awslambda/urls.py @@ -11,6 +11,8 @@ url_paths = { '{0}/(?P[^/]+)/functions/?$': response.root, r'{0}/(?P[^/]+)/functions/(?P[\w_-]+)/?$': response.function, r'{0}/(?P[^/]+)/functions/(?P[\w_-]+)/versions/?$': response.versions, + r'{0}/(?P[^/]+)/event-source-mappings/?$': response.event_source_mappings, + r'{0}/(?P[^/]+)/event-source-mappings/(?P[\w_-]+)/?$': response.event_source_mapping, r'{0}/(?P[^/]+)/functions/(?P[\w_-]+)/invocations/?$': response.invoke, r'{0}/(?P[^/]+)/functions/(?P[\w_-]+)/invoke-async/?$': response.invoke_async, r'{0}/(?P[^/]+)/tags/(?P.+)': response.tag, diff --git a/moto/batch/models.py b/moto/batch/models.py index c47ca6e97..caa442802 100644 --- a/moto/batch/models.py +++ b/moto/batch/models.py @@ -514,10 +514,13 @@ class BatchBackend(BaseBackend): return self._job_definitions.get(arn) def get_job_definition_by_name(self, name): - for comp_env in self._job_definitions.values(): - if comp_env.name == name: - return comp_env - return None + latest_revision = -1 + latest_job = None + for job_def in self._job_definitions.values(): + if job_def.name == name and job_def.revision > latest_revision: + latest_job = job_def + latest_revision = job_def.revision + return latest_job def get_job_definition_by_name_revision(self, name, revision): for job_def in self._job_definitions.values(): @@ -534,10 +537,13 @@ class BatchBackend(BaseBackend): :return: Job definition or None :rtype: JobDefinition or None """ - env = self.get_job_definition_by_arn(identifier) - if env is None: - env = self.get_job_definition_by_name(identifier) - return env + job_def = self.get_job_definition_by_arn(identifier) + if job_def is None: + if ':' in identifier: + job_def = self.get_job_definition_by_name_revision(*identifier.split(':', 1)) + else: + job_def = self.get_job_definition_by_name(identifier) + return job_def def get_job_definitions(self, identifier): """ @@ -984,9 +990,7 @@ class BatchBackend(BaseBackend): # TODO parameters, retries (which is a dict raw from request), job dependancies and container overrides are ignored for now # Look for job definition - job_def = self.get_job_definition_by_arn(job_def_id) - if job_def is None and ':' in job_def_id: - job_def = self.get_job_definition_by_name_revision(*job_def_id.split(':', 1)) + job_def = self.get_job_definition(job_def_id) if job_def is None: raise ClientException('Job definition {0} does not exist'.format(job_def_id)) diff --git a/moto/cloudformation/parsing.py b/moto/cloudformation/parsing.py index 3bf994bed..f2e03bd81 100644 --- a/moto/cloudformation/parsing.py +++ b/moto/cloudformation/parsing.py @@ -246,7 +246,8 @@ def resource_name_property_from_type(resource_type): def generate_resource_name(resource_type, stack_name, logical_id): - if resource_type == "AWS::ElasticLoadBalancingV2::TargetGroup": + if resource_type in ["AWS::ElasticLoadBalancingV2::TargetGroup", + "AWS::ElasticLoadBalancingV2::LoadBalancer"]: # Target group names need to be less than 32 characters, so when cloudformation creates a name for you # it makes sure to stay under that limit name_prefix = '{0}-{1}'.format(stack_name, logical_id) diff --git a/moto/cloudformation/utils.py b/moto/cloudformation/utils.py index de75d2c15..e4290ce1a 100644 --- a/moto/cloudformation/utils.py +++ b/moto/cloudformation/utils.py @@ -4,6 +4,7 @@ import six import random import yaml import os +import string from cfnlint import decode, core @@ -29,7 +30,7 @@ def generate_stackset_arn(stackset_id, region_name): def random_suffix(): size = 12 - chars = list(range(10)) + ['A-Z'] + chars = list(range(10)) + list(string.ascii_uppercase) return ''.join(six.text_type(random.choice(chars)) for x in range(size)) diff --git a/moto/cloudwatch/responses.py b/moto/cloudwatch/responses.py index 8118f35ba..bf176e1be 100644 --- a/moto/cloudwatch/responses.py +++ b/moto/cloudwatch/responses.py @@ -275,7 +275,7 @@ GET_METRIC_STATISTICS_TEMPLATE = """ 128: + raise TagKeyTooBig(tag_key, param=exception_param) + + # Validate that the tag key fits the proper Regex: + # [\w\s_.:/=+\-@]+ SHOULD be the same as the Java regex on the AWS documentation: [\p{L}\p{Z}\p{N}_.:/=+\-@]+ + match = re.findall(r'[\w\s_.:/=+\-@]+', tag_key) + # Kudos if you can come up with a better way of doing a global search :) + if not len(match) or len(match[0]) < len(tag_key): + raise InvalidTagCharacters(tag_key, param=exception_param) + + +def check_tag_duplicate(all_tags, tag_key): + """Validates that a tag key is not a duplicate + + :param all_tags: Dict to check if there is a duplicate tag. + :param tag_key: The tag key to check against. + :return: + """ + if all_tags.get(tag_key): + raise DuplicateTags() + + +def validate_tags(tags): + proper_tags = {} + + if len(tags) > 50: + raise TooManyTags(tags) + + for tag in tags: + # Validate the Key: + validate_tag_key(tag['Key']) + check_tag_duplicate(proper_tags, tag['Key']) + + # Validate the Value: + if len(tag['Value']) > 256: + raise TagValueTooBig(tag['Value']) + + proper_tags[tag['Key']] = tag['Value'] + + return proper_tags + + class ConfigEmptyDictable(BaseModel): """Base class to make serialization easy. This assumes that the sub-class will NOT return 'None's in the JSON.""" + def __init__(self, capitalize_start=False, capitalize_arn=True): + """Assists with the serialization of the config object + :param capitalize_start: For some Config services, the first letter is lowercase -- for others it's capital + :param capitalize_arn: For some Config services, the API expects 'ARN' and for others, it expects 'Arn' + """ + self.capitalize_start = capitalize_start + self.capitalize_arn = capitalize_arn + def to_dict(self): data = {} for item, value in self.__dict__.items(): if value is not None: if isinstance(value, ConfigEmptyDictable): - data[snake_to_camels(item)] = value.to_dict() + data[snake_to_camels(item, self.capitalize_start, self.capitalize_arn)] = value.to_dict() else: - data[snake_to_camels(item)] = value + data[snake_to_camels(item, self.capitalize_start, self.capitalize_arn)] = value + + # Cleanse the extra properties: + for prop in POP_STRINGS: + data.pop(prop, None) return data @@ -50,8 +141,9 @@ class ConfigEmptyDictable(BaseModel): class ConfigRecorderStatus(ConfigEmptyDictable): def __init__(self, name): - self.name = name + super(ConfigRecorderStatus, self).__init__() + self.name = name self.recording = False self.last_start_time = None self.last_stop_time = None @@ -75,12 +167,16 @@ class ConfigRecorderStatus(ConfigEmptyDictable): class ConfigDeliverySnapshotProperties(ConfigEmptyDictable): def __init__(self, delivery_frequency): + super(ConfigDeliverySnapshotProperties, self).__init__() + self.delivery_frequency = delivery_frequency class ConfigDeliveryChannel(ConfigEmptyDictable): def __init__(self, name, s3_bucket_name, prefix=None, sns_arn=None, snapshot_properties=None): + super(ConfigDeliveryChannel, self).__init__() + self.name = name self.s3_bucket_name = s3_bucket_name self.s3_key_prefix = prefix @@ -91,6 +187,8 @@ class ConfigDeliveryChannel(ConfigEmptyDictable): class RecordingGroup(ConfigEmptyDictable): def __init__(self, all_supported=True, include_global_resource_types=False, resource_types=None): + super(RecordingGroup, self).__init__() + self.all_supported = all_supported self.include_global_resource_types = include_global_resource_types self.resource_types = resource_types @@ -99,6 +197,8 @@ class RecordingGroup(ConfigEmptyDictable): class ConfigRecorder(ConfigEmptyDictable): def __init__(self, role_arn, recording_group, name='default', status=None): + super(ConfigRecorder, self).__init__() + self.name = name self.role_arn = role_arn self.recording_group = recording_group @@ -109,18 +209,118 @@ class ConfigRecorder(ConfigEmptyDictable): self.status = status +class AccountAggregatorSource(ConfigEmptyDictable): + + def __init__(self, account_ids, aws_regions=None, all_aws_regions=None): + super(AccountAggregatorSource, self).__init__(capitalize_start=True) + + # Can't have both the regions and all_regions flag present -- also can't have them both missing: + if aws_regions and all_aws_regions: + raise InvalidParameterValueException('Your configuration aggregator contains a list of regions and also specifies ' + 'the use of all regions. You must choose one of these options.') + + if not (aws_regions or all_aws_regions): + raise InvalidParameterValueException('Your request does not specify any regions. Select AWS Config-supported ' + 'regions and try again.') + + self.account_ids = account_ids + self.aws_regions = aws_regions + + if not all_aws_regions: + all_aws_regions = False + + self.all_aws_regions = all_aws_regions + + +class OrganizationAggregationSource(ConfigEmptyDictable): + + def __init__(self, role_arn, aws_regions=None, all_aws_regions=None): + super(OrganizationAggregationSource, self).__init__(capitalize_start=True, capitalize_arn=False) + + # Can't have both the regions and all_regions flag present -- also can't have them both missing: + if aws_regions and all_aws_regions: + raise InvalidParameterValueException('Your configuration aggregator contains a list of regions and also specifies ' + 'the use of all regions. You must choose one of these options.') + + if not (aws_regions or all_aws_regions): + raise InvalidParameterValueException('Your request does not specify any regions. Select AWS Config-supported ' + 'regions and try again.') + + self.role_arn = role_arn + self.aws_regions = aws_regions + + if not all_aws_regions: + all_aws_regions = False + + self.all_aws_regions = all_aws_regions + + +class ConfigAggregator(ConfigEmptyDictable): + + def __init__(self, name, region, account_sources=None, org_source=None, tags=None): + super(ConfigAggregator, self).__init__(capitalize_start=True, capitalize_arn=False) + + self.configuration_aggregator_name = name + self.configuration_aggregator_arn = 'arn:aws:config:{region}:{id}:config-aggregator/config-aggregator-{random}'.format( + region=region, + id=DEFAULT_ACCOUNT_ID, + random=random_string() + ) + self.account_aggregation_sources = account_sources + self.organization_aggregation_source = org_source + self.creation_time = datetime2int(datetime.utcnow()) + self.last_updated_time = datetime2int(datetime.utcnow()) + + # Tags are listed in the list_tags_for_resource API call ... not implementing yet -- please feel free to! + self.tags = tags or {} + + # Override the to_dict so that we can format the tags properly... + def to_dict(self): + result = super(ConfigAggregator, self).to_dict() + + # Override the account aggregation sources if present: + if self.account_aggregation_sources: + result['AccountAggregationSources'] = [a.to_dict() for a in self.account_aggregation_sources] + + # Tags are listed in the list_tags_for_resource API call ... not implementing yet -- please feel free to! + # if self.tags: + # result['Tags'] = [{'Key': key, 'Value': value} for key, value in self.tags.items()] + + return result + + +class ConfigAggregationAuthorization(ConfigEmptyDictable): + + def __init__(self, current_region, authorized_account_id, authorized_aws_region, tags=None): + super(ConfigAggregationAuthorization, self).__init__(capitalize_start=True, capitalize_arn=False) + + self.aggregation_authorization_arn = 'arn:aws:config:{region}:{id}:aggregation-authorization/' \ + '{auth_account}/{auth_region}'.format(region=current_region, + id=DEFAULT_ACCOUNT_ID, + auth_account=authorized_account_id, + auth_region=authorized_aws_region) + self.authorized_account_id = authorized_account_id + self.authorized_aws_region = authorized_aws_region + self.creation_time = datetime2int(datetime.utcnow()) + + # Tags are listed in the list_tags_for_resource API call ... not implementing yet -- please feel free to! + self.tags = tags or {} + + class ConfigBackend(BaseBackend): def __init__(self): self.recorders = {} self.delivery_channels = {} + self.config_aggregators = {} + self.aggregation_authorizations = {} @staticmethod def _validate_resource_types(resource_list): # Load the service file: resource_package = 'botocore' resource_path = '/'.join(('data', 'config', '2014-11-12', 'service-2.json')) - conifg_schema = json.loads(pkg_resources.resource_string(resource_package, resource_path)) + config_schema = json.loads(pkg_resources.resource_string(resource_package, resource_path)) # Verify that each entry exists in the supported list: bad_list = [] @@ -128,11 +328,11 @@ class ConfigBackend(BaseBackend): # For PY2: r_str = str(resource) - if r_str not in conifg_schema['shapes']['ResourceType']['enum']: + if r_str not in config_schema['shapes']['ResourceType']['enum']: bad_list.append(r_str) if bad_list: - raise InvalidResourceTypeException(bad_list, conifg_schema['shapes']['ResourceType']['enum']) + raise InvalidResourceTypeException(bad_list, config_schema['shapes']['ResourceType']['enum']) @staticmethod def _validate_delivery_snapshot_properties(properties): @@ -147,6 +347,158 @@ class ConfigBackend(BaseBackend): raise InvalidDeliveryFrequency(properties.get('deliveryFrequency', None), conifg_schema['shapes']['MaximumExecutionFrequency']['enum']) + def put_configuration_aggregator(self, config_aggregator, region): + # Validate the name: + if len(config_aggregator['ConfigurationAggregatorName']) > 256: + raise NameTooLongException(config_aggregator['ConfigurationAggregatorName'], 'configurationAggregatorName') + + account_sources = None + org_source = None + + # Tag validation: + tags = validate_tags(config_aggregator.get('Tags', [])) + + # Exception if both AccountAggregationSources and OrganizationAggregationSource are supplied: + if config_aggregator.get('AccountAggregationSources') and config_aggregator.get('OrganizationAggregationSource'): + raise InvalidParameterValueException('The configuration aggregator cannot be created because your request contains both the' + ' AccountAggregationSource and the OrganizationAggregationSource. Include only ' + 'one aggregation source and try again.') + + # If neither are supplied: + if not config_aggregator.get('AccountAggregationSources') and not config_aggregator.get('OrganizationAggregationSource'): + raise InvalidParameterValueException('The configuration aggregator cannot be created because your request is missing either ' + 'the AccountAggregationSource or the OrganizationAggregationSource. Include the ' + 'appropriate aggregation source and try again.') + + if config_aggregator.get('AccountAggregationSources'): + # Currently, only 1 account aggregation source can be set: + if len(config_aggregator['AccountAggregationSources']) > 1: + raise TooManyAccountSources(len(config_aggregator['AccountAggregationSources'])) + + account_sources = [] + for a in config_aggregator['AccountAggregationSources']: + account_sources.append(AccountAggregatorSource(a['AccountIds'], aws_regions=a.get('AwsRegions'), + all_aws_regions=a.get('AllAwsRegions'))) + + else: + org_source = OrganizationAggregationSource(config_aggregator['OrganizationAggregationSource']['RoleArn'], + aws_regions=config_aggregator['OrganizationAggregationSource'].get('AwsRegions'), + all_aws_regions=config_aggregator['OrganizationAggregationSource'].get( + 'AllAwsRegions')) + + # Grab the existing one if it exists and update it: + if not self.config_aggregators.get(config_aggregator['ConfigurationAggregatorName']): + aggregator = ConfigAggregator(config_aggregator['ConfigurationAggregatorName'], region, account_sources=account_sources, + org_source=org_source, tags=tags) + self.config_aggregators[config_aggregator['ConfigurationAggregatorName']] = aggregator + + else: + aggregator = self.config_aggregators[config_aggregator['ConfigurationAggregatorName']] + aggregator.tags = tags + aggregator.account_aggregation_sources = account_sources + aggregator.organization_aggregation_source = org_source + aggregator.last_updated_time = datetime2int(datetime.utcnow()) + + return aggregator.to_dict() + + def describe_configuration_aggregators(self, names, token, limit): + limit = DEFAULT_PAGE_SIZE if not limit or limit < 0 else limit + agg_list = [] + result = {'ConfigurationAggregators': []} + + if names: + for name in names: + if not self.config_aggregators.get(name): + raise NoSuchConfigurationAggregatorException(number=len(names)) + + agg_list.append(name) + + else: + agg_list = list(self.config_aggregators.keys()) + + # Empty? + if not agg_list: + return result + + # Sort by name: + sorted_aggregators = sorted(agg_list) + + # Get the start: + if not token: + start = 0 + else: + # Tokens for this moto feature are just the next names of the items in the list: + if not self.config_aggregators.get(token): + raise InvalidNextTokenException() + + start = sorted_aggregators.index(token) + + # Get the list of items to collect: + agg_list = sorted_aggregators[start:(start + limit)] + result['ConfigurationAggregators'] = [self.config_aggregators[agg].to_dict() for agg in agg_list] + + if len(sorted_aggregators) > (start + limit): + result['NextToken'] = sorted_aggregators[start + limit] + + return result + + def delete_configuration_aggregator(self, config_aggregator): + if not self.config_aggregators.get(config_aggregator): + raise NoSuchConfigurationAggregatorException() + + del self.config_aggregators[config_aggregator] + + def put_aggregation_authorization(self, current_region, authorized_account, authorized_region, tags): + # Tag validation: + tags = validate_tags(tags or []) + + # Does this already exist? + key = '{}/{}'.format(authorized_account, authorized_region) + agg_auth = self.aggregation_authorizations.get(key) + if not agg_auth: + agg_auth = ConfigAggregationAuthorization(current_region, authorized_account, authorized_region, tags=tags) + self.aggregation_authorizations['{}/{}'.format(authorized_account, authorized_region)] = agg_auth + else: + # Only update the tags: + agg_auth.tags = tags + + return agg_auth.to_dict() + + def describe_aggregation_authorizations(self, token, limit): + limit = DEFAULT_PAGE_SIZE if not limit or limit < 0 else limit + result = {'AggregationAuthorizations': []} + + if not self.aggregation_authorizations: + return result + + # Sort by name: + sorted_authorizations = sorted(self.aggregation_authorizations.keys()) + + # Get the start: + if not token: + start = 0 + else: + # Tokens for this moto feature are just the next names of the items in the list: + if not self.aggregation_authorizations.get(token): + raise InvalidNextTokenException() + + start = sorted_authorizations.index(token) + + # Get the list of items to collect: + auth_list = sorted_authorizations[start:(start + limit)] + result['AggregationAuthorizations'] = [self.aggregation_authorizations[auth].to_dict() for auth in auth_list] + + if len(sorted_authorizations) > (start + limit): + result['NextToken'] = sorted_authorizations[start + limit] + + return result + + def delete_aggregation_authorization(self, authorized_account, authorized_region): + # This will always return a 200 -- regardless if there is or isn't an existing + # aggregation authorization. + key = '{}/{}'.format(authorized_account, authorized_region) + self.aggregation_authorizations.pop(key, None) + def put_configuration_recorder(self, config_recorder): # Validate the name: if not config_recorder.get('name'): diff --git a/moto/config/responses.py b/moto/config/responses.py index 286b2349f..03612d403 100644 --- a/moto/config/responses.py +++ b/moto/config/responses.py @@ -13,6 +13,39 @@ class ConfigResponse(BaseResponse): self.config_backend.put_configuration_recorder(self._get_param('ConfigurationRecorder')) return "" + def put_configuration_aggregator(self): + aggregator = self.config_backend.put_configuration_aggregator(json.loads(self.body), self.region) + schema = {'ConfigurationAggregator': aggregator} + return json.dumps(schema) + + def describe_configuration_aggregators(self): + aggregators = self.config_backend.describe_configuration_aggregators(self._get_param('ConfigurationAggregatorNames'), + self._get_param('NextToken'), + self._get_param('Limit')) + return json.dumps(aggregators) + + def delete_configuration_aggregator(self): + self.config_backend.delete_configuration_aggregator(self._get_param('ConfigurationAggregatorName')) + return "" + + def put_aggregation_authorization(self): + agg_auth = self.config_backend.put_aggregation_authorization(self.region, + self._get_param('AuthorizedAccountId'), + self._get_param('AuthorizedAwsRegion'), + self._get_param('Tags')) + schema = {'AggregationAuthorization': agg_auth} + return json.dumps(schema) + + def describe_aggregation_authorizations(self): + authorizations = self.config_backend.describe_aggregation_authorizations(self._get_param('NextToken'), self._get_param('Limit')) + + return json.dumps(authorizations) + + def delete_aggregation_authorization(self): + self.config_backend.delete_aggregation_authorization(self._get_param('AuthorizedAccountId'), self._get_param('AuthorizedAwsRegion')) + + return "" + def describe_configuration_recorders(self): recorders = self.config_backend.describe_configuration_recorders(self._get_param('ConfigurationRecorderNames')) schema = {'ConfigurationRecorders': recorders} diff --git a/moto/core/__init__.py b/moto/core/__init__.py index 9e2c1e70f..801e675df 100644 --- a/moto/core/__init__.py +++ b/moto/core/__init__.py @@ -1,4 +1,7 @@ from __future__ import unicode_literals + from .models import BaseModel, BaseBackend, moto_api_backend # flake8: noqa +from .responses import ActionAuthenticatorMixin moto_api_backends = {"global": moto_api_backend} +set_initial_no_auth_action_count = ActionAuthenticatorMixin.set_initial_no_auth_action_count diff --git a/moto/core/exceptions.py b/moto/core/exceptions.py index 40202f7bd..06cfd8895 100644 --- a/moto/core/exceptions.py +++ b/moto/core/exceptions.py @@ -65,3 +65,42 @@ class JsonRESTError(RESTError): def get_body(self, *args, **kwargs): return self.description + + +class SignatureDoesNotMatchError(RESTError): + code = 403 + + def __init__(self): + super(SignatureDoesNotMatchError, self).__init__( + 'SignatureDoesNotMatch', + "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.") + + +class InvalidClientTokenIdError(RESTError): + code = 403 + + def __init__(self): + super(InvalidClientTokenIdError, self).__init__( + 'InvalidClientTokenId', + "The security token included in the request is invalid.") + + +class AccessDeniedError(RESTError): + code = 403 + + def __init__(self, user_arn, action): + super(AccessDeniedError, self).__init__( + 'AccessDenied', + "User: {user_arn} is not authorized to perform: {operation}".format( + user_arn=user_arn, + operation=action + )) + + +class AuthFailureError(RESTError): + code = 401 + + def __init__(self): + super(AuthFailureError, self).__init__( + 'AuthFailure', + "AWS was not able to validate the provided access credentials") diff --git a/moto/core/models.py b/moto/core/models.py index 9fe1e96bd..896f9ac4a 100644 --- a/moto/core/models.py +++ b/moto/core/models.py @@ -12,6 +12,7 @@ from collections import defaultdict from botocore.handlers import BUILTIN_HANDLERS from botocore.awsrequest import AWSResponse +import mock from moto import settings import responses from moto.packages.httpretty import HTTPretty @@ -22,11 +23,6 @@ from .utils import ( ) -# "Mock" the AWS credentials as they can't be mocked in Botocore currently -os.environ.setdefault("AWS_ACCESS_KEY_ID", "foobar_key") -os.environ.setdefault("AWS_SECRET_ACCESS_KEY", "foobar_secret") - - class BaseMockAWS(object): nested_count = 0 @@ -42,6 +38,10 @@ class BaseMockAWS(object): self.backends_for_urls.update(self.backends) self.backends_for_urls.update(default_backends) + # "Mock" the AWS credentials as they can't be mocked in Botocore currently + FAKE_KEYS = {"AWS_ACCESS_KEY_ID": "foobar_key", "AWS_SECRET_ACCESS_KEY": "foobar_secret"} + self.env_variables_mocks = mock.patch.dict(os.environ, FAKE_KEYS) + if self.__class__.nested_count == 0: self.reset() @@ -52,11 +52,14 @@ class BaseMockAWS(object): def __enter__(self): self.start() + return self def __exit__(self, *args): self.stop() def start(self, reset=True): + self.env_variables_mocks.start() + self.__class__.nested_count += 1 if reset: for backend in self.backends.values(): @@ -65,6 +68,7 @@ class BaseMockAWS(object): self.enable_patching() def stop(self): + self.env_variables_mocks.stop() self.__class__.nested_count -= 1 if self.__class__.nested_count < 0: @@ -465,10 +469,14 @@ class BaseModel(object): class BaseBackend(object): - def reset(self): + def _reset_model_refs(self): + # Remove all references to the models stored for service, models in model_data.items(): for model_name, model in models.items(): model.instances = [] + + def reset(self): + self._reset_model_refs() self.__dict__ = {} self.__init__() diff --git a/moto/core/responses.py b/moto/core/responses.py index 9da36b865..b60f10a20 100644 --- a/moto/core/responses.py +++ b/moto/core/responses.py @@ -1,13 +1,17 @@ from __future__ import unicode_literals +import functools from collections import defaultdict import datetime import json import logging import re import io +import requests import pytz + +from moto.core.access_control import IAMRequest, S3IAMRequest from moto.core.exceptions import DryRunClientError from jinja2 import Environment, DictLoader, TemplateNotFound @@ -22,7 +26,7 @@ from werkzeug.exceptions import HTTPException import boto3 from moto.compat import OrderedDict from moto.core.utils import camelcase_to_underscores, method_names_from_class - +from moto import settings log = logging.getLogger(__name__) @@ -103,7 +107,54 @@ class _TemplateEnvironmentMixin(object): return self.environment.get_template(template_id) -class BaseResponse(_TemplateEnvironmentMixin): +class ActionAuthenticatorMixin(object): + + request_count = 0 + + def _authenticate_and_authorize_action(self, iam_request_cls): + if ActionAuthenticatorMixin.request_count >= settings.INITIAL_NO_AUTH_ACTION_COUNT: + iam_request = iam_request_cls(method=self.method, path=self.path, data=self.data, headers=self.headers) + iam_request.check_signature() + iam_request.check_action_permitted() + else: + ActionAuthenticatorMixin.request_count += 1 + + def _authenticate_and_authorize_normal_action(self): + self._authenticate_and_authorize_action(IAMRequest) + + def _authenticate_and_authorize_s3_action(self): + self._authenticate_and_authorize_action(S3IAMRequest) + + @staticmethod + def set_initial_no_auth_action_count(initial_no_auth_action_count): + def decorator(function): + def wrapper(*args, **kwargs): + if settings.TEST_SERVER_MODE: + response = requests.post("http://localhost:5000/moto-api/reset-auth", data=str(initial_no_auth_action_count).encode()) + original_initial_no_auth_action_count = response.json()['PREVIOUS_INITIAL_NO_AUTH_ACTION_COUNT'] + else: + original_initial_no_auth_action_count = settings.INITIAL_NO_AUTH_ACTION_COUNT + original_request_count = ActionAuthenticatorMixin.request_count + settings.INITIAL_NO_AUTH_ACTION_COUNT = initial_no_auth_action_count + ActionAuthenticatorMixin.request_count = 0 + try: + result = function(*args, **kwargs) + finally: + if settings.TEST_SERVER_MODE: + requests.post("http://localhost:5000/moto-api/reset-auth", data=str(original_initial_no_auth_action_count).encode()) + else: + ActionAuthenticatorMixin.request_count = original_request_count + settings.INITIAL_NO_AUTH_ACTION_COUNT = original_initial_no_auth_action_count + return result + + functools.update_wrapper(wrapper, function) + wrapper.__wrapped__ = function + return wrapper + + return decorator + + +class BaseResponse(_TemplateEnvironmentMixin, ActionAuthenticatorMixin): default_region = 'us-east-1' # to extract region, use [^.] @@ -167,6 +218,7 @@ class BaseResponse(_TemplateEnvironmentMixin): self.uri = full_url self.path = urlparse(full_url).path self.querystring = querystring + self.data = querystring self.method = request.method self.region = self.get_region_from_url(request, full_url) self.uri_match = None @@ -273,6 +325,13 @@ class BaseResponse(_TemplateEnvironmentMixin): def call_action(self): headers = self.response_headers + + try: + self._authenticate_and_authorize_normal_action() + except HTTPException as http_error: + response = http_error.description, dict(status=http_error.code) + return self._send_response(headers, response) + action = camelcase_to_underscores(self._get_action()) method_names = method_names_from_class(self.__class__) if action in method_names: @@ -285,16 +344,7 @@ class BaseResponse(_TemplateEnvironmentMixin): if isinstance(response, six.string_types): return 200, headers, response else: - if len(response) == 2: - body, new_headers = response - else: - status, new_headers, body = response - status = new_headers.get('status', 200) - headers.update(new_headers) - # Cast status to string - if "status" in headers: - headers['status'] = str(headers['status']) - return status, headers, body + return self._send_response(headers, response) if not action: return 404, headers, '' @@ -302,6 +352,19 @@ class BaseResponse(_TemplateEnvironmentMixin): raise NotImplementedError( "The {0} action has not been implemented".format(action)) + @staticmethod + def _send_response(headers, response): + if len(response) == 2: + body, new_headers = response + else: + status, new_headers, body = response + status = new_headers.get('status', 200) + headers.update(new_headers) + # Cast status to string + if "status" in headers: + headers['status'] = str(headers['status']) + return status, headers, body + def _get_param(self, param_name, if_none=None): val = self.querystring.get(param_name) if val is not None: @@ -569,6 +632,14 @@ class MotoAPIResponse(BaseResponse): return 200, {}, json.dumps({"status": "ok"}) return 400, {}, json.dumps({"Error": "Need to POST to reset Moto"}) + def reset_auth_response(self, request, full_url, headers): + if request.method == "POST": + previous_initial_no_auth_action_count = settings.INITIAL_NO_AUTH_ACTION_COUNT + settings.INITIAL_NO_AUTH_ACTION_COUNT = float(request.data.decode()) + ActionAuthenticatorMixin.request_count = 0 + return 200, {}, json.dumps({"status": "ok", "PREVIOUS_INITIAL_NO_AUTH_ACTION_COUNT": str(previous_initial_no_auth_action_count)}) + return 400, {}, json.dumps({"Error": "Need to POST to reset Moto Auth"}) + def model_data(self, request, full_url, headers): from moto.core.models import model_data diff --git a/moto/core/urls.py b/moto/core/urls.py index 4d4906d77..46025221e 100644 --- a/moto/core/urls.py +++ b/moto/core/urls.py @@ -11,4 +11,5 @@ url_paths = { '{0}/moto-api/$': response_instance.dashboard, '{0}/moto-api/data.json': response_instance.model_data, '{0}/moto-api/reset': response_instance.reset_response, + '{0}/moto-api/reset-auth': response_instance.reset_auth_response, } diff --git a/moto/dynamodb2/comparisons.py b/moto/dynamodb2/comparisons.py index 6d37345fe..151a314f1 100644 --- a/moto/dynamodb2/comparisons.py +++ b/moto/dynamodb2/comparisons.py @@ -1,6 +1,94 @@ from __future__ import unicode_literals import re import six +import re +from collections import deque +from collections import namedtuple + + +def get_filter_expression(expr, names, values): + """ + Parse a filter expression into an Op. + + Examples + expr = 'Id > 5 AND attribute_exists(test) AND Id BETWEEN 5 AND 6 OR length < 6 AND contains(test, 1) AND 5 IN (4,5, 6) OR (Id < 5 AND 5 > Id)' + expr = 'Id > 5 AND Subs < 7' + """ + parser = ConditionExpressionParser(expr, names, values) + return parser.parse() + + +def get_expected(expected): + """ + Parse a filter expression into an Op. + + Examples + expr = 'Id > 5 AND attribute_exists(test) AND Id BETWEEN 5 AND 6 OR length < 6 AND contains(test, 1) AND 5 IN (4,5, 6) OR (Id < 5 AND 5 > Id)' + expr = 'Id > 5 AND Subs < 7' + """ + ops = { + 'EQ': OpEqual, + 'NE': OpNotEqual, + 'LE': OpLessThanOrEqual, + 'LT': OpLessThan, + 'GE': OpGreaterThanOrEqual, + 'GT': OpGreaterThan, + 'NOT_NULL': FuncAttrExists, + 'NULL': FuncAttrNotExists, + 'CONTAINS': FuncContains, + 'NOT_CONTAINS': FuncNotContains, + 'BEGINS_WITH': FuncBeginsWith, + 'IN': FuncIn, + 'BETWEEN': FuncBetween, + } + + # NOTE: Always uses ConditionalOperator=AND + conditions = [] + for key, cond in expected.items(): + path = AttributePath([key]) + if 'Exists' in cond: + if cond['Exists']: + conditions.append(FuncAttrExists(path)) + else: + conditions.append(FuncAttrNotExists(path)) + elif 'Value' in cond: + conditions.append(OpEqual(path, AttributeValue(cond['Value']))) + elif 'ComparisonOperator' in cond: + operator_name = cond['ComparisonOperator'] + values = [ + AttributeValue(v) + for v in cond.get("AttributeValueList", [])] + OpClass = ops[operator_name] + conditions.append(OpClass(path, *values)) + + # NOTE: Ignore ConditionalOperator + ConditionalOp = OpAnd + if conditions: + output = conditions[0] + for condition in conditions[1:]: + output = ConditionalOp(output, condition) + else: + return OpDefault(None, None) + + return output + + +class Op(object): + """ + Base class for a FilterExpression operator + """ + OP = '' + + def __init__(self, lhs, rhs): + self.lhs = lhs + self.rhs = rhs + + def expr(self, item): + raise NotImplementedError("Expr not defined for {0}".format(type(self))) + + def __repr__(self): + return '({0} {1} {2})'.format(self.lhs, self.OP, self.rhs) + # TODO add tests for all of these EQ_FUNCTION = lambda item_value, test_value: item_value == test_value # flake8: noqa @@ -49,292 +137,799 @@ class RecursionStopIteration(StopIteration): pass -def get_filter_expression(expr, names, values): - # Examples - # expr = 'Id > 5 AND attribute_exists(test) AND Id BETWEEN 5 AND 6 OR length < 6 AND contains(test, 1) AND 5 IN (4,5, 6) OR (Id < 5 AND 5 > Id)' - # expr = 'Id > 5 AND Subs < 7' - if names is None: - names = {} - if values is None: - values = {} +class ConditionExpressionParser: + def __init__(self, condition_expression, expression_attribute_names, + expression_attribute_values): + self.condition_expression = condition_expression + self.expression_attribute_names = expression_attribute_names + self.expression_attribute_values = expression_attribute_values - # Do substitutions - for key, value in names.items(): - expr = expr.replace(key, value) + def parse(self): + """Returns a syntax tree for the expression. - # Store correct types of values for use later - values_map = {} - for key, value in values.items(): - if 'N' in value: - values_map[key] = float(value['N']) - elif 'BOOL' in value: - values_map[key] = value['BOOL'] - elif 'S' in value: - values_map[key] = value['S'] - elif 'NS' in value: - values_map[key] = tuple(value['NS']) - elif 'SS' in value: - values_map[key] = tuple(value['SS']) - elif 'L' in value: - values_map[key] = tuple(value['L']) + The tree, and all of the nodes in the tree are a tuple of + - kind: str + - children/value: + list of nodes for parent nodes + value for leaf nodes + + Raises ValueError if the condition expression is invalid + Raises KeyError if expression attribute names/values are invalid + + Here are the types of nodes that can be returned. + The types of child nodes are denoted with a colon (:). + An arbitrary number of children is denoted with ... + + Condition: + ('OR', [lhs : Condition, rhs : Condition]) + ('AND', [lhs: Condition, rhs: Condition]) + ('NOT', [argument: Condition]) + ('PARENTHESES', [argument: Condition]) + ('FUNCTION', [('LITERAL', function_name: str), argument: Operand, ...]) + ('BETWEEN', [query: Operand, low: Operand, high: Operand]) + ('IN', [query: Operand, possible_value: Operand, ...]) + ('COMPARISON', [lhs: Operand, ('LITERAL', comparator: str), rhs: Operand]) + + Operand: + ('EXPRESSION_ATTRIBUTE_VALUE', value: dict, e.g. {'S': 'foobar'}) + ('PATH', [('LITERAL', path_element: str), ...]) + NOTE: Expression attribute names will be expanded + ('FUNCTION', [('LITERAL', 'size'), argument: Operand]) + + Literal: + ('LITERAL', value: str) + + """ + if not self.condition_expression: + return OpDefault(None, None) + nodes = self._lex_condition_expression() + nodes = self._parse_paths(nodes) + # NOTE: The docs say that functions should be parsed after + # IN, BETWEEN, and comparisons like <=. + # However, these expressions are invalid as function arguments, + # so it is okay to parse functions first. This needs to be done + # to interpret size() correctly as an operand. + nodes = self._apply_functions(nodes) + nodes = self._apply_comparator(nodes) + nodes = self._apply_in(nodes) + nodes = self._apply_between(nodes) + nodes = self._apply_parens_and_booleans(nodes) + node = nodes[0] + op = self._make_op_condition(node) + return op + + class Kind: + """Enum defining types of nodes in the syntax tree.""" + + # Condition nodes + # --------------- + OR = 'OR' + AND = 'AND' + NOT = 'NOT' + PARENTHESES = 'PARENTHESES' + FUNCTION = 'FUNCTION' + BETWEEN = 'BETWEEN' + IN = 'IN' + COMPARISON = 'COMPARISON' + + # Operand nodes + # ------------- + EXPRESSION_ATTRIBUTE_VALUE = 'EXPRESSION_ATTRIBUTE_VALUE' + PATH = 'PATH' + + # Literal nodes + # -------------- + LITERAL = 'LITERAL' + + + class Nonterminal: + """Enum defining nonterminals for productions.""" + + CONDITION = 'CONDITION' + OPERAND = 'OPERAND' + COMPARATOR = 'COMPARATOR' + FUNCTION_NAME = 'FUNCTION_NAME' + IDENTIFIER = 'IDENTIFIER' + AND = 'AND' + OR = 'OR' + NOT = 'NOT' + BETWEEN = 'BETWEEN' + IN = 'IN' + COMMA = 'COMMA' + LEFT_PAREN = 'LEFT_PAREN' + RIGHT_PAREN = 'RIGHT_PAREN' + WHITESPACE = 'WHITESPACE' + + + Node = namedtuple('Node', ['nonterminal', 'kind', 'text', 'value', 'children']) + + def _lex_condition_expression(self): + nodes = deque() + remaining_expression = self.condition_expression + while remaining_expression: + node, remaining_expression = \ + self._lex_one_node(remaining_expression) + if node.nonterminal == self.Nonterminal.WHITESPACE: + continue + nodes.append(node) + return nodes + + def _lex_one_node(self, remaining_expression): + # TODO: Handle indexing like [1] + attribute_regex = '(:|#)?[A-z0-9\-_]+' + patterns = [( + self.Nonterminal.WHITESPACE, re.compile('^ +') + ), ( + self.Nonterminal.COMPARATOR, re.compile( + '^(' + # Put long expressions first for greedy matching + '<>|' + '<=|' + '>=|' + '=|' + '<|' + '>)'), + ), ( + self.Nonterminal.OPERAND, re.compile( + '^' + + attribute_regex + '(\.' + attribute_regex + '|\[[0-9]\])*') + ), ( + self.Nonterminal.COMMA, re.compile('^,') + ), ( + self.Nonterminal.LEFT_PAREN, re.compile('^\(') + ), ( + self.Nonterminal.RIGHT_PAREN, re.compile('^\)') + )] + + for nonterminal, pattern in patterns: + match = pattern.match(remaining_expression) + if match: + match_text = match.group() + break + else: # pragma: no cover + raise ValueError("Cannot parse condition starting at: " + + remaining_expression) + + value = match_text + node = self.Node( + nonterminal=nonterminal, + kind=self.Kind.LITERAL, + text=match_text, + value=match_text, + children=[]) + + remaining_expression = remaining_expression[len(match_text):] + + return node, remaining_expression + + def _parse_paths(self, nodes): + output = deque() + + while nodes: + node = nodes.popleft() + + if node.nonterminal == self.Nonterminal.OPERAND: + path = node.value.replace('[', '.[').split('.') + children = [ + self._parse_path_element(name) + for name in path] + if len(children) == 1: + child = children[0] + if child.nonterminal != self.Nonterminal.IDENTIFIER: + output.append(child) + continue + else: + for child in children: + self._assert( + child.nonterminal == self.Nonterminal.IDENTIFIER, + "Cannot use %s in path" % child.text, [node]) + output.append(self.Node( + nonterminal=self.Nonterminal.OPERAND, + kind=self.Kind.PATH, + text=node.text, + value=None, + children=children)) + else: + output.append(node) + return output + + def _parse_path_element(self, name): + reserved = { + 'and': self.Nonterminal.AND, + 'or': self.Nonterminal.OR, + 'in': self.Nonterminal.IN, + 'between': self.Nonterminal.BETWEEN, + 'not': self.Nonterminal.NOT, + } + + functions = { + 'attribute_exists', + 'attribute_not_exists', + 'attribute_type', + 'begins_with', + 'contains', + 'size', + } + + + if name.lower() in reserved: + # e.g. AND + nonterminal = reserved[name.lower()] + return self.Node( + nonterminal=nonterminal, + kind=self.Kind.LITERAL, + text=name, + value=name, + children=[]) + elif name in functions: + # e.g. attribute_exists + return self.Node( + nonterminal=self.Nonterminal.FUNCTION_NAME, + kind=self.Kind.LITERAL, + text=name, + value=name, + children=[]) + elif name.startswith(':'): + # e.g. :value0 + return self.Node( + nonterminal=self.Nonterminal.OPERAND, + kind=self.Kind.EXPRESSION_ATTRIBUTE_VALUE, + text=name, + value=self._lookup_expression_attribute_value(name), + children=[]) + elif name.startswith('#'): + # e.g. #name0 + return self.Node( + nonterminal=self.Nonterminal.IDENTIFIER, + kind=self.Kind.LITERAL, + text=name, + value=self._lookup_expression_attribute_name(name), + children=[]) + elif name.startswith('['): + # e.g. [123] + if not name.endswith(']'): # pragma: no cover + raise ValueError("Bad path element %s" % name) + return self.Node( + nonterminal=self.Nonterminal.IDENTIFIER, + kind=self.Kind.LITERAL, + text=name, + value=int(name[1:-1]), + children=[]) else: - raise NotImplementedError() + # e.g. ItemId + return self.Node( + nonterminal=self.Nonterminal.IDENTIFIER, + kind=self.Kind.LITERAL, + text=name, + value=name, + children=[]) - # Remove all spaces, tbf we could just skip them in the next step. - # The number of known options is really small so we can do a fair bit of cheating - expr = list(expr.strip()) + def _lookup_expression_attribute_value(self, name): + return self.expression_attribute_values[name] - # DodgyTokenisation stage 1 - def is_value(val): - return val not in ('<', '>', '=', '(', ')') + def _lookup_expression_attribute_name(self, name): + return self.expression_attribute_names[name] - def contains_keyword(val): - for kw in ('BETWEEN', 'IN', 'AND', 'OR', 'NOT'): - if kw in val: - return kw - return None + # NOTE: The following constructions are ordered from high precedence to low precedence + # according to + # https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Precedence + # + # = <> < <= > >= + # IN + # BETWEEN + # attribute_exists attribute_not_exists begins_with contains + # Parentheses + # NOT + # AND + # OR + # + # The grammar is taken from + # https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Syntax + # + # condition-expression ::= + # operand comparator operand + # operand BETWEEN operand AND operand + # operand IN ( operand (',' operand (, ...) )) + # function + # condition AND condition + # condition OR condition + # NOT condition + # ( condition ) + # + # comparator ::= + # = + # <> + # < + # <= + # > + # >= + # + # function ::= + # attribute_exists (path) + # attribute_not_exists (path) + # attribute_type (path, type) + # begins_with (path, substr) + # contains (path, operand) + # size (path) - def is_function(val): - return val in ('attribute_exists', 'attribute_not_exists', 'attribute_type', 'begins_with', 'contains', 'size') + def _matches(self, nodes, production): + """Check if the nodes start with the given production. - # Does the main part of splitting between sections of characters - tokens = [] - stack = '' - while len(expr) > 0: - current_char = expr.pop(0) + Parameters + ---------- + nodes: list of Node + production: list of str + The name of a Nonterminal, or '*' for anything - if current_char == ' ': - if len(stack) > 0: - tokens.append(stack) - stack = '' - elif current_char == ',': # Split params , - if len(stack) > 0: - tokens.append(stack) - stack = '' - elif is_value(current_char): - stack += current_char + """ + if len(nodes) < len(production): + return False + for i in range(len(production)): + if production[i] == '*': + continue + expected = getattr(self.Nonterminal, production[i]) + if nodes[i].nonterminal != expected: + return False + return True - kw = contains_keyword(stack) - if kw is not None: - # We have a kw in the stack, could be AND or something like 5AND - tmp = stack.replace(kw, '') - if len(tmp) > 0: - tokens.append(tmp) - tokens.append(kw) - stack = '' - else: - if len(stack) > 0: - tokens.append(stack) - tokens.append(current_char) - stack = '' - if len(stack) > 0: - tokens.append(stack) + def _apply_comparator(self, nodes): + """Apply condition := operand comparator operand.""" + output = deque() - def is_op(val): - return val in ('<', '>', '=', '>=', '<=', '<>', 'BETWEEN', 'IN', 'AND', 'OR', 'NOT') + while nodes: + if self._matches(nodes, ['*', 'COMPARATOR']): + self._assert( + self._matches(nodes, ['OPERAND', 'COMPARATOR', 'OPERAND']), + "Bad comparison", list(nodes)[:3]) + lhs = nodes.popleft() + comparator = nodes.popleft() + rhs = nodes.popleft() + nodes.appendleft(self.Node( + nonterminal=self.Nonterminal.CONDITION, + kind=self.Kind.COMPARISON, + text=" ".join([ + lhs.text, + comparator.text, + rhs.text]), + value=None, + children=[lhs, comparator, rhs])) + else: + output.append(nodes.popleft()) + return output - # DodgyTokenisation stage 2, it groups together some elements to make RPN'ing it later easier. - def handle_token(token, tokens2, token_iterator): - # ok so this essentially groups up some tokens to make later parsing easier, - # when it encounters brackets it will recurse and then unrecurse when RecursionStopIteration is raised. - if token == ')': - raise RecursionStopIteration() # Should be recursive so this should work - elif token == '(': - temp_list = [] - - try: + def _apply_in(self, nodes): + """Apply condition := operand IN ( operand , ... ).""" + output = deque() + while nodes: + if self._matches(nodes, ['*', 'IN']): + self._assert( + self._matches(nodes, ['OPERAND', 'IN', 'LEFT_PAREN']), + "Bad IN expression", list(nodes)[:3]) + lhs = nodes.popleft() + in_node = nodes.popleft() + left_paren = nodes.popleft() + all_children = [lhs, in_node, left_paren] + rhs = [] while True: - next_token = six.next(token_iterator) - handle_token(next_token, temp_list, token_iterator) - except RecursionStopIteration: - pass # Continue - except StopIteration: - ValueError('Malformed filter expression, type1') - - # Sigh, we only want to group a tuple if it doesnt contain operators - if any([is_op(item) for item in temp_list]): - # Its an expression - tokens2.append('(') - tokens2.extend(temp_list) - tokens2.append(')') + if self._matches(nodes, ['OPERAND', 'COMMA']): + operand = nodes.popleft() + separator = nodes.popleft() + all_children += [operand, separator] + rhs.append(operand) + elif self._matches(nodes, ['OPERAND', 'RIGHT_PAREN']): + operand = nodes.popleft() + separator = nodes.popleft() + all_children += [operand, separator] + rhs.append(operand) + break # Close + else: + self._assert( + False, + "Bad IN expression starting at", nodes) + nodes.appendleft(self.Node( + nonterminal=self.Nonterminal.CONDITION, + kind=self.Kind.IN, + text=" ".join([t.text for t in all_children]), + value=None, + children=[lhs] + rhs)) else: - tokens2.append(tuple(temp_list)) - elif token == 'BETWEEN': - field = tokens2.pop() - # if values map contains a number, it would be a float - # so we need to int() it anyway - op1 = six.next(token_iterator) - op1 = int(values_map.get(op1, op1)) - and_op = six.next(token_iterator) - assert and_op == 'AND' - op2 = six.next(token_iterator) - op2 = int(values_map.get(op2, op2)) - tokens2.append(['between', field, op1, op2]) - elif is_function(token): - function_list = [token] + output.append(nodes.popleft()) + return output - lbracket = six.next(token_iterator) - assert lbracket == '(' - - next_token = six.next(token_iterator) - while next_token != ')': - if next_token in values_map: - next_token = values_map[next_token] - function_list.append(next_token) - next_token = six.next(token_iterator) - - tokens2.append(function_list) - else: - # Convert tokens back to real types - if token in values_map: - token = values_map[token] - - # Need to join >= <= <> - if len(tokens2) > 0 and ((tokens2[-1] == '>' and token == '=') or (tokens2[-1] == '<' and token == '=') or (tokens2[-1] == '<' and token == '>')): - tokens2.append(tokens2.pop() + token) + def _apply_between(self, nodes): + """Apply condition := operand BETWEEN operand AND operand.""" + output = deque() + while nodes: + if self._matches(nodes, ['*', 'BETWEEN']): + self._assert( + self._matches(nodes, ['OPERAND', 'BETWEEN', 'OPERAND', + 'AND', 'OPERAND']), + "Bad BETWEEN expression", list(nodes)[:5]) + lhs = nodes.popleft() + between_node = nodes.popleft() + low = nodes.popleft() + and_node = nodes.popleft() + high = nodes.popleft() + all_children = [lhs, between_node, low, and_node, high] + nodes.appendleft(self.Node( + nonterminal=self.Nonterminal.CONDITION, + kind=self.Kind.BETWEEN, + text=" ".join([t.text for t in all_children]), + value=None, + children=[lhs, low, high])) else: - tokens2.append(token) + output.append(nodes.popleft()) + return output - tokens2 = [] - token_iterator = iter(tokens) - for token in token_iterator: - handle_token(token, tokens2, token_iterator) - - # Start of the Shunting-Yard algorithm. <-- Proper beast algorithm! - def is_number(val): - return val not in ('<', '>', '=', '>=', '<=', '<>', 'BETWEEN', 'IN', 'AND', 'OR', 'NOT') - - OPS = {'<': 5, '>': 5, '=': 5, '>=': 5, '<=': 5, '<>': 5, 'IN': 8, 'AND': 11, 'OR': 12, 'NOT': 10, 'BETWEEN': 9, '(': 100, ')': 100} - - def shunting_yard(token_list): - output = [] - op_stack = [] - - # Basically takes in an infix notation calculation, converts it to a reverse polish notation where there is no - # ambiguity on which order operators are applied. - while len(token_list) > 0: - token = token_list.pop(0) - - if token == '(': - op_stack.append(token) - elif token == ')': - while len(op_stack) > 0 and op_stack[-1] != '(': - output.append(op_stack.pop()) - lbracket = op_stack.pop() - assert lbracket == '(' - - elif is_number(token): - output.append(token) + def _apply_functions(self, nodes): + """Apply condition := function_name (operand , ...).""" + output = deque() + either_kind = {self.Kind.PATH, self.Kind.EXPRESSION_ATTRIBUTE_VALUE} + expected_argument_kind_map = { + 'attribute_exists': [{self.Kind.PATH}], + 'attribute_not_exists': [{self.Kind.PATH}], + 'attribute_type': [either_kind, {self.Kind.EXPRESSION_ATTRIBUTE_VALUE}], + 'begins_with': [either_kind, either_kind], + 'contains': [either_kind, either_kind], + 'size': [{self.Kind.PATH}], + } + while nodes: + if self._matches(nodes, ['FUNCTION_NAME']): + self._assert( + self._matches(nodes, ['FUNCTION_NAME', 'LEFT_PAREN', + 'OPERAND', '*']), + "Bad function expression at", list(nodes)[:4]) + function_name = nodes.popleft() + left_paren = nodes.popleft() + all_children = [function_name, left_paren] + arguments = [] + while True: + if self._matches(nodes, ['OPERAND', 'COMMA']): + operand = nodes.popleft() + separator = nodes.popleft() + all_children += [operand, separator] + arguments.append(operand) + elif self._matches(nodes, ['OPERAND', 'RIGHT_PAREN']): + operand = nodes.popleft() + separator = nodes.popleft() + all_children += [operand, separator] + arguments.append(operand) + break # Close paren + else: + self._assert( + False, + "Bad function expression", all_children + list(nodes)[:2]) + expected_kinds = expected_argument_kind_map[function_name.value] + self._assert( + len(arguments) == len(expected_kinds), + "Wrong number of arguments in", all_children) + for i in range(len(expected_kinds)): + self._assert( + arguments[i].kind in expected_kinds[i], + "Wrong type for argument %d in" % i, all_children) + if function_name.value == 'size': + nonterminal = self.Nonterminal.OPERAND + else: + nonterminal = self.Nonterminal.CONDITION + nodes.appendleft(self.Node( + nonterminal=nonterminal, + kind=self.Kind.FUNCTION, + text=" ".join([t.text for t in all_children]), + value=None, + children=[function_name] + arguments)) else: - # Must be operator kw + output.append(nodes.popleft()) + return output - # Cheat, NOT is our only RIGHT associative operator, should really have dict of operator associativity - while len(op_stack) > 0 and OPS[op_stack[-1]] <= OPS[token] and op_stack[-1] != 'NOT': - output.append(op_stack.pop()) - op_stack.append(token) - while len(op_stack) > 0: - output.append(op_stack.pop()) + def _apply_parens_and_booleans(self, nodes, left_paren=None): + """Apply condition := ( condition ) and booleans.""" + output = deque() + while nodes: + if self._matches(nodes, ['LEFT_PAREN']): + parsed = self._apply_parens_and_booleans(nodes, left_paren=nodes.popleft()) + self._assert( + len(parsed) >= 1, + "Failed to close parentheses at", nodes) + parens = parsed.popleft() + self._assert( + parens.kind == self.Kind.PARENTHESES, + "Failed to close parentheses at", nodes) + output.append(parens) + nodes = parsed + elif self._matches(nodes, ['RIGHT_PAREN']): + self._assert( + left_paren is not None, + "Unmatched ) at", nodes) + close_paren = nodes.popleft() + children = self._apply_booleans(output) + all_children = [left_paren] + list(children) + [close_paren] + return deque([ + self.Node( + nonterminal=self.Nonterminal.CONDITION, + kind=self.Kind.PARENTHESES, + text=" ".join([t.text for t in all_children]), + value=None, + children=list(children), + )] + list(nodes)) + else: + output.append(nodes.popleft()) + + self._assert( + left_paren is None, + "Unmatched ( at", list(output)) + return self._apply_booleans(output) + + def _apply_booleans(self, nodes): + """Apply and, or, and not constructions.""" + nodes = self._apply_not(nodes) + nodes = self._apply_and(nodes) + nodes = self._apply_or(nodes) + # The expression should reduce to a single condition + self._assert( + len(nodes) == 1, + "Unexpected expression at", list(nodes)[1:]) + self._assert( + nodes[0].nonterminal == self.Nonterminal.CONDITION, + "Incomplete condition", nodes) + return nodes + + def _apply_not(self, nodes): + """Apply condition := NOT condition.""" + output = deque() + while nodes: + if self._matches(nodes, ['NOT']): + self._assert( + self._matches(nodes, ['NOT', 'CONDITION']), + "Bad NOT expression", list(nodes)[:2]) + not_node = nodes.popleft() + child = nodes.popleft() + nodes.appendleft(self.Node( + nonterminal=self.Nonterminal.CONDITION, + kind=self.Kind.NOT, + text=" ".join([not_node.text, child.text]), + value=None, + children=[child])) + else: + output.append(nodes.popleft()) return output - output = shunting_yard(tokens2) - - # Hacky function to convert dynamo functions (which are represented as lists) to their Class equivalent - def to_func(val): - if isinstance(val, list): - func_name = val.pop(0) - # Expand rest of the list to arguments - val = FUNC_CLASS[func_name](*val) - - return val - - # Simple reverse polish notation execution. Builts up a nested filter object. - # The filter object then takes a dynamo item and returns true/false - stack = [] - for token in output: - if is_op(token): - op_cls = OP_CLASS[token] - - if token == 'NOT': - op1 = stack.pop() - op2 = True + def _apply_and(self, nodes): + """Apply condition := condition AND condition.""" + output = deque() + while nodes: + if self._matches(nodes, ['*', 'AND']): + self._assert( + self._matches(nodes, ['CONDITION', 'AND', 'CONDITION']), + "Bad AND expression", list(nodes)[:3]) + lhs = nodes.popleft() + and_node = nodes.popleft() + rhs = nodes.popleft() + all_children = [lhs, and_node, rhs] + nodes.appendleft(self.Node( + nonterminal=self.Nonterminal.CONDITION, + kind=self.Kind.AND, + text=" ".join([t.text for t in all_children]), + value=None, + children=[lhs, rhs])) else: - op2 = stack.pop() - op1 = stack.pop() + output.append(nodes.popleft()) - stack.append(op_cls(op1, op2)) + return output + + def _apply_or(self, nodes): + """Apply condition := condition OR condition.""" + output = deque() + while nodes: + if self._matches(nodes, ['*', 'OR']): + self._assert( + self._matches(nodes, ['CONDITION', 'OR', 'CONDITION']), + "Bad OR expression", list(nodes)[:3]) + lhs = nodes.popleft() + or_node = nodes.popleft() + rhs = nodes.popleft() + all_children = [lhs, or_node, rhs] + nodes.appendleft(self.Node( + nonterminal=self.Nonterminal.CONDITION, + kind=self.Kind.OR, + text=" ".join([t.text for t in all_children]), + value=None, + children=[lhs, rhs])) + else: + output.append(nodes.popleft()) + + return output + + def _make_operand(self, node): + if node.kind == self.Kind.PATH: + return AttributePath([child.value for child in node.children]) + elif node.kind == self.Kind.EXPRESSION_ATTRIBUTE_VALUE: + return AttributeValue(node.value) + elif node.kind == self.Kind.FUNCTION: + # size() + function_node = node.children[0] + arguments = node.children[1:] + function_name = function_node.value + arguments = [self._make_operand(arg) for arg in arguments] + return FUNC_CLASS[function_name](*arguments) + else: # pragma: no cover + raise ValueError("Unknown operand: %r" % node) + + + def _make_op_condition(self, node): + if node.kind == self.Kind.OR: + lhs, rhs = node.children + return OpOr( + self._make_op_condition(lhs), + self._make_op_condition(rhs)) + elif node.kind == self.Kind.AND: + lhs, rhs = node.children + return OpAnd( + self._make_op_condition(lhs), + self._make_op_condition(rhs)) + elif node.kind == self.Kind.NOT: + child, = node.children + return OpNot(self._make_op_condition(child)) + elif node.kind == self.Kind.PARENTHESES: + child, = node.children + return self._make_op_condition(child) + elif node.kind == self.Kind.FUNCTION: + function_node = node.children[0] + arguments = node.children[1:] + function_name = function_node.value + arguments = [self._make_operand(arg) for arg in arguments] + return FUNC_CLASS[function_name](*arguments) + elif node.kind == self.Kind.BETWEEN: + query, low, high = node.children + return FuncBetween( + self._make_operand(query), + self._make_operand(low), + self._make_operand(high)) + elif node.kind == self.Kind.IN: + query = node.children[0] + possible_values = node.children[1:] + query = self._make_operand(query) + possible_values = [self._make_operand(v) for v in possible_values] + return FuncIn(query, *possible_values) + elif node.kind == self.Kind.COMPARISON: + lhs, comparator, rhs = node.children + return COMPARATOR_CLASS[comparator.value]( + self._make_operand(lhs), + self._make_operand(rhs)) + else: # pragma: no cover + raise ValueError("Unknown expression node kind %r" % node.kind) + + def _print_debug(self, nodes): # pragma: no cover + print('ROOT') + for node in nodes: + self._print_node_recursive(node, depth=1) + + def _print_node_recursive(self, node, depth=0): # pragma: no cover + if len(node.children) > 0: + print(' ' * depth, node.nonterminal, node.kind) + for child in node.children: + self._print_node_recursive(child, depth=depth + 1) else: - stack.append(to_func(token)) - - result = stack.pop(0) - if len(stack) > 0: - raise ValueError('Malformed filter expression, type2') - - return result + print(' ' * depth, node.nonterminal, node.kind, node.value) -class Op(object): - """ - Base class for a FilterExpression operator - """ - OP = '' - def __init__(self, lhs, rhs): - self.lhs = lhs - self.rhs = rhs + def _assert(self, condition, message, nodes): + if not condition: + raise ValueError(message + " " + " ".join([t.text for t in nodes])) + + +class Operand(object): + def expr(self, item): + raise NotImplementedError + + def get_type(self, item): + raise NotImplementedError + + +class AttributePath(Operand): + def __init__(self, path): + """Initialize the AttributePath. + + Parameters + ---------- + path: list of int/str - def _lhs(self, item): """ - :type item: moto.dynamodb2.models.Item - """ - lhs = self.lhs - if isinstance(self.lhs, (Op, Func)): - lhs = self.lhs.expr(item) - elif isinstance(self.lhs, six.string_types): - try: - lhs = item.attrs[self.lhs].cast_value - except Exception: - pass + assert len(path) >= 1 + self.path = path - return lhs + def _get_attr(self, item): + if item is None: + return None - def _rhs(self, item): - rhs = self.rhs - if isinstance(self.rhs, (Op, Func)): - rhs = self.rhs.expr(item) - elif isinstance(self.rhs, six.string_types): - try: - rhs = item.attrs[self.rhs].cast_value - except Exception: - pass - return rhs + base = self.path[0] + if base not in item.attrs: + return None + attr = item.attrs[base] + + for name in self.path[1:]: + attr = attr.child_attr(name) + if attr is None: + return None + + return attr def expr(self, item): - return True + attr = self._get_attr(item) + if attr is None: + return None + else: + return attr.cast_value + + def get_type(self, item): + attr = self._get_attr(item) + if attr is None: + return None + else: + return attr.type def __repr__(self): - return '({0} {1} {2})'.format(self.lhs, self.OP, self.rhs) + return ".".join(self.path) -class Func(object): - """ - Base class for a FilterExpression function - """ - FUNC = 'Unknown' +class AttributeValue(Operand): + def __init__(self, value): + """Initialize the AttributePath. + + Parameters + ---------- + value: dict + e.g. {'N': '1.234'} + + """ + self.type = list(value.keys())[0] + self.value = value[self.type] def expr(self, item): - return True + # TODO: Reuse DynamoType code + if self.type == 'N': + try: + return int(self.value) + except ValueError: + return float(self.value) + elif self.type in ['SS', 'NS', 'BS']: + sub_type = self.type[0] + return set([AttributeValue({sub_type: v}).expr(item) + for v in self.value]) + elif self.type == 'L': + return [AttributeValue(v).expr(item) for v in self.value] + elif self.type == 'M': + return dict([ + (k, AttributeValue(v).expr(item)) + for k, v in self.value.items()]) + else: + return self.value + return self.value + + def get_type(self, item): + return self.type def __repr__(self): - return 'Func(...)'.format(self.FUNC) + return repr(self.value) + + +class OpDefault(Op): + OP = 'NONE' + + def expr(self, item): + """If no condition is specified, always True.""" + return True class OpNot(Op): OP = 'NOT' - def expr(self, item): - lhs = self._lhs(item) + def __init__(self, lhs): + super(OpNot, self).__init__(lhs, None) + def expr(self, item): + lhs = self.lhs.expr(item) return not lhs def __str__(self): @@ -345,8 +940,8 @@ class OpAnd(Op): OP = 'AND' def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) + lhs = self.lhs.expr(item) + rhs = self.rhs.expr(item) return lhs and rhs @@ -354,8 +949,8 @@ class OpLessThan(Op): OP = '<' def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) + lhs = self.lhs.expr(item) + rhs = self.rhs.expr(item) return lhs < rhs @@ -363,8 +958,8 @@ class OpGreaterThan(Op): OP = '>' def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) + lhs = self.lhs.expr(item) + rhs = self.rhs.expr(item) return lhs > rhs @@ -372,8 +967,8 @@ class OpEqual(Op): OP = '=' def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) + lhs = self.lhs.expr(item) + rhs = self.rhs.expr(item) return lhs == rhs @@ -381,8 +976,8 @@ class OpNotEqual(Op): OP = '<>' def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) + lhs = self.lhs.expr(item) + rhs = self.rhs.expr(item) return lhs != rhs @@ -390,8 +985,8 @@ class OpLessThanOrEqual(Op): OP = '<=' def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) + lhs = self.lhs.expr(item) + rhs = self.rhs.expr(item) return lhs <= rhs @@ -399,8 +994,8 @@ class OpGreaterThanOrEqual(Op): OP = '>=' def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) + lhs = self.lhs.expr(item) + rhs = self.rhs.expr(item) return lhs >= rhs @@ -408,18 +1003,26 @@ class OpOr(Op): OP = 'OR' def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) - return lhs or rhs + lhs = self.lhs.expr(item) + return lhs or self.rhs.expr(item) -class OpIn(Op): - OP = 'IN' +class Func(object): + """ + Base class for a FilterExpression function + """ + FUNC = 'Unknown' + + def __init__(self, *arguments): + self.arguments = arguments def expr(self, item): - lhs = self._lhs(item) - rhs = self._rhs(item) - return lhs in rhs + raise NotImplementedError + + def __repr__(self): + return '{0}({1})'.format( + self.FUNC, + " ".join([repr(arg) for arg in self.arguments])) class FuncAttrExists(Func): @@ -427,19 +1030,14 @@ class FuncAttrExists(Func): def __init__(self, attribute): self.attr = attribute + super(FuncAttrExists, self).__init__(attribute) def expr(self, item): - return self.attr in item.attrs + return self.attr.get_type(item) is not None -class FuncAttrNotExists(Func): - FUNC = 'attribute_not_exists' - - def __init__(self, attribute): - self.attr = attribute - - def expr(self, item): - return self.attr not in item.attrs +def FuncAttrNotExists(attribute): + return OpNot(FuncAttrExists(attribute)) class FuncAttrType(Func): @@ -448,9 +1046,10 @@ class FuncAttrType(Func): def __init__(self, attribute, _type): self.attr = attribute self.type = _type + super(FuncAttrType, self).__init__(attribute, _type) def expr(self, item): - return self.attr in item.attrs and item.attrs[self.attr].type == self.type + return self.attr.get_type(item) == self.type.expr(item) class FuncBeginsWith(Func): @@ -459,9 +1058,14 @@ class FuncBeginsWith(Func): def __init__(self, attribute, substr): self.attr = attribute self.substr = substr + super(FuncBeginsWith, self).__init__(attribute, substr) def expr(self, item): - return self.attr in item.attrs and item.attrs[self.attr].type == 'S' and item.attrs[self.attr].value.startswith(self.substr) + if self.attr.get_type(item) != 'S': + return False + if self.substr.get_type(item) != 'S': + return False + return self.attr.expr(item).startswith(self.substr.expr(item)) class FuncContains(Func): @@ -470,51 +1074,67 @@ class FuncContains(Func): def __init__(self, attribute, operand): self.attr = attribute self.operand = operand + super(FuncContains, self).__init__(attribute, operand) def expr(self, item): - if self.attr not in item.attrs: - return False - - if item.attrs[self.attr].type in ('S', 'SS', 'NS', 'BS', 'L', 'M'): - return self.operand in item.attrs[self.attr].value + if self.attr.get_type(item) in ('S', 'SS', 'NS', 'BS', 'L'): + try: + return self.operand.expr(item) in self.attr.expr(item) + except TypeError: + return False return False +def FuncNotContains(attribute, operand): + return OpNot(FuncContains(attribute, operand)) + + class FuncSize(Func): - FUNC = 'contains' + FUNC = 'size' def __init__(self, attribute): self.attr = attribute + super(FuncSize, self).__init__(attribute) def expr(self, item): - if self.attr not in item.attrs: + if self.attr.get_type(item) is None: raise ValueError('Invalid attribute name {0}'.format(self.attr)) - if item.attrs[self.attr].type in ('S', 'SS', 'NS', 'B', 'BS', 'L', 'M'): - return len(item.attrs[self.attr].value) + if self.attr.get_type(item) in ('S', 'SS', 'NS', 'B', 'BS', 'L', 'M'): + return len(self.attr.expr(item)) raise ValueError('Invalid filter expression') class FuncBetween(Func): - FUNC = 'between' + FUNC = 'BETWEEN' def __init__(self, attribute, start, end): self.attr = attribute self.start = start self.end = end + super(FuncBetween, self).__init__(attribute, start, end) def expr(self, item): - if self.attr not in item.attrs: - raise ValueError('Invalid attribute name {0}'.format(self.attr)) - - return self.start <= item.attrs[self.attr].cast_value <= self.end + return self.start.expr(item) <= self.attr.expr(item) <= self.end.expr(item) -OP_CLASS = { - 'NOT': OpNot, - 'AND': OpAnd, - 'OR': OpOr, - 'IN': OpIn, +class FuncIn(Func): + FUNC = 'IN' + + def __init__(self, attribute, *possible_values): + self.attr = attribute + self.possible_values = possible_values + super(FuncIn, self).__init__(attribute, *possible_values) + + def expr(self, item): + for possible_value in self.possible_values: + if self.attr.expr(item) == possible_value.expr(item): + return True + + return False + + +COMPARATOR_CLASS = { '<': OpLessThan, '>': OpGreaterThan, '<=': OpLessThanOrEqual, diff --git a/moto/dynamodb2/models.py b/moto/dynamodb2/models.py index 6bcde41b2..e868caaa8 100644 --- a/moto/dynamodb2/models.py +++ b/moto/dynamodb2/models.py @@ -6,13 +6,16 @@ import decimal import json import re import uuid +import six import boto3 from moto.compat import OrderedDict from moto.core import BaseBackend, BaseModel from moto.core.utils import unix_time from moto.core.exceptions import JsonRESTError -from .comparisons import get_comparison_func, get_filter_expression, Op +from .comparisons import get_comparison_func +from .comparisons import get_filter_expression +from .comparisons import get_expected from .exceptions import InvalidIndexNameError @@ -68,10 +71,34 @@ class DynamoType(object): except ValueError: return float(self.value) elif self.is_set(): - return set(self.value) + sub_type = self.type[0] + return set([DynamoType({sub_type: v}).cast_value + for v in self.value]) + elif self.is_list(): + return [DynamoType(v).cast_value for v in self.value] + elif self.is_map(): + return dict([ + (k, DynamoType(v).cast_value) + for k, v in self.value.items()]) else: return self.value + def child_attr(self, key): + """ + Get Map or List children by key. str for Map, int for List. + + Returns DynamoType or None. + """ + if isinstance(key, six.string_types) and self.is_map() and key in self.value: + return DynamoType(self.value[key]) + + if isinstance(key, int) and self.is_list(): + idx = key + if idx >= 0 and idx < len(self.value): + return DynamoType(self.value[idx]) + + return None + def to_json(self): return {self.type: self.value} @@ -89,6 +116,12 @@ class DynamoType(object): def is_set(self): return self.type == 'SS' or self.type == 'NS' or self.type == 'BS' + def is_list(self): + return self.type == 'L' + + def is_map(self): + return self.type == 'M' + def same_type(self, other): return self.type == other.type @@ -265,7 +298,9 @@ class Item(BaseModel): new_value = list(update_action['Value'].values())[0] if action == 'PUT': # TODO deal with other types - if isinstance(new_value, list) or isinstance(new_value, set): + if isinstance(new_value, list): + self.attrs[attribute_name] = DynamoType({"L": new_value}) + elif isinstance(new_value, set): self.attrs[attribute_name] = DynamoType({"SS": new_value}) elif isinstance(new_value, dict): self.attrs[attribute_name] = DynamoType({"M": new_value}) @@ -504,7 +539,9 @@ class Table(BaseModel): keys.append(range_key) return keys - def put_item(self, item_attrs, expected=None, overwrite=False): + def put_item(self, item_attrs, expected=None, condition_expression=None, + expression_attribute_names=None, + expression_attribute_values=None, overwrite=False): hash_value = DynamoType(item_attrs.get(self.hash_key_attr)) if self.has_range_key: range_value = DynamoType(item_attrs.get(self.range_key_attr)) @@ -527,29 +564,15 @@ class Table(BaseModel): self.range_key_type, item_attrs) if not overwrite: - if current is None: - current_attr = {} - elif hasattr(current, 'attrs'): - current_attr = current.attrs - else: - current_attr = current + if not get_expected(expected).expr(current): + raise ValueError('The conditional request failed') + condition_op = get_filter_expression( + condition_expression, + expression_attribute_names, + expression_attribute_values) + if not condition_op.expr(current): + raise ValueError('The conditional request failed') - for key, val in expected.items(): - if 'Exists' in val and val['Exists'] is False \ - or 'ComparisonOperator' in val and val['ComparisonOperator'] == 'NULL': - if key in current_attr: - raise ValueError("The conditional request failed") - elif key not in current_attr: - raise ValueError("The conditional request failed") - elif 'Value' in val and DynamoType(val['Value']).value != current_attr[key].value: - raise ValueError("The conditional request failed") - elif 'ComparisonOperator' in val: - dynamo_types = [ - DynamoType(ele) for ele in - val.get("AttributeValueList", []) - ] - if not current_attr[key].compare(val['ComparisonOperator'], dynamo_types): - raise ValueError('The conditional request failed') if range_value: self.items[hash_value][range_value] = item else: @@ -724,7 +747,7 @@ class Table(BaseModel): if idx_col_set.issubset(set(hash_set.attrs)): yield hash_set - def scan(self, filters, limit, exclusive_start_key, filter_expression=None, index_name=None): + def scan(self, filters, limit, exclusive_start_key, filter_expression=None, index_name=None, projection_expression=None): results = [] scanned_count = 0 all_indexes = self.all_indexes() @@ -763,6 +786,14 @@ class Table(BaseModel): if passes_all_conditions: results.append(item) + if projection_expression: + expressions = [x.strip() for x in projection_expression.split(',')] + results = copy.deepcopy(results) + for result in results: + for attr in list(result.attrs): + if attr not in expressions: + result.attrs.pop(attr) + results, last_evaluated_key = self._trim_results(results, limit, exclusive_start_key, index_name) return results, scanned_count, last_evaluated_key @@ -894,11 +925,15 @@ class DynamoDBBackend(BaseBackend): table.global_indexes = list(gsis_by_name.values()) return table - def put_item(self, table_name, item_attrs, expected=None, overwrite=False): + def put_item(self, table_name, item_attrs, expected=None, + condition_expression=None, expression_attribute_names=None, + expression_attribute_values=None, overwrite=False): table = self.tables.get(table_name) if not table: return None - return table.put_item(item_attrs, expected, overwrite) + return table.put_item(item_attrs, expected, condition_expression, + expression_attribute_names, + expression_attribute_values, overwrite) def get_table_keys_name(self, table_name, keys): """ @@ -954,15 +989,12 @@ class DynamoDBBackend(BaseBackend): range_values = [DynamoType(range_value) for range_value in range_value_dicts] - if filter_expression is not None: - filter_expression = get_filter_expression(filter_expression, expr_names, expr_values) - else: - filter_expression = Op(None, None) # Will always eval to true + filter_expression = get_filter_expression(filter_expression, expr_names, expr_values) return table.query(hash_key, range_comparison, range_values, limit, exclusive_start_key, scan_index_forward, projection_expression, index_name, filter_expression, **filter_kwargs) - def scan(self, table_name, filters, limit, exclusive_start_key, filter_expression, expr_names, expr_values, index_name): + def scan(self, table_name, filters, limit, exclusive_start_key, filter_expression, expr_names, expr_values, index_name, projection_expression): table = self.tables.get(table_name) if not table: return None, None, None @@ -972,15 +1004,14 @@ class DynamoDBBackend(BaseBackend): dynamo_types = [DynamoType(value) for value in comparison_values] scan_filters[key] = (comparison_operator, dynamo_types) - if filter_expression is not None: - filter_expression = get_filter_expression(filter_expression, expr_names, expr_values) - else: - filter_expression = Op(None, None) # Will always eval to true + filter_expression = get_filter_expression(filter_expression, expr_names, expr_values) - return table.scan(scan_filters, limit, exclusive_start_key, filter_expression, index_name) + projection_expression = ','.join([expr_names.get(attr, attr) for attr in projection_expression.replace(' ', '').split(',')]) + + return table.scan(scan_filters, limit, exclusive_start_key, filter_expression, index_name, projection_expression) def update_item(self, table_name, key, update_expression, attribute_updates, expression_attribute_names, - expression_attribute_values, expected=None): + expression_attribute_values, expected=None, condition_expression=None): table = self.get_table(table_name) if all([table.hash_key_attr in key, table.range_key_attr in key]): @@ -999,32 +1030,17 @@ class DynamoDBBackend(BaseBackend): item = table.get_item(hash_value, range_value) - if item is None: - item_attr = {} - elif hasattr(item, 'attrs'): - item_attr = item.attrs - else: - item_attr = item - if not expected: expected = {} - for key, val in expected.items(): - if 'Exists' in val and val['Exists'] is False \ - or 'ComparisonOperator' in val and val['ComparisonOperator'] == 'NULL': - if key in item_attr: - raise ValueError("The conditional request failed") - elif key not in item_attr: - raise ValueError("The conditional request failed") - elif 'Value' in val and DynamoType(val['Value']).value != item_attr[key].value: - raise ValueError("The conditional request failed") - elif 'ComparisonOperator' in val: - dynamo_types = [ - DynamoType(ele) for ele in - val.get("AttributeValueList", []) - ] - if not item_attr[key].compare(val['ComparisonOperator'], dynamo_types): - raise ValueError('The conditional request failed') + if not get_expected(expected).expr(item): + raise ValueError('The conditional request failed') + condition_op = get_filter_expression( + condition_expression, + expression_attribute_names, + expression_attribute_values) + if not condition_op.expr(item): + raise ValueError('The conditional request failed') # Update does not fail on new items, so create one if item is None: diff --git a/moto/dynamodb2/responses.py b/moto/dynamodb2/responses.py index 7eb565747..3e9fbb553 100644 --- a/moto/dynamodb2/responses.py +++ b/moto/dynamodb2/responses.py @@ -32,67 +32,6 @@ def get_empty_str_error(): )) -def condition_expression_to_expected(condition_expression, expression_attribute_names, expression_attribute_values): - """ - Limited condition expression syntax parsing. - Supports Global Negation ex: NOT(inner expressions). - Supports simple AND conditions ex: cond_a AND cond_b and cond_c. - Atomic expressions supported are attribute_exists(key), attribute_not_exists(key) and #key = :value. - """ - expected = {} - if condition_expression and 'OR' not in condition_expression: - reverse_re = re.compile('^NOT\s*\((.*)\)$') - reverse_m = reverse_re.match(condition_expression.strip()) - - reverse = False - if reverse_m: - reverse = True - condition_expression = reverse_m.group(1) - - cond_items = [c.strip() for c in condition_expression.split('AND')] - if cond_items: - exists_re = re.compile('^attribute_exists\s*\((.*)\)$') - not_exists_re = re.compile( - '^attribute_not_exists\s*\((.*)\)$') - equals_re = re.compile('^(#?\w+)\s*=\s*(\:?\w+)') - - for cond in cond_items: - exists_m = exists_re.match(cond) - not_exists_m = not_exists_re.match(cond) - equals_m = equals_re.match(cond) - - if exists_m: - attribute_name = expression_attribute_names_lookup(exists_m.group(1), expression_attribute_names) - expected[attribute_name] = {'Exists': True if not reverse else False} - elif not_exists_m: - attribute_name = expression_attribute_names_lookup(not_exists_m.group(1), expression_attribute_names) - expected[attribute_name] = {'Exists': False if not reverse else True} - elif equals_m: - attribute_name = expression_attribute_names_lookup(equals_m.group(1), expression_attribute_names) - attribute_value = expression_attribute_values_lookup(equals_m.group(2), expression_attribute_values) - expected[attribute_name] = { - 'AttributeValueList': [attribute_value], - 'ComparisonOperator': 'EQ' if not reverse else 'NEQ'} - - return expected - - -def expression_attribute_names_lookup(attribute_name, expression_attribute_names): - if attribute_name.startswith('#') and attribute_name in expression_attribute_names: - return expression_attribute_names[attribute_name] - else: - return attribute_name - - -def expression_attribute_values_lookup(attribute_value, expression_attribute_values): - if isinstance(attribute_value, six.string_types) and \ - attribute_value.startswith(':') and\ - attribute_value in expression_attribute_values: - return expression_attribute_values[attribute_value] - else: - return attribute_value - - class DynamoHandler(BaseResponse): def get_endpoint_name(self, headers): @@ -166,7 +105,7 @@ class DynamoHandler(BaseResponse): when BillingMode is PAY_PER_REQUEST') throughput = None else: # Provisioned (default billing mode) - throughput = body["ProvisionedThroughput"] + throughput = body.get("ProvisionedThroughput") # getting the schema key_schema = body['KeySchema'] # getting attribute definition @@ -288,18 +227,18 @@ class DynamoHandler(BaseResponse): # Attempt to parse simple ConditionExpressions into an Expected # expression - if not expected: - condition_expression = self.body.get('ConditionExpression') - expression_attribute_names = self.body.get('ExpressionAttributeNames', {}) - expression_attribute_values = self.body.get('ExpressionAttributeValues', {}) - expected = condition_expression_to_expected(condition_expression, - expression_attribute_names, - expression_attribute_values) - if expected: - overwrite = False + condition_expression = self.body.get('ConditionExpression') + expression_attribute_names = self.body.get('ExpressionAttributeNames', {}) + expression_attribute_values = self.body.get('ExpressionAttributeValues', {}) + + if condition_expression: + overwrite = False try: - result = self.dynamodb_backend.put_item(name, item, expected, overwrite) + result = self.dynamodb_backend.put_item( + name, item, expected, condition_expression, + expression_attribute_names, expression_attribute_values, + overwrite) except ValueError: er = 'com.amazonaws.dynamodb.v20111205#ConditionalCheckFailedException' return self.error(er, 'A condition specified in the operation could not be evaluated.') @@ -379,6 +318,9 @@ class DynamoHandler(BaseResponse): for table_name, table_request in table_batches.items(): keys = table_request['Keys'] + if self._contains_duplicates(keys): + er = 'com.amazon.coral.validate#ValidationException' + return self.error(er, 'Provided list of item keys contains duplicates') attributes_to_get = table_request.get('AttributesToGet') results["Responses"][table_name] = [] for key in keys: @@ -394,6 +336,15 @@ class DynamoHandler(BaseResponse): }) return dynamo_json_dump(results) + def _contains_duplicates(self, keys): + unique_keys = [] + for k in keys: + if k in unique_keys: + return True + else: + unique_keys.append(k) + return False + def query(self): name = self.body['TableName'] # {u'KeyConditionExpression': u'#n0 = :v0', u'ExpressionAttributeValues': {u':v0': {u'S': u'johndoe'}}, u'ExpressionAttributeNames': {u'#n0': u'username'}} @@ -558,7 +509,7 @@ class DynamoHandler(BaseResponse): filter_expression = self.body.get('FilterExpression') expression_attribute_values = self.body.get('ExpressionAttributeValues', {}) expression_attribute_names = self.body.get('ExpressionAttributeNames', {}) - + projection_expression = self.body.get('ProjectionExpression', '') exclusive_start_key = self.body.get('ExclusiveStartKey') limit = self.body.get("Limit") index_name = self.body.get('IndexName') @@ -570,7 +521,8 @@ class DynamoHandler(BaseResponse): filter_expression, expression_attribute_names, expression_attribute_values, - index_name) + index_name, + projection_expression) except InvalidIndexNameError as err: er = 'com.amazonaws.dynamodb.v20111205#ValidationException' return self.error(er, str(err)) @@ -625,7 +577,7 @@ class DynamoHandler(BaseResponse): name = self.body['TableName'] key = self.body['Key'] return_values = self.body.get('ReturnValues', 'NONE') - update_expression = self.body.get('UpdateExpression') + update_expression = self.body.get('UpdateExpression', '').strip() attribute_updates = self.body.get('AttributeUpdates') expression_attribute_names = self.body.get( 'ExpressionAttributeNames', {}) @@ -652,24 +604,20 @@ class DynamoHandler(BaseResponse): # Attempt to parse simple ConditionExpressions into an Expected # expression - if not expected: - condition_expression = self.body.get('ConditionExpression') - expression_attribute_names = self.body.get('ExpressionAttributeNames', {}) - expression_attribute_values = self.body.get('ExpressionAttributeValues', {}) - expected = condition_expression_to_expected(condition_expression, - expression_attribute_names, - expression_attribute_values) + condition_expression = self.body.get('ConditionExpression') + expression_attribute_names = self.body.get('ExpressionAttributeNames', {}) + expression_attribute_values = self.body.get('ExpressionAttributeValues', {}) # Support spaces between operators in an update expression # E.g. `a = b + c` -> `a=b+c` if update_expression: update_expression = re.sub( - '\s*([=\+-])\s*', '\\1', update_expression) + r'\s*([=\+-])\s*', '\\1', update_expression) try: item = self.dynamodb_backend.update_item( name, key, update_expression, attribute_updates, expression_attribute_names, - expression_attribute_values, expected + expression_attribute_values, expected, condition_expression ) except ValueError: er = 'com.amazonaws.dynamodb.v20111205#ConditionalCheckFailedException' diff --git a/moto/ec2/exceptions.py b/moto/ec2/exceptions.py index 1357d49e2..b7a49cc57 100644 --- a/moto/ec2/exceptions.py +++ b/moto/ec2/exceptions.py @@ -332,6 +332,15 @@ class InvalidParameterValueErrorTagNull(EC2ClientError): "Tag value cannot be null. Use empty string instead.") +class InvalidParameterValueErrorUnknownAttribute(EC2ClientError): + + def __init__(self, parameter_value): + super(InvalidParameterValueErrorUnknownAttribute, self).__init__( + "InvalidParameterValue", + "Value ({0}) for parameter attribute is invalid. Unknown attribute." + .format(parameter_value)) + + class InvalidInternetGatewayIdError(EC2ClientError): def __init__(self, internet_gateway_id): @@ -430,6 +439,16 @@ class OperationNotPermitted(EC2ClientError): ) +class InvalidAvailabilityZoneError(EC2ClientError): + + def __init__(self, availability_zone_value, valid_availability_zones): + super(InvalidAvailabilityZoneError, self).__init__( + "InvalidParameterValue", + "Value ({0}) for parameter availabilityZone is invalid. " + "Subnets can currently only be created in the following availability zones: {1}.".format(availability_zone_value, valid_availability_zones) + ) + + class NetworkAclEntryAlreadyExistsError(EC2ClientError): def __init__(self, rule_number): @@ -504,3 +523,11 @@ class OperationNotPermitted3(EC2ClientError): pcx_id, acceptor_region) ) + + +class InvalidLaunchTemplateNameError(EC2ClientError): + def __init__(self): + super(InvalidLaunchTemplateNameError, self).__init__( + "InvalidLaunchTemplateName.AlreadyExistsException", + "Launch template name already in use." + ) diff --git a/moto/ec2/models.py b/moto/ec2/models.py index b894853d2..10d6f2b28 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -20,7 +20,6 @@ from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType from boto.ec2.spotinstancerequest import SpotInstanceRequest as BotoSpotRequest from boto.ec2.launchspecification import LaunchSpecification - from moto.compat import OrderedDict from moto.core import BaseBackend from moto.core.models import Model, BaseModel @@ -36,6 +35,7 @@ from .exceptions import ( InvalidAMIIdError, InvalidAMIAttributeItemValueError, InvalidAssociationIdError, + InvalidAvailabilityZoneError, InvalidCIDRBlockParameterError, InvalidCIDRSubnetError, InvalidCustomerGatewayIdError, @@ -48,11 +48,13 @@ from .exceptions import ( InvalidKeyPairDuplicateError, InvalidKeyPairFormatError, InvalidKeyPairNameError, + InvalidLaunchTemplateNameError, InvalidNetworkAclIdError, InvalidNetworkAttachmentIdError, InvalidNetworkInterfaceIdError, InvalidParameterValueError, InvalidParameterValueErrorTagNull, + InvalidParameterValueErrorUnknownAttribute, InvalidPermissionNotFoundError, InvalidPermissionDuplicateError, InvalidRouteTableIdError, @@ -96,6 +98,7 @@ from .utils import ( random_internet_gateway_id, random_ip, random_ipv6_cidr, + random_launch_template_id, random_nat_gateway_id, random_key_pair, random_private_ip, @@ -140,6 +143,8 @@ AMIS = json.load( __name__, 'resources/amis.json'), 'r') ) +OWNER_ID = "111122223333" + def utc_date_and_time(): return datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.000Z') @@ -199,7 +204,7 @@ class TaggedEC2Resource(BaseModel): class NetworkInterface(TaggedEC2Resource): def __init__(self, ec2_backend, subnet, private_ip_address, device_index=0, - public_ip_auto_assign=True, group_ids=None): + public_ip_auto_assign=True, group_ids=None, description=None): self.ec2_backend = ec2_backend self.id = random_eni_id() self.device_index = device_index @@ -207,6 +212,7 @@ class NetworkInterface(TaggedEC2Resource): self.subnet = subnet self.instance = None self.attachment_id = None + self.description = description self.public_ip = None self.public_ip_auto_assign = public_ip_auto_assign @@ -244,11 +250,13 @@ class NetworkInterface(TaggedEC2Resource): subnet = None private_ip_address = properties.get('PrivateIpAddress', None) + description = properties.get('Description', None) network_interface = ec2_backend.create_network_interface( subnet, private_ip_address, - group_ids=security_group_ids + group_ids=security_group_ids, + description=description ) return network_interface @@ -296,6 +304,8 @@ class NetworkInterface(TaggedEC2Resource): return [group.id for group in self._group_set] elif filter_name == 'availability-zone': return self.subnet.availability_zone + elif filter_name == 'description': + return self.description else: return super(NetworkInterface, self).get_filter_value( filter_name, 'DescribeNetworkInterfaces') @@ -306,9 +316,9 @@ class NetworkInterfaceBackend(object): self.enis = {} super(NetworkInterfaceBackend, self).__init__() - def create_network_interface(self, subnet, private_ip_address, group_ids=None, **kwargs): + def create_network_interface(self, subnet, private_ip_address, group_ids=None, description=None, **kwargs): eni = NetworkInterface( - self, subnet, private_ip_address, group_ids=group_ids, **kwargs) + self, subnet, private_ip_address, group_ids=group_ids, description=description, **kwargs) self.enis[eni.id] = eni return eni @@ -341,6 +351,12 @@ class NetworkInterfaceBackend(object): if group.id in _filter_value: enis.append(eni) break + elif _filter == 'private-ip-address:': + enis = [eni for eni in enis if eni.private_ip_address in _filter_value] + elif _filter == 'subnet-id': + enis = [eni for eni in enis if eni.subnet.id in _filter_value] + elif _filter == 'description': + enis = [eni for eni in enis if eni.description in _filter_value] else: self.raise_not_implemented_error( "The filter '{0}' for DescribeNetworkInterfaces".format(_filter)) @@ -382,6 +398,10 @@ class NetworkInterfaceBackend(object): class Instance(TaggedEC2Resource, BotoInstance): + VALID_ATTRIBUTES = {'instanceType', 'kernel', 'ramdisk', 'userData', 'disableApiTermination', + 'instanceInitiatedShutdownBehavior', 'rootDeviceName', 'blockDeviceMapping', + 'productCodes', 'sourceDestCheck', 'groupSet', 'ebsOptimized', 'sriovNetSupport'} + def __init__(self, ec2_backend, image_id, user_data, security_groups, **kwargs): super(Instance, self).__init__() self.ec2_backend = ec2_backend @@ -404,11 +424,13 @@ class Instance(TaggedEC2Resource, BotoInstance): self.launch_time = utc_date_and_time() self.ami_launch_index = kwargs.get("ami_launch_index", 0) self.disable_api_termination = kwargs.get("disable_api_termination", False) + self.instance_initiated_shutdown_behavior = kwargs.get("instance_initiated_shutdown_behavior", "stop") + self.sriov_net_support = "simple" self._spot_fleet_id = kwargs.get("spot_fleet_id", None) - associate_public_ip = kwargs.get("associate_public_ip", False) + self.associate_public_ip = kwargs.get("associate_public_ip", False) if in_ec2_classic: # If we are in EC2-Classic, autoassign a public IP - associate_public_ip = True + self.associate_public_ip = True amis = self.ec2_backend.describe_images(filters={'image-id': image_id}) ami = amis[0] if amis else None @@ -439,9 +461,9 @@ class Instance(TaggedEC2Resource, BotoInstance): self.vpc_id = subnet.vpc_id self._placement.zone = subnet.availability_zone - if associate_public_ip is None: + if self.associate_public_ip is None: # Mapping public ip hasnt been explicitly enabled or disabled - associate_public_ip = subnet.map_public_ip_on_launch == 'true' + self.associate_public_ip = subnet.map_public_ip_on_launch == 'true' elif placement: self._placement.zone = placement else: @@ -453,7 +475,7 @@ class Instance(TaggedEC2Resource, BotoInstance): self.prep_nics( kwargs.get("nics", {}), private_ip=kwargs.get("private_ip"), - associate_public_ip=associate_public_ip + associate_public_ip=self.associate_public_ip ) def __del__(self): @@ -787,14 +809,22 @@ class InstanceBackend(object): setattr(instance, key, value) return instance - def modify_instance_security_groups(self, instance_id, new_group_list): + def modify_instance_security_groups(self, instance_id, new_group_id_list): instance = self.get_instance(instance_id) + new_group_list = [] + for new_group_id in new_group_id_list: + new_group_list.append(self.get_security_group_from_id(new_group_id)) setattr(instance, 'security_groups', new_group_list) return instance - def describe_instance_attribute(self, instance_id, key): - if key == 'group_set': + def describe_instance_attribute(self, instance_id, attribute): + if attribute not in Instance.VALID_ATTRIBUTES: + raise InvalidParameterValueErrorUnknownAttribute(attribute) + + if attribute == 'groupSet': key = 'security_groups' + else: + key = camelcase_to_underscores(attribute) instance = self.get_instance(instance_id) value = getattr(instance, key) return instance, value @@ -1060,7 +1090,7 @@ class TagBackend(object): class Ami(TaggedEC2Resource): def __init__(self, ec2_backend, ami_id, instance=None, source_ami=None, - name=None, description=None, owner_id=111122223333, + name=None, description=None, owner_id=OWNER_ID, public=False, virtualization_type=None, architecture=None, state='available', creation_date=None, platform=None, image_type='machine', image_location=None, hypervisor=None, @@ -1173,7 +1203,7 @@ class AmiBackend(object): ami = Ami(self, ami_id, instance=instance, source_ami=None, name=name, description=description, - owner_id=context.get_current_user() if context else '111122223333') + owner_id=context.get_current_user() if context else OWNER_ID) self.amis[ami_id] = ami return ami @@ -1288,17 +1318,107 @@ class Region(object): class Zone(object): - def __init__(self, name, region_name): + def __init__(self, name, region_name, zone_id): self.name = name self.region_name = region_name + self.zone_id = zone_id class RegionsAndZonesBackend(object): regions = [Region(ri.name, ri.endpoint) for ri in boto.ec2.regions()] - zones = dict( - (region, [Zone(region + c, region) for c in 'abc']) - for region in [r.name for r in regions]) + zones = { + 'ap-south-1': [ + Zone(region_name="ap-south-1", name="ap-south-1a", zone_id="aps1-az1"), + Zone(region_name="ap-south-1", name="ap-south-1b", zone_id="aps1-az3") + ], + 'eu-west-3': [ + Zone(region_name="eu-west-3", name="eu-west-3a", zone_id="euw3-az1"), + Zone(region_name="eu-west-3", name="eu-west-3b", zone_id="euw3-az2"), + Zone(region_name="eu-west-3", name="eu-west-3c", zone_id="euw3-az3") + ], + 'eu-north-1': [ + Zone(region_name="eu-north-1", name="eu-north-1a", zone_id="eun1-az1"), + Zone(region_name="eu-north-1", name="eu-north-1b", zone_id="eun1-az2"), + Zone(region_name="eu-north-1", name="eu-north-1c", zone_id="eun1-az3") + ], + 'eu-west-2': [ + Zone(region_name="eu-west-2", name="eu-west-2a", zone_id="euw2-az2"), + Zone(region_name="eu-west-2", name="eu-west-2b", zone_id="euw2-az3"), + Zone(region_name="eu-west-2", name="eu-west-2c", zone_id="euw2-az1") + ], + 'eu-west-1': [ + Zone(region_name="eu-west-1", name="eu-west-1a", zone_id="euw1-az3"), + Zone(region_name="eu-west-1", name="eu-west-1b", zone_id="euw1-az1"), + Zone(region_name="eu-west-1", name="eu-west-1c", zone_id="euw1-az2") + ], + 'ap-northeast-3': [ + Zone(region_name="ap-northeast-3", name="ap-northeast-2a", zone_id="apne3-az1") + ], + 'ap-northeast-2': [ + Zone(region_name="ap-northeast-2", name="ap-northeast-2a", zone_id="apne2-az1"), + Zone(region_name="ap-northeast-2", name="ap-northeast-2c", zone_id="apne2-az3") + ], + 'ap-northeast-1': [ + Zone(region_name="ap-northeast-1", name="ap-northeast-1a", zone_id="apne1-az4"), + Zone(region_name="ap-northeast-1", name="ap-northeast-1c", zone_id="apne1-az1"), + Zone(region_name="ap-northeast-1", name="ap-northeast-1d", zone_id="apne1-az2") + ], + 'sa-east-1': [ + Zone(region_name="sa-east-1", name="sa-east-1a", zone_id="sae1-az1"), + Zone(region_name="sa-east-1", name="sa-east-1c", zone_id="sae1-az3") + ], + 'ca-central-1': [ + Zone(region_name="ca-central-1", name="ca-central-1a", zone_id="cac1-az1"), + Zone(region_name="ca-central-1", name="ca-central-1b", zone_id="cac1-az2") + ], + 'ap-southeast-1': [ + Zone(region_name="ap-southeast-1", name="ap-southeast-1a", zone_id="apse1-az1"), + Zone(region_name="ap-southeast-1", name="ap-southeast-1b", zone_id="apse1-az2"), + Zone(region_name="ap-southeast-1", name="ap-southeast-1c", zone_id="apse1-az3") + ], + 'ap-southeast-2': [ + Zone(region_name="ap-southeast-2", name="ap-southeast-2a", zone_id="apse2-az1"), + Zone(region_name="ap-southeast-2", name="ap-southeast-2b", zone_id="apse2-az3"), + Zone(region_name="ap-southeast-2", name="ap-southeast-2c", zone_id="apse2-az2") + ], + 'eu-central-1': [ + Zone(region_name="eu-central-1", name="eu-central-1a", zone_id="euc1-az2"), + Zone(region_name="eu-central-1", name="eu-central-1b", zone_id="euc1-az3"), + Zone(region_name="eu-central-1", name="eu-central-1c", zone_id="euc1-az1") + ], + 'us-east-1': [ + Zone(region_name="us-east-1", name="us-east-1a", zone_id="use1-az6"), + Zone(region_name="us-east-1", name="us-east-1b", zone_id="use1-az1"), + Zone(region_name="us-east-1", name="us-east-1c", zone_id="use1-az2"), + Zone(region_name="us-east-1", name="us-east-1d", zone_id="use1-az4"), + Zone(region_name="us-east-1", name="us-east-1e", zone_id="use1-az3"), + Zone(region_name="us-east-1", name="us-east-1f", zone_id="use1-az5") + ], + 'us-east-2': [ + Zone(region_name="us-east-2", name="us-east-2a", zone_id="use2-az1"), + Zone(region_name="us-east-2", name="us-east-2b", zone_id="use2-az2"), + Zone(region_name="us-east-2", name="us-east-2c", zone_id="use2-az3") + ], + 'us-west-1': [ + Zone(region_name="us-west-1", name="us-west-1a", zone_id="usw1-az3"), + Zone(region_name="us-west-1", name="us-west-1b", zone_id="usw1-az1") + ], + 'us-west-2': [ + Zone(region_name="us-west-2", name="us-west-2a", zone_id="usw2-az2"), + Zone(region_name="us-west-2", name="us-west-2b", zone_id="usw2-az1"), + Zone(region_name="us-west-2", name="us-west-2c", zone_id="usw2-az3") + ], + 'cn-north-1': [ + Zone(region_name="cn-north-1", name="cn-north-1a", zone_id="cnn1-az1"), + Zone(region_name="cn-north-1", name="cn-north-1b", zone_id="cnn1-az2") + ], + 'us-gov-west-1': [ + Zone(region_name="us-gov-west-1", name="us-gov-west-1a", zone_id="usgw1-az1"), + Zone(region_name="us-gov-west-1", name="us-gov-west-1b", zone_id="usgw1-az2"), + Zone(region_name="us-gov-west-1", name="us-gov-west-1c", zone_id="usgw1-az3") + ] + } def describe_regions(self, region_names=[]): if len(region_names) == 0: @@ -1351,7 +1471,7 @@ class SecurityGroup(TaggedEC2Resource): self.egress_rules = [SecurityRule(-1, None, None, ['0.0.0.0/0'], [])] self.enis = {} self.vpc_id = vpc_id - self.owner_id = "123456789012" + self.owner_id = OWNER_ID @classmethod def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): @@ -1872,7 +1992,7 @@ class Volume(TaggedEC2Resource): class Snapshot(TaggedEC2Resource): - def __init__(self, ec2_backend, snapshot_id, volume, description, encrypted=False, owner_id='123456789012'): + def __init__(self, ec2_backend, snapshot_id, volume, description, encrypted=False, owner_id=OWNER_ID): self.id = snapshot_id self.volume = volume self.description = description @@ -2374,7 +2494,7 @@ class VPCPeeringConnectionBackend(object): class Subnet(TaggedEC2Resource): def __init__(self, ec2_backend, subnet_id, vpc_id, cidr_block, availability_zone, default_for_az, - map_public_ip_on_launch): + map_public_ip_on_launch, owner_id=OWNER_ID, assign_ipv6_address_on_creation=False): self.ec2_backend = ec2_backend self.id = subnet_id self.vpc_id = vpc_id @@ -2383,6 +2503,9 @@ class Subnet(TaggedEC2Resource): self._availability_zone = availability_zone self.default_for_az = default_for_az self.map_public_ip_on_launch = map_public_ip_on_launch + self.owner_id = owner_id + self.assign_ipv6_address_on_creation = assign_ipv6_address_on_creation + self.ipv6_cidr_block_associations = [] # Theory is we assign ip's as we go (as 16,777,214 usable IPs in a /8) self._subnet_ip_generator = self.cidr.hosts() @@ -2412,7 +2535,7 @@ class Subnet(TaggedEC2Resource): @property def availability_zone(self): - return self._availability_zone + return self._availability_zone.name @property def physical_resource_id(self): @@ -2509,7 +2632,7 @@ class SubnetBackend(object): return subnets[subnet_id] raise InvalidSubnetIdError(subnet_id) - def create_subnet(self, vpc_id, cidr_block, availability_zone): + def create_subnet(self, vpc_id, cidr_block, availability_zone, context=None): subnet_id = random_subnet_id() vpc = self.get_vpc(vpc_id) # Validate VPC exists and the supplied CIDR block is a subnet of the VPC's vpc_cidr_block = ipaddress.IPv4Network(six.text_type(vpc.cidr_block), strict=False) @@ -2529,8 +2652,15 @@ class SubnetBackend(object): # consider it the default default_for_az = str(availability_zone not in self.subnets).lower() map_public_ip_on_launch = default_for_az - subnet = Subnet(self, subnet_id, vpc_id, cidr_block, availability_zone, - default_for_az, map_public_ip_on_launch) + if availability_zone is None: + availability_zone = 'us-east-1a' + try: + availability_zone_data = next(zone for zones in RegionsAndZonesBackend.zones.values() for zone in zones if zone.name == availability_zone) + except StopIteration: + raise InvalidAvailabilityZoneError(availability_zone, ", ".join([zone.name for zones in RegionsAndZonesBackend.zones.values() for zone in zones])) + subnet = Subnet(self, subnet_id, vpc_id, cidr_block, availability_zone_data, + default_for_az, map_public_ip_on_launch, + owner_id=context.get_current_user() if context else OWNER_ID, assign_ipv6_address_on_creation=False) # AWS associates a new subnet with the default Network ACL self.associate_default_network_acl_with_subnet(subnet_id, vpc_id) @@ -2558,11 +2688,12 @@ class SubnetBackend(object): return subnets.pop(subnet_id, None) raise InvalidSubnetIdError(subnet_id) - def modify_subnet_attribute(self, subnet_id, map_public_ip): + def modify_subnet_attribute(self, subnet_id, attr_name, attr_value): subnet = self.get_subnet(subnet_id) - if map_public_ip not in ('true', 'false'): - raise InvalidParameterValueError(map_public_ip) - subnet.map_public_ip_on_launch = map_public_ip + if attr_name in ('map_public_ip_on_launch', 'assign_ipv6_address_on_creation'): + setattr(subnet, attr_name, attr_value) + else: + raise InvalidParameterValueError(attr_name) class SubnetRouteTableAssociation(object): @@ -3983,6 +4114,92 @@ class NatGatewayBackend(object): return self.nat_gateways.pop(nat_gateway_id) +class LaunchTemplateVersion(object): + def __init__(self, template, number, data, description): + self.template = template + self.number = number + self.data = data + self.description = description + self.create_time = utc_date_and_time() + + +class LaunchTemplate(TaggedEC2Resource): + def __init__(self, backend, name, template_data, version_description): + self.ec2_backend = backend + self.name = name + self.id = random_launch_template_id() + self.create_time = utc_date_and_time() + + self.versions = [] + self.create_version(template_data, version_description) + self.default_version_number = 1 + + def create_version(self, data, description): + num = len(self.versions) + 1 + version = LaunchTemplateVersion(self, num, data, description) + self.versions.append(version) + return version + + def is_default(self, version): + return self.default_version == version.number + + def get_version(self, num): + return self.versions[num - 1] + + def default_version(self): + return self.versions[self.default_version_number - 1] + + def latest_version(self): + return self.versions[-1] + + @property + def latest_version_number(self): + return self.latest_version().number + + def get_filter_value(self, filter_name): + if filter_name == 'launch-template-name': + return self.name + else: + return super(LaunchTemplate, self).get_filter_value( + filter_name, "DescribeLaunchTemplates") + + +class LaunchTemplateBackend(object): + def __init__(self): + self.launch_template_name_to_ids = {} + self.launch_templates = OrderedDict() + self.launch_template_insert_order = [] + super(LaunchTemplateBackend, self).__init__() + + def create_launch_template(self, name, description, template_data): + if name in self.launch_template_name_to_ids: + raise InvalidLaunchTemplateNameError() + template = LaunchTemplate(self, name, template_data, description) + self.launch_templates[template.id] = template + self.launch_template_name_to_ids[template.name] = template.id + self.launch_template_insert_order.append(template.id) + return template + + def get_launch_template(self, template_id): + return self.launch_templates[template_id] + + def get_launch_template_by_name(self, name): + return self.get_launch_template(self.launch_template_name_to_ids[name]) + + def get_launch_templates(self, template_names=None, template_ids=None, filters=None): + if template_names and not template_ids: + template_ids = [] + for name in template_names: + template_ids.append(self.launch_template_name_to_ids[name]) + + if template_ids: + templates = [self.launch_templates[tid] for tid in template_ids] + else: + templates = list(self.launch_templates.values()) + + return generic_filter(filters, templates) + + class EC2Backend(BaseBackend, InstanceBackend, TagBackend, EBSBackend, RegionsAndZonesBackend, SecurityGroupBackend, AmiBackend, VPCBackend, SubnetBackend, SubnetRouteTableAssociationBackend, @@ -3992,7 +4209,7 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, EBSBackend, VPCGatewayAttachmentBackend, SpotFleetBackend, SpotRequestBackend, ElasticAddressBackend, KeyPairBackend, DHCPOptionsSetBackend, NetworkAclBackend, VpnGatewayBackend, - CustomerGatewayBackend, NatGatewayBackend): + CustomerGatewayBackend, NatGatewayBackend, LaunchTemplateBackend): def __init__(self, region_name): self.region_name = region_name super(EC2Backend, self).__init__() @@ -4047,6 +4264,8 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, EBSBackend, elif resource_prefix == EC2_RESOURCE_TO_PREFIX['internet-gateway']: self.describe_internet_gateways( internet_gateway_ids=[resource_id]) + elif resource_prefix == EC2_RESOURCE_TO_PREFIX['launch-template']: + self.get_launch_template(resource_id) elif resource_prefix == EC2_RESOURCE_TO_PREFIX['network-acl']: self.get_all_network_acls() elif resource_prefix == EC2_RESOURCE_TO_PREFIX['network-interface']: diff --git a/moto/ec2/responses/__init__.py b/moto/ec2/responses/__init__.py index 1222a7ef8..d0648eb50 100644 --- a/moto/ec2/responses/__init__.py +++ b/moto/ec2/responses/__init__.py @@ -14,6 +14,7 @@ from .instances import InstanceResponse from .internet_gateways import InternetGateways from .ip_addresses import IPAddresses from .key_pairs import KeyPairs +from .launch_templates import LaunchTemplates from .monitoring import Monitoring from .network_acls import NetworkACLs from .placement_groups import PlacementGroups @@ -49,6 +50,7 @@ class EC2Response( InternetGateways, IPAddresses, KeyPairs, + LaunchTemplates, Monitoring, NetworkACLs, PlacementGroups, diff --git a/moto/ec2/responses/elastic_network_interfaces.py b/moto/ec2/responses/elastic_network_interfaces.py index dc8b92df8..9c37e70da 100644 --- a/moto/ec2/responses/elastic_network_interfaces.py +++ b/moto/ec2/responses/elastic_network_interfaces.py @@ -10,9 +10,10 @@ class ElasticNetworkInterfaces(BaseResponse): private_ip_address = self._get_param('PrivateIpAddress') groups = self._get_multi_param('SecurityGroupId') subnet = self.ec2_backend.get_subnet(subnet_id) + description = self._get_param('Description') if self.is_not_dryrun('CreateNetworkInterface'): eni = self.ec2_backend.create_network_interface( - subnet, private_ip_address, groups) + subnet, private_ip_address, groups, description) template = self.response_template( CREATE_NETWORK_INTERFACE_RESPONSE) return template.render(eni=eni) @@ -78,7 +79,11 @@ CREATE_NETWORK_INTERFACE_RESPONSE = """ {{ eni.subnet.id }} {{ eni.subnet.vpc_id }} us-west-2a + {% if eni.description %} + {{ eni.description }} + {% else %} + {% endif %} 498654062920 false pending @@ -121,7 +126,7 @@ DESCRIBE_NETWORK_INTERFACES_RESPONSE = """{{ eni.subnet.id }} {{ eni.subnet.vpc_id }} us-west-2a - Primary network interface + {{ eni.description }} 190610284047 false {% if eni.attachment_id %} diff --git a/moto/ec2/responses/instances.py b/moto/ec2/responses/instances.py index a5359daca..82c2b1997 100644 --- a/moto/ec2/responses/instances.py +++ b/moto/ec2/responses/instances.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals from boto.ec2.instancetype import InstanceType + +from moto.autoscaling import autoscaling_backends from moto.core.responses import BaseResponse from moto.core.utils import camelcase_to_underscores from moto.ec2.utils import filters_from_querystring, \ @@ -46,6 +48,7 @@ class InstanceResponse(BaseResponse): associate_public_ip = self._get_param('AssociatePublicIpAddress') key_name = self._get_param('KeyName') ebs_optimized = self._get_param('EbsOptimized') + instance_initiated_shutdown_behavior = self._get_param("InstanceInitiatedShutdownBehavior") tags = self._parse_tag_specification("TagSpecification") region_name = self.region @@ -55,7 +58,7 @@ class InstanceResponse(BaseResponse): instance_type=instance_type, placement=placement, region_name=region_name, subnet_id=subnet_id, owner_id=owner_id, key_name=key_name, security_group_ids=security_group_ids, nics=nics, private_ip=private_ip, associate_public_ip=associate_public_ip, - tags=tags, ebs_optimized=ebs_optimized) + tags=tags, ebs_optimized=ebs_optimized, instance_initiated_shutdown_behavior=instance_initiated_shutdown_behavior) template = self.response_template(EC2_RUN_INSTANCES) return template.render(reservation=new_reservation) @@ -64,6 +67,7 @@ class InstanceResponse(BaseResponse): instance_ids = self._get_multi_param('InstanceId') if self.is_not_dryrun('TerminateInstance'): instances = self.ec2_backend.terminate_instances(instance_ids) + autoscaling_backends[self.region].notify_terminate_instances(instance_ids) template = self.response_template(EC2_TERMINATE_INSTANCES) return template.render(instances=instances) @@ -113,12 +117,11 @@ class InstanceResponse(BaseResponse): # TODO this and modify below should raise IncorrectInstanceState if # instance not in stopped state attribute = self._get_param('Attribute') - key = camelcase_to_underscores(attribute) instance_id = self._get_param('InstanceId') instance, value = self.ec2_backend.describe_instance_attribute( - instance_id, key) + instance_id, attribute) - if key == "group_set": + if attribute == "groupSet": template = self.response_template( EC2_DESCRIBE_INSTANCE_GROUPSET_ATTRIBUTE) else: @@ -597,7 +600,9 @@ EC2_DESCRIBE_INSTANCE_ATTRIBUTE = """59dbff89-35bd-4eac-99ed-be587EXAMPLE {{ instance.id }} <{{ attribute }}> - {% for sg_id in value %} + {% for sg in value %} - {{ sg_id }} + {{ sg.id }} {% endfor %} diff --git a/moto/ec2/responses/subnets.py b/moto/ec2/responses/subnets.py index ba4f78a5e..0412d9e8b 100644 --- a/moto/ec2/responses/subnets.py +++ b/moto/ec2/responses/subnets.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import random from moto.core.responses import BaseResponse +from moto.core.utils import camelcase_to_underscores from moto.ec2.utils import filters_from_querystring @@ -16,6 +17,7 @@ class Subnets(BaseResponse): vpc_id, cidr_block, availability_zone, + context=self, ) template = self.response_template(CREATE_SUBNET_RESPONSE) return template.render(subnet=subnet) @@ -35,9 +37,14 @@ class Subnets(BaseResponse): def modify_subnet_attribute(self): subnet_id = self._get_param('SubnetId') - map_public_ip = self._get_param('MapPublicIpOnLaunch.Value') - self.ec2_backend.modify_subnet_attribute(subnet_id, map_public_ip) - return MODIFY_SUBNET_ATTRIBUTE_RESPONSE + + for attribute in ('MapPublicIpOnLaunch', 'AssignIpv6AddressOnCreation'): + if self.querystring.get('%s.Value' % attribute): + attr_name = camelcase_to_underscores(attribute) + attr_value = self.querystring.get('%s.Value' % attribute)[0] + self.ec2_backend.modify_subnet_attribute( + subnet_id, attr_name, attr_value) + return MODIFY_SUBNET_ATTRIBUTE_RESPONSE CREATE_SUBNET_RESPONSE = """ @@ -49,17 +56,14 @@ CREATE_SUBNET_RESPONSE = """ {{ subnet.vpc_id }} {{ subnet.cidr_block }} 251 - {{ subnet.availability_zone }} - - {% for tag in subnet.get_tags() %} - - {{ tag.resource_id }} - {{ tag.resource_type }} - {{ tag.key }} - {{ tag.value }} - - {% endfor %} - + {{ subnet._availability_zone.name }} + {{ subnet._availability_zone.zone_id }} + {{ subnet.default_for_az }} + {{ subnet.map_public_ip_on_launch }} + {{ subnet.owner_id }} + {{ subnet.assign_ipv6_address_on_creation }} + {{ subnet.ipv6_cidr_block_associations }} + arn:aws:ec2:{{ subnet._availability_zone.name[0:-1] }}:{{ subnet.owner_id }}:subnet/{{ subnet.id }} """ @@ -80,19 +84,26 @@ DESCRIBE_SUBNETS_RESPONSE = """ {{ subnet.vpc_id }} {{ subnet.cidr_block }} 251 - {{ subnet.availability_zone }} + {{ subnet._availability_zone.name }} + {{ subnet._availability_zone.zone_id }} {{ subnet.default_for_az }} {{ subnet.map_public_ip_on_launch }} - - {% for tag in subnet.get_tags() %} - - {{ tag.resource_id }} - {{ tag.resource_type }} - {{ tag.key }} - {{ tag.value }} - - {% endfor %} - + {{ subnet.owner_id }} + {{ subnet.assign_ipv6_address_on_creation }} + {{ subnet.ipv6_cidr_block_associations }} + arn:aws:ec2:{{ subnet._availability_zone.name[0:-1] }}:{{ subnet.owner_id }}:subnet/{{ subnet.id }} + {% if subnet.get_tags() %} + + {% for tag in subnet.get_tags() %} + + {{ tag.resource_id }} + {{ tag.resource_type }} + {{ tag.key }} + {{ tag.value }} + + {% endfor %} + + {% endif %} {% endfor %} diff --git a/moto/ec2/utils.py b/moto/ec2/utils.py index a998f18ef..e67cb39f4 100644 --- a/moto/ec2/utils.py +++ b/moto/ec2/utils.py @@ -20,6 +20,7 @@ EC2_RESOURCE_TO_PREFIX = { 'image': 'ami', 'instance': 'i', 'internet-gateway': 'igw', + 'launch-template': 'lt', 'nat-gateway': 'nat', 'network-acl': 'acl', 'network-acl-subnet-assoc': 'aclassoc', @@ -161,6 +162,10 @@ def random_nat_gateway_id(): return random_id(prefix=EC2_RESOURCE_TO_PREFIX['nat-gateway'], size=17) +def random_launch_template_id(): + return random_id(prefix=EC2_RESOURCE_TO_PREFIX['launch-template'], size=17) + + def random_public_ip(): return '54.214.{0}.{1}'.format(random.choice(range(255)), random.choice(range(255))) diff --git a/moto/ecr/models.py b/moto/ecr/models.py index 4849ffbfa..b03f25dee 100644 --- a/moto/ecr/models.py +++ b/moto/ecr/models.py @@ -1,7 +1,9 @@ from __future__ import unicode_literals import hashlib +import re from copy import copy +from datetime import datetime from random import random from botocore.exceptions import ParamValidationError @@ -105,7 +107,7 @@ class Image(BaseObject): self.repository = repository self.registry_id = registry_id self.image_digest = digest - self.image_pushed_at = None + self.image_pushed_at = str(datetime.utcnow().isoformat()) def _create_digest(self): image_contents = 'docker_image{0}'.format(int(random() * 10 ** 6)) @@ -119,6 +121,12 @@ class Image(BaseObject): def get_image_manifest(self): return self.image_manifest + def remove_tag(self, tag): + if tag is not None and tag in self.image_tags: + self.image_tags.remove(tag) + if self.image_tags: + self.image_tag = self.image_tags[-1] + def update_tag(self, tag): self.image_tag = tag if tag not in self.image_tags and tag is not None: @@ -151,7 +159,7 @@ class Image(BaseObject): response_object['repositoryName'] = self.repository response_object['registryId'] = self.registry_id response_object['imageSizeInBytes'] = self.image_size_in_bytes - response_object['imagePushedAt'] = '2017-05-09' + response_object['imagePushedAt'] = self.image_pushed_at return {k: v for k, v in response_object.items() if v is not None and v != []} @property @@ -165,6 +173,13 @@ class Image(BaseObject): response_object['registryId'] = self.registry_id return {k: v for k, v in response_object.items() if v is not None and v != [None]} + @property + def response_batch_delete_image(self): + response_object = {} + response_object['imageDigest'] = self.get_image_digest() + response_object['imageTag'] = self.image_tag + return {k: v for k, v in response_object.items() if v is not None and v != [None]} + class ECRBackend(BaseBackend): @@ -310,6 +325,106 @@ class ECRBackend(BaseBackend): return response + def batch_delete_image(self, repository_name, registry_id=None, image_ids=None): + if repository_name in self.repositories: + repository = self.repositories[repository_name] + else: + raise RepositoryNotFoundException( + repository_name, registry_id or DEFAULT_REGISTRY_ID + ) + + if not image_ids: + raise ParamValidationError( + msg='Missing required parameter in input: "imageIds"' + ) + + response = { + "imageIds": [], + "failures": [] + } + + for image_id in image_ids: + image_found = False + + # Is request missing both digest and tag? + if "imageDigest" not in image_id and "imageTag" not in image_id: + response["failures"].append( + { + "imageId": {}, + "failureCode": "MissingDigestAndTag", + "failureReason": "Invalid request parameters: both tag and digest cannot be null", + } + ) + continue + + # If we have a digest, is it valid? + if "imageDigest" in image_id: + pattern = re.compile("^[0-9a-zA-Z_+\.-]+:[0-9a-fA-F]{64}") + if not pattern.match(image_id.get("imageDigest")): + response["failures"].append( + { + "imageId": { + "imageDigest": image_id.get("imageDigest", "null") + }, + "failureCode": "InvalidImageDigest", + "failureReason": "Invalid request parameters: image digest should satisfy the regex '[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+'", + } + ) + continue + + for num, image in enumerate(repository.images): + + # Search by matching both digest and tag + if "imageDigest" in image_id and "imageTag" in image_id: + if ( + image_id["imageDigest"] == image.get_image_digest() and + image_id["imageTag"] in image.image_tags + ): + image_found = True + for image_tag in reversed(image.image_tags): + repository.images[num].image_tag = image_tag + response["imageIds"].append( + image.response_batch_delete_image + ) + repository.images[num].remove_tag(image_tag) + del repository.images[num] + + # Search by matching digest + elif "imageDigest" in image_id and image.get_image_digest() == image_id["imageDigest"]: + image_found = True + for image_tag in reversed(image.image_tags): + repository.images[num].image_tag = image_tag + response["imageIds"].append(image.response_batch_delete_image) + repository.images[num].remove_tag(image_tag) + del repository.images[num] + + # Search by matching tag + elif "imageTag" in image_id and image_id["imageTag"] in image.image_tags: + image_found = True + repository.images[num].image_tag = image_id["imageTag"] + response["imageIds"].append(image.response_batch_delete_image) + if len(image.image_tags) > 1: + repository.images[num].remove_tag(image_id["imageTag"]) + else: + repository.images.remove(image) + + if not image_found: + failure_response = { + "imageId": {}, + "failureCode": "ImageNotFound", + "failureReason": "Requested image not found", + } + + if "imageDigest" in image_id: + failure_response["imageId"]["imageDigest"] = image_id.get("imageDigest", "null") + + if "imageTag" in image_id: + failure_response["imageId"]["imageTag"] = image_id.get("imageTag", "null") + + response["failures"].append(failure_response) + + return response + ecr_backends = {} for region, ec2_backend in ec2_backends.items(): diff --git a/moto/ecr/responses.py b/moto/ecr/responses.py index af237769f..f758176ad 100644 --- a/moto/ecr/responses.py +++ b/moto/ecr/responses.py @@ -84,9 +84,12 @@ class ECRResponse(BaseResponse): 'ECR.batch_check_layer_availability is not yet implemented') def batch_delete_image(self): - if self.is_not_dryrun('BatchDeleteImage'): - raise NotImplementedError( - 'ECR.batch_delete_image is not yet implemented') + repository_str = self._get_param('repositoryName') + registry_id = self._get_param('registryId') + image_ids = self._get_param('imageIds') + + response = self.ecr_backend.batch_delete_image(repository_str, registry_id, image_ids) + return json.dumps(response) def batch_get_image(self): repository_str = self._get_param('repositoryName') diff --git a/moto/ecs/exceptions.py b/moto/ecs/exceptions.py index bb7e685c8..6e329f227 100644 --- a/moto/ecs/exceptions.py +++ b/moto/ecs/exceptions.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -from moto.core.exceptions import RESTError +from moto.core.exceptions import RESTError, JsonRESTError class ServiceNotFoundException(RESTError): @@ -11,3 +11,13 @@ class ServiceNotFoundException(RESTError): message="The service {0} does not exist".format(service_name), template='error_json', ) + + +class TaskDefinitionNotFoundException(JsonRESTError): + code = 400 + + def __init__(self): + super(TaskDefinitionNotFoundException, self).__init__( + error_type="ClientException", + message="The specified task definition does not exist.", + ) diff --git a/moto/ecs/models.py b/moto/ecs/models.py index a314c7776..863cfc49e 100644 --- a/moto/ecs/models.py +++ b/moto/ecs/models.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals +import re import uuid from datetime import datetime from random import random, randint @@ -7,10 +8,14 @@ import boto3 import pytz from moto.core.exceptions import JsonRESTError from moto.core import BaseBackend, BaseModel +from moto.core.utils import unix_time from moto.ec2 import ec2_backends from copy import copy -from .exceptions import ServiceNotFoundException +from .exceptions import ( + ServiceNotFoundException, + TaskDefinitionNotFoundException +) class BaseObject(BaseModel): @@ -103,12 +108,13 @@ class Cluster(BaseObject): class TaskDefinition(BaseObject): - def __init__(self, family, revision, container_definitions, volumes=None): + def __init__(self, family, revision, container_definitions, volumes=None, tags=None): self.family = family self.revision = revision self.arn = 'arn:aws:ecs:us-east-1:012345678910:task-definition/{0}:{1}'.format( family, revision) self.container_definitions = container_definitions + self.tags = tags if tags is not None else [] if volumes is None: self.volumes = [] else: @@ -119,6 +125,7 @@ class TaskDefinition(BaseObject): response_object = self.gen_response_object() response_object['taskDefinitionArn'] = response_object['arn'] del response_object['arn'] + del response_object['tags'] return response_object @property @@ -225,9 +232,9 @@ class Service(BaseObject): for deployment in response_object['deployments']: if isinstance(deployment['createdAt'], datetime): - deployment['createdAt'] = deployment['createdAt'].isoformat() + deployment['createdAt'] = unix_time(deployment['createdAt'].replace(tzinfo=None)) if isinstance(deployment['updatedAt'], datetime): - deployment['updatedAt'] = deployment['updatedAt'].isoformat() + deployment['updatedAt'] = unix_time(deployment['updatedAt'].replace(tzinfo=None)) return response_object @@ -422,11 +429,9 @@ class EC2ContainerServiceBackend(BaseBackend): revision = int(revision) else: family = task_definition_name - revision = len(self.task_definitions.get(family, [])) + revision = self._get_last_task_definition_revision_id(family) - if family in self.task_definitions and 0 < revision <= len(self.task_definitions[family]): - return self.task_definitions[family][revision - 1] - elif family in self.task_definitions and revision == -1: + if family in self.task_definitions and revision in self.task_definitions[family]: return self.task_definitions[family][revision] else: raise Exception( @@ -466,15 +471,16 @@ class EC2ContainerServiceBackend(BaseBackend): else: raise Exception("{0} is not a cluster".format(cluster_name)) - def register_task_definition(self, family, container_definitions, volumes): + def register_task_definition(self, family, container_definitions, volumes, tags=None): if family in self.task_definitions: - revision = len(self.task_definitions[family]) + 1 + last_id = self._get_last_task_definition_revision_id(family) + revision = (last_id or 0) + 1 else: - self.task_definitions[family] = [] + self.task_definitions[family] = {} revision = 1 task_definition = TaskDefinition( - family, revision, container_definitions, volumes) - self.task_definitions[family].append(task_definition) + family, revision, container_definitions, volumes, tags) + self.task_definitions[family][revision] = task_definition return task_definition @@ -484,16 +490,18 @@ class EC2ContainerServiceBackend(BaseBackend): """ task_arns = [] for task_definition_list in self.task_definitions.values(): - task_arns.extend( - [task_definition.arn for task_definition in task_definition_list]) + task_arns.extend([ + task_definition.arn + for task_definition in task_definition_list.values() + ]) return task_arns def deregister_task_definition(self, task_definition_str): task_definition_name = task_definition_str.split('/')[-1] family, revision = task_definition_name.split(':') revision = int(revision) - if family in self.task_definitions and 0 < revision <= len(self.task_definitions[family]): - return self.task_definitions[family].pop(revision - 1) + if family in self.task_definitions and revision in self.task_definitions[family]: + return self.task_definitions[family].pop(revision) else: raise Exception( "{0} is not a task_definition".format(task_definition_name)) @@ -950,6 +958,29 @@ class EC2ContainerServiceBackend(BaseBackend): yield task_fam + def list_tags_for_resource(self, resource_arn): + """Currently only implemented for task definitions""" + match = re.match( + "^arn:aws:ecs:(?P[^:]+):(?P[^:]+):(?P[^:]+)/(?P.*)$", + resource_arn) + if not match: + raise JsonRESTError('InvalidParameterException', 'The ARN provided is invalid.') + + service = match.group("service") + if service == "task-definition": + for task_definition in self.task_definitions.values(): + for revision in task_definition.values(): + if revision.arn == resource_arn: + return revision.tags + else: + raise TaskDefinitionNotFoundException() + raise NotImplementedError() + + def _get_last_task_definition_revision_id(self, family): + definitions = self.task_definitions.get(family, {}) + if definitions: + return max(definitions.keys()) + available_regions = boto3.session.Session().get_available_regions("ecs") ecs_backends = {region: EC2ContainerServiceBackend(region) for region in available_regions} diff --git a/moto/ecs/responses.py b/moto/ecs/responses.py index 92b769fad..abb79ea78 100644 --- a/moto/ecs/responses.py +++ b/moto/ecs/responses.py @@ -62,8 +62,9 @@ class EC2ContainerServiceResponse(BaseResponse): family = self._get_param('family') container_definitions = self._get_param('containerDefinitions') volumes = self._get_param('volumes') + tags = self._get_param('tags') task_definition = self.ecs_backend.register_task_definition( - family, container_definitions, volumes) + family, container_definitions, volumes, tags) return json.dumps({ 'taskDefinition': task_definition.response_object }) @@ -313,3 +314,8 @@ class EC2ContainerServiceResponse(BaseResponse): results = self.ecs_backend.list_task_definition_families(family_prefix, status, max_results, next_token) return json.dumps({'families': list(results)}) + + def list_tags_for_resource(self): + resource_arn = self._get_param('resourceArn') + tags = self.ecs_backend.list_tags_for_resource(resource_arn) + return json.dumps({'tags': tags}) diff --git a/moto/elbv2/models.py b/moto/elbv2/models.py index 8d98f187d..7e73c7042 100644 --- a/moto/elbv2/models.py +++ b/moto/elbv2/models.py @@ -2,9 +2,11 @@ from __future__ import unicode_literals import datetime import re +from jinja2 import Template from moto.compat import OrderedDict from moto.core.exceptions import RESTError from moto.core import BaseBackend, BaseModel +from moto.core.utils import camelcase_to_underscores from moto.ec2.models import ec2_backends from moto.acm.models import acm_backends from .utils import make_arn_for_target_group @@ -35,12 +37,13 @@ from .exceptions import ( class FakeHealthStatus(BaseModel): - def __init__(self, instance_id, port, health_port, status, reason=None): + def __init__(self, instance_id, port, health_port, status, reason=None, description=None): self.instance_id = instance_id self.port = port self.health_port = health_port self.status = status self.reason = reason + self.description = description class FakeTargetGroup(BaseModel): @@ -69,7 +72,7 @@ class FakeTargetGroup(BaseModel): self.protocol = protocol self.port = port self.healthcheck_protocol = healthcheck_protocol or 'HTTP' - self.healthcheck_port = healthcheck_port or 'traffic-port' + self.healthcheck_port = healthcheck_port or str(self.port) self.healthcheck_path = healthcheck_path or '/' self.healthcheck_interval_seconds = healthcheck_interval_seconds or 30 self.healthcheck_timeout_seconds = healthcheck_timeout_seconds or 5 @@ -112,10 +115,14 @@ class FakeTargetGroup(BaseModel): raise TooManyTagsError() self.tags[key] = value - def health_for(self, target): + def health_for(self, target, ec2_backend): t = self.targets.get(target['id']) if t is None: raise InvalidTargetError() + if t['id'].startswith("i-"): # EC2 instance ID + instance = ec2_backend.get_instance_by_id(t['id']) + if instance.state == "stopped": + return FakeHealthStatus(t['id'], t['port'], self.healthcheck_port, 'unused', 'Target.InvalidState', 'Target is in the stopped state') return FakeHealthStatus(t['id'], t['port'], self.healthcheck_port, 'healthy') @classmethod @@ -208,13 +215,12 @@ class FakeListener(BaseModel): action_type = action['Type'] if action_type == 'forward': default_actions.append({'type': action_type, 'target_group_arn': action['TargetGroupArn']}) - elif action_type == 'redirect': - redirect_action = {'type': action_type, } - for redirect_config_key, redirect_config_value in action['RedirectConfig'].items(): + elif action_type in ['redirect', 'authenticate-cognito']: + redirect_action = {'type': action_type} + key = 'RedirectConfig' if action_type == 'redirect' else 'AuthenticateCognitoConfig' + for redirect_config_key, redirect_config_value in action[key].items(): # need to match the output of _get_list_prefix - if redirect_config_key == 'StatusCode': - redirect_config_key = 'status_code' - redirect_action['redirect_config._' + redirect_config_key.lower()] = redirect_config_value + redirect_action[camelcase_to_underscores(key) + '._' + camelcase_to_underscores(redirect_config_key)] = redirect_config_value default_actions.append(redirect_action) else: raise InvalidActionTypeError(action_type, i + 1) @@ -226,6 +232,32 @@ class FakeListener(BaseModel): return listener +class FakeAction(BaseModel): + def __init__(self, data): + self.data = data + self.type = data.get("type") + + def to_xml(self): + template = Template("""{{ action.type }} + {% if action.type == "forward" %} + {{ action.data["target_group_arn"] }} + {% elif action.type == "redirect" %} + + {{ action.data["redirect_config._protocol"] }} + {{ action.data["redirect_config._port"] }} + {{ action.data["redirect_config._status_code"] }} + + {% elif action.type == "authenticate-cognito" %} + + {{ action.data["authenticate_cognito_config._user_pool_arn"] }} + {{ action.data["authenticate_cognito_config._user_pool_client_id"] }} + {{ action.data["authenticate_cognito_config._user_pool_domain"] }} + + {% endif %} + """) + return template.render(action=self) + + class FakeRule(BaseModel): def __init__(self, listener_arn, conditions, priority, actions, is_default): @@ -397,6 +429,7 @@ class ELBv2Backend(BaseBackend): return new_load_balancer def create_rule(self, listener_arn, conditions, priority, actions): + actions = [FakeAction(action) for action in actions] listeners = self.describe_listeners(None, [listener_arn]) if not listeners: raise ListenerNotFoundError() @@ -424,20 +457,7 @@ class ELBv2Backend(BaseBackend): if rule.priority == priority: raise PriorityInUseError() - # validate Actions - target_group_arns = [target_group.arn for target_group in self.target_groups.values()] - for i, action in enumerate(actions): - index = i + 1 - action_type = action['type'] - if action_type == 'forward': - action_target_group_arn = action['target_group_arn'] - if action_target_group_arn not in target_group_arns: - raise ActionTargetGroupNotFoundError(action_target_group_arn) - elif action_type == 'redirect': - # nothing to do - pass - else: - raise InvalidActionTypeError(action_type, index) + self._validate_actions(actions) # TODO: check for error 'TooManyRegistrationsForTargetId' # TODO: check for error 'TooManyRules' @@ -447,6 +467,21 @@ class ELBv2Backend(BaseBackend): listener.register(rule) return [rule] + def _validate_actions(self, actions): + # validate Actions + target_group_arns = [target_group.arn for target_group in self.target_groups.values()] + for i, action in enumerate(actions): + index = i + 1 + action_type = action.type + if action_type == 'forward': + action_target_group_arn = action.data['target_group_arn'] + if action_target_group_arn not in target_group_arns: + raise ActionTargetGroupNotFoundError(action_target_group_arn) + elif action_type in ['redirect', 'authenticate-cognito']: + pass + else: + raise InvalidActionTypeError(action_type, index) + def create_target_group(self, name, **kwargs): if len(name) > 32: raise InvalidTargetGroupNameError( @@ -490,26 +525,22 @@ class ELBv2Backend(BaseBackend): return target_group def create_listener(self, load_balancer_arn, protocol, port, ssl_policy, certificate, default_actions): + default_actions = [FakeAction(action) for action in default_actions] balancer = self.load_balancers.get(load_balancer_arn) if balancer is None: raise LoadBalancerNotFoundError() if port in balancer.listeners: raise DuplicateListenerError() + self._validate_actions(default_actions) + arn = load_balancer_arn.replace(':loadbalancer/', ':listener/') + "/%s%s" % (port, id(self)) listener = FakeListener(load_balancer_arn, arn, protocol, port, ssl_policy, certificate, default_actions) balancer.listeners[listener.arn] = listener - for i, action in enumerate(default_actions): - action_type = action['type'] - if action_type == 'forward': - if action['target_group_arn'] in self.target_groups.keys(): - target_group = self.target_groups[action['target_group_arn']] - target_group.load_balancer_arns.append(load_balancer_arn) - elif action_type == 'redirect': - # nothing to do - pass - else: - raise InvalidActionTypeError(action_type, i + 1) + for action in default_actions: + if action.type == 'forward': + target_group = self.target_groups[action.data['target_group_arn']] + target_group.load_balancer_arns.append(load_balancer_arn) return listener @@ -643,6 +674,7 @@ class ELBv2Backend(BaseBackend): raise ListenerNotFoundError() def modify_rule(self, rule_arn, conditions, actions): + actions = [FakeAction(action) for action in actions] # if conditions or actions is empty list, do not update the attributes if not conditions and not actions: raise InvalidModifyRuleArgumentsError() @@ -668,20 +700,7 @@ class ELBv2Backend(BaseBackend): # TODO: check pattern of value for 'path-pattern' # validate Actions - target_group_arns = [target_group.arn for target_group in self.target_groups.values()] - if actions: - for i, action in enumerate(actions): - index = i + 1 - action_type = action['type'] - if action_type == 'forward': - action_target_group_arn = action['target_group_arn'] - if action_target_group_arn not in target_group_arns: - raise ActionTargetGroupNotFoundError(action_target_group_arn) - elif action_type == 'redirect': - # nothing to do - pass - else: - raise InvalidActionTypeError(action_type, index) + self._validate_actions(actions) # TODO: check for error 'TooManyRegistrationsForTargetId' # TODO: check for error 'TooManyRules' @@ -712,7 +731,7 @@ class ELBv2Backend(BaseBackend): if not targets: targets = target_group.targets.values() - return [target_group.health_for(target) for target in targets] + return [target_group.health_for(target, self.ec2_backend) for target in targets] def set_rule_priorities(self, rule_priorities): # validate @@ -846,6 +865,7 @@ class ELBv2Backend(BaseBackend): return target_group def modify_listener(self, arn, port=None, protocol=None, ssl_policy=None, certificates=None, default_actions=None): + default_actions = [FakeAction(action) for action in default_actions] for load_balancer in self.load_balancers.values(): if arn in load_balancer.listeners: break @@ -912,7 +932,7 @@ class ELBv2Backend(BaseBackend): for listener in load_balancer.listeners.values(): for rule in listener.rules: for action in rule.actions: - if action.get('target_group_arn') == target_group_arn: + if action.data.get('target_group_arn') == target_group_arn: return True return False diff --git a/moto/elbv2/responses.py b/moto/elbv2/responses.py index 3ca53240b..25c23bb17 100644 --- a/moto/elbv2/responses.py +++ b/moto/elbv2/responses.py @@ -775,16 +775,7 @@ CREATE_LISTENER_TEMPLATE = """{{ action["target_group_arn"] }} - {% elif action["type"] == "redirect" %} - - {{ action["redirect_config._protocol"] }} - {{ action["redirect_config._port"] }} - {{ action["redirect_config._status_code"] }} - - {% endif %} + {{ action.to_xml() }} {% endfor %} @@ -888,16 +879,7 @@ DESCRIBE_RULES_TEMPLATE = """ - {% if action["type"] == "forward" %} - {{ action["target_group_arn"] }} - {% elif action["type"] == "redirect" %} - - {{ action["redirect_config._protocol"] }} - {{ action["redirect_config._port"] }} - {{ action["redirect_config._status_code"] }} - - {% endif %} + {{ action.to_xml() }} {% endfor %} @@ -989,16 +971,7 @@ DESCRIBE_LISTENERS_TEMPLATE = """{{ action["target_group_arn"] }}m - {% elif action["type"] == "redirect" %} - - {{ action["redirect_config._protocol"] }} - {{ action["redirect_config._port"] }} - {{ action["redirect_config._status_code"] }} - - {% endif %} + {{ action.to_xml() }} {% endfor %} @@ -1048,8 +1021,7 @@ MODIFY_RULE_TEMPLATE = """ - {{ action["target_group_arn"] }} + {{ action.to_xml() }} {% endfor %} @@ -1208,6 +1180,12 @@ DESCRIBE_TARGET_HEALTH_TEMPLATE = """{{ action["target_group_arn"] }} - {% elif action["type"] == "redirect" %} - - {{ action["redirect_config._protocol"] }} - {{ action["redirect_config._port"] }} - {{ action["redirect_config._status_code"] }} - - {% endif %} + {{ action.to_xml() }} {% endfor %} diff --git a/moto/glue/models.py b/moto/glue/models.py index 407c3a020..0989e0e9b 100644 --- a/moto/glue/models.py +++ b/moto/glue/models.py @@ -138,6 +138,12 @@ class FakeTable(BaseModel): raise PartitionAlreadyExistsException() self.partitions[key] = partition + def delete_partition(self, values): + try: + del self.partitions[str(values)] + except KeyError: + raise PartitionNotFoundException() + class FakePartition(BaseModel): def __init__(self, database_name, table_name, partiton_input): diff --git a/moto/glue/responses.py b/moto/glue/responses.py index 8f09022ca..875513e7f 100644 --- a/moto/glue/responses.py +++ b/moto/glue/responses.py @@ -4,6 +4,11 @@ import json from moto.core.responses import BaseResponse from .models import glue_backend +from .exceptions import ( + PartitionAlreadyExistsException, + PartitionNotFoundException, + TableNotFoundException +) class GlueResponse(BaseResponse): @@ -90,6 +95,28 @@ class GlueResponse(BaseResponse): resp = self.glue_backend.delete_table(database_name, table_name) return json.dumps(resp) + def batch_delete_table(self): + database_name = self.parameters.get('DatabaseName') + + errors = [] + for table_name in self.parameters.get('TablesToDelete'): + try: + self.glue_backend.delete_table(database_name, table_name) + except TableNotFoundException: + errors.append({ + "TableName": table_name, + "ErrorDetail": { + "ErrorCode": "EntityNotFoundException", + "ErrorMessage": "Table not found" + } + }) + + out = {} + if errors: + out["Errors"] = errors + + return json.dumps(out) + def get_partitions(self): database_name = self.parameters.get('DatabaseName') table_name = self.parameters.get('TableName') @@ -114,6 +141,23 @@ class GlueResponse(BaseResponse): return json.dumps({'Partition': p.as_dict()}) + def batch_get_partition(self): + database_name = self.parameters.get('DatabaseName') + table_name = self.parameters.get('TableName') + partitions_to_get = self.parameters.get('PartitionsToGet') + + table = self.glue_backend.get_table(database_name, table_name) + + partitions = [] + for values in partitions_to_get: + try: + p = table.get_partition(values=values["Values"]) + partitions.append(p.as_dict()) + except PartitionNotFoundException: + continue + + return json.dumps({'Partitions': partitions}) + def create_partition(self): database_name = self.parameters.get('DatabaseName') table_name = self.parameters.get('TableName') @@ -124,6 +168,30 @@ class GlueResponse(BaseResponse): return "" + def batch_create_partition(self): + database_name = self.parameters.get('DatabaseName') + table_name = self.parameters.get('TableName') + table = self.glue_backend.get_table(database_name, table_name) + + errors_output = [] + for part_input in self.parameters.get('PartitionInputList'): + try: + table.create_partition(part_input) + except PartitionAlreadyExistsException: + errors_output.append({ + 'PartitionValues': part_input['Values'], + 'ErrorDetail': { + 'ErrorCode': 'AlreadyExistsException', + 'ErrorMessage': 'Partition already exists.' + } + }) + + out = {} + if errors_output: + out["Errors"] = errors_output + + return json.dumps(out) + def update_partition(self): database_name = self.parameters.get('DatabaseName') table_name = self.parameters.get('TableName') @@ -134,3 +202,38 @@ class GlueResponse(BaseResponse): table.update_partition(part_to_update, part_input) return "" + + def delete_partition(self): + database_name = self.parameters.get('DatabaseName') + table_name = self.parameters.get('TableName') + part_to_delete = self.parameters.get('PartitionValues') + + table = self.glue_backend.get_table(database_name, table_name) + table.delete_partition(part_to_delete) + + return "" + + def batch_delete_partition(self): + database_name = self.parameters.get('DatabaseName') + table_name = self.parameters.get('TableName') + table = self.glue_backend.get_table(database_name, table_name) + + errors_output = [] + for part_input in self.parameters.get('PartitionsToDelete'): + values = part_input.get('Values') + try: + table.delete_partition(values) + except PartitionNotFoundException: + errors_output.append({ + 'PartitionValues': values, + 'ErrorDetail': { + 'ErrorCode': 'EntityNotFoundException', + 'ErrorMessage': 'Partition not found', + } + }) + + out = {} + if errors_output: + out['Errors'] = errors_output + + return json.dumps(out) diff --git a/moto/iam/aws_managed_policies.py b/moto/iam/aws_managed_policies.py index df348c0d9..a8fca28e0 100644 --- a/moto/iam/aws_managed_policies.py +++ b/moto/iam/aws_managed_policies.py @@ -1,6 +1,49 @@ # Imported via `make aws_managed_policies` aws_managed_policies_data = """ { + "APIGatewayServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/APIGatewayServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-20T17:23:10+00:00", + "DefaultVersionId": "v4", + "Document": { + "Statement": [ + { + "Action": [ + "elasticloadbalancing:AddListenerCertificates", + "elasticloadbalancing:RemoveListenerCertificates", + "elasticloadbalancing:ModifyListener", + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingTargets", + "xray:GetSamplingRules" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "firehose:DescribeDeliveryStream", + "firehose:PutRecord", + "firehose:PutRecordBatch" + ], + "Effect": "Allow", + "Resource": "arn:aws:firehose:*:*:deliverystream/amazon-apigateway-*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJQQDZNLDBF2ULTWK6", + "PolicyName": "APIGatewayServiceRolePolicy", + "UpdateDate": "2019-05-20T18:22:18+00:00", + "VersionId": "v4" + }, "AWSAccountActivityAccess": { "Arn": "arn:aws:iam::aws:policy/AWSAccountActivityAccess", "AttachmentCount": 0, @@ -21,6 +64,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJQRYCWMFX5J3E333K", "PolicyName": "AWSAccountActivityAccess", "UpdateDate": "2015-02-06T18:41:18+00:00", @@ -46,6 +90,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJLIB4VSBVO47ZSBB6", "PolicyName": "AWSAccountUsageReportAccess", "UpdateDate": "2015-02-06T18:41:19+00:00", @@ -127,11 +172,499 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIA3DIL7BYQ35ISM4K", "PolicyName": "AWSAgentlessDiscoveryService", "UpdateDate": "2016-08-02T01:35:11+00:00", "VersionId": "v1" }, + "AWSAppMeshFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSAppMeshFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-04-16T17:50:40+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "appmesh:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4ILVZ5BWFU", + "PolicyName": "AWSAppMeshFullAccess", + "UpdateDate": "2019-04-16T17:50:40+00:00", + "VersionId": "v1" + }, + "AWSAppMeshReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AWSAppMeshReadOnly", + "AttachmentCount": 0, + "CreateDate": "2019-04-16T17:51:11+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "appmesh:Describe*", + "appmesh:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4HOPFCIWXP", + "PolicyName": "AWSAppMeshReadOnly", + "UpdateDate": "2019-04-16T17:51:11+00:00", + "VersionId": "v1" + }, + "AWSAppMeshServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSAppMeshServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-06-03T18:30:51+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "servicediscovery:DiscoverInstances" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "CloudMapServiceDiscovery" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4B5IHMMEND", + "PolicyName": "AWSAppMeshServiceRolePolicy", + "UpdateDate": "2019-06-03T18:30:51+00:00", + "VersionId": "v1" + }, + "AWSAppSyncAdministrator": { + "Arn": "arn:aws:iam::aws:policy/AWSAppSyncAdministrator", + "AttachmentCount": 0, + "CreateDate": "2018-03-20T21:20:28+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "appsync:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "appsync.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJBYY36AJPXTTWIXCY", + "PolicyName": "AWSAppSyncAdministrator", + "UpdateDate": "2018-03-20T21:20:28+00:00", + "VersionId": "v1" + }, + "AWSAppSyncInvokeFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSAppSyncInvokeFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-03-20T21:21:20+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "appsync:GraphQL", + "appsync:GetGraphqlApi", + "appsync:ListGraphqlApis", + "appsync:ListApiKeys" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAILMPWRRZN27MPE3VM", + "PolicyName": "AWSAppSyncInvokeFullAccess", + "UpdateDate": "2018-03-20T21:21:20+00:00", + "VersionId": "v1" + }, + "AWSAppSyncPushToCloudWatchLogs": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs", + "AttachmentCount": 0, + "CreateDate": "2018-04-09T19:38:55+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIWN7WNO34HLMJPUQS", + "PolicyName": "AWSAppSyncPushToCloudWatchLogs", + "UpdateDate": "2018-04-09T19:38:55+00:00", + "VersionId": "v1" + }, + "AWSAppSyncSchemaAuthor": { + "Arn": "arn:aws:iam::aws:policy/AWSAppSyncSchemaAuthor", + "AttachmentCount": 0, + "CreateDate": "2018-03-20T21:21:06+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "appsync:GraphQL", + "appsync:CreateResolver", + "appsync:CreateType", + "appsync:DeleteResolver", + "appsync:DeleteType", + "appsync:GetResolver", + "appsync:GetType", + "appsync:GetDataSource", + "appsync:GetSchemaCreationStatus", + "appsync:GetIntrospectionSchema", + "appsync:GetGraphqlApi", + "appsync:ListTypes", + "appsync:ListApiKeys", + "appsync:ListResolvers", + "appsync:ListDataSources", + "appsync:ListGraphqlApis", + "appsync:StartSchemaCreation", + "appsync:UpdateResolver", + "appsync:UpdateType" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIUCF5WVTOFQXFKY5E", + "PolicyName": "AWSAppSyncSchemaAuthor", + "UpdateDate": "2018-03-20T21:21:06+00:00", + "VersionId": "v1" + }, + "AWSApplicationAutoScalingCustomResourcePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSApplicationAutoScalingCustomResourcePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-06-04T23:22:44+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "execute-api:Invoke", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJYTKXPX6DO32Z4XXA", + "PolicyName": "AWSApplicationAutoScalingCustomResourcePolicy", + "UpdateDate": "2018-06-04T23:22:44+00:00", + "VersionId": "v1" + }, + "AWSApplicationAutoscalingAppStreamFleetPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSApplicationAutoscalingAppStreamFleetPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-20T19:04:06+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "appstream:UpdateFleet", + "appstream:DescribeFleets", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIRI724OWKP56ZG62M", + "PolicyName": "AWSApplicationAutoscalingAppStreamFleetPolicy", + "UpdateDate": "2017-10-20T19:04:06+00:00", + "VersionId": "v1" + }, + "AWSApplicationAutoscalingDynamoDBTablePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSApplicationAutoscalingDynamoDBTablePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-20T21:34:57+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "dynamodb:DescribeTable", + "dynamodb:UpdateTable", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJOVQMDI3JFCBW4LFO", + "PolicyName": "AWSApplicationAutoscalingDynamoDBTablePolicy", + "UpdateDate": "2017-10-20T21:34:57+00:00", + "VersionId": "v1" + }, + "AWSApplicationAutoscalingEC2SpotFleetRequestPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSApplicationAutoscalingEC2SpotFleetRequestPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-25T18:23:27+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:DescribeSpotFleetRequests", + "ec2:ModifySpotFleetRequest", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJNRH3VE3WW4Q4RDTU", + "PolicyName": "AWSApplicationAutoscalingEC2SpotFleetRequestPolicy", + "UpdateDate": "2017-10-25T18:23:27+00:00", + "VersionId": "v1" + }, + "AWSApplicationAutoscalingECSServicePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSApplicationAutoscalingECSServicePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-25T23:53:08+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ecs:DescribeServices", + "ecs:UpdateService", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJFXLLV7AKH5PSFOYG", + "PolicyName": "AWSApplicationAutoscalingECSServicePolicy", + "UpdateDate": "2017-10-25T23:53:08+00:00", + "VersionId": "v1" + }, + "AWSApplicationAutoscalingEMRInstanceGroupPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSApplicationAutoscalingEMRInstanceGroupPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-26T00:57:39+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "elasticmapreduce:ListInstanceGroups", + "elasticmapreduce:ModifyInstanceGroups", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIQ6M5Z7LQY2YSG2JS", + "PolicyName": "AWSApplicationAutoscalingEMRInstanceGroupPolicy", + "UpdateDate": "2017-10-26T00:57:39+00:00", + "VersionId": "v1" + }, + "AWSApplicationAutoscalingRDSClusterPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSApplicationAutoscalingRDSClusterPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-17T17:46:56+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "rds:AddTagsToResource", + "rds:CreateDBInstance", + "rds:DeleteDBInstance", + "rds:DescribeDBClusters", + "rds:DescribeDBInstances", + "rds:ModifyDBCluster", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": "rds.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7XS52I27Q2JVKALU", + "PolicyName": "AWSApplicationAutoscalingRDSClusterPolicy", + "UpdateDate": "2018-08-07T19:14:24+00:00", + "VersionId": "v3" + }, + "AWSApplicationAutoscalingSageMakerEndpointPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSApplicationAutoscalingSageMakerEndpointPolicy", + "AttachmentCount": 0, + "CreateDate": "2018-02-06T19:58:21+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "sagemaker:DescribeEndpoint", + "sagemaker:DescribeEndpointConfig", + "sagemaker:UpdateEndpointWeightsAndCapacities", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI5DBEBNRZQ4SXYTAW", + "PolicyName": "AWSApplicationAutoscalingSageMakerEndpointPolicy", + "UpdateDate": "2018-02-06T19:58:21+00:00", + "VersionId": "v1" + }, "AWSApplicationDiscoveryAgentAccess": { "Arn": "arn:aws:iam::aws:policy/AWSApplicationDiscoveryAgentAccess", "AttachmentCount": 0, @@ -152,6 +685,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAICZIOVAGC6JPF3WHC", "PolicyName": "AWSApplicationDiscoveryAgentAccess", "UpdateDate": "2016-05-11T21:38:47+00:00", @@ -161,11 +695,157 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AWSApplicationDiscoveryServiceFullAccess", "AttachmentCount": 0, "CreateDate": "2016-05-11T21:30:50+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "mgh:*", + "discovery:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:GetRole" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "continuousexport.discovery.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/continuousexport.discovery.amazonaws.com/AWSServiceRoleForApplicationDiscoveryServiceContinuousExport*" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/continuousexport.discovery.amazonaws.com/AWSServiceRoleForApplicationDiscoveryServiceContinuousExport*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJBNJEA6ZXM2SBOPDU", + "PolicyName": "AWSApplicationDiscoveryServiceFullAccess", + "UpdateDate": "2018-08-16T16:02:27+00:00", + "VersionId": "v3" + }, + "AWSArtifactAccountSync": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSArtifactAccountSync", + "AttachmentCount": 0, + "CreateDate": "2018-04-10T23:04:33+00:00", "DefaultVersionId": "v1", "Document": { "Statement": [ { - "Action": "discovery:*", + "Action": [ + "organizations:ListAccounts", + "organizations:DescribeOrganization" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJMVPXRWZJZWDTYDNC", + "PolicyName": "AWSArtifactAccountSync", + "UpdateDate": "2018-04-10T23:04:33+00:00", + "VersionId": "v1" + }, + "AWSAutoScalingPlansEC2AutoScalingPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSAutoScalingPlansEC2AutoScalingPolicy", + "AttachmentCount": 0, + "CreateDate": "2018-08-23T22:46:59+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudwatch:GetMetricData", + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:DescribeScheduledActions", + "autoscaling:BatchPutScheduledUpdateGroupAction", + "autoscaling:BatchDeleteScheduledAction" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIXWLPZPD4RYBM3JSU", + "PolicyName": "AWSAutoScalingPlansEC2AutoScalingPolicy", + "UpdateDate": "2018-08-23T22:46:59+00:00", + "VersionId": "v1" + }, + "AWSB9InternalServicePolicy": { + "Arn": "arn:aws:iam::aws:policy/AWSB9InternalServicePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-12-13T18:48:22+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterfacePermission", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:DescribeSecurityGroups", + "greengrass:CreateDeployment", + "greengrass:CreateGroupVersion", + "greengrass:CreateFunctionDefinition", + "greengrass:CreateFunctionDefinitionVersion", + "greengrass:GetDeploymentStatus", + "greengrass:GetGroup", + "greengrass:GetGroupVersion", + "greengrass:GetCoreDefinitionVersion", + "greengrass:GetFunctionDefinitionVersion", + "greengrass:GetAssociatedRole", + "lambda:CreateFunction" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:UpdateFunctionCode", + "lambda:GetFunction", + "lambda:UpdateFunctionConfiguration" + ], + "Effect": "Allow", + "Resource": "arn:aws:lambda:*:*:function:aws-robomaker-*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringEqualsIfExists": { + "iam:PassedToService": "lambda.amazonaws.com" + } + }, "Effect": "Allow", "Resource": "*" } @@ -175,16 +855,532 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", - "PolicyId": "ANPAJBNJEA6ZXM2SBOPDU", - "PolicyName": "AWSApplicationDiscoveryServiceFullAccess", - "UpdateDate": "2016-05-11T21:30:50+00:00", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIWR2IIOQ7JJGVQOPW", + "PolicyName": "AWSB9InternalServicePolicy", + "UpdateDate": "2018-12-13T18:48:22+00:00", "VersionId": "v1" }, + "AWSBackupAdminPolicy": { + "Arn": "arn:aws:iam::aws:policy/AWSBackupAdminPolicy", + "AttachmentCount": 0, + "CreateDate": "2019-01-19T02:34:31+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": "backup:*", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "backup-storage:*", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "rds:DescribeDBSnapshots", + "rds:ListTagsForResource", + "rds:DescribeDBInstances", + "rds:describeDBSnapshots", + "rds:describeDBEngineVersions", + "rds:describeOptionGroups", + "rds:describeOrderableDBInstanceOptions", + "rds:describeDBSubnetGroups" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "dynamodb:ListBackups", + "dynamodb:ListTables" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "elasticfilesystem:DescribeFilesystems" + ], + "Effect": "Allow", + "Resource": "arn:aws:elasticfilesystem:*:*:file-system/*" + }, + { + "Action": [ + "ec2:DescribeSnapshots", + "ec2:DescribeVolumes", + "ec2:describeAvailabilityZones" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "tag:GetTagKeys", + "tag:GetTagValues", + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "storagegateway:DescribeCachediSCSIVolumes", + "storagegateway:DescribeStorediSCSIVolumes" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:gateway/*/volume/*" + }, + { + "Action": [ + "storagegateway:ListGateways" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:*" + }, + { + "Action": [ + "storagegateway:DescribeGatewayInformation", + "storagegateway:ListVolumes", + "storagegateway:ListLocalDisks" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:gateway/*" + }, + { + "Action": [ + "iam:ListRoles", + "iam:GetRole", + "iam:GetUser" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": "backup.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/*AwsBackup*", + "arn:aws:iam::*:role/*AWSBackup*" + ] + }, + { + "Action": [ + "kms:ListKeys", + "kms:DescribeKey", + "kms:GenerateDataKey", + "kms:RetireGrant", + "kms:CreateGrant", + "kms:ListAliases", + "kms:Decrypt" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJWFPFHACTI7XN6M2C", + "PolicyName": "AWSBackupAdminPolicy", + "UpdateDate": "2019-03-11T22:14:30+00:00", + "VersionId": "v2" + }, + "AWSBackupOperatorPolicy": { + "Arn": "arn:aws:iam::aws:policy/AWSBackupOperatorPolicy", + "AttachmentCount": 0, + "CreateDate": "2019-01-19T02:31:55+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "backup:Get*", + "backup:List*", + "backup:Describe*", + "backup:CreateBackupSelection", + "backup:DeleteBackupSelection", + "backup:GetRecoveryPointRestoreMetadata", + "backup:StartBackupJob", + "backup:StartRestoreJob" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "rds:DescribeDBSnapshots", + "rds:ListTagsForResource", + "rds:DescribeDBInstances", + "rds:describeDBSnapshots", + "rds:describeDBEngineVersions", + "rds:describeOptionGroups", + "rds:describeOrderableDBInstanceOptions", + "rds:describeDBSubnetGroups" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "dynamodb:ListBackups", + "dynamodb:ListTables" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "elasticfilesystem:DescribeFilesystems" + ], + "Effect": "Allow", + "Resource": "arn:aws:elasticfilesystem:*:*:file-system/*" + }, + { + "Action": [ + "ec2:DescribeSnapshots", + "ec2:DescribeVolumes", + "ec2:describeAvailabilityZones" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "tag:GetTagKeys", + "tag:GetTagValues", + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "storagegateway:DescribeCachediSCSIVolumes", + "storagegateway:DescribeStorediSCSIVolumes" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:gateway/*/volume/*" + }, + { + "Action": [ + "storagegateway:ListGateways" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:*" + }, + { + "Action": [ + "storagegateway:DescribeGatewayInformation", + "storagegateway:ListVolumes", + "storagegateway:ListLocalDisks" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:gateway/*" + }, + { + "Action": [ + "iam:ListRoles", + "iam:GetRole", + "iam:GetUser" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": "backup.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/*AwsBackup*", + "arn:aws:iam::*:role/*AWSBackup*" + ] + }, + { + "Action": [ + "kms:ListKeys", + "kms:DescribeKey", + "kms:GenerateDataKey", + "kms:RetireGrant", + "kms:CreateGrant", + "kms:ListAliases", + "kms:Decrypt" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7BHZKKS47SGORCJE", + "PolicyName": "AWSBackupOperatorPolicy", + "UpdateDate": "2019-03-11T22:18:12+00:00", + "VersionId": "v2" + }, + "AWSBackupServiceRolePolicyForBackup": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup", + "AttachmentCount": 0, + "CreateDate": "2019-01-10T21:01:28+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "dynamodb:DescribeTable", + "dynamodb:CreateBackup" + ], + "Effect": "Allow", + "Resource": "arn:aws:dynamodb:*:*:table/*" + }, + { + "Action": [ + "dynamodb:DescribeBackup", + "dynamodb:DeleteBackup" + ], + "Effect": "Allow", + "Resource": "arn:aws:dynamodb:*:*:table/*/backup/*" + }, + { + "Action": [ + "rds:AddTagsToResource", + "rds:ListTagsForResource", + "rds:DescribeDBSnapshots", + "rds:CreateDBSnapshot", + "rds:CopyDBSnapshot", + "rds:DescribeDBInstances" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "rds:DeleteDBSnapshot" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:rds:*:*:snapshot:awsbackup:*" + ] + }, + { + "Action": [ + "storagegateway:CreateSnapshot" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:gateway/*/volume/*" + }, + { + "Action": [ + "ec2:CreateTags", + "ec2:DeleteSnapshot" + ], + "Effect": "Allow", + "Resource": "arn:aws:ec2:*::snapshot/*" + }, + { + "Action": [ + "ec2:DescribeSnapshots" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "elasticfilesystem:Backup" + ], + "Effect": "Allow", + "Resource": "arn:aws:elasticfilesystem:*:*:file-system/*" + }, + { + "Action": [ + "ec2:CreateSnapshot", + "ec2:DeleteSnapshot", + "ec2:DescribeVolumes", + "ec2:DescribeSnapshots" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*::snapshot/*", + "arn:aws:ec2:*:*:volume/*" + ] + }, + { + "Action": "kms:DescribeKey", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "kms:CreateGrant", + "Condition": { + "Bool": { + "kms:GrantIsForAWSResource": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIOOYZSLZZXWFJJ5N2", + "PolicyName": "AWSBackupServiceRolePolicyForBackup", + "UpdateDate": "2019-04-25T19:15:48+00:00", + "VersionId": "v2" + }, + "AWSBackupServiceRolePolicyForRestores": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores", + "AttachmentCount": 0, + "CreateDate": "2019-01-12T00:23:54+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "dynamodb:Scan", + "dynamodb:Query", + "dynamodb:UpdateItem", + "dynamodb:PutItem", + "dynamodb:GetItem", + "dynamodb:DeleteItem", + "dynamodb:BatchWriteItem", + "dynamodb:DescribeTable" + ], + "Effect": "Allow", + "Resource": "arn:aws:dynamodb:*:*:table/*" + }, + { + "Action": [ + "dynamodb:RestoreTableFromBackup" + ], + "Effect": "Allow", + "Resource": "arn:aws:dynamodb:*:*:table/*/backup/*" + }, + { + "Action": [ + "ec2:CreateVolume", + "ec2:DeleteVolume" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*::snapshot/*", + "arn:aws:ec2:*:*:volume/*" + ] + }, + { + "Action": [ + "ec2:DescribeSnapshots", + "ec2:DescribeVolumes" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "storagegateway:DeleteVolume", + "storagegateway:DescribeCachediSCSIVolumes", + "storagegateway:DescribeStorediSCSIVolumes" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:gateway/*/volume/*" + }, + { + "Action": [ + "storagegateway:DescribeGatewayInformation", + "storagegateway:CreateStorediSCSIVolume", + "storagegateway:CreateCachediSCSIVolume" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:gateway/*" + }, + { + "Action": [ + "storagegateway:ListVolumes" + ], + "Effect": "Allow", + "Resource": "arn:aws:storagegateway:*:*:*" + }, + { + "Action": [ + "rds:DescribeDBInstances", + "rds:DescribeDBSnapshots", + "rds:ListTagsForResource", + "rds:RestoreDBInstanceFromDBSnapshot", + "rds:DeleteDBInstance", + "rds:AddTagsToResource" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "elasticfilesystem:Restore", + "elasticfilesystem:CreateFilesystem", + "elasticfilesystem:DescribeFilesystems", + "elasticfilesystem:DeleteFilesystem" + ], + "Effect": "Allow", + "Resource": "arn:aws:elasticfilesystem:*:*:file-system/*" + }, + { + "Action": "kms:DescribeKey", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "kms:CreateGrant", + "Condition": { + "Bool": { + "kms:GrantIsForAWSResource": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJZCCL6F2WPVOUXZKI", + "PolicyName": "AWSBackupServiceRolePolicyForRestores", + "UpdateDate": "2019-04-25T19:17:26+00:00", + "VersionId": "v3" + }, "AWSBatchFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSBatchFullAccess", "AttachmentCount": 0, - "CreateDate": "2016-12-13T00:38:59+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2016-12-06T19:35:42+00:00", + "DefaultVersionId": "v5", "Document": { "Statement": [ { @@ -194,6 +1390,10 @@ aws_managed_policies_data = """ "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups", "ec2:DescribeKeyPairs", + "ec2:DescribeVpcs", + "ec2:DescribeImages", + "ec2:DescribeLaunchTemplates", + "ec2:DescribeLaunchTemplateVersions", "ecs:DescribeClusters", "ecs:Describe*", "ecs:List*", @@ -214,7 +1414,9 @@ aws_managed_policies_data = """ "Effect": "Allow", "Resource": [ "arn:aws:iam::*:role/AWSBatchServiceRole", + "arn:aws:iam::*:role/service-role/AWSBatchServiceRole", "arn:aws:iam::*:role/ecsInstanceRole", + "arn:aws:iam::*:instance-profile/ecsInstanceRole", "arn:aws:iam::*:role/iaws-ec2-spot-fleet-role", "arn:aws:iam::*:role/aws-ec2-spot-fleet-role", "arn:aws:iam::*:role/AWSBatchJobRole*" @@ -226,34 +1428,68 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ7K2KIWB3HZVK3CUO", "PolicyName": "AWSBatchFullAccess", - "UpdateDate": "2016-12-13T00:38:59+00:00", - "VersionId": "v2" + "UpdateDate": "2018-11-05T21:09:23+00:00", + "VersionId": "v5" + }, + "AWSBatchServiceEventTargetRole": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSBatchServiceEventTargetRole", + "AttachmentCount": 0, + "CreateDate": "2018-02-28T22:31:13+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "batch:SubmitJob" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAICVHHZ6XHNMA6VE3Q", + "PolicyName": "AWSBatchServiceEventTargetRole", + "UpdateDate": "2018-02-28T22:31:13+00:00", + "VersionId": "v1" }, "AWSBatchServiceRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSBatchServiceRole", "AttachmentCount": 0, - "CreateDate": "2017-05-11T20:44:52+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2016-12-06T19:36:24+00:00", + "DefaultVersionId": "v9", "Document": { "Statement": [ { "Action": [ "ec2:DescribeAccountAttributes", "ec2:DescribeInstances", + "ec2:DescribeInstanceAttribute", "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups", "ec2:DescribeKeyPairs", "ec2:DescribeImages", "ec2:DescribeImageAttribute", + "ec2:DescribeSpotInstanceRequests", "ec2:DescribeSpotFleetInstances", "ec2:DescribeSpotFleetRequests", "ec2:DescribeSpotPriceHistory", + "ec2:DescribeVpcClassicLink", + "ec2:DescribeLaunchTemplateVersions", + "ec2:CreateLaunchTemplate", + "ec2:DeleteLaunchTemplate", "ec2:RequestSpotFleet", "ec2:CancelSpotFleetRequests", "ec2:ModifySpotFleetRequest", "ec2:TerminateInstances", + "ec2:RunInstances", "autoscaling:DescribeAccountLimits", "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeLaunchConfigurations", @@ -291,10 +1527,54 @@ aws_managed_policies_data = """ "logs:PutLogEvents", "logs:DescribeLogGroups", "iam:GetInstanceProfile", - "iam:PassRole" + "iam:GetRole" ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ecs-tasks.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": [ + "spot.amazonaws.com", + "spotfleet.amazonaws.com", + "autoscaling.amazonaws.com", + "ecs.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Condition": { + "StringEquals": { + "ec2:CreateAction": "RunInstances" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] } ], "Version": "2012-10-17" @@ -302,10 +1582,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIUETIXPCKASQJURFE", "PolicyName": "AWSBatchServiceRole", - "UpdateDate": "2017-05-11T20:44:52+00:00", - "VersionId": "v4" + "UpdateDate": "2018-10-30T19:00:56+00:00", + "VersionId": "v9" }, "AWSCertificateManagerFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCertificateManagerFullAccess", @@ -327,15 +1608,149 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJYCHABBP6VQIVBCBQ", "PolicyName": "AWSCertificateManagerFullAccess", "UpdateDate": "2016-01-21T17:02:36+00:00", "VersionId": "v1" }, + "AWSCertificateManagerPrivateCAAuditor": { + "Arn": "arn:aws:iam::aws:policy/AWSCertificateManagerPrivateCAAuditor", + "AttachmentCount": 0, + "CreateDate": "2018-10-23T16:51:08+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "acm-pca:CreateCertificateAuthorityAuditReport", + "acm-pca:DescribeCertificateAuthority", + "acm-pca:DescribeCertificateAuthorityAuditReport", + "acm-pca:GetCertificateAuthorityCsr", + "acm-pca:GetCertificateAuthorityCertificate", + "acm-pca:GetCertificate", + "acm-pca:ListPermissions", + "acm-pca:ListTags" + ], + "Effect": "Allow", + "Resource": "arn:aws:acm-pca:*:*:certificate-authority/*" + }, + { + "Action": [ + "acm-pca:ListCertificateAuthorities" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJW77VE4UEBJ4PEXEY", + "PolicyName": "AWSCertificateManagerPrivateCAAuditor", + "UpdateDate": "2019-03-14T17:17:38+00:00", + "VersionId": "v3" + }, + "AWSCertificateManagerPrivateCAFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSCertificateManagerPrivateCAFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-10-23T16:54:50+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "acm-pca:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIRTQUC55CREAWFLBG", + "PolicyName": "AWSCertificateManagerPrivateCAFullAccess", + "UpdateDate": "2018-10-23T16:54:50+00:00", + "VersionId": "v1" + }, + "AWSCertificateManagerPrivateCAReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AWSCertificateManagerPrivateCAReadOnly", + "AttachmentCount": 0, + "CreateDate": "2018-10-23T16:57:04+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": { + "Action": [ + "acm-pca:DescribeCertificateAuthority", + "acm-pca:DescribeCertificateAuthorityAuditReport", + "acm-pca:ListCertificateAuthorities", + "acm-pca:GetCertificateAuthorityCsr", + "acm-pca:GetCertificateAuthorityCertificate", + "acm-pca:GetCertificate", + "acm-pca:ListPermissions", + "acm-pca:ListTags" + ], + "Effect": "Allow", + "Resource": "*" + }, + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJQAQT3WIXOXY7TD4A", + "PolicyName": "AWSCertificateManagerPrivateCAReadOnly", + "UpdateDate": "2019-03-14T17:17:21+00:00", + "VersionId": "v2" + }, + "AWSCertificateManagerPrivateCAUser": { + "Arn": "arn:aws:iam::aws:policy/AWSCertificateManagerPrivateCAUser", + "AttachmentCount": 0, + "CreateDate": "2018-10-23T16:53:33+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "acm-pca:IssueCertificate", + "acm-pca:RevokeCertificate", + "acm-pca:GetCertificate", + "acm-pca:ListPermissions" + ], + "Effect": "Allow", + "Resource": "arn:aws:acm-pca:*:*:certificate-authority/*" + }, + { + "Action": [ + "acm-pca:ListCertificateAuthorities" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJBXCSJJULLMRWSNII", + "PolicyName": "AWSCertificateManagerPrivateCAUser", + "UpdateDate": "2019-03-14T17:17:02+00:00", + "VersionId": "v3" + }, "AWSCertificateManagerReadOnly": { "Arn": "arn:aws:iam::aws:policy/AWSCertificateManagerReadOnly", "AttachmentCount": 0, - "CreateDate": "2016-04-21T15:08:16+00:00", + "CreateDate": "2016-01-21T17:07:33+00:00", "DefaultVersionId": "v2", "Document": { "Statement": { @@ -353,26 +1768,274 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI4GSWX6S4MESJ3EWC", "PolicyName": "AWSCertificateManagerReadOnly", "UpdateDate": "2016-04-21T15:08:16+00:00", "VersionId": "v2" }, - "AWSCloudFormationReadOnlyAccess": { - "Arn": "arn:aws:iam::aws:policy/AWSCloudFormationReadOnlyAccess", + "AWSCloud9Administrator": { + "Arn": "arn:aws:iam::aws:policy/AWSCloud9Administrator", "AttachmentCount": 0, - "CreateDate": "2015-02-06T18:39:49+00:00", + "CreateDate": "2017-11-30T16:17:28+00:00", "DefaultVersionId": "v1", "Document": { "Statement": [ { "Action": [ + "cloud9:*", + "iam:GetUser", + "iam:ListUsers", + "ec2:DescribeVpcs", + "ec2:DescribeSubnets" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringLike": { + "iam:AWSServiceName": "cloud9.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIQ4KWP455WDTCBGWK", + "PolicyName": "AWSCloud9Administrator", + "UpdateDate": "2017-11-30T16:17:28+00:00", + "VersionId": "v1" + }, + "AWSCloud9EnvironmentMember": { + "Arn": "arn:aws:iam::aws:policy/AWSCloud9EnvironmentMember", + "AttachmentCount": 0, + "CreateDate": "2017-11-30T16:18:28+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloud9:GetUserSettings", + "cloud9:UpdateUserSettings", + "iam:GetUser", + "iam:ListUsers" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloud9:DescribeEnvironmentMemberships" + ], + "Condition": { + "Null": { + "cloud9:EnvironmentId": "true", + "cloud9:UserArn": "true" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI54ULAIPVT5HFTYGK", + "PolicyName": "AWSCloud9EnvironmentMember", + "UpdateDate": "2017-11-30T16:18:28+00:00", + "VersionId": "v1" + }, + "AWSCloud9ServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSCloud9ServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-30T13:44:08+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:RunInstances", + "ec2:CreateSecurityGroup", + "ec2:DescribeVpcs", + "ec2:DescribeSubnets", + "ec2:DescribeSecurityGroups", + "ec2:DescribeInstances", + "cloudformation:CreateStack", "cloudformation:DescribeStacks", "cloudformation:DescribeStackEvents", - "cloudformation:DescribeStackResource", - "cloudformation:DescribeStackResources", - "cloudformation:GetTemplate", - "cloudformation:List*" + "cloudformation:DescribeStackResources" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:TerminateInstances", + "ec2:DeleteSecurityGroup", + "ec2:AuthorizeSecurityGroupIngress" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloudformation:DeleteStack" + ], + "Effect": "Allow", + "Resource": "arn:aws:cloudformation:*:*:stack/aws-cloud9-*" + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Condition": { + "StringLike": { + "aws:RequestTag/Name": "aws-cloud9-*" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:ec2:*:*:instance/*" + }, + { + "Action": [ + "ec2:StartInstances", + "ec2:StopInstances" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/aws:cloudformation:stack-name": "aws-cloud9-*" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJFXGCBXQIZATFZ4YG", + "PolicyName": "AWSCloud9ServiceRolePolicy", + "UpdateDate": "2018-02-27T10:20:24+00:00", + "VersionId": "v2" + }, + "AWSCloud9User": { + "Arn": "arn:aws:iam::aws:policy/AWSCloud9User", + "AttachmentCount": 0, + "CreateDate": "2017-11-30T16:16:17+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "cloud9:ValidateEnvironmentName", + "cloud9:UpdateUserSettings", + "cloud9:GetUserSettings", + "iam:GetUser", + "iam:ListUsers", + "ec2:DescribeVpcs", + "ec2:DescribeSubnets" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloud9:CreateEnvironmentEC2", + "cloud9:CreateEnvironmentSSH" + ], + "Condition": { + "Null": { + "cloud9:OwnerArn": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloud9:GetUserPublicKey" + ], + "Condition": { + "Null": { + "cloud9:UserArn": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloud9:DescribeEnvironmentMemberships" + ], + "Condition": { + "Null": { + "cloud9:EnvironmentId": "true", + "cloud9:UserArn": "true" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringLike": { + "iam:AWSServiceName": "cloud9.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJPFGFWQF67QVARP6U", + "PolicyName": "AWSCloud9User", + "UpdateDate": "2018-07-02T08:46:37+00:00", + "VersionId": "v3" + }, + "AWSCloudFormationReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSCloudFormationReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2015-02-06T18:39:49+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "cloudformation:Describe*", + "cloudformation:EstimateTemplateCost", + "cloudformation:Get*", + "cloudformation:List*", + "cloudformation:ValidateTemplate", + "cloudformation:DetectStackDrift", + "cloudformation:DetectStackResourceDrift" ], "Effect": "Allow", "Resource": "*" @@ -383,9 +2046,38 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJWVBEE4I2POWLODLW", "PolicyName": "AWSCloudFormationReadOnlyAccess", - "UpdateDate": "2015-02-06T18:39:49+00:00", + "UpdateDate": "2019-02-06T22:16:02+00:00", + "VersionId": "v3" + }, + "AWSCloudFrontLogger": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSCloudFrontLogger", + "AttachmentCount": 0, + "CreateDate": "2018-06-12T20:15:23+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "arn:aws:logs:*:*:/aws/cloudfront/*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIOI7RPKLCNINBTRP4", + "PolicyName": "AWSCloudFrontLogger", + "UpdateDate": "2018-06-12T20:15:23+00:00", "VersionId": "v1" }, "AWSCloudHSMFullAccess": { @@ -406,6 +2098,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIMBQYQZM7F63DA2UU", "PolicyName": "AWSCloudHSMFullAccess", "UpdateDate": "2015-02-06T18:39:51+00:00", @@ -433,6 +2126,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAISVCBSY7YDBOT67KE", "PolicyName": "AWSCloudHSMReadOnlyAccess", "UpdateDate": "2015-02-06T18:39:52+00:00", @@ -467,16 +2161,153 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI7QIUU4GC66SF26WE", "PolicyName": "AWSCloudHSMRole", "UpdateDate": "2015-02-06T18:41:23+00:00", "VersionId": "v1" }, + "AWSCloudMapDiscoverInstanceAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSCloudMapDiscoverInstanceAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-29T00:02:42+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "servicediscovery:DiscoverInstances" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIPRD7PYYQVYPDME4K", + "PolicyName": "AWSCloudMapDiscoverInstanceAccess", + "UpdateDate": "2018-11-29T00:02:42+00:00", + "VersionId": "v1" + }, + "AWSCloudMapFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSCloudMapFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T23:57:31+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "route53:GetHostedZone", + "route53:ListHostedZonesByName", + "route53:CreateHostedZone", + "route53:DeleteHostedZone", + "route53:ChangeResourceRecordSets", + "route53:CreateHealthCheck", + "route53:GetHealthCheck", + "route53:DeleteHealthCheck", + "route53:UpdateHealthCheck", + "ec2:DescribeVpcs", + "ec2:DescribeRegions", + "servicediscovery:*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIZPIMAQZJS3WUXUJM", + "PolicyName": "AWSCloudMapFullAccess", + "UpdateDate": "2018-11-28T23:57:31+00:00", + "VersionId": "v1" + }, + "AWSCloudMapReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSCloudMapReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T23:45:26+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "servicediscovery:Get*", + "servicediscovery:List*", + "servicediscovery:DiscoverInstances" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIOHISHKLCJTVQQL5E", + "PolicyName": "AWSCloudMapReadOnlyAccess", + "UpdateDate": "2018-11-28T23:45:26+00:00", + "VersionId": "v1" + }, + "AWSCloudMapRegisterInstanceAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSCloudMapRegisterInstanceAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-29T00:04:57+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "route53:GetHostedZone", + "route53:ListHostedZonesByName", + "route53:ChangeResourceRecordSets", + "route53:CreateHealthCheck", + "route53:GetHealthCheck", + "route53:DeleteHealthCheck", + "route53:UpdateHealthCheck", + "servicediscovery:Get*", + "servicediscovery:List*", + "servicediscovery:RegisterInstance", + "servicediscovery:DeregisterInstance", + "servicediscovery:DiscoverInstances" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI4P5Z5HXVWJ75WQBC", + "PolicyName": "AWSCloudMapRegisterInstanceAccess", + "UpdateDate": "2018-11-29T00:04:57+00:00", + "VersionId": "v1" + }, "AWSCloudTrailFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCloudTrailFullAccess", "AttachmentCount": 0, - "CreateDate": "2016-02-16T18:31:28+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2015-02-06T18:39:58+00:00", + "DefaultVersionId": "v7", "Document": { "Statement": [ { @@ -534,6 +2365,13 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "lambda:ListFunctions" + ], + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -541,16 +2379,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIQNUJTQYDRJPC3BNK", "PolicyName": "AWSCloudTrailFullAccess", - "UpdateDate": "2016-02-16T18:31:28+00:00", - "VersionId": "v4" + "UpdateDate": "2019-05-21T23:39:06+00:00", + "VersionId": "v7" }, "AWSCloudTrailReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCloudTrailReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-12-14T20:41:52+00:00", - "DefaultVersionId": "v6", + "CreateDate": "2015-02-06T18:39:59+00:00", + "DefaultVersionId": "v7", "Document": { "Statement": [ { @@ -570,7 +2409,8 @@ aws_managed_policies_data = """ "cloudtrail:ListPublicKeys", "cloudtrail:GetEventSelectors", "s3:ListAllMyBuckets", - "kms:ListAliases" + "kms:ListAliases", + "lambda:ListFunctions" ], "Effect": "Allow", "Resource": "*" @@ -581,16 +2421,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJDU7KJADWBSEQ3E7S", "PolicyName": "AWSCloudTrailReadOnlyAccess", - "UpdateDate": "2016-12-14T20:41:52+00:00", - "VersionId": "v6" + "UpdateDate": "2017-12-11T19:51:37+00:00", + "VersionId": "v7" }, "AWSCodeBuildAdminAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCodeBuildAdminAccess", "AttachmentCount": 0, "CreateDate": "2016-12-01T19:04:44+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v6", "Document": { "Statement": [ { @@ -601,8 +2442,22 @@ aws_managed_policies_data = """ "codecommit:GetRepository", "codecommit:ListBranches", "codecommit:ListRepositories", + "cloudwatch:GetMetricStatistics", + "ec2:DescribeVpcs", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", "ecr:DescribeRepositories", "ecr:ListImages", + "events:DeleteRule", + "events:DescribeRule", + "events:DisableRule", + "events:EnableRule", + "events:ListTargetsByRule", + "events:ListRuleNamesByTarget", + "events:PutRule", + "events:PutTargets", + "events:RemoveTargets", + "logs:GetLogEvents", "s3:GetBucketLocation", "s3:ListAllMyBuckets" ], @@ -611,10 +2466,17 @@ aws_managed_policies_data = """ }, { "Action": [ - "logs:GetLogEvents" + "logs:DeleteLogGroup" ], "Effect": "Allow", "Resource": "arn:aws:logs:*:*:log-group:/aws/codebuild/*:log-stream:*" + }, + { + "Action": [ + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": "arn:aws:ssm:*:*:parameter/CodeBuild/*" } ], "Version": "2012-10-17" @@ -622,16 +2484,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJQJGIOIE3CD2TQXDS", "PolicyName": "AWSCodeBuildAdminAccess", - "UpdateDate": "2016-12-01T19:04:44+00:00", - "VersionId": "v1" + "UpdateDate": "2018-11-15T21:21:56+00:00", + "VersionId": "v6" }, "AWSCodeBuildDeveloperAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCodeBuildDeveloperAccess", "AttachmentCount": 0, "CreateDate": "2016-12-01T19:02:32+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -645,6 +2508,11 @@ aws_managed_policies_data = """ "codecommit:GetCommit", "codecommit:GetRepository", "codecommit:ListBranches", + "cloudwatch:GetMetricStatistics", + "events:DescribeRule", + "events:ListTargetsByRule", + "events:ListRuleNamesByTarget", + "logs:GetLogEvents", "s3:GetBucketLocation", "s3:ListAllMyBuckets" ], @@ -653,10 +2521,10 @@ aws_managed_policies_data = """ }, { "Action": [ - "logs:GetLogEvents" + "ssm:PutParameter" ], "Effect": "Allow", - "Resource": "arn:aws:logs:*:*:log-group:/aws/codebuild/*:log-stream:*" + "Resource": "arn:aws:ssm:*:*:parameter/CodeBuild/*" } ], "Version": "2012-10-17" @@ -664,16 +2532,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIMKTMR34XSBQW45HS", "PolicyName": "AWSCodeBuildDeveloperAccess", - "UpdateDate": "2016-12-01T19:02:32+00:00", - "VersionId": "v1" + "UpdateDate": "2018-11-15T21:32:53+00:00", + "VersionId": "v4" }, "AWSCodeBuildReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCodeBuildReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2016-12-01T19:03:41+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -683,17 +2552,15 @@ aws_managed_policies_data = """ "codebuild:List*", "codecommit:GetBranch", "codecommit:GetCommit", - "codecommit:GetRepository" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ + "codecommit:GetRepository", + "cloudwatch:GetMetricStatistics", + "events:DescribeRule", + "events:ListTargetsByRule", + "events:ListRuleNamesByTarget", "logs:GetLogEvents" ], "Effect": "Allow", - "Resource": "arn:aws:logs:*:*:log-group:/aws/codebuild/*:log-stream:*" + "Resource": "*" } ], "Version": "2012-10-17" @@ -701,16 +2568,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJIZZWN6557F5HVP2K", "PolicyName": "AWSCodeBuildReadOnlyAccess", - "UpdateDate": "2016-12-01T19:03:41+00:00", - "VersionId": "v1" + "UpdateDate": "2018-11-15T21:38:34+00:00", + "VersionId": "v3" }, "AWSCodeCommitFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCodeCommitFullAccess", "AttachmentCount": 0, "CreateDate": "2015-07-09T17:02:19+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -719,6 +2587,94 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "events:DeleteRule", + "events:DescribeRule", + "events:DisableRule", + "events:EnableRule", + "events:PutRule", + "events:PutTargets", + "events:RemoveTargets", + "events:ListTargetsByRule" + ], + "Effect": "Allow", + "Resource": "arn:aws:events:*:*:rule/codecommit*", + "Sid": "CloudWatchEventsCodeCommitRulesAccess" + }, + { + "Action": [ + "sns:CreateTopic", + "sns:DeleteTopic", + "sns:Subscribe", + "sns:Unsubscribe", + "sns:SetTopicAttributes" + ], + "Effect": "Allow", + "Resource": "arn:aws:sns:*:*:codecommit*", + "Sid": "SNSTopicAndSubscriptionAccess" + }, + { + "Action": [ + "sns:ListTopics", + "sns:ListSubscriptionsByTopic", + "sns:GetTopicAttributes" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "SNSTopicAndSubscriptionReadAccess" + }, + { + "Action": [ + "lambda:ListFunctions" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "LambdaReadOnlyListAccess" + }, + { + "Action": [ + "iam:ListUsers" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "IAMReadOnlyListAccess" + }, + { + "Action": [ + "iam:ListAccessKeys", + "iam:ListSSHPublicKeys", + "iam:ListServiceSpecificCredentials", + "iam:ListAccessKeys", + "iam:GetSSHPublicKey" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:user/${aws:username}", + "Sid": "IAMReadOnlyConsoleAccess" + }, + { + "Action": [ + "iam:DeleteSSHPublicKey", + "iam:GetSSHPublicKey", + "iam:ListSSHPublicKeys", + "iam:UpdateSSHPublicKey", + "iam:UploadSSHPublicKey" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:user/${aws:username}", + "Sid": "IAMUserSSHKeys" + }, + { + "Action": [ + "iam:CreateServiceSpecificCredential", + "iam:UpdateServiceSpecificCredential", + "iam:DeleteServiceSpecificCredential", + "iam:ResetServiceSpecificCredential" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:user/${aws:username}", + "Sid": "IAMSelfManageServiceSpecificCredentials" } ], "Version": "2012-10-17" @@ -726,34 +2682,126 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI4VCZ3XPIZLQ5NZV2", "PolicyName": "AWSCodeCommitFullAccess", - "UpdateDate": "2015-07-09T17:02:19+00:00", - "VersionId": "v1" + "UpdateDate": "2017-11-20T20:04:31+00:00", + "VersionId": "v2" }, "AWSCodeCommitPowerUser": { "Arn": "arn:aws:iam::aws:policy/AWSCodeCommitPowerUser", "AttachmentCount": 0, - "CreateDate": "2017-05-22T21:12:48+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2015-07-09T17:06:49+00:00", + "DefaultVersionId": "v6", "Document": { "Statement": [ { "Action": [ - "codecommit:BatchGetRepositories", - "codecommit:CreateBranch", - "codecommit:CreateRepository", - "codecommit:DeleteBranch", + "codecommit:BatchGet*", + "codecommit:BatchDescribe*", "codecommit:Get*", - "codecommit:GitPull", - "codecommit:GitPush", "codecommit:List*", + "codecommit:Create*", + "codecommit:DeleteBranch", + "codecommit:DeleteFile", + "codecommit:Describe*", "codecommit:Put*", + "codecommit:Post*", + "codecommit:Merge*", + "codecommit:TagResource", "codecommit:Test*", - "codecommit:Update*" + "codecommit:UntagResource", + "codecommit:Update*", + "codecommit:GitPull", + "codecommit:GitPush" ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "events:DeleteRule", + "events:DescribeRule", + "events:DisableRule", + "events:EnableRule", + "events:PutRule", + "events:PutTargets", + "events:RemoveTargets", + "events:ListTargetsByRule" + ], + "Effect": "Allow", + "Resource": "arn:aws:events:*:*:rule/codecommit*", + "Sid": "CloudWatchEventsCodeCommitRulesAccess" + }, + { + "Action": [ + "sns:Subscribe", + "sns:Unsubscribe" + ], + "Effect": "Allow", + "Resource": "arn:aws:sns:*:*:codecommit*", + "Sid": "SNSTopicAndSubscriptionAccess" + }, + { + "Action": [ + "sns:ListTopics", + "sns:ListSubscriptionsByTopic", + "sns:GetTopicAttributes" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "SNSTopicAndSubscriptionReadAccess" + }, + { + "Action": [ + "lambda:ListFunctions" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "LambdaReadOnlyListAccess" + }, + { + "Action": [ + "iam:ListUsers" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "IAMReadOnlyListAccess" + }, + { + "Action": [ + "iam:ListAccessKeys", + "iam:ListSSHPublicKeys", + "iam:ListServiceSpecificCredentials", + "iam:ListAccessKeys", + "iam:GetSSHPublicKey" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:user/${aws:username}", + "Sid": "IAMReadOnlyConsoleAccess" + }, + { + "Action": [ + "iam:DeleteSSHPublicKey", + "iam:GetSSHPublicKey", + "iam:ListSSHPublicKeys", + "iam:UpdateSSHPublicKey", + "iam:UploadSSHPublicKey" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:user/${aws:username}", + "Sid": "IAMUserSSHKeys" + }, + { + "Action": [ + "iam:CreateServiceSpecificCredential", + "iam:UpdateServiceSpecificCredential", + "iam:DeleteServiceSpecificCredential", + "iam:ResetServiceSpecificCredential" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:user/${aws:username}", + "Sid": "IAMSelfManageServiceSpecificCredentials" } ], "Version": "2012-10-17" @@ -761,27 +2809,77 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI4UIINUVGB5SEC57G", "PolicyName": "AWSCodeCommitPowerUser", - "UpdateDate": "2017-05-22T21:12:48+00:00", - "VersionId": "v3" + "UpdateDate": "2019-05-30T19:37:08+00:00", + "VersionId": "v6" }, "AWSCodeCommitReadOnly": { "Arn": "arn:aws:iam::aws:policy/AWSCodeCommitReadOnly", "AttachmentCount": 0, "CreateDate": "2015-07-09T17:05:06+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { "Action": [ - "codecommit:BatchGetRepositories", + "codecommit:BatchGet*", + "codecommit:BatchDescribe*", "codecommit:Get*", - "codecommit:GitPull", - "codecommit:List*" + "codecommit:Describe*", + "codecommit:List*", + "codecommit:GitPull" ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "events:DescribeRule", + "events:ListTargetsByRule" + ], + "Effect": "Allow", + "Resource": "arn:aws:events:*:*:rule/codecommit*", + "Sid": "CloudWatchEventsCodeCommitRulesReadOnlyAccess" + }, + { + "Action": [ + "sns:ListTopics", + "sns:ListSubscriptionsByTopic", + "sns:GetTopicAttributes" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "SNSSubscriptionAccess" + }, + { + "Action": [ + "lambda:ListFunctions" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "LambdaReadOnlyListAccess" + }, + { + "Action": [ + "iam:ListUsers" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "IAMReadOnlyListAccess" + }, + { + "Action": [ + "iam:ListAccessKeys", + "iam:ListSSHPublicKeys", + "iam:ListServiceSpecificCredentials", + "iam:ListAccessKeys", + "iam:GetSSHPublicKey" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:user/${aws:username}", + "Sid": "IAMReadOnlyConsoleAccess" } ], "Version": "2012-10-17" @@ -789,10 +2887,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJACNSXR7Z2VLJW3D6", "PolicyName": "AWSCodeCommitReadOnly", - "UpdateDate": "2015-07-09T17:05:06+00:00", - "VersionId": "v1" + "UpdateDate": "2019-05-15T17:26:42+00:00", + "VersionId": "v3" }, "AWSCodeDeployDeployerAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCodeDeployDeployerAccess", @@ -818,6 +2917,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJUWEPOMGLMVXJAPUI", "PolicyName": "AWSCodeDeployDeployerAccess", "UpdateDate": "2015-05-19T18:18:43+00:00", @@ -841,6 +2941,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIONKN3TJZUKXCHXWC", "PolicyName": "AWSCodeDeployFullAccess", "UpdateDate": "2015-05-19T18:13:23+00:00", @@ -868,6 +2969,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAILZHHKCKB4NE7XOIQ", "PolicyName": "AWSCodeDeployReadOnlyAccess", "UpdateDate": "2015-05-19T18:21:32+00:00", @@ -876,7 +2978,7 @@ aws_managed_policies_data = """ "AWSCodeDeployRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole", "AttachmentCount": 0, - "CreateDate": "2017-09-11T19:09:51+00:00", + "CreateDate": "2015-05-04T18:05:37+00:00", "DefaultVersionId": "v6", "Document": { "Statement": [ @@ -931,15 +3033,213 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ2NKMKD73QS5NBFLA", "PolicyName": "AWSCodeDeployRole", "UpdateDate": "2017-09-11T19:09:51+00:00", "VersionId": "v6" }, + "AWSCodeDeployRoleForECS": { + "Arn": "arn:aws:iam::aws:policy/AWSCodeDeployRoleForECS", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T20:40:57+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ecs:DescribeServices", + "ecs:CreateTaskSet", + "ecs:UpdateServicePrimaryTaskSet", + "ecs:DeleteTaskSet", + "elasticloadbalancing:DescribeTargetGroups", + "elasticloadbalancing:DescribeListeners", + "elasticloadbalancing:ModifyListener", + "elasticloadbalancing:DescribeRules", + "elasticloadbalancing:ModifyRule", + "lambda:InvokeFunction", + "cloudwatch:DescribeAlarms", + "sns:Publish", + "s3:GetObject", + "s3:GetObjectMetadata", + "s3:GetObjectVersion" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "ecs-tasks.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIIL3KXEKRGEN2HFIO", + "PolicyName": "AWSCodeDeployRoleForECS", + "UpdateDate": "2018-12-19T17:57:04+00:00", + "VersionId": "v2" + }, + "AWSCodeDeployRoleForECSLimited": { + "Arn": "arn:aws:iam::aws:policy/AWSCodeDeployRoleForECSLimited", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T20:42:42+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ecs:DescribeServices", + "ecs:CreateTaskSet", + "ecs:UpdateServicePrimaryTaskSet", + "ecs:DeleteTaskSet", + "cloudwatch:DescribeAlarms" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "arn:aws:sns:*:*:CodeDeployTopic_*" + }, + { + "Action": [ + "elasticloadbalancing:DescribeTargetGroups", + "elasticloadbalancing:DescribeListeners", + "elasticloadbalancing:ModifyListener", + "elasticloadbalancing:DescribeRules", + "elasticloadbalancing:ModifyRule" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": "arn:aws:lambda:*:*:function:CodeDeployHook_*" + }, + { + "Action": [ + "s3:GetObject", + "s3:GetObjectMetadata", + "s3:GetObjectVersion" + ], + "Condition": { + "StringEquals": { + "s3:ExistingObjectTag/UseWithCodeDeploy": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "ecs-tasks.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/ecsTaskExecutionRole", + "arn:aws:iam::*:role/ECSTaskExecution*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ6Z7L2IOXEFFOGD2M", + "PolicyName": "AWSCodeDeployRoleForECSLimited", + "UpdateDate": "2018-12-19T18:06:16+00:00", + "VersionId": "v2" + }, + "AWSCodeDeployRoleForLambda": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSCodeDeployRoleForLambda", + "AttachmentCount": 0, + "CreateDate": "2017-11-28T14:05:44+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "cloudwatch:DescribeAlarms", + "lambda:UpdateAlias", + "lambda:GetAlias", + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion" + ], + "Effect": "Allow", + "Resource": "arn:aws:s3:::*/CodeDeploy/*" + }, + { + "Action": [ + "s3:GetObject", + "s3:GetObjectVersion" + ], + "Condition": { + "StringEquals": { + "s3:ExistingObjectTag/UseWithCodeDeploy": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": "arn:aws:lambda:*:*:function:CodeDeployHook_*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJA3RQZIKNOSJ4ZQSA", + "PolicyName": "AWSCodeDeployRoleForLambda", + "UpdateDate": "2017-12-01T22:32:58+00:00", + "VersionId": "v2" + }, "AWSCodePipelineApproverAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCodePipelineApproverAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-02T17:24:58+00:00", + "CreateDate": "2016-07-28T18:59:17+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -961,6 +3261,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAICXNWK42SQ6LMDXM2", "PolicyName": "AWSCodePipelineApproverAccess", "UpdateDate": "2017-08-02T17:24:58+00:00", @@ -990,6 +3291,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJFW5Z32BTVF76VCYC", "PolicyName": "AWSCodePipelineCustomActionAccess", "UpdateDate": "2015-07-09T17:02:54+00:00", @@ -998,7 +3300,7 @@ aws_managed_policies_data = """ "AWSCodePipelineFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCodePipelineFullAccess", "AttachmentCount": 0, - "CreateDate": "2016-11-01T19:59:46+00:00", + "CreateDate": "2015-07-09T16:58:07+00:00", "DefaultVersionId": "v5", "Document": { "Statement": [ @@ -1038,6 +3340,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJP5LH77KSAT2KHQGG", "PolicyName": "AWSCodePipelineFullAccess", "UpdateDate": "2016-11-01T19:59:46+00:00", @@ -1046,7 +3349,7 @@ aws_managed_policies_data = """ "AWSCodePipelineReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSCodePipelineReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-02T17:25:18+00:00", + "CreateDate": "2015-07-09T16:43:57+00:00", "DefaultVersionId": "v6", "Document": { "Statement": [ @@ -1086,6 +3389,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAILFKZXIBOTNC5TO2Q", "PolicyName": "AWSCodePipelineReadOnlyAccess", "UpdateDate": "2017-08-02T17:25:18+00:00", @@ -1095,7 +3399,7 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AWSCodeStarFullAccess", "AttachmentCount": 0, "CreateDate": "2017-04-19T16:23:19+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -1103,7 +3407,9 @@ aws_managed_policies_data = """ "codestar:*", "ec2:DescribeKeyPairs", "ec2:DescribeVpcs", - "ec2:DescribeSubnets" + "ec2:DescribeSubnets", + "cloud9:DescribeEnvironment*", + "cloud9:ValidateEnvironmentName" ], "Effect": "Allow", "Resource": "*", @@ -1126,27 +3432,47 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIXI233TFUGLZOJBEC", "PolicyName": "AWSCodeStarFullAccess", - "UpdateDate": "2017-04-19T16:23:19+00:00", - "VersionId": "v1" + "UpdateDate": "2018-01-10T21:54:06+00:00", + "VersionId": "v2" }, "AWSCodeStarServiceRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSCodeStarServiceRole", "AttachmentCount": 0, - "CreateDate": "2017-07-13T19:53:22+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2017-04-19T15:20:50+00:00", + "DefaultVersionId": "v9", "Document": { "Statement": [ + { + "Action": [ + "events:PutTargets", + "events:RemoveTargets", + "events:PutRule", + "events:DeleteRule", + "events:DescribeRule" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:events:*:*:rule/awscodestar-*" + ], + "Sid": "ProjectEventRules" + }, { "Action": [ "cloudformation:*Stack*", + "cloudformation:CreateChangeSet", + "cloudformation:ExecuteChangeSet", + "cloudformation:DeleteChangeSet", "cloudformation:GetTemplate" ], "Effect": "Allow", "Resource": [ "arn:aws:cloudformation:*:*:stack/awscodestar-*", - "arn:aws:cloudformation:*:*:stack/awseb-*" + "arn:aws:cloudformation:*:*:stack/awseb-*", + "arn:aws:cloudformation:*:*:stack/aws-cloud9-*", + "arn:aws:cloudformation:*:aws:transform/CodeStar*" ], "Sid": "ProjectStack" }, @@ -1184,12 +3510,7 @@ aws_managed_policies_data = """ }, { "Action": [ - "codestar:*Project", - "codestar:*Resource*", - "codestar:List*", - "codestar:Describe*", - "codestar:Get*", - "codestar:AssociateTeamMember", + "codestar:*", "codecommit:*", "codepipeline:*", "codedeploy:*", @@ -1202,7 +3523,11 @@ aws_managed_policies_data = """ "elasticloadbalancing:*", "iam:ListRoles", "logs:*", - "sns:*" + "sns:*", + "cloud9:CreateEnvironmentEC2", + "cloud9:DeleteEnvironment", + "cloud9:DescribeEnvironment*", + "cloud9:ListEnvironments" ], "Effect": "Allow", "Resource": "*", @@ -1217,6 +3542,7 @@ aws_managed_policies_data = """ "iam:DetachRolePolicy", "iam:GetRole", "iam:PassRole", + "iam:GetRolePolicy", "iam:PutRolePolicy", "iam:SetDefaultPolicyVersion", "iam:CreatePolicy", @@ -1257,7 +3583,9 @@ aws_managed_policies_data = """ "iam:CreatePolicyVersion", "iam:DeletePolicyVersion", "iam:ListEntitiesForPolicy", - "iam:ListPolicyVersions" + "iam:ListPolicyVersions", + "iam:GetPolicy", + "iam:GetPolicyVersion" ], "Effect": "Allow", "Resource": [ @@ -1275,6 +3603,29 @@ aws_managed_policies_data = """ "arn:aws:iam::*:role/service-role/aws-codestar-service-role" ], "Sid": "InspectServiceRole" + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "cloud9.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*", + "Sid": "IAMLinkRole" + }, + { + "Action": [ + "config:DescribeConfigRules" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DescribeConfigRuleForARN" } ], "Version": "2012-10-17" @@ -1282,16 +3633,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIN6D4M2KD3NBOC4M4", "PolicyName": "AWSCodeStarServiceRole", - "UpdateDate": "2017-07-13T19:53:22+00:00", - "VersionId": "v2" + "UpdateDate": "2019-04-24T19:25:28+00:00", + "VersionId": "v9" }, "AWSConfigRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSConfigRole", "AttachmentCount": 0, - "CreateDate": "2017-08-14T19:04:46+00:00", - "DefaultVersionId": "v10", + "CreateDate": "2015-04-02T17:36:23+00:00", + "DefaultVersionId": "v25", "Document": { "Statement": [ { @@ -1302,7 +3654,11 @@ aws_managed_policies_data = """ "config:Get*", "config:List*", "config:Describe*", + "config:BatchGet*", + "config:Select*", + "cloudtrail:GetEventSelectors", "cloudtrail:GetTrailStatus", + "cloudtrail:ListTags", "s3:GetObject", "iam:GetAccountAuthorizationDetails", "iam:GetAccountPasswordPolicy", @@ -1315,6 +3671,8 @@ aws_managed_policies_data = """ "iam:GetRolePolicy", "iam:GetUser", "iam:GetUserPolicy", + "iam:GenerateCredentialReport", + "iam:GetCredentialReport", "iam:ListAttachedGroupPolicies", "iam:ListAttachedRolePolicies", "iam:ListAttachedUserPolicies", @@ -1325,6 +3683,7 @@ aws_managed_policies_data = """ "iam:ListPolicyVersions", "iam:ListRolePolicies", "iam:ListUserPolicies", + "iam:ListVirtualMFADevices", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeLoadBalancerAttributes", "elasticloadbalancing:DescribeLoadBalancerPolicies", @@ -1354,6 +3713,10 @@ aws_managed_policies_data = """ "s3:GetLifecycleConfiguration", "s3:GetReplicationConfiguration", "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:GetEncryptionConfiguration", + "s3:GetBucketPublicAccessBlock", + "s3:GetAccountPublicAccessBlock", "redshift:DescribeClusterParameterGroups", "redshift:DescribeClusterParameters", "redshift:DescribeClusterSecurityGroups", @@ -1374,7 +3737,29 @@ aws_managed_policies_data = """ "autoscaling:DescribeLifecycleHooks", "autoscaling:DescribePolicies", "autoscaling:DescribeScheduledActions", - "autoscaling:DescribeTags" + "autoscaling:DescribeTags", + "lambda:GetFunction", + "lambda:GetPolicy", + "lambda:ListFunctions", + "lambda:GetAlias", + "lambda:ListAliases", + "waf-regional:GetWebACLForResource", + "waf-regional:GetWebACL", + "cloudfront:ListTagsForResource", + "guardduty:ListDetectors", + "guardduty:GetMasterAccount", + "guardduty:GetDetector", + "codepipeline:ListPipelines", + "codepipeline:GetPipeline", + "codepipeline:GetPipelineState", + "kms:ListKeys", + "kms:GetKeyRotationStatus", + "kms:DescribeKey", + "ssm:DescribeDocument", + "ssm:GetDocument", + "ssm:DescribeAutomationExecutions", + "ssm:GetAutomationExecution", + "shield:DescribeProtection" ], "Effect": "Allow", "Resource": "*" @@ -1385,16 +3770,45 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIQRXRDRGJUA33ELIO", "PolicyName": "AWSConfigRole", - "UpdateDate": "2017-08-14T19:04:46+00:00", - "VersionId": "v10" + "UpdateDate": "2019-05-13T21:29:39+00:00", + "VersionId": "v25" + }, + "AWSConfigRoleForOrganizations": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSConfigRoleForOrganizations", + "AttachmentCount": 0, + "CreateDate": "2018-03-19T22:53:01+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "organizations:ListAccounts", + "organizations:DescribeOrganization", + "organizations:ListAWSServiceAccessForOrganization" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIEHGYAUTHXSXZAW2E", + "PolicyName": "AWSConfigRoleForOrganizations", + "UpdateDate": "2018-03-19T22:53:01+00:00", + "VersionId": "v1" }, "AWSConfigRulesExecutionRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSConfigRulesExecutionRole", "AttachmentCount": 0, "CreateDate": "2016-03-25T17:59:36+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -1409,7 +3823,9 @@ aws_managed_policies_data = """ "config:Put*", "config:Get*", "config:List*", - "config:Describe*" + "config:Describe*", + "config:BatchGet*", + "config:Select*" ], "Effect": "Allow", "Resource": "*" @@ -1420,16 +3836,153 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJUB3KIKTA4PU4OYAA", "PolicyName": "AWSConfigRulesExecutionRole", - "UpdateDate": "2016-03-25T17:59:36+00:00", - "VersionId": "v1" + "UpdateDate": "2019-05-13T21:33:30+00:00", + "VersionId": "v3" + }, + "AWSConfigServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSConfigServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-05-30T23:31:46+00:00", + "DefaultVersionId": "v11", + "Document": { + "Statement": [ + { + "Action": [ + "cloudtrail:DescribeTrails", + "cloudtrail:GetEventSelectors", + "ec2:Describe*", + "config:Put*", + "config:Get*", + "config:List*", + "config:Describe*", + "config:BatchGet*", + "config:Select*", + "cloudtrail:GetTrailStatus", + "cloudtrail:ListTags", + "iam:GenerateCredentialReport", + "iam:GetCredentialReport", + "iam:GetAccountAuthorizationDetails", + "iam:GetAccountPasswordPolicy", + "iam:GetAccountSummary", + "iam:GetGroup", + "iam:GetGroupPolicy", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole", + "iam:GetRolePolicy", + "iam:GetUser", + "iam:GetUserPolicy", + "iam:ListAttachedGroupPolicies", + "iam:ListAttachedRolePolicies", + "iam:ListAttachedUserPolicies", + "iam:ListEntitiesForPolicy", + "iam:ListGroupPolicies", + "iam:ListGroupsForUser", + "iam:ListInstanceProfilesForRole", + "iam:ListPolicyVersions", + "iam:ListRolePolicies", + "iam:ListUserPolicies", + "iam:ListVirtualMFADevices", + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeLoadBalancerAttributes", + "elasticloadbalancing:DescribeLoadBalancerPolicies", + "elasticloadbalancing:DescribeTags", + "acm:DescribeCertificate", + "acm:ListCertificates", + "acm:ListTagsForCertificate", + "rds:DescribeDBInstances", + "rds:DescribeDBSecurityGroups", + "rds:DescribeDBSnapshotAttributes", + "rds:DescribeDBSnapshots", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEventSubscriptions", + "rds:ListTagsForResource", + "rds:DescribeDBClusters", + "s3:GetAccelerateConfiguration", + "s3:GetBucketAcl", + "s3:GetBucketCORS", + "s3:GetBucketLocation", + "s3:GetBucketLogging", + "s3:GetBucketNotification", + "s3:GetBucketPolicy", + "s3:GetBucketRequestPayment", + "s3:GetBucketTagging", + "s3:GetBucketVersioning", + "s3:GetBucketWebsite", + "s3:GetLifecycleConfiguration", + "s3:GetReplicationConfiguration", + "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:GetEncryptionConfiguration", + "s3:GetBucketPublicAccessBlock", + "s3:GetAccountPublicAccessBlock", + "redshift:DescribeClusterParameterGroups", + "redshift:DescribeClusterParameters", + "redshift:DescribeClusterSecurityGroups", + "redshift:DescribeClusterSnapshots", + "redshift:DescribeClusterSubnetGroups", + "redshift:DescribeClusters", + "redshift:DescribeEventSubscriptions", + "redshift:DescribeLoggingStatus", + "dynamodb:DescribeLimits", + "dynamodb:DescribeTable", + "dynamodb:ListTables", + "dynamodb:ListTagsOfResource", + "cloudwatch:DescribeAlarms", + "application-autoscaling:DescribeScalableTargets", + "application-autoscaling:DescribeScalingPolicies", + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:DescribeLaunchConfigurations", + "autoscaling:DescribeLifecycleHooks", + "autoscaling:DescribePolicies", + "autoscaling:DescribeScheduledActions", + "autoscaling:DescribeTags", + "lambda:GetFunction", + "lambda:GetPolicy", + "lambda:ListFunctions", + "lambda:GetAlias", + "lambda:ListAliases", + "waf-regional:GetWebACLForResource", + "waf-regional:GetWebACL", + "cloudfront:ListTagsForResource", + "guardduty:ListDetectors", + "guardduty:GetMasterAccount", + "guardduty:GetDetector", + "codepipeline:ListPipelines", + "codepipeline:GetPipeline", + "codepipeline:GetPipelineState", + "kms:ListKeys", + "kms:GetKeyRotationStatus", + "kms:DescribeKey", + "ssm:DescribeDocument", + "ssm:GetDocument", + "ssm:DescribeAutomationExecutions", + "ssm:GetAutomationExecution", + "shield:DescribeProtection" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJUCWFHNZER665LLQQ", + "PolicyName": "AWSConfigServiceRolePolicy", + "UpdateDate": "2019-05-13T21:18:44+00:00", + "VersionId": "v11" }, "AWSConfigUserAccess": { "Arn": "arn:aws:iam::aws:policy/AWSConfigUserAccess", "AttachmentCount": 0, - "CreateDate": "2016-08-30T19:15:19+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2015-02-18T19:38:41+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -1438,6 +3991,7 @@ aws_managed_policies_data = """ "config:Describe*", "config:Deliver*", "config:List*", + "config:Select*", "tag:GetResources", "tag:GetTagKeys", "cloudtrail:DescribeTrails", @@ -1453,15 +4007,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIWTTSFJ7KKJE3MWGA", "PolicyName": "AWSConfigUserAccess", - "UpdateDate": "2016-08-30T19:15:19+00:00", - "VersionId": "v3" + "UpdateDate": "2019-03-18T20:27:47+00:00", + "VersionId": "v4" }, "AWSConnector": { "Arn": "arn:aws:iam::aws:policy/AWSConnector", "AttachmentCount": 0, - "CreateDate": "2015-09-28T19:50:38+00:00", + "CreateDate": "2015-02-11T17:14:31+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -1545,16 +4100,182 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ6YATONJHICG3DJ3U", "PolicyName": "AWSConnector", "UpdateDate": "2015-09-28T19:50:38+00:00", "VersionId": "v3" }, + "AWSControlTowerServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSControlTowerServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-05-03T18:19:11+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "cloudformation:CreateStack", + "cloudformation:CreateStackInstances", + "cloudformation:CreateStackSet", + "cloudformation:DeleteStack", + "cloudformation:DeleteStackInstances", + "cloudformation:DeleteStackSet", + "cloudformation:DescribeStackInstance", + "cloudformation:DescribeStacks", + "cloudformation:DescribeStackSet", + "cloudformation:DescribeStackSetOperation", + "cloudformation:GetTemplate", + "cloudformation:ListStackInstances", + "cloudformation:UpdateStack", + "cloudformation:UpdateStackInstances", + "cloudformation:UpdateStackSet" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:cloudformation:*:*:stack/AWSControlTower*/*", + "arn:aws:cloudformation:*:*:stack/StackSet-AWSControlTower*/*", + "arn:aws:cloudformation:*:*:stackset/AWSControlTower*:*" + ] + }, + { + "Action": [ + "cloudtrail:CreateTrail", + "cloudtrail:DeleteTrail", + "cloudtrail:GetTrailStatus", + "cloudtrail:StartLogging", + "cloudtrail:StopLogging", + "cloudtrail:UpdateTrail", + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:PutRetentionPolicy" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:aws-controltower/CloudTrailLogs:*", + "arn:aws:cloudtrail:*:*:trail/aws-controltower*" + ] + }, + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-controltower*/*" + ] + }, + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/AWSControlTowerExecution" + ] + }, + { + "Action": [ + "cloudtrail:DescribeTrails", + "ec2:DescribeAvailabilityZones", + "iam:ListRoles", + "logs:CreateLogGroup", + "logs:DescribeLogGroups", + "organizations:CreateAccount", + "organizations:DescribeAccount", + "organizations:DescribeCreateAccountStatus", + "organizations:DescribeOrganization", + "organizations:DescribeOrganizationalUnit", + "organizations:DescribePolicy", + "organizations:ListAccounts", + "organizations:ListAccountsForParent", + "organizations:ListAWSServiceAccessForOrganization", + "organizations:ListChildren", + "organizations:ListOrganizationalUnitsForParent", + "organizations:ListParents", + "organizations:ListPoliciesForTarget", + "organizations:ListRoots", + "organizations:MoveAccount", + "servicecatalog:AssociatePrincipalWithPortfolio" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:GetRole", + "iam:GetUser", + "iam:ListAttachedRolePolicies", + "iam:GetRolePolicy" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/service-role/AWSControlTowerStackSetRole", + "arn:aws:iam::*:role/service-role/AWSControlTowerCloudTrailRole" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4MW35THVLF", + "PolicyName": "AWSControlTowerServiceRolePolicy", + "UpdateDate": "2019-05-23T19:14:24+00:00", + "VersionId": "v2" + }, + "AWSDataLifecycleManagerServiceRole": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSDataLifecycleManagerServiceRole", + "AttachmentCount": 0, + "CreateDate": "2018-07-06T19:34:16+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateSnapshot", + "ec2:CreateSnapshots", + "ec2:DeleteSnapshot", + "ec2:DescribeInstances", + "ec2:DescribeVolumes", + "ec2:DescribeSnapshots" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Effect": "Allow", + "Resource": "arn:aws:ec2:*::snapshot/*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIZRLOKFUFE7YXQOJS", + "PolicyName": "AWSDataLifecycleManagerServiceRole", + "UpdateDate": "2019-05-29T16:44:12+00:00", + "VersionId": "v2" + }, "AWSDataPipelineRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSDataPipelineRole", "AttachmentCount": 0, - "CreateDate": "2016-02-22T17:17:38+00:00", - "DefaultVersionId": "v5", + "CreateDate": "2015-02-06T18:41:24+00:00", + "DefaultVersionId": "v6", "Document": { "Statement": [ { @@ -1622,6 +4343,19 @@ aws_managed_policies_data = """ "Resource": [ "*" ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "elasticmapreduce.amazonaws.com", + "spot.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -1629,15 +4363,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIKCP6XS3ESGF4GLO2", "PolicyName": "AWSDataPipelineRole", - "UpdateDate": "2016-02-22T17:17:38+00:00", - "VersionId": "v5" + "UpdateDate": "2017-12-22T23:43:28+00:00", + "VersionId": "v6" }, "AWSDataPipeline_FullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSDataPipeline_FullAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-17T18:48:39+00:00", + "CreateDate": "2017-01-19T23:14:54+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -1676,6 +4411,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIXOFIG7RSBMRPHXJ4", "PolicyName": "AWSDataPipeline_FullAccess", "UpdateDate": "2017-08-17T18:48:39+00:00", @@ -1684,7 +4420,7 @@ aws_managed_policies_data = """ "AWSDataPipeline_PowerUser": { "Arn": "arn:aws:iam::aws:policy/AWSDataPipeline_PowerUser", "AttachmentCount": 0, - "CreateDate": "2017-08-17T18:49:42+00:00", + "CreateDate": "2017-01-19T23:16:46+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -1722,11 +4458,826 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIMXGLVY6DVR24VTYS", "PolicyName": "AWSDataPipeline_PowerUser", "UpdateDate": "2017-08-17T18:49:42+00:00", "VersionId": "v2" }, + "AWSDataSyncFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSDataSyncFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-18T19:40:36+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "datasync:*", + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:ModifyNetworkInterfaceAttribute", + "elasticfilesystem:DescribeFileSystems", + "elasticfilesystem:DescribeMountTargets", + "iam:GetRole", + "iam:ListRoles", + "logs:CreateLogGroup", + "logs:DescribeLogGroups", + "s3:ListAllMyBuckets", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "datasync.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJGOHCDUQULZJKDGT4", + "PolicyName": "AWSDataSyncFullAccess", + "UpdateDate": "2019-01-18T19:40:36+00:00", + "VersionId": "v1" + }, + "AWSDataSyncReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSDataSyncReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-18T19:18:44+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "datasync:Describe*", + "datasync:List*", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "elasticfilesystem:DescribeFileSystems", + "elasticfilesystem:DescribeMountTargets", + "iam:GetRole", + "iam:ListRoles", + "logs:DescribeLogGroups", + "s3:ListAllMyBuckets", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJRYVEZEDR7ZEAGYLY", + "PolicyName": "AWSDataSyncReadOnlyAccess", + "UpdateDate": "2019-01-18T19:18:44+00:00", + "VersionId": "v1" + }, + "AWSDeepLensLambdaFunctionAccessPolicy": { + "Arn": "arn:aws:iam::aws:policy/AWSDeepLensLambdaFunctionAccessPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T15:47:18+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "s3:ListBucket", + "s3:GetObject", + "s3:ListObjects" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::deeplens*/*", + "arn:aws:s3:::deeplens*" + ], + "Sid": "DeepLensS3ObjectAccess" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:PutLogEvents", + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": "arn:aws:logs:*:*:log-group:/aws/greengrass/*", + "Sid": "DeepLensGreenGrassCloudWatchAccess" + }, + { + "Action": [ + "deeplens:*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensAccess" + }, + { + "Action": [ + "kinesisvideo:DescribeStream", + "kinesisvideo:CreateStream", + "kinesisvideo:GetDataEndpoint", + "kinesisvideo:PutMedia" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensKinesisVideoAccess" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIKIEE4PRM54V4G3ZG", + "PolicyName": "AWSDeepLensLambdaFunctionAccessPolicy", + "UpdateDate": "2018-05-29T22:08:02+00:00", + "VersionId": "v3" + }, + "AWSDeepLensServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSDeepLensServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T15:46:36+00:00", + "DefaultVersionId": "v5", + "Document": { + "Statement": [ + { + "Action": [ + "iot:CreateThing", + "iot:DeleteThing", + "iot:DeleteThingShadow", + "iot:DescribeThing", + "iot:GetThingShadow", + "iot:UpdateThing", + "iot:UpdateThingShadow" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iot:*:*:thing/deeplens*" + ], + "Sid": "DeepLensIoTThingAccess" + }, + { + "Action": [ + "iot:AttachThingPrincipal", + "iot:DetachThingPrincipal", + "iot:UpdateCertificate", + "iot:DeleteCertificate", + "iot:DetachPrincipalPolicy" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iot:*:*:thing/deeplens*", + "arn:aws:iot:*:*:cert/*" + ], + "Sid": "DeepLensIoTCertificateAccess" + }, + { + "Action": [ + "iot:CreateKeysAndCertificate", + "iot:CreatePolicy", + "iot:CreatePolicyVersion" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensIoTCreateCertificateAndPolicyAccess" + }, + { + "Action": [ + "iot:AttachPrincipalPolicy" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iot:*:*:policy/deeplens*", + "arn:aws:iot:*:*:cert/*" + ], + "Sid": "DeepLensIoTAttachCertificatePolicyAccess" + }, + { + "Action": [ + "iot:GetThingShadow", + "iot:UpdateThingShadow" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iot:*:*:thing/deeplens*" + ], + "Sid": "DeepLensIoTDataAccess" + }, + { + "Action": [ + "iot:DescribeEndpoint" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensIoTEndpointAccess" + }, + { + "Action": [ + "deeplens:*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensAccess" + }, + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::deeplens*" + ], + "Sid": "DeepLensS3ObjectAccess" + }, + { + "Action": [ + "s3:DeleteBucket", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::deeplens*" + ], + "Sid": "DeepLensS3Buckets" + }, + { + "Action": [ + "s3:CreateBucket" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensCreateS3Buckets" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "greengrass.amazonaws.com", + "sagemaker.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensIAMPassRoleAccess" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEqualsIfExists": { + "iam:PassedToService": "lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/AWSDeepLens*", + "arn:aws:iam::*:role/service-role/AWSDeepLens*" + ], + "Sid": "DeepLensIAMLambdaPassRoleAccess" + }, + { + "Action": [ + "greengrass:AssociateRoleToGroup", + "greengrass:AssociateServiceRoleToAccount", + "greengrass:CreateResourceDefinition", + "greengrass:CreateResourceDefinitionVersion", + "greengrass:CreateCoreDefinition", + "greengrass:CreateCoreDefinitionVersion", + "greengrass:CreateDeployment", + "greengrass:CreateFunctionDefinition", + "greengrass:CreateFunctionDefinitionVersion", + "greengrass:CreateGroup", + "greengrass:CreateGroupCertificateAuthority", + "greengrass:CreateGroupVersion", + "greengrass:CreateLoggerDefinition", + "greengrass:CreateLoggerDefinitionVersion", + "greengrass:CreateSubscriptionDefinition", + "greengrass:CreateSubscriptionDefinitionVersion", + "greengrass:DeleteCoreDefinition", + "greengrass:DeleteFunctionDefinition", + "greengrass:DeleteGroup", + "greengrass:DeleteLoggerDefinition", + "greengrass:DeleteSubscriptionDefinition", + "greengrass:DisassociateRoleFromGroup", + "greengrass:DisassociateServiceRoleFromAccount", + "greengrass:GetAssociatedRole", + "greengrass:GetConnectivityInfo", + "greengrass:GetCoreDefinition", + "greengrass:GetCoreDefinitionVersion", + "greengrass:GetDeploymentStatus", + "greengrass:GetDeviceDefinition", + "greengrass:GetDeviceDefinitionVersion", + "greengrass:GetFunctionDefinition", + "greengrass:GetFunctionDefinitionVersion", + "greengrass:GetGroup", + "greengrass:GetGroupCertificateAuthority", + "greengrass:GetGroupCertificateConfiguration", + "greengrass:GetGroupVersion", + "greengrass:GetLoggerDefinition", + "greengrass:GetLoggerDefinitionVersion", + "greengrass:GetResourceDefinition", + "greengrass:GetServiceRoleForAccount", + "greengrass:GetSubscriptionDefinition", + "greengrass:GetSubscriptionDefinitionVersion", + "greengrass:ListCoreDefinitionVersions", + "greengrass:ListCoreDefinitions", + "greengrass:ListDeployments", + "greengrass:ListDeviceDefinitionVersions", + "greengrass:ListDeviceDefinitions", + "greengrass:ListFunctionDefinitionVersions", + "greengrass:ListFunctionDefinitions", + "greengrass:ListGroupCertificateAuthorities", + "greengrass:ListGroupVersions", + "greengrass:ListGroups", + "greengrass:ListLoggerDefinitionVersions", + "greengrass:ListLoggerDefinitions", + "greengrass:ListSubscriptionDefinitionVersions", + "greengrass:ListSubscriptionDefinitions", + "greengrass:ResetDeployments", + "greengrass:UpdateConnectivityInfo", + "greengrass:UpdateCoreDefinition", + "greengrass:UpdateDeviceDefinition", + "greengrass:UpdateFunctionDefinition", + "greengrass:UpdateGroup", + "greengrass:UpdateGroupCertificateConfiguration", + "greengrass:UpdateLoggerDefinition", + "greengrass:UpdateSubscriptionDefinition", + "greengrass:UpdateResourceDefinition" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensGreenGrassAccess" + }, + { + "Action": [ + "lambda:CreateFunction", + "lambda:DeleteFunction", + "lambda:GetFunction", + "lambda:GetFunctionConfiguration", + "lambda:ListFunctions", + "lambda:ListVersionsByFunction", + "lambda:PublishVersion", + "lambda:UpdateFunctionCode", + "lambda:UpdateFunctionConfiguration" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:lambda:*:*:function:deeplens*" + ], + "Sid": "DeepLensLambdaAdminFunctionAccess" + }, + { + "Action": [ + "lambda:GetFunction", + "lambda:GetFunctionConfiguration", + "lambda:ListFunctions", + "lambda:ListVersionsByFunction" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:lambda:*:*:function:*" + ], + "Sid": "DeepLensLambdaUsersFunctionAccess" + }, + { + "Action": [ + "sagemaker:CreateTrainingJob", + "sagemaker:DescribeTrainingJob", + "sagemaker:StopTrainingJob" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:sagemaker:*:*:training-job/deeplens*" + ], + "Sid": "DeepLensSageMakerWriteAccess" + }, + { + "Action": [ + "sagemaker:DescribeTrainingJob" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:sagemaker:*:*:training-job/*" + ], + "Sid": "DeepLensSageMakerReadAccess" + }, + { + "Action": [ + "acuity:CreateStream", + "acuity:DescribeStream", + "acuity:DeleteStream" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:acuity:*:*:stream/deeplens*/*" + ], + "Sid": "DeepLensAcuityStreamAccess" + }, + { + "Action": [ + "acuity:GetDataEndpoint" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "DeepLensAcuityEndpointAccess" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJK2Z2S7FPJFCYGR72", + "PolicyName": "AWSDeepLensServiceRolePolicy", + "UpdateDate": "2018-06-07T21:25:01+00:00", + "VersionId": "v5" + }, + "AWSDeepRacerCloudFormationAccessPolicy": { + "Arn": "arn:aws:iam::aws:policy/AWSDeepRacerCloudFormationAccessPolicy", + "AttachmentCount": 0, + "CreateDate": "2019-02-28T21:59:49+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudformation:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:AllocateAddress", + "ec2:AttachInternetGateway", + "ec2:AssociateRouteTable", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateInternetGateway", + "ec2:CreateNatGateway", + "ec2:CreateNetworkAcl", + "ec2:CreateNetworkAclEntry", + "ec2:CreateRoute", + "ec2:CreateRouteTable", + "ec2:CreateSecurityGroup", + "ec2:CreateSubnet", + "ec2:CreateTags", + "ec2:CreateVpc", + "ec2:DeleteInternetGateway", + "ec2:DeleteNatGateway", + "ec2:DeleteNetworkAcl", + "ec2:DeleteNetworkAclEntry", + "ec2:DeleteRoute", + "ec2:DeleteRouteTable", + "ec2:DeleteSecurityGroup", + "ec2:DeleteSubnet", + "ec2:DeleteTags", + "ec2:DeleteVpc", + "ec2:DescribeAddresses", + "ec2:DescribeInternetGateways", + "ec2:DescribeNatGateways", + "ec2:DescribeNetworkAcls", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeTags", + "ec2:DescribeVpcs", + "ec2:DetachInternetGateway", + "ec2:DisassociateRouteTable", + "ec2:ModifyVpcAttribute", + "ec2:ReleaseAddress", + "ec2:ReplaceNetworkAclAssociation", + "ec2:RevokeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJYG7FM75UF5CW5ICS", + "PolicyName": "AWSDeepRacerCloudFormationAccessPolicy", + "UpdateDate": "2019-02-28T21:59:49+00:00", + "VersionId": "v1" + }, + "AWSDeepRacerRoboMakerAccessPolicy": { + "Arn": "arn:aws:iam::aws:policy/AWSDeepRacerRoboMakerAccessPolicy", + "AttachmentCount": 0, + "CreateDate": "2019-02-28T21:59:58+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "robomaker:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloudwatch:PutMetricData", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSubnets", + "ec2:DescribeSecurityGroups", + "ec2:DescribeVpcs" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/robomaker/SimulationJobs", + "arn:aws:logs:*:*:log-group:/aws/robomaker/SimulationJobs:log-stream:*" + ] + }, + { + "Action": [ + "s3:GetObject", + "s3:GetBucketLocation", + "s3:ListBucket", + "s3:ListAllMyBuckets", + "s3:PutObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*DeepRacer*", + "arn:aws:s3:::*Deepracer*", + "arn:aws:s3:::*deepracer*", + "arn:aws:s3:::dr-*" + ] + }, + { + "Action": [ + "s3:GetObject" + ], + "Condition": { + "StringEqualsIgnoreCase": { + "s3:ExistingObjectTag/DeepRacer": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "kinesisvideo:CreateStream", + "kinesisvideo:DescribeStream", + "kinesisvideo:GetDataEndpoint", + "kinesisvideo:PutMedia", + "kinesisvideo:TagStream" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:kinesisvideo:*:*:stream/dr-*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIUKGYRTDCUFOMRGAM", + "PolicyName": "AWSDeepRacerRoboMakerAccessPolicy", + "UpdateDate": "2019-02-28T21:59:58+00:00", + "VersionId": "v1" + }, + "AWSDeepRacerServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSDeepRacerServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-02-28T21:58:09+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "deepracer:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "robomaker:*", + "sagemaker:*", + "sts:*", + "s3:ListAllMyBuckets" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloudformation:ListStackResources", + "cloudformation:DescribeStacks", + "cloudformation:CreateStack", + "cloudformation:DeleteStack", + "cloudformation:DescribeStackResource", + "cloudformation:DescribeStackResources", + "cloudformation:DescribeStackEvents", + "cloudformation:DetectStackDrift", + "cloudformation:DescribeStackDriftDetectionStatus", + "cloudformation:DescribeStackResourceDrifts" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "robomaker.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/AWSDeepRacer*", + "arn:aws:iam::*:role/service-role/AWSDeepRacer*" + ] + }, + { + "Action": [ + "cloudwatch:GetMetricData", + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:GetLogEvents", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:CreateFunction", + "lambda:DeleteFunction", + "lambda:GetFunction", + "lambda:InvokeFunction", + "lambda:UpdateFunctionCode" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:lambda:*:*:function:*DeepRacer*", + "arn:aws:lambda:*:*:function:*Deepracer*", + "arn:aws:lambda:*:*:function:*deepracer*", + "arn:aws:lambda:*:*:function:*dr-*" + ] + }, + { + "Action": [ + "s3:GetObject", + "s3:GetBucketLocation", + "s3:DeleteObject", + "s3:ListBucket", + "s3:PutObject", + "s3:PutBucketPolicy", + "s3:GetBucketAcl" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*DeepRacer*", + "arn:aws:s3:::*Deepracer*", + "arn:aws:s3:::*deepracer*", + "arn:aws:s3:::dr-*" + ] + }, + { + "Action": [ + "s3:GetObject" + ], + "Condition": { + "StringEqualsIgnoreCase": { + "s3:ExistingObjectTag/DeepRacer": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "kinesisvideo:CreateStream", + "kinesisvideo:DeleteStream", + "kinesisvideo:DescribeStream", + "kinesisvideo:GetDataEndpoint", + "kinesisvideo:GetHLSStreamingSessionURL", + "kinesisvideo:GetMedia", + "kinesisvideo:PutMedia", + "kinesisvideo:TagStream" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:kinesisvideo:*:*:stream/dr-*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJTUAQLIAVBJ7LZ32S", + "PolicyName": "AWSDeepRacerServiceRolePolicy", + "UpdateDate": "2019-04-06T04:08:05+00:00", + "VersionId": "v2" + }, + "AWSDenyAll": { + "Arn": "arn:aws:iam::aws:policy/AWSDenyAll", + "AttachmentCount": 0, + "CreateDate": "2019-05-01T22:36:14+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "*" + ], + "Effect": "Deny", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4P43IUQ5E5", + "PolicyName": "AWSDenyAll", + "UpdateDate": "2019-05-01T22:36:14+00:00", + "VersionId": "v1" + }, "AWSDeviceFarmFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSDeviceFarmFullAccess", "AttachmentCount": 0, @@ -1747,6 +5298,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJO7KEDP4VYJPNT5UW", "PolicyName": "AWSDeviceFarmFullAccess", "UpdateDate": "2015-07-13T16:37:38+00:00", @@ -1756,12 +5308,14 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AWSDirectConnectFullAccess", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:07+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { "Action": [ - "directconnect:*" + "directconnect:*", + "ec2:DescribeVpnGateways", + "ec2:DescribeTransitGateways" ], "Effect": "Allow", "Resource": "*" @@ -1772,21 +5326,24 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJQF2QKZSK74KTIHOW", "PolicyName": "AWSDirectConnectFullAccess", - "UpdateDate": "2015-02-06T18:40:07+00:00", - "VersionId": "v1" + "UpdateDate": "2019-04-30T15:29:29+00:00", + "VersionId": "v3" }, "AWSDirectConnectReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSDirectConnectReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:08+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { "Action": [ - "directconnect:Describe*" + "directconnect:Describe*", + "ec2:DescribeVpnGateways", + "ec2:DescribeTransitGateways" ], "Effect": "Allow", "Resource": "*" @@ -1797,16 +5354,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI23HZ27SI6FQMGNQ2", "PolicyName": "AWSDirectConnectReadOnlyAccess", - "UpdateDate": "2015-02-06T18:40:08+00:00", - "VersionId": "v1" + "UpdateDate": "2019-04-30T15:23:18+00:00", + "VersionId": "v3" }, "AWSDirectoryServiceFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSDirectoryServiceFullAccess", "AttachmentCount": 0, - "CreateDate": "2016-02-24T23:10:36+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2015-02-06T18:41:11+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -1823,10 +5381,19 @@ aws_managed_policies_data = """ "ec2:DescribeVpcs", "ec2:RevokeSecurityGroupEgress", "ec2:RevokeSecurityGroupIngress", + "ec2:DescribeSecurityGroups", "sns:GetTopicAttributes", "sns:ListSubscriptions", "sns:ListSubscriptionsByTopic", - "sns:ListTopics" + "sns:ListTopics", + "iam:ListRoles", + "organizations:ListAccountsForParent", + "organizations:ListRoots", + "organizations:ListAccounts", + "organizations:DescribeOrganization", + "organizations:DescribeAccount", + "organizations:ListOrganizationalUnitsForParent", + "organizations:ListAWSServiceAccessForOrganization" ], "Effect": "Allow", "Resource": "*" @@ -1841,6 +5408,32 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "arn:aws:sns:*:*:DirectoryMonitoring*" + }, + { + "Action": [ + "organizations:EnableAWSServiceAccess", + "organizations:DisableAWSServiceAccess" + ], + "Condition": { + "ForAllValues:StringLike": { + "organizations:ServicePrincipal": [ + "ds.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateTags", + "ec2:DeleteTags" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:network-interface/*", + "arn:aws:ec2:*:*:security-group/*" + ] } ], "Version": "2012-10-17" @@ -1848,16 +5441,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAINAW5ANUWTH3R4ANI", "PolicyName": "AWSDirectoryServiceFullAccess", - "UpdateDate": "2016-02-24T23:10:36+00:00", - "VersionId": "v2" + "UpdateDate": "2019-02-05T20:29:43+00:00", + "VersionId": "v4" }, "AWSDirectoryServiceReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSDirectoryServiceReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-02-24T23:11:18+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2015-02-06T18:41:12+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -1873,7 +5467,10 @@ aws_managed_policies_data = """ "sns:ListTopics", "sns:GetTopicAttributes", "sns:ListSubscriptions", - "sns:ListSubscriptionsByTopic" + "sns:ListSubscriptionsByTopic", + "organizations:DescribeAccount", + "organizations:DescribeOrganization", + "organizations:ListAWSServiceAccessForOrganization" ], "Effect": "Allow", "Resource": "*" @@ -1884,23 +5481,160 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIHWYO6WSDNCG64M2W", "PolicyName": "AWSDirectoryServiceReadOnlyAccess", - "UpdateDate": "2016-02-24T23:11:18+00:00", - "VersionId": "v3" + "UpdateDate": "2018-09-25T21:54:01+00:00", + "VersionId": "v4" }, - "AWSEC2SpotServiceRolePolicy": { - "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSEC2SpotServiceRolePolicy", + "AWSDiscoveryContinuousExportFirehosePolicy": { + "Arn": "arn:aws:iam::aws:policy/AWSDiscoveryContinuousExportFirehosePolicy", "AttachmentCount": 0, - "CreateDate": "2017-09-18T18:51:54+00:00", + "CreateDate": "2018-08-09T18:29:39+00:00", "DefaultVersionId": "v1", "Document": { "Statement": [ { "Action": [ - "ec2:DescribeInstances", - "ec2:StartInstances", - "ec2:StopInstances" + "glue:GetTableVersions" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:AbortMultipartUpload", + "s3:GetBucketLocation", + "s3:GetObject", + "s3:ListBucket", + "s3:ListBucketMultipartUploads", + "s3:PutObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-application-discovery-service-*", + "arn:aws:s3:::aws-application-discovery-service-*/*" + ] + }, + { + "Action": [ + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/application-discovery-service/firehose:log-stream:*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIX6FHUTEUNXYDFZ7C", + "PolicyName": "AWSDiscoveryContinuousExportFirehosePolicy", + "UpdateDate": "2018-08-09T18:29:39+00:00", + "VersionId": "v1" + }, + "AWSEC2FleetServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSEC2FleetServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-03-21T00:08:55+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:DescribeImages", + "ec2:DescribeSubnets", + "ec2:RequestSpotInstances", + "ec2:DescribeInstanceStatus", + "ec2:RunInstances" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "spot.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*", + "Sid": "EC2SpotManagement" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ec2.amazonaws.com.cn" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:instance/*", + "arn:aws:ec2:*:*:spot-instances-request/*" + ] + }, + { + "Action": [ + "ec2:TerminateInstances" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/aws:ec2:fleet-id": "*" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJCL355O4TC27CPKVC", + "PolicyName": "AWSEC2FleetServiceRolePolicy", + "UpdateDate": "2018-04-19T21:37:07+00:00", + "VersionId": "v2" + }, + "AWSEC2SpotFleetServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSEC2SpotFleetServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-23T19:13:06+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:DescribeImages", + "ec2:DescribeSubnets", + "ec2:RequestSpotInstances", + "ec2:DescribeInstanceStatus", + "ec2:RunInstances" ], "Effect": "Allow", "Resource": [ @@ -1912,14 +5646,39 @@ aws_managed_policies_data = """ "iam:PassRole" ], "Condition": { - "StringLike": { - "iam:PassedToService": "ec2.amazonaws.com" + "StringEquals": { + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ec2.amazonaws.com.cn" + ] } }, "Effect": "Allow", "Resource": [ "*" ] + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:instance/*", + "arn:aws:ec2:*:*:spot-instances-request/*" + ] + }, + { + "Action": [ + "ec2:TerminateInstances" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/aws:ec2spot:fleet-request-id": "*" + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -1927,10 +5686,85 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAILWCVTZD57EMYWMBO", + "PolicyName": "AWSEC2SpotFleetServiceRolePolicy", + "UpdateDate": "2018-03-28T19:04:33+00:00", + "VersionId": "v3" + }, + "AWSEC2SpotServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSEC2SpotServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-09-18T18:51:54+00:00", + "DefaultVersionId": "v4", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:DescribeInstances", + "ec2:StartInstances", + "ec2:StopInstances", + "ec2:RunInstances" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "ec2:RunInstances" + ], + "Condition": { + "StringNotEquals": { + "ec2:InstanceMarketType": "spot" + } + }, + "Effect": "Deny", + "Resource": [ + "arn:aws:ec2:*:*:instance/*" + ] + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ec2.amazonaws.com.cn" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Condition": { + "StringEquals": { + "ec2:CreateAction": "RunInstances" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIZJJBQNXQYVKTEXGM", "PolicyName": "AWSEC2SpotServiceRolePolicy", - "UpdateDate": "2017-09-18T18:51:54+00:00", - "VersionId": "v1" + "UpdateDate": "2018-12-12T00:13:51+00:00", + "VersionId": "v4" }, "AWSElasticBeanstalkCustomPlatformforEC2Role": { "Arn": "arn:aws:iam::aws:policy/AWSElasticBeanstalkCustomPlatformforEC2Role", @@ -2008,6 +5842,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJRVFXSS6LEIQGBKDY", "PolicyName": "AWSElasticBeanstalkCustomPlatformforEC2Role", "UpdateDate": "2017-02-21T22:50:30+00:00", @@ -2016,8 +5851,8 @@ aws_managed_policies_data = """ "AWSElasticBeanstalkEnhancedHealth": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkEnhancedHealth", "AttachmentCount": 0, - "CreateDate": "2016-08-22T20:28:36+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2016-02-08T23:17:27+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -2036,12 +5871,22 @@ aws_managed_policies_data = """ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeScalingActivities", - "autoscaling:DescribeNotificationConfigurations" + "autoscaling:DescribeNotificationConfigurations", + "sns:Publish" ], "Effect": "Allow", "Resource": [ "*" ] + }, + { + "Action": [ + "logs:DescribeLogStreams", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "arn:aws:logs:*:*:log-group:/aws/elasticbeanstalk/*:log-stream:*" } ], "Version": "2012-10-17" @@ -2049,16 +5894,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIH5EFJNMOGUUTKLFE", "PolicyName": "AWSElasticBeanstalkEnhancedHealth", - "UpdateDate": "2016-08-22T20:28:36+00:00", - "VersionId": "v2" + "UpdateDate": "2018-04-09T22:12:53+00:00", + "VersionId": "v4" }, "AWSElasticBeanstalkFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSElasticBeanstalkFullAccess", "AttachmentCount": 0, - "CreateDate": "2016-12-21T01:00:13+00:00", - "DefaultVersionId": "v5", + "CreateDate": "2015-02-06T18:40:18+00:00", + "DefaultVersionId": "v7", "Document": { "Statement": [ { @@ -2107,6 +5953,34 @@ aws_managed_policies_data = """ "arn:aws:iam::*:instance-profile/aws-elasticbeanstalk*" ] }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringLike": { + "iam:AWSServiceName": "autoscaling.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling*" + ] + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringLike": { + "iam:AWSServiceName": "elasticbeanstalk.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/elasticbeanstalk.amazonaws.com/AWSServiceRoleForElasticBeanstalk*" + ] + }, { "Action": [ "iam:AttachRolePolicy" @@ -2128,15 +6002,49 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIZYX2YLLBW2LJVUFW", "PolicyName": "AWSElasticBeanstalkFullAccess", - "UpdateDate": "2016-12-21T01:00:13+00:00", - "VersionId": "v5" + "UpdateDate": "2018-02-23T19:36:01+00:00", + "VersionId": "v7" + }, + "AWSElasticBeanstalkMaintenance": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSElasticBeanstalkMaintenance", + "AttachmentCount": 0, + "CreateDate": "2019-01-11T23:22:52+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": { + "Action": [ + "cloudformation:CreateChangeSet", + "cloudformation:DescribeChangeSet", + "cloudformation:ExecuteChangeSet", + "cloudformation:DeleteChangeSet", + "cloudformation:ListChangeSets", + "cloudformation:DescribeStacks" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:cloudformation:*:*:stack/awseb-*", + "arn:aws:cloudformation:*:*:stack/eb-*" + ], + "Sid": "AllowCloudformationChangeSetOperationsOnElasticBeanstalkStacks" + }, + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJQPH22XGBH2VV2LSW", + "PolicyName": "AWSElasticBeanstalkMaintenance", + "UpdateDate": "2019-01-11T23:22:52+00:00", + "VersionId": "v1" }, "AWSElasticBeanstalkMulticontainerDocker": { "Arn": "arn:aws:iam::aws:policy/AWSElasticBeanstalkMulticontainerDocker", "AttachmentCount": 0, - "CreateDate": "2016-06-06T23:45:37+00:00", + "CreateDate": "2016-02-08T23:15:29+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -2163,6 +6071,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ45SBYG72SD6SHJEY", "PolicyName": "AWSElasticBeanstalkMulticontainerDocker", "UpdateDate": "2016-06-06T23:45:37+00:00", @@ -2210,6 +6119,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI47KNGXDAXFD4SDHG", "PolicyName": "AWSElasticBeanstalkReadOnlyAccess", "UpdateDate": "2015-02-06T18:40:19+00:00", @@ -2218,8 +6128,8 @@ aws_managed_policies_data = """ "AWSElasticBeanstalkService": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalkService", "AttachmentCount": 0, - "CreateDate": "2017-06-21T16:49:23+00:00", - "DefaultVersionId": "v11", + "CreateDate": "2016-04-11T20:27:23+00:00", + "DefaultVersionId": "v15", "Document": { "Statement": [ { @@ -2254,6 +6164,17 @@ aws_managed_policies_data = """ ], "Sid": "AllowS3OperationsOnElasticBeanstalkBuckets" }, + { + "Action": "ec2:RunInstances", + "Condition": { + "ArnLike": { + "ec2:LaunchTemplate": "arn:aws:ec2:*:*:launch-template/*" + } + }, + "Effect": "Allow", + "Resource": "*", + "Sid": "AllowLaunchTemplateRunInstances" + }, { "Action": [ "autoscaling:AttachInstances", @@ -2271,7 +6192,10 @@ aws_managed_policies_data = """ "autoscaling:DescribeScalingActivities", "autoscaling:DescribeScheduledActions", "autoscaling:DetachInstances", + "autoscaling:DeletePolicy", + "autoscaling:PutScalingPolicy", "autoscaling:PutScheduledUpdateGroupAction", + "autoscaling:PutNotificationConfiguration", "autoscaling:ResumeProcesses", "autoscaling:SetDesiredCapacity", "autoscaling:SuspendProcesses", @@ -2282,6 +6206,12 @@ aws_managed_policies_data = """ "ec2:AllocateAddress", "ec2:AuthorizeSecurityGroupEgress", "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateLaunchTemplate", + "ec2:CreateLaunchTemplateVersion", + "ec2:DescribeLaunchTemplates", + "ec2:DescribeLaunchTemplateVersions", + "ec2:DeleteLaunchTemplate", + "ec2:DeleteLaunchTemplateVersions", "ec2:CreateSecurityGroup", "ec2:DeleteSecurityGroup", "ec2:DescribeAccountAttributes", @@ -2293,6 +6223,9 @@ aws_managed_policies_data = """ "ec2:DescribeSnapshots", "ec2:DescribeSubnets", "ec2:DescribeVpcs", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeSpotInstanceRequests", + "ec2:DescribeVpcClassicLink", "ec2:DisassociateAddress", "ec2:ReleaseAddress", "ec2:RevokeSecurityGroupEgress", @@ -2319,6 +6252,7 @@ aws_managed_policies_data = """ "iam:PassRole", "logs:CreateLogGroup", "logs:PutRetentionPolicy", + "logs:DescribeLogGroups", "rds:DescribeDBEngineVersions", "rds:DescribeDBInstances", "rds:DescribeOrderableDBInstanceOptions", @@ -2353,144 +6287,66 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJKQ5SN74ZQ4WASXBM", "PolicyName": "AWSElasticBeanstalkService", - "UpdateDate": "2017-06-21T16:49:23+00:00", - "VersionId": "v11" + "UpdateDate": "2019-02-05T17:46:21+00:00", + "VersionId": "v15" }, "AWSElasticBeanstalkServiceRolePolicy": { "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSElasticBeanstalkServiceRolePolicy", "AttachmentCount": 0, "CreateDate": "2017-09-13T23:46:37+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v5", "Document": { "Statement": [ { "Action": [ - "iam:PassRole" - ], - "Condition": { - "StringLikeIfExists": { - "iam:PassedToService": "elasticbeanstalk.amazonaws.com" - } - }, - "Effect": "Allow", - "Resource": "*", - "Sid": "AllowPassRoleToElasticBeanstalk" - }, - { - "Action": [ - "cloudformation:*" + "cloudformation:DescribeStackResource", + "cloudformation:DescribeStackResources", + "cloudformation:DescribeStacks" ], "Effect": "Allow", "Resource": [ "arn:aws:cloudformation:*:*:stack/awseb-*", "arn:aws:cloudformation:*:*:stack/eb-*" ], - "Sid": "AllowCloudformationOperationsOnElasticBeanstalkStacks" + "Sid": "AllowCloudformationReadOperationsOnElasticBeanstalkStacks" }, { "Action": [ - "logs:DeleteLogGroup" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:logs:*:*:log-group:/aws/elasticbeanstalk*" - ], - "Sid": "AllowDeleteCloudwatchLogGroups" - }, - { - "Action": [ - "s3:*" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:s3:::elasticbeanstalk-*", - "arn:aws:s3:::elasticbeanstalk-*/*" - ], - "Sid": "AllowS3OperationsOnElasticBeanstalkBuckets" - }, - { - "Action": [ - "autoscaling:AttachInstances", - "autoscaling:CreateAutoScalingGroup", - "autoscaling:CreateLaunchConfiguration", - "autoscaling:DeleteLaunchConfiguration", - "autoscaling:DeleteAutoScalingGroup", - "autoscaling:DeleteScheduledAction", - "autoscaling:DescribeAccountLimits", "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", - "autoscaling:DescribeLaunchConfigurations", - "autoscaling:DescribeLoadBalancers", "autoscaling:DescribeNotificationConfigurations", "autoscaling:DescribeScalingActivities", - "autoscaling:DescribeScheduledActions", - "autoscaling:DetachInstances", - "autoscaling:PutScheduledUpdateGroupAction", - "autoscaling:ResumeProcesses", - "autoscaling:SetDesiredCapacity", - "autoscaling:SuspendProcesses", - "autoscaling:TerminateInstanceInAutoScalingGroup", - "autoscaling:UpdateAutoScalingGroup", - "cloudwatch:PutMetricAlarm", + "autoscaling:PutNotificationConfiguration", + "ec2:DescribeInstanceStatus", "ec2:AssociateAddress", - "ec2:AllocateAddress", - "ec2:AuthorizeSecurityGroupEgress", - "ec2:AuthorizeSecurityGroupIngress", - "ec2:CreateSecurityGroup", - "ec2:DeleteSecurityGroup", - "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", - "ec2:DescribeImages", "ec2:DescribeInstances", - "ec2:DescribeKeyPairs", "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeVpcs", - "ec2:DisassociateAddress", - "ec2:ReleaseAddress", - "ec2:RevokeSecurityGroupEgress", - "ec2:RevokeSecurityGroupIngress", - "ec2:TerminateInstances", - "ecs:CreateCluster", - "ecs:DeleteCluster", - "ecs:DescribeClusters", - "ecs:RegisterTaskDefinition", - "elasticbeanstalk:*", - "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer", - "elasticloadbalancing:ConfigureHealthCheck", - "elasticloadbalancing:CreateLoadBalancer", - "elasticloadbalancing:DeleteLoadBalancer", - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", "elasticloadbalancing:DescribeInstanceHealth", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeTargetHealth", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer", "elasticloadbalancing:DescribeTargetGroups", - "elasticloadbalancing:RegisterTargets", - "elasticloadbalancing:DeregisterTargets", - "iam:ListRoles", - "logs:CreateLogGroup", - "logs:PutRetentionPolicy", - "rds:DescribeDBInstances", - "rds:DescribeOrderableDBInstanceOptions", - "rds:DescribeDBEngineVersions", - "sns:ListTopics", - "sns:GetTopicAttributes", - "sns:ListSubscriptionsByTopic", "sqs:GetQueueAttributes", "sqs:GetQueueUrl", - "codebuild:CreateProject", - "codebuild:DeleteProject", - "codebuild:BatchGetBuilds", - "codebuild:StartBuild" + "sns:Publish" ], "Effect": "Allow", "Resource": [ "*" ], "Sid": "AllowOperations" + }, + { + "Action": [ + "logs:DescribeLogStreams", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "arn:aws:logs:*:*:log-group:/aws/elasticbeanstalk/*:log-stream:*" } ], "Version": "2012-10-17" @@ -2498,16 +6354,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIID62QSI3OSIPQXTM", "PolicyName": "AWSElasticBeanstalkServiceRolePolicy", - "UpdateDate": "2017-09-13T23:46:37+00:00", - "VersionId": "v1" + "UpdateDate": "2018-04-09T22:06:23+00:00", + "VersionId": "v5" }, "AWSElasticBeanstalkWebTier": { "Arn": "arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier", "AttachmentCount": 0, - "CreateDate": "2016-12-21T02:06:25+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2016-02-08T23:08:54+00:00", + "DefaultVersionId": "v6", "Document": { "Statement": [ { @@ -2526,7 +6383,10 @@ aws_managed_policies_data = """ { "Action": [ "xray:PutTraceSegments", - "xray:PutTelemetryRecords" + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + "xray:GetSamplingStatisticSummaries" ], "Effect": "Allow", "Resource": "*", @@ -2535,7 +6395,9 @@ aws_managed_policies_data = """ { "Action": [ "logs:PutLogEvents", - "logs:CreateLogStream" + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:DescribeLogGroups" ], "Effect": "Allow", "Resource": [ @@ -2549,16 +6411,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIUF4325SJYOREKW3A", "PolicyName": "AWSElasticBeanstalkWebTier", - "UpdateDate": "2016-12-21T02:06:25+00:00", - "VersionId": "v4" + "UpdateDate": "2019-03-01T00:04:49+00:00", + "VersionId": "v6" }, "AWSElasticBeanstalkWorkerTier": { "Arn": "arn:aws:iam::aws:policy/AWSElasticBeanstalkWorkerTier", "AttachmentCount": 0, - "CreateDate": "2016-12-21T02:01:55+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2016-02-08T23:12:02+00:00", + "DefaultVersionId": "v5", "Document": { "Statement": [ { @@ -2572,7 +6435,10 @@ aws_managed_policies_data = """ { "Action": [ "xray:PutTraceSegments", - "xray:PutTelemetryRecords" + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + "xray:GetSamplingStatisticSummaries" ], "Effect": "Allow", "Resource": "*", @@ -2636,10 +6502,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJQDLBRSJVKVF4JMSK", "PolicyName": "AWSElasticBeanstalkWorkerTier", - "UpdateDate": "2016-12-21T02:01:55+00:00", - "VersionId": "v4" + "UpdateDate": "2019-03-01T00:07:00+00:00", + "VersionId": "v5" }, "AWSElasticLoadBalancingClassicServiceRolePolicy": { "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSElasticLoadBalancingClassicServiceRolePolicy", @@ -2682,6 +6549,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIUMWW3QP7DPZPNVU4", "PolicyName": "AWSElasticLoadBalancingClassicServiceRolePolicy", "UpdateDate": "2017-09-19T22:36:18+00:00", @@ -2691,13 +6559,14 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSElasticLoadBalancingServiceRolePolicy", "AttachmentCount": 0, "CreateDate": "2017-09-19T22:19:04+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { "Action": [ "ec2:DescribeAddresses", "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups", "ec2:DescribeVpcs", @@ -2717,7 +6586,12 @@ aws_managed_policies_data = """ "ec2:DetachNetworkInterface", "ec2:AssignPrivateIpAddresses", "ec2:AssignIpv6Addresses", - "ec2:UnassignIpv6Addresses" + "ec2:UnassignIpv6Addresses", + "logs:CreateLogDelivery", + "logs:GetLogDelivery", + "logs:UpdateLogDelivery", + "logs:DeleteLogDelivery", + "logs:ListLogDeliveries" ], "Effect": "Allow", "Resource": "*" @@ -2728,9 +6602,195 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIMHWGGSRHLOQUICJQ", "PolicyName": "AWSElasticLoadBalancingServiceRolePolicy", - "UpdateDate": "2017-09-19T22:19:04+00:00", + "UpdateDate": "2019-03-18T21:51:14+00:00", + "VersionId": "v3" + }, + "AWSElementalMediaConvertFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSElementalMediaConvertFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-06-25T19:25:35+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "mediaconvert:*", + "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:ListObjects" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "mediaconvert.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIXDREOCL6LV7RBJWC", + "PolicyName": "AWSElementalMediaConvertFullAccess", + "UpdateDate": "2018-06-25T19:25:35+00:00", + "VersionId": "v1" + }, + "AWSElementalMediaConvertReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AWSElementalMediaConvertReadOnly", + "AttachmentCount": 0, + "CreateDate": "2018-06-25T19:25:14+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "mediaconvert:Get*", + "mediaconvert:List*", + "mediaconvert:DescribeEndpoints", + "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:ListObjects" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJSXYOBSLJN3JEDO42", + "PolicyName": "AWSElementalMediaConvertReadOnly", + "UpdateDate": "2018-06-25T19:25:14+00:00", + "VersionId": "v1" + }, + "AWSElementalMediaPackageFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSElementalMediaPackageFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-12-29T23:39:52+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": { + "Action": "mediapackage:*", + "Effect": "Allow", + "Resource": "*" + }, + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIYI6IYR3JRFAVNQHC", + "PolicyName": "AWSElementalMediaPackageFullAccess", + "UpdateDate": "2017-12-29T23:39:52+00:00", + "VersionId": "v1" + }, + "AWSElementalMediaPackageReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AWSElementalMediaPackageReadOnly", + "AttachmentCount": 0, + "CreateDate": "2017-12-30T00:04:29+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": { + "Action": [ + "mediapackage:List*", + "mediapackage:Describe*" + ], + "Effect": "Allow", + "Resource": "*" + }, + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ42DVTPUHKXNYZQCO", + "PolicyName": "AWSElementalMediaPackageReadOnly", + "UpdateDate": "2017-12-30T00:04:29+00:00", + "VersionId": "v1" + }, + "AWSElementalMediaStoreFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSElementalMediaStoreFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-03-05T23:15:31+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "mediastore:*" + ], + "Condition": { + "Bool": { + "aws:SecureTransport": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJZFYFW2QXSNK7OH6Y", + "PolicyName": "AWSElementalMediaStoreFullAccess", + "UpdateDate": "2018-03-05T23:15:31+00:00", + "VersionId": "v1" + }, + "AWSElementalMediaStoreReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AWSElementalMediaStoreReadOnly", + "AttachmentCount": 0, + "CreateDate": "2018-03-08T19:48:22+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "mediastore:Get*", + "mediastore:List*", + "mediastore:Describe*" + ], + "Condition": { + "Bool": { + "aws:SecureTransport": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI4EFXRATQYOFTAEFM", + "PolicyName": "AWSElementalMediaStoreReadOnly", + "UpdateDate": "2018-03-08T19:48:22+00:00", "VersionId": "v1" }, "AWSEnhancedClassicNetworkingMangementPolicy": { @@ -2754,16 +6814,355 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI7T4V2HZTS72QVO52", "PolicyName": "AWSEnhancedClassicNetworkingMangementPolicy", "UpdateDate": "2017-09-20T17:29:09+00:00", "VersionId": "v1" }, + "AWSFMAdminFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSFMAdminFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-05-09T18:06:18+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "fms:*", + "waf:*", + "waf-regional:*", + "elasticloadbalancing:SetWebACL", + "organizations:DescribeOrganization" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJLAGM5X6WSNPF4EAQ", + "PolicyName": "AWSFMAdminFullAccess", + "UpdateDate": "2018-05-09T18:06:18+00:00", + "VersionId": "v1" + }, + "AWSFMAdminReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSFMAdminReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-05-09T20:07:39+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "fms:Get*", + "fms:List*", + "waf:Get*", + "waf:List*", + "waf-regional:Get*", + "waf-regional:List*", + "organizations:DescribeOrganization" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJA3UKVVBN62QFIKLW", + "PolicyName": "AWSFMAdminReadOnlyAccess", + "UpdateDate": "2018-05-09T20:07:39+00:00", + "VersionId": "v1" + }, + "AWSFMMemberReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSFMMemberReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-05-09T21:05:29+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "fms:GetAdminAccount", + "waf:Get*", + "waf:List*", + "waf-regional:Get*", + "waf-regional:List*", + "organizations:DescribeOrganization" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIB2IVAQ4XXNHHA3DW", + "PolicyName": "AWSFMMemberReadOnlyAccess", + "UpdateDate": "2018-05-09T21:05:29+00:00", + "VersionId": "v1" + }, + "AWSGlobalAcceleratorSLRPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSGlobalAcceleratorSLRPolicy", + "AttachmentCount": 0, + "CreateDate": "2019-04-05T19:39:13+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DeleteNetworkInterface" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "ec2:DeleteSecurityGroup", + "Condition": { + "StringEquals": { + "ec2:ResourceTag/AWSServiceName": "GlobalAccelerator" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateSecurityGroup", + "ec2:DescribeSecurityGroups" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "elasticloadbalancing:DescribeLoadBalancers", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "ec2:CreateTags", + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:security-group/*", + "arn:aws:ec2:*:*:network-interface/*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4EJ5ZEQR2C", + "PolicyName": "AWSGlobalAcceleratorSLRPolicy", + "UpdateDate": "2019-04-05T19:39:13+00:00", + "VersionId": "v1" + }, "AWSGlueConsoleFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSGlueConsoleFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-09-13T00:12:54+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2017-08-14T13:37:39+00:00", + "DefaultVersionId": "v12", + "Document": { + "Statement": [ + { + "Action": [ + "glue:*", + "redshift:DescribeClusters", + "redshift:DescribeClusterSubnetGroups", + "iam:ListRoles", + "iam:ListUsers", + "iam:ListGroups", + "iam:ListRolePolicies", + "iam:GetRole", + "iam:GetRolePolicy", + "iam:ListAttachedRolePolicies", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:DescribeVpcEndpoints", + "ec2:DescribeRouteTables", + "ec2:DescribeVpcAttribute", + "ec2:DescribeKeyPairs", + "ec2:DescribeInstances", + "ec2:DescribeImages", + "rds:DescribeDBInstances", + "rds:DescribeDBClusters", + "rds:DescribeDBSubnetGroups", + "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:GetBucketAcl", + "s3:GetBucketLocation", + "cloudformation:DescribeStacks", + "cloudformation:GetTemplateSummary", + "dynamodb:ListTables", + "kms:ListAliases", + "kms:DescribeKey", + "cloudwatch:GetMetricData", + "cloudwatch:ListDashboards" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "s3:GetObject", + "s3:PutObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-glue-*/*", + "arn:aws:s3:::*/*aws-glue-*/*", + "arn:aws:s3:::aws-glue-*" + ] + }, + { + "Action": [ + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "s3:CreateBucket" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-glue-*" + ] + }, + { + "Action": [ + "logs:GetLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:/aws-glue/*" + ] + }, + { + "Action": [ + "cloudformation:CreateStack", + "cloudformation:DeleteStack" + ], + "Effect": "Allow", + "Resource": "arn:aws:cloudformation:*:*:stack/aws-glue*/*" + }, + { + "Action": [ + "ec2:RunInstances" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:instance/*", + "arn:aws:ec2:*:*:key-pair/*", + "arn:aws:ec2:*:*:image/*", + "arn:aws:ec2:*:*:security-group/*", + "arn:aws:ec2:*:*:network-interface/*", + "arn:aws:ec2:*:*:subnet/*", + "arn:aws:ec2:*:*:volume/*" + ] + }, + { + "Action": [ + "ec2:TerminateInstances", + "ec2:CreateTags", + "ec2:DeleteTags" + ], + "Condition": { + "StringEquals": { + "ec2:ResourceTag/aws:cloudformation:logical-id": "ZeppelinInstance" + }, + "StringLike": { + "ec2:ResourceTag/aws:cloudformation:stack-id": "arn:aws:cloudformation:*:*:stack/aws-glue-*/*" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:instance/*" + ] + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "glue.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/AWSGlueServiceRole*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "ec2.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/AWSGlueServiceNotebookRole*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "glue.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/service-role/AWSGlueServiceRole*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJNZGDEOD7MISOVSVI", + "PolicyName": "AWSGlueConsoleFullAccess", + "UpdateDate": "2019-02-11T19:49:01+00:00", + "VersionId": "v12" + }, + "AWSGlueConsoleSageMakerNotebookFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSGlueConsoleSageMakerNotebookFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-10-05T17:52:35+00:00", + "DefaultVersionId": "v1", "Document": { "Statement": [ { @@ -2775,6 +7174,7 @@ aws_managed_policies_data = """ "iam:ListRolePolicies", "iam:GetRole", "iam:GetRolePolicy", + "iam:ListAttachedRolePolicies", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeVpcs", @@ -2783,13 +7183,29 @@ aws_managed_policies_data = """ "ec2:DescribeVpcAttribute", "ec2:DescribeKeyPairs", "ec2:DescribeInstances", + "ec2:DescribeImages", + "ec2:CreateNetworkInterface", + "ec2:AttachNetworkInterface", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DeleteNetworkInterface", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInternetGateways", + "ec2:DescribeNetworkInterfaces", "rds:DescribeDBInstances", "s3:ListAllMyBuckets", "s3:ListBucket", "s3:GetBucketAcl", "s3:GetBucketLocation", "cloudformation:DescribeStacks", - "cloudformation:GetTemplateSummary" + "cloudformation:GetTemplateSummary", + "dynamodb:ListTables", + "kms:ListAliases", + "kms:DescribeKey", + "sagemaker:ListNotebookInstances", + "sagemaker:ListNotebookInstanceLifecycleConfigs", + "cloudformation:ListStacks", + "cloudwatch:GetMetricData", + "cloudwatch:ListDashboards" ], "Effect": "Allow", "Resource": [ @@ -2834,18 +7250,64 @@ aws_managed_policies_data = """ "Effect": "Allow", "Resource": "arn:aws:cloudformation:*:*:stack/aws-glue*/*" }, + { + "Action": [ + "sagemaker:CreatePresignedNotebookInstanceUrl", + "sagemaker:CreateNotebookInstance", + "sagemaker:DeleteNotebookInstance", + "sagemaker:DescribeNotebookInstance", + "sagemaker:DescribeNotebookInstanceLifecycleConfig", + "sagemaker:DeleteNotebookInstanceLifecycleConfig", + "sagemaker:StartNotebookInstance", + "sagemaker:CreateNotebookInstanceLifecycleConfig", + "sagemaker:StopNotebookInstance", + "sagemaker:UpdateNotebookInstance", + "sagemaker:ListTags" + ], + "Effect": "Allow", + "Resource": "arn:aws:sagemaker:*:*:notebook-instance/aws-glue-*" + }, + { + "Action": [ + "ec2:RunInstances" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:instance/*", + "arn:aws:ec2:*:*:key-pair/*", + "arn:aws:ec2:*:*:image/*", + "arn:aws:ec2:*:*:security-group/*", + "arn:aws:ec2:*:*:network-interface/*", + "arn:aws:ec2:*:*:subnet/*", + "arn:aws:ec2:*:*:volume/*" + ] + }, { "Action": [ "ec2:TerminateInstances", - "ec2:RunInstances", "ec2:CreateTags", "ec2:DeleteTags" ], "Condition": { - "ForAllValues:StringEquals": { - "aws:TagKeys": [ - "aws-glue-dev-endpoint" - ] + "StringEquals": { + "ec2:ResourceTag/aws:cloudformation:logical-id": "ZeppelinInstance" + }, + "StringLike": { + "ec2:ResourceTag/aws:cloudformation:stack-id": "arn:aws:cloudformation:*:*:stack/aws-glue-*/*" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:instance/*" + ] + }, + { + "Action": [ + "tag:GetResources" + ], + "Condition": { + "StringEquals": { + "aws:TagKeys": "aws-glue-*" } }, "Effect": "Allow", @@ -2880,6 +7342,36 @@ aws_managed_policies_data = """ }, "Effect": "Allow", "Resource": "arn:aws:iam::*:role/AWSGlueServiceNotebookRole*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "sagemaker.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/AWSGlueServiceSageMakerNotebookRole*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "glue.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/service-role/AWSGlueServiceRole*" + ] } ], "Version": "2012-10-17" @@ -2887,15 +7379,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", - "PolicyId": "ANPAJNZGDEOD7MISOVSVI", - "PolicyName": "AWSGlueConsoleFullAccess", - "UpdateDate": "2017-09-13T00:12:54+00:00", - "VersionId": "v2" + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJELFOHJC42QS3ZSYY", + "PolicyName": "AWSGlueConsoleSageMakerNotebookFullAccess", + "UpdateDate": "2018-10-05T17:52:35+00:00", + "VersionId": "v1" }, "AWSGlueServiceNotebookRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSGlueServiceNotebookRole", "AttachmentCount": 0, - "CreateDate": "2017-08-17T18:08:29+00:00", + "CreateDate": "2017-08-14T13:37:42+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -3000,6 +7493,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIMRC6VZUHJYCTKWFI", "PolicyName": "AWSGlueServiceNotebookRole", "UpdateDate": "2017-08-17T18:08:29+00:00", @@ -3008,8 +7502,8 @@ aws_managed_policies_data = """ "AWSGlueServiceRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole", "AttachmentCount": 0, - "CreateDate": "2017-08-23T21:35:25+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2017-08-14T13:37:21+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -3029,7 +7523,8 @@ aws_managed_policies_data = """ "ec2:DescribeVpcAttribute", "iam:ListRolePolicies", "iam:GetRole", - "iam:GetRolePolicy" + "iam:GetRolePolicy", + "cloudwatch:PutMetricData" ], "Effect": "Allow", "Resource": [ @@ -3103,10 +7598,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIRUJCPEBPMEZFAS32", "PolicyName": "AWSGlueServiceRole", - "UpdateDate": "2017-08-23T21:35:25+00:00", - "VersionId": "v3" + "UpdateDate": "2018-06-25T18:23:09+00:00", + "VersionId": "v4" }, "AWSGreengrassFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSGreengrassFullAccess", @@ -3128,16 +7624,44 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJWPV6OBK4QONH4J3O", "PolicyName": "AWSGreengrassFullAccess", "UpdateDate": "2017-05-03T00:47:37+00:00", "VersionId": "v1" }, + "AWSGreengrassReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSGreengrassReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-10-30T16:01:43+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "greengrass:List*", + "greengrass:Get*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJLSKLXFVTQTZ5GY3I", + "PolicyName": "AWSGreengrassReadOnlyAccess", + "UpdateDate": "2018-10-30T16:01:43+00:00", + "VersionId": "v1" + }, "AWSGreengrassResourceAccessRolePolicy": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSGreengrassResourceAccessRolePolicy", "AttachmentCount": 0, - "CreateDate": "2017-05-26T23:10:54+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2017-02-14T21:17:24+00:00", + "DefaultVersionId": "v5", "Document": { "Statement": [ { @@ -3187,6 +7711,47 @@ aws_managed_policies_data = """ "Effect": "Allow", "Resource": "*", "Sid": "AllowGreengrassToGetLambdaFunctions" + }, + { + "Action": [ + "secretsmanager:GetSecretValue" + ], + "Effect": "Allow", + "Resource": "arn:aws:secretsmanager:*:*:secret:greengrass-*", + "Sid": "AllowGreengrassToGetGreengrassSecrets" + }, + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*Greengrass*", + "arn:aws:s3:::*GreenGrass*", + "arn:aws:s3:::*greengrass*", + "arn:aws:s3:::*Sagemaker*", + "arn:aws:s3:::*SageMaker*", + "arn:aws:s3:::*sagemaker*" + ], + "Sid": "AllowGreengrassAccessToS3Objects" + }, + { + "Action": [ + "s3:GetBucketLocation" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "AllowGreengrassAccessToS3BucketLocation" + }, + { + "Action": [ + "sagemaker:DescribeTrainingJob" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:sagemaker:*:*:training-job/*" + ], + "Sid": "AllowGreengrassAccessToSageMakerTrainingJobs" } ], "Version": "2012-10-17" @@ -3194,10 +7759,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJPKEIMB6YMXDEVRTM", "PolicyName": "AWSGreengrassResourceAccessRolePolicy", - "UpdateDate": "2017-05-26T23:10:54+00:00", - "VersionId": "v3" + "UpdateDate": "2018-11-14T00:35:02+00:00", + "VersionId": "v5" }, "AWSHealthFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSHealthFullAccess", @@ -3219,11 +7785,38 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI3CUMPCPEUPCSXC4Y", "PolicyName": "AWSHealthFullAccess", "UpdateDate": "2016-12-06T12:30:31+00:00", "VersionId": "v1" }, + "AWSIQFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIQFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-04-04T23:13:42+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iq:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4P4TAHETXT", + "PolicyName": "AWSIQFullAccess", + "UpdateDate": "2019-04-04T23:13:42+00:00", + "VersionId": "v1" + }, "AWSImportExportFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSImportExportFullAccess", "AttachmentCount": 0, @@ -3244,6 +7837,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJCQCT4JGTLC6722MQ", "PolicyName": "AWSImportExportFullAccess", "UpdateDate": "2015-02-06T18:40:43+00:00", @@ -3270,74 +7864,283 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJNTV4OG52ESYZHCNK", "PolicyName": "AWSImportExportReadOnlyAccess", "UpdateDate": "2015-02-06T18:40:42+00:00", "VersionId": "v1" }, + "AWSIoT1ClickFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoT1ClickFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-05-11T22:10:14+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iot1click:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJPQNJPDUDESCCAMIA", + "PolicyName": "AWSIoT1ClickFullAccess", + "UpdateDate": "2018-05-11T22:10:14+00:00", + "VersionId": "v1" + }, + "AWSIoT1ClickReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoT1ClickReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-05-11T21:49:24+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iot1click:Describe*", + "iot1click:Get*", + "iot1click:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI35VTLD3EBNY2JGXS", + "PolicyName": "AWSIoT1ClickReadOnlyAccess", + "UpdateDate": "2018-05-11T21:49:24+00:00", + "VersionId": "v1" + }, + "AWSIoTAnalyticsFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoTAnalyticsFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-06-18T23:02:45+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iotanalytics:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7FB5ZEKQN445QGKY", + "PolicyName": "AWSIoTAnalyticsFullAccess", + "UpdateDate": "2018-06-18T23:02:45+00:00", + "VersionId": "v1" + }, + "AWSIoTAnalyticsReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoTAnalyticsReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-06-18T21:37:49+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iotanalytics:Describe*", + "iotanalytics:List*", + "iotanalytics:Get*", + "iotanalytics:SampleChannelData" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ3Z4LYBELMXGFLGMI", + "PolicyName": "AWSIoTAnalyticsReadOnlyAccess", + "UpdateDate": "2018-06-18T21:37:49+00:00", + "VersionId": "v1" + }, "AWSIoTConfigAccess": { "Arn": "arn:aws:iam::aws:policy/AWSIoTConfigAccess", "AttachmentCount": 0, - "CreateDate": "2016-07-27T20:41:18+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2015-10-27T21:52:07+00:00", + "DefaultVersionId": "v8", "Document": { "Statement": [ { "Action": [ "iot:AcceptCertificateTransfer", + "iot:AddThingToThingGroup", + "iot:AssociateTargetsWithJob", + "iot:AttachPolicy", "iot:AttachPrincipalPolicy", "iot:AttachThingPrincipal", "iot:CancelCertificateTransfer", + "iot:CancelJob", + "iot:CancelJobExecution", + "iot:ClearDefaultAuthorizer", + "iot:CreateAuthorizer", "iot:CreateCertificateFromCsr", + "iot:CreateJob", "iot:CreateKeysAndCertificate", + "iot:CreateOTAUpdate", "iot:CreatePolicy", "iot:CreatePolicyVersion", + "iot:CreateRoleAlias", + "iot:CreateStream", "iot:CreateThing", + "iot:CreateThingGroup", "iot:CreateThingType", "iot:CreateTopicRule", - "iot:DeleteCertificate", + "iot:DeleteAuthorizer", "iot:DeleteCACertificate", + "iot:DeleteCertificate", + "iot:DeleteJob", + "iot:DeleteJobExecution", + "iot:DeleteOTAUpdate", "iot:DeletePolicy", "iot:DeletePolicyVersion", "iot:DeleteRegistrationCode", + "iot:DeleteRoleAlias", + "iot:DeleteStream", "iot:DeleteThing", + "iot:DeleteThingGroup", "iot:DeleteThingType", "iot:DeleteTopicRule", + "iot:DeleteV2LoggingLevel", "iot:DeprecateThingType", - "iot:DescribeCertificate", + "iot:DescribeAuthorizer", "iot:DescribeCACertificate", + "iot:DescribeCertificate", + "iot:DescribeCertificateTag", + "iot:DescribeDefaultAuthorizer", "iot:DescribeEndpoint", + "iot:DescribeEventConfigurations", + "iot:DescribeIndex", + "iot:DescribeJob", + "iot:DescribeJobExecution", + "iot:DescribeRoleAlias", + "iot:DescribeStream", "iot:DescribeThing", + "iot:DescribeThingGroup", + "iot:DescribeThingRegistrationTask", "iot:DescribeThingType", + "iot:DetachPolicy", "iot:DetachPrincipalPolicy", "iot:DetachThingPrincipal", + "iot:DisableTopicRule", + "iot:EnableTopicRule", + "iot:GetEffectivePolicies", + "iot:GetIndexingConfiguration", + "iot:GetJobDocument", "iot:GetLoggingOptions", + "iot:GetOTAUpdate", "iot:GetPolicy", "iot:GetPolicyVersion", "iot:GetRegistrationCode", "iot:GetTopicRule", - "iot:ListCertificates", + "iot:GetV2LoggingOptions", + "iot:ListAttachedPolicies", + "iot:ListAuthorizers", "iot:ListCACertificates", + "iot:ListCertificates", "iot:ListCertificatesByCA", + "iot:ListIndices", + "iot:ListJobExecutionsForJob", + "iot:ListJobExecutionsForThing", + "iot:ListJobs", + "iot:ListOTAUpdates", + "iot:ListOutgoingCertificates", "iot:ListPolicies", "iot:ListPolicyPrincipals", "iot:ListPolicyVersions", "iot:ListPrincipalPolicies", "iot:ListPrincipalThings", + "iot:ListRoleAliases", + "iot:ListStreams", + "iot:ListTargetsForPolicy", + "iot:ListThingGroups", + "iot:ListThingGroupsForThing", "iot:ListThingPrincipals", + "iot:ListThingRegistrationTaskReports", + "iot:ListThingRegistrationTasks", "iot:ListThings", + "iot:ListThingsInThingGroup", "iot:ListThingTypes", "iot:ListTopicRules", - "iot:RegisterCertificate", + "iot:ListV2LoggingLevels", "iot:RegisterCACertificate", + "iot:RegisterCertificate", + "iot:RegisterThing", "iot:RejectCertificateTransfer", + "iot:RemoveThingFromThingGroup", "iot:ReplaceTopicRule", + "iot:SearchIndex", + "iot:SetDefaultAuthorizer", "iot:SetDefaultPolicyVersion", "iot:SetLoggingOptions", + "iot:SetV2LoggingLevel", + "iot:SetV2LoggingOptions", + "iot:StartThingRegistrationTask", + "iot:StopThingRegistrationTask", + "iot:TestAuthorization", + "iot:TestInvokeAuthorizer", "iot:TransferCertificate", - "iot:UpdateCertificate", + "iot:UpdateAuthorizer", "iot:UpdateCACertificate", - "iot:UpdateThing" + "iot:UpdateCertificate", + "iot:UpdateCertificateTag", + "iot:UpdateEventConfigurations", + "iot:UpdateIndexingConfiguration", + "iot:UpdateRoleAlias", + "iot:UpdateStream", + "iot:UpdateThing", + "iot:UpdateThingGroup", + "iot:UpdateThingGroupsForThing", + "iot:UpdateAccountAuditConfiguration", + "iot:DescribeAccountAuditConfiguration", + "iot:DeleteAccountAuditConfiguration", + "iot:StartOnDemandAuditTask", + "iot:CancelAuditTask", + "iot:DescribeAuditTask", + "iot:ListAuditTasks", + "iot:CreateScheduledAudit", + "iot:UpdateScheduledAudit", + "iot:DeleteScheduledAudit", + "iot:DescribeScheduledAudit", + "iot:ListScheduledAudits", + "iot:ListAuditFindings", + "iot:CreateSecurityProfile", + "iot:DescribeSecurityProfile", + "iot:UpdateSecurityProfile", + "iot:DeleteSecurityProfile", + "iot:AttachSecurityProfile", + "iot:DetachSecurityProfile", + "iot:ListSecurityProfiles", + "iot:ListSecurityProfilesForTarget", + "iot:ListTargetsForSecurityProfile", + "iot:ListActiveViolations", + "iot:ListViolationEvents", + "iot:ValidateSecurityProfileBehaviors" ], "Effect": "Allow", "Resource": "*" @@ -3348,42 +8151,92 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIWWGD4LM4EMXNRL7I", "PolicyName": "AWSIoTConfigAccess", - "UpdateDate": "2016-07-27T20:41:18+00:00", - "VersionId": "v4" + "UpdateDate": "2018-10-01T17:22:32+00:00", + "VersionId": "v8" }, "AWSIoTConfigReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSIoTConfigReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-07-27T20:41:36+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2015-10-27T21:52:31+00:00", + "DefaultVersionId": "v7", "Document": { "Statement": [ { "Action": [ - "iot:DescribeCertificate", + "iot:DescribeAuthorizer", "iot:DescribeCACertificate", + "iot:DescribeCertificate", + "iot:DescribeCertificateTag", + "iot:DescribeDefaultAuthorizer", "iot:DescribeEndpoint", + "iot:DescribeEventConfigurations", + "iot:DescribeIndex", + "iot:DescribeJob", + "iot:DescribeJobExecution", + "iot:DescribeRoleAlias", + "iot:DescribeStream", "iot:DescribeThing", + "iot:DescribeThingGroup", + "iot:DescribeThingRegistrationTask", "iot:DescribeThingType", + "iot:GetEffectivePolicies", + "iot:GetIndexingConfiguration", + "iot:GetJobDocument", "iot:GetLoggingOptions", + "iot:GetOTAUpdate", "iot:GetPolicy", "iot:GetPolicyVersion", "iot:GetRegistrationCode", "iot:GetTopicRule", + "iot:GetV2LoggingOptions", + "iot:ListAttachedPolicies", + "iot:ListAuthorizers", + "iot:ListCACertificates", "iot:ListCertificates", "iot:ListCertificatesByCA", - "iot:ListCACertificates", + "iot:ListIndices", + "iot:ListJobExecutionsForJob", + "iot:ListJobExecutionsForThing", + "iot:ListJobs", + "iot:ListOTAUpdates", + "iot:ListOutgoingCertificates", "iot:ListPolicies", "iot:ListPolicyPrincipals", "iot:ListPolicyVersions", "iot:ListPrincipalPolicies", "iot:ListPrincipalThings", + "iot:ListRoleAliases", + "iot:ListStreams", + "iot:ListTargetsForPolicy", + "iot:ListThingGroups", + "iot:ListThingGroupsForThing", "iot:ListThingPrincipals", + "iot:ListThingRegistrationTaskReports", + "iot:ListThingRegistrationTasks", "iot:ListThings", + "iot:ListThingsInThingGroup", "iot:ListThingTypes", - "iot:ListTopicRules" + "iot:ListTopicRules", + "iot:ListV2LoggingLevels", + "iot:SearchIndex", + "iot:TestAuthorization", + "iot:TestInvokeAuthorizer", + "iot:DescribeAccountAuditConfiguration", + "iot:DescribeAuditTask", + "iot:ListAuditTasks", + "iot:DescribeScheduledAudit", + "iot:ListScheduledAudits", + "iot:ListAuditFindings", + "iot:DescribeSecurityProfile", + "iot:ListSecurityProfiles", + "iot:ListSecurityProfilesForTarget", + "iot:ListTargetsForSecurityProfile", + "iot:ListActiveViolations", + "iot:ListViolationEvents", + "iot:ValidateSecurityProfileBehaviors" ], "Effect": "Allow", "Resource": "*" @@ -3394,16 +8247,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJHENEMXGX4XMFOIOI", "PolicyName": "AWSIoTConfigReadOnlyAccess", - "UpdateDate": "2016-07-27T20:41:36+00:00", - "VersionId": "v4" + "UpdateDate": "2018-07-18T21:22:11+00:00", + "VersionId": "v7" }, "AWSIoTDataAccess": { "Arn": "arn:aws:iam::aws:policy/AWSIoTDataAccess", "AttachmentCount": 0, "CreateDate": "2015-10-27T21:51:18+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -3413,7 +8267,8 @@ aws_managed_policies_data = """ "iot:Subscribe", "iot:Receive", "iot:GetThingShadow", - "iot:UpdateThingShadow" + "iot:UpdateThingShadow", + "iot:DeleteThingShadow" ], "Effect": "Allow", "Resource": "*" @@ -3424,9 +8279,106 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJM2KI2UJDR24XPS2K", "PolicyName": "AWSIoTDataAccess", - "UpdateDate": "2015-10-27T21:51:18+00:00", + "UpdateDate": "2017-11-16T18:24:11+00:00", + "VersionId": "v2" + }, + "AWSIoTDeviceDefenderAudit": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSIoTDeviceDefenderAudit", + "AttachmentCount": 0, + "CreateDate": "2018-07-18T21:17:40+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iot:GetLoggingOptions", + "iot:GetV2LoggingOptions", + "iot:ListCACertificates", + "iot:ListCertificates", + "iot:DescribeCACertificate", + "iot:DescribeCertificate", + "iot:ListPolicies", + "iot:GetPolicy", + "iot:GetEffectivePolicies", + "cognito-identity:GetIdentityPoolRoles", + "iam:ListRolePolicies", + "iam:ListAttachedRolePolicies", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRolePolicy" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJKUN6OAGIHZ66TRKO", + "PolicyName": "AWSIoTDeviceDefenderAudit", + "UpdateDate": "2018-07-18T21:17:40+00:00", + "VersionId": "v1" + }, + "AWSIoTEventsFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoTEventsFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-10T22:51:57+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iotevents:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJGA726P7LVUWJZ2LM", + "PolicyName": "AWSIoTEventsFullAccess", + "UpdateDate": "2019-01-10T22:51:57+00:00", + "VersionId": "v1" + }, + "AWSIoTEventsReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoTEventsReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-10T22:50:08+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iotevents:Describe*", + "iotevents:List*", + "iotevents:Get*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJYJFNAR7CN5JW52PG", + "PolicyName": "AWSIoTEventsReadOnlyAccess", + "UpdateDate": "2019-01-10T22:50:08+00:00", "VersionId": "v1" }, "AWSIoTFullAccess": { @@ -3449,6 +8401,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJU2FPGG6PQWN72V2G", "PolicyName": "AWSIoTFullAccess", "UpdateDate": "2015-10-08T15:19:49+00:00", @@ -3482,25 +8435,22 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI6R6Z2FHHGS454W7W", "PolicyName": "AWSIoTLogging", "UpdateDate": "2015-10-08T15:17:25+00:00", "VersionId": "v1" }, - "AWSIoTRuleActions": { - "Arn": "arn:aws:iam::aws:policy/service-role/AWSIoTRuleActions", + "AWSIoTOTAUpdate": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSIoTOTAUpdate", "AttachmentCount": 0, - "CreateDate": "2015-10-08T15:14:51+00:00", + "CreateDate": "2017-12-20T20:36:53+00:00", "DefaultVersionId": "v1", "Document": { "Statement": { "Action": [ - "dynamodb:PutItem", - "kinesis:PutRecord", - "iot:Publish", - "s3:PutObject", - "sns:Publish", - "sqs:SendMessage*" + "iot:CreateJob", + "signer:DescribeSigningJob" ], "Effect": "Allow", "Resource": "*" @@ -3510,15 +8460,282 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJLJYWX53STBZFPUEY", + "PolicyName": "AWSIoTOTAUpdate", + "UpdateDate": "2017-12-20T20:36:53+00:00", + "VersionId": "v1" + }, + "AWSIoTRuleActions": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSIoTRuleActions", + "AttachmentCount": 0, + "CreateDate": "2015-10-08T15:14:51+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": { + "Action": [ + "dynamodb:PutItem", + "kinesis:PutRecord", + "iot:Publish", + "s3:PutObject", + "sns:Publish", + "sqs:SendMessage*", + "cloudwatch:SetAlarmState", + "cloudwatch:PutMetricData", + "es:ESHttpPut", + "firehose:PutRecord" + ], + "Effect": "Allow", + "Resource": "*" + }, + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJEZ6FS7BUZVUHMOKY", "PolicyName": "AWSIoTRuleActions", - "UpdateDate": "2015-10-08T15:14:51+00:00", + "UpdateDate": "2018-01-16T19:28:19+00:00", + "VersionId": "v2" + }, + "AWSIoTSiteWiseConsoleFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoTSiteWiseConsoleFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-05-31T21:37:49+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": "iotsitewise:*", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iotanalytics:List*", + "iotanalytics:Describe*", + "iotanalytics:Create*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iot:DescribeEndpoint", + "iot:GetThingShadow" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "greengrass:GetGroup", + "greengrass:GetGroupVersion", + "greengrass:GetCoreDefinitionVersion", + "greengrass:ListGroups" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "secretsmanager:ListSecrets", + "secretsmanager:CreateSecret" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "secretsmanager:UpdateSecret" + ], + "Effect": "Allow", + "Resource": "arn:aws:secretsmanager:*:*:secret:greengrass-*" + }, + { + "Action": [ + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "iotsitewise.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/iotsitewise.amazonaws.com/AWSServiceRoleForIoTSiteWise*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": "iotsitewise.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/iotsitewise.amazonaws.com/AWSServiceRoleForIoTSiteWise*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4K7KP5VA7F", + "PolicyName": "AWSIoTSiteWiseConsoleFullAccess", + "UpdateDate": "2019-05-31T21:37:49+00:00", + "VersionId": "v1" + }, + "AWSIoTSiteWiseFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoTSiteWiseFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-12-04T20:53:39+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iotsitewise:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAILUK3XBM6TZ5Q3PX2", + "PolicyName": "AWSIoTSiteWiseFullAccess", + "UpdateDate": "2018-12-04T20:53:39+00:00", + "VersionId": "v1" + }, + "AWSIoTSiteWiseReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSIoTSiteWiseReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-12-04T20:55:11+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iotsitewise:Describe*", + "iotsitewise:List*", + "iotsitewise:Get*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJLHEAFKME2QL64WKK", + "PolicyName": "AWSIoTSiteWiseReadOnlyAccess", + "UpdateDate": "2018-12-04T20:55:11+00:00", + "VersionId": "v1" + }, + "AWSIoTThingsRegistration": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSIoTThingsRegistration", + "AttachmentCount": 0, + "CreateDate": "2017-12-01T20:21:52+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iot:AddThingToThingGroup", + "iot:AttachPrincipalPolicy", + "iot:AttachThingPrincipal", + "iot:CreateCertificateFromCsr", + "iot:CreatePolicy", + "iot:CreateThing", + "iot:DescribeCertificate", + "iot:DescribeThing", + "iot:DescribeThingGroup", + "iot:DescribeThingType", + "iot:DetachThingPrincipal", + "iot:GetPolicy", + "iot:ListPolicyPrincipals", + "iot:ListPrincipalPolicies", + "iot:ListPrincipalThings", + "iot:ListThingGroupsForThing", + "iot:ListThingPrincipals", + "iot:RegisterCertificate", + "iot:RegisterThing", + "iot:RemoveThingFromThingGroup", + "iot:UpdateCertificate", + "iot:UpdateThing", + "iot:UpdateThingGroupsForThing" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI3YQXTC5XAEVTJNEU", + "PolicyName": "AWSIoTThingsRegistration", + "UpdateDate": "2017-12-01T20:21:52+00:00", + "VersionId": "v1" + }, + "AWSKeyManagementServiceCustomKeyStoresServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSKeyManagementServiceCustomKeyStoresServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-14T20:10:53+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudhsm:Describe*", + "ec2:CreateNetworkInterface", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateSecurityGroup", + "ec2:DescribeSecurityGroups", + "ec2:RevokeSecurityGroupEgress", + "ec2:DeleteSecurityGroup" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIADMJEHVVYK5AUQOO", + "PolicyName": "AWSKeyManagementServiceCustomKeyStoresServiceRolePolicy", + "UpdateDate": "2018-11-14T20:10:53+00:00", "VersionId": "v1" }, "AWSKeyManagementServicePowerUser": { "Arn": "arn:aws:iam::aws:policy/AWSKeyManagementServicePowerUser", - "AttachmentCount": 1, - "CreateDate": "2017-03-07T00:55:11+00:00", + "AttachmentCount": 0, + "CreateDate": "2015-02-06T18:40:40+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -3546,6 +8763,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJNPP7PPPPMJRV2SA4", "PolicyName": "AWSKeyManagementServicePowerUser", "UpdateDate": "2017-03-07T00:55:11+00:00", @@ -3553,7 +8771,7 @@ aws_managed_policies_data = """ }, "AWSLambdaBasicExecutionRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "AttachmentCount": 0, + "AttachmentCount": 2, "CreateDate": "2015-04-09T15:03:43+00:00", "DefaultVersionId": "v1", "Document": { @@ -3573,6 +8791,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJNCQGXC42545SKXIK", "PolicyName": "AWSLambdaBasicExecutionRole", "UpdateDate": "2015-04-09T15:03:43+00:00", @@ -3604,6 +8823,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIP7WNAGMIPYNW4WQG", "PolicyName": "AWSLambdaDynamoDBExecutionRole", "UpdateDate": "2015-04-09T15:09:29+00:00", @@ -3631,6 +8851,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJXAW2Q3KPTURUT2QC", "PolicyName": "AWSLambdaENIManagementAccess", "UpdateDate": "2016-12-06T00:37:27+00:00", @@ -3664,6 +8885,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJE5FX7FQZSU5XAKGO", "PolicyName": "AWSLambdaExecute", "UpdateDate": "2015-02-06T18:40:46+00:00", @@ -3672,55 +8894,64 @@ aws_managed_policies_data = """ "AWSLambdaFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSLambdaFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-05-25T19:08:45+00:00", - "DefaultVersionId": "v7", + "CreateDate": "2015-02-06T18:40:45+00:00", + "DefaultVersionId": "v8", "Document": { "Statement": [ { "Action": [ + "cloudformation:DescribeChangeSet", + "cloudformation:DescribeStackResources", + "cloudformation:DescribeStacks", + "cloudformation:GetTemplate", + "cloudformation:ListStackResources", "cloudwatch:*", "cognito-identity:ListIdentityPools", "cognito-sync:GetCognitoEvents", "cognito-sync:SetCognitoEvents", "dynamodb:*", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", "events:*", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole", + "iam:GetRolePolicy", "iam:ListAttachedRolePolicies", "iam:ListRolePolicies", "iam:ListRoles", "iam:PassRole", + "iot:AttachPrincipalPolicy", + "iot:AttachThingPrincipal", + "iot:CreateKeysAndCertificate", + "iot:CreatePolicy", + "iot:CreateThing", + "iot:CreateTopicRule", + "iot:DescribeEndpoint", + "iot:GetTopicRule", + "iot:ListPolicies", + "iot:ListThings", + "iot:ListTopicRules", + "iot:ReplaceTopicRule", "kinesis:DescribeStream", "kinesis:ListStreams", "kinesis:PutRecord", + "kms:ListAliases", "lambda:*", "logs:*", "s3:*", "sns:ListSubscriptions", "sns:ListSubscriptionsByTopic", "sns:ListTopics", + "sns:Publish", "sns:Subscribe", "sns:Unsubscribe", - "sns:Publish", "sqs:ListQueues", "sqs:SendMessage", "tag:GetResources", - "kms:ListAliases", - "ec2:DescribeVpcs", - "ec2:DescribeSubnets", - "ec2:DescribeSecurityGroups", - "iot:GetTopicRule", - "iot:ListTopicRules", - "iot:CreateTopicRule", - "iot:ReplaceTopicRule", - "iot:AttachPrincipalPolicy", - "iot:AttachThingPrincipal", - "iot:CreateKeysAndCertificate", - "iot:CreatePolicy", - "iot:CreateThing", - "iot:ListPolicies", - "iot:ListThings", - "iot:DescribeEndpoint", - "xray:PutTraceSegments", - "xray:PutTelemetryRecords" + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" ], "Effect": "Allow", "Resource": "*" @@ -3731,10 +8962,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI6E2CYYMI4XI7AA5K", "PolicyName": "AWSLambdaFullAccess", - "UpdateDate": "2017-05-25T19:08:45+00:00", - "VersionId": "v7" + "UpdateDate": "2017-11-27T23:22:38+00:00", + "VersionId": "v8" }, "AWSLambdaInvocation-DynamoDB": { "Arn": "arn:aws:iam::aws:policy/AWSLambdaInvocation-DynamoDB", @@ -3766,6 +8998,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJTHQ3EKCQALQDYG5G", "PolicyName": "AWSLambdaInvocation-DynamoDB", "UpdateDate": "2015-02-06T18:40:47+00:00", @@ -3775,15 +9008,18 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaKinesisExecutionRole", "AttachmentCount": 0, "CreateDate": "2015-04-09T15:14:16+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ "kinesis:DescribeStream", + "kinesis:DescribeStreamSummary", "kinesis:GetRecords", "kinesis:GetShardIterator", + "kinesis:ListShards", "kinesis:ListStreams", + "kinesis:SubscribeToShard", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" @@ -3797,20 +9033,26 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJHOLKJPXV4GBRMJUQ", "PolicyName": "AWSLambdaKinesisExecutionRole", - "UpdateDate": "2015-04-09T15:14:16+00:00", - "VersionId": "v1" + "UpdateDate": "2018-11-19T20:09:24+00:00", + "VersionId": "v2" }, "AWSLambdaReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSLambdaReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-05-04T18:22:29+00:00", - "DefaultVersionId": "v6", + "CreateDate": "2015-02-06T18:40:44+00:00", + "DefaultVersionId": "v8", "Document": { "Statement": [ { "Action": [ + "cloudformation:DescribeChangeSet", + "cloudformation:DescribeStackResources", + "cloudformation:DescribeStacks", + "cloudformation:GetTemplate", + "cloudformation:ListStackResources", "cloudwatch:Describe*", "cloudwatch:Get*", "cloudwatch:List*", @@ -3824,33 +9066,39 @@ aws_managed_policies_data = """ "dynamodb:ListTables", "dynamodb:Query", "dynamodb:Scan", - "events:List*", - "events:Describe*", - "iam:ListRoles", - "kinesis:DescribeStream", - "kinesis:ListStreams", - "lambda:List*", - "lambda:Get*", - "logs:DescribeMetricFilters", - "logs:GetLogEvents", - "logs:DescribeLogGroups", - "logs:DescribeLogStreams", - "s3:Get*", - "s3:List*", - "sns:ListTopics", - "sns:ListSubscriptions", - "sns:ListSubscriptionsByTopic", - "sqs:ListQueues", - "tag:GetResources", - "kms:ListAliases", - "ec2:DescribeVpcs", - "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups", - "iot:GetTopicRules", - "iot:ListTopicRules", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "events:Describe*", + "events:List*", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole", + "iam:GetRolePolicy", + "iam:ListAttachedRolePolicies", + "iam:ListRolePolicies", + "iam:ListRoles", + "iot:DescribeEndpoint", + "iot:GetTopicRule", "iot:ListPolicies", "iot:ListThings", - "iot:DescribeEndpoint" + "iot:ListTopicRules", + "kinesis:DescribeStream", + "kinesis:ListStreams", + "kms:ListAliases", + "lambda:Get*", + "lambda:List*", + "logs:DescribeLogGroups", + "logs:DescribeLogStreams", + "logs:DescribeMetricFilters", + "logs:GetLogEvents", + "s3:Get*", + "s3:List*", + "sns:ListSubscriptions", + "sns:ListSubscriptionsByTopic", + "sns:ListTopics", + "sqs:ListQueues", + "tag:GetResources" ], "Effect": "Allow", "Resource": "*" @@ -3861,10 +9109,67 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJLDG7J3CGUHFN4YN6", "PolicyName": "AWSLambdaReadOnlyAccess", - "UpdateDate": "2017-05-04T18:22:29+00:00", - "VersionId": "v6" + "UpdateDate": "2018-09-06T18:04:54+00:00", + "VersionId": "v8" + }, + "AWSLambdaReplicator": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSLambdaReplicator", + "AttachmentCount": 0, + "CreateDate": "2017-05-23T17:53:03+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "lambda:CreateFunction", + "lambda:DeleteFunction", + "lambda:DisableReplication" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:lambda:*:*:function:*" + ], + "Sid": "LambdaCreateDeletePermission" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLikeIfExists": { + "iam:PassedToService": "lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "IamPassRolePermission" + }, + { + "Action": [ + "cloudfront:ListDistributionsByLambdaFunction" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "CloudFrontListDistributions" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIIQFXZNNLL3E2HKTG", + "PolicyName": "AWSLambdaReplicator", + "UpdateDate": "2017-12-08T00:17:54+00:00", + "VersionId": "v3" }, "AWSLambdaRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaRole", @@ -3888,11 +9193,43 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJX4DPCRGTC4NFDUXI", "PolicyName": "AWSLambdaRole", "UpdateDate": "2015-02-06T18:41:28+00:00", "VersionId": "v1" }, + "AWSLambdaSQSQueueExecutionRole": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaSQSQueueExecutionRole", + "AttachmentCount": 0, + "CreateDate": "2018-06-14T21:50:45+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "sqs:ReceiveMessage", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJFWJZI6JNND4TSELK", + "PolicyName": "AWSLambdaSQSQueueExecutionRole", + "UpdateDate": "2018-06-14T21:50:45+00:00", + "VersionId": "v1" + }, "AWSLambdaVPCAccessExecutionRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole", "AttachmentCount": 0, @@ -3918,16 +9255,322 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJVTME3YLVNL72YR2K", "PolicyName": "AWSLambdaVPCAccessExecutionRole", "UpdateDate": "2016-02-11T23:15:26+00:00", "VersionId": "v1" }, + "AWSLicenseManagerMasterAccountRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSLicenseManagerMasterAccountRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T19:03:51+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "s3:GetBucketLocation", + "s3:ListBucket", + "s3:GetLifecycleConfiguration", + "s3:PutLifecycleConfiguration", + "s3:GetBucketPolicy", + "s3:PutBucketPolicy" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-license-manager-service-*" + ], + "Sid": "S3BucketPermissions" + }, + { + "Action": [ + "s3:AbortMultipartUpload", + "s3:PutObject", + "s3:GetObject", + "s3:ListBucketMultipartUploads", + "s3:ListMultipartUploadParts" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-license-manager-service-*" + ], + "Sid": "S3ObjectPermissions1" + }, + { + "Action": [ + "s3:DeleteObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-license-manager-service-*/resource_sync/*" + ], + "Sid": "S3ObjectPermissions2" + }, + { + "Action": [ + "athena:GetQueryExecution", + "athena:GetQueryResults", + "athena:StartQueryExecution" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "AthenaPermissions" + }, + { + "Action": [ + "glue:GetTable", + "glue:GetPartition", + "glue:GetPartitions" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "GluePermissions" + }, + { + "Action": [ + "organizations:DescribeOrganization", + "organizations:ListAccounts", + "organizations:DescribeAccount", + "organizations:ListChildren", + "organizations:ListParents", + "organizations:ListAccountsForParent", + "organizations:ListRoots", + "organizations:ListAWSServiceAccessForOrganization" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "OrganizationPermissions" + }, + { + "Action": [ + "ram:GetResourceShares", + "ram:GetResourceShareAssociations", + "ram:TagResource" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "RAMPermissions1" + }, + { + "Action": [ + "ram:CreateResourceShare" + ], + "Condition": { + "StringEquals": { + "aws:RequestTag/Service": "LicenseManager" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "RAMPermissions2" + }, + { + "Action": [ + "ram:AssociateResourceShare", + "ram:DisassociateResourceShare", + "ram:UpdateResourceShare", + "ram:DeleteResourceShare" + ], + "Condition": { + "StringEquals": { + "ram:ResourceTag/Service": "LicenseManager" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "RAMPermissions3" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIJE2NOZW2BDEHYUH2", + "PolicyName": "AWSLicenseManagerMasterAccountRolePolicy", + "UpdateDate": "2018-11-26T19:03:51+00:00", + "VersionId": "v1" + }, + "AWSLicenseManagerMemberAccountRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSLicenseManagerMemberAccountRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T19:04:32+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "license-manager:UpdateLicenseSpecificationsForResource" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "LicenseManagerPermissions" + }, + { + "Action": [ + "ssm:ListInventoryEntries", + "ssm:GetInventory", + "ssm:CreateAssociation", + "ssm:CreateResourceDataSync", + "ssm:DeleteResourceDataSync", + "ssm:ListResourceDataSync", + "ssm:ListAssociations" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "SSMPermissions" + }, + { + "Action": [ + "ram:AcceptResourceShareInvitation", + "ram:GetResourceShareInvitations" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "RAMPermissions" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJZTYEY2LEGBYAVUY4", + "PolicyName": "AWSLicenseManagerMemberAccountRolePolicy", + "UpdateDate": "2018-11-26T19:04:32+00:00", + "VersionId": "v1" + }, + "AWSLicenseManagerServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSLicenseManagerServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T19:02:53+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "s3:GetBucketLocation", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-license-manager-service-*" + ], + "Sid": "S3BucketPermissions1" + }, + { + "Action": [ + "s3:ListAllMyBuckets" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "S3BucketPermissions2" + }, + { + "Action": [ + "s3:PutObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::aws-license-manager-service-*" + ], + "Sid": "S3ObjectPermissions" + }, + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:sns:*:*:aws-license-manager-service-*" + ], + "Sid": "SNSAccountPermissions" + }, + { + "Action": [ + "sns:ListTopics" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "SNSTopicPermissions" + }, + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeImages", + "ec2:DescribeHosts" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "EC2Permissions" + }, + { + "Action": [ + "ssm:ListInventoryEntries", + "ssm:GetInventory", + "ssm:CreateAssociation" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "SSMPermissions" + }, + { + "Action": [ + "organizations:ListAWSServiceAccessForOrganization", + "organizations:DescribeOrganization" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "OrganizationPermissions" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIM7JPETWHTYNBQSZE", + "PolicyName": "AWSLicenseManagerServiceRolePolicy", + "UpdateDate": "2018-11-26T19:02:53+00:00", + "VersionId": "v1" + }, "AWSMarketplaceFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSMarketplaceFullAccess", "AttachmentCount": 0, "CreateDate": "2015-02-11T17:21:45+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -3960,6 +9603,67 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "ec2:CopyImage", + "ec2:DeregisterImage", + "ec2:DescribeSnapshots", + "ec2:DeleteSnapshot", + "ec2:CreateImage", + "ec2:DescribeInstanceStatus", + "ssm:GetAutomationExecution", + "ssm:UpdateDocumentDefaultVersion", + "ssm:CreateDocument", + "ssm:StartAutomationExecution", + "ssm:ListDocuments", + "ssm:UpdateDocument", + "ssm:DescribeDocument", + "sns:ListTopics", + "sns:GetTopicAttributes", + "sns:CreateTopic", + "iam:GetRole", + "iam:GetInstanceProfile", + "iam:ListRoles", + "iam:ListInstanceProfiles" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:ListBucket", + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*image-build*" + ] + }, + { + "Action": [ + "sns:Publish", + "sns:setTopicAttributes" + ], + "Effect": "Allow", + "Resource": "arn:aws:sns:*:*:*image-build*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ssm.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] } ], "Version": "2012-10-17" @@ -3967,10 +9671,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI2DV5ULJSO2FYVPYG", "PolicyName": "AWSMarketplaceFullAccess", - "UpdateDate": "2015-02-11T17:21:45+00:00", - "VersionId": "v1" + "UpdateDate": "2018-08-08T21:13:02+00:00", + "VersionId": "v3" }, "AWSMarketplaceGetEntitlements": { "Arn": "arn:aws:iam::aws:policy/AWSMarketplaceGetEntitlements", @@ -3992,11 +9697,121 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJLPIMQE4WMHDC2K7C", "PolicyName": "AWSMarketplaceGetEntitlements", "UpdateDate": "2017-03-27T19:37:24+00:00", "VersionId": "v1" }, + "AWSMarketplaceImageBuildFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSMarketplaceImageBuildFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-07-31T23:29:49+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "aws-marketplace:ListBuilds", + "aws-marketplace:StartBuild", + "aws-marketplace:DescribeBuilds" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "ec2:TerminateInstances", + "Condition": { + "StringLike": { + "ec2:ResourceTag/marketplace-image-build:build-id": "*" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ssm.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/*Automation*", + "arn:aws:iam::*:role/*Instance*" + ] + }, + { + "Action": [ + "ssm:GetAutomationExecution", + "ssm:CreateDocument", + "ssm:StartAutomationExecution", + "ssm:ListDocuments", + "ssm:UpdateDocument", + "ssm:UpdateDocumentDefaultVersion", + "ssm:DescribeDocument", + "ec2:DeregisterImage", + "ec2:CopyImage", + "ec2:DescribeSnapshots", + "ec2:DescribeSecurityGroups", + "ec2:DescribeImages", + "ec2:DescribeSubnets", + "ec2:DeleteSnapshot", + "ec2:CreateImage", + "ec2:RunInstances", + "ec2:DescribeInstanceStatus", + "sns:GetTopicAttributes", + "iam:GetRole", + "iam:GetInstanceProfile" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetObject", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*image-build*" + ] + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*::image/*", + "arn:aws:ec2:*:*:instance/*" + ] + }, + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:sns:*:*:*image-build*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI4QBMJWC3BNHBHN6I", + "PolicyName": "AWSMarketplaceImageBuildFullAccess", + "UpdateDate": "2018-08-08T21:11:59+00:00", + "VersionId": "v2" + }, "AWSMarketplaceManageSubscriptions": { "Arn": "arn:aws:iam::aws:policy/AWSMarketplaceManageSubscriptions", "AttachmentCount": 0, @@ -4019,6 +9834,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJRDW2WIFN7QLUAKBQ", "PolicyName": "AWSMarketplaceManageSubscriptions", "UpdateDate": "2015-02-06T18:40:32+00:00", @@ -4044,6 +9860,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ65YJPG7CC7LDXNA6", "PolicyName": "AWSMarketplaceMeteringFullAccess", "UpdateDate": "2016-03-17T22:39:22+00:00", @@ -4053,7 +9870,7 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AWSMarketplaceRead-only", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:31+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -4070,6 +9887,18 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "aws-marketplace:ListBuilds", + "aws-marketplace:DescribeBuilds", + "iam:ListRoles", + "iam:ListInstanceProfiles", + "sns:GetTopicAttributes", + "sns:ListTopics" + ], + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -4077,10 +9906,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJOOM6LETKURTJ3XZ2", "PolicyName": "AWSMarketplaceRead-only", - "UpdateDate": "2015-02-06T18:40:31+00:00", - "VersionId": "v1" + "UpdateDate": "2018-07-31T23:24:24+00:00", + "VersionId": "v2" }, "AWSMigrationHubDMSAccess": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSMigrationHubDMSAccess", @@ -4127,6 +9957,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIUQB56VA4JHLN7G2W", "PolicyName": "AWSMigrationHubDMSAccess", "UpdateDate": "2017-08-14T14:00:06+00:00", @@ -4155,6 +9986,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAITRMRLSV7JAL6YIGG", "PolicyName": "AWSMigrationHubDiscoveryAccess", "UpdateDate": "2017-08-14T13:30:51+00:00", @@ -4163,8 +9995,8 @@ aws_managed_policies_data = """ "AWSMigrationHubFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSMigrationHubFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-14T14:09:27+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2017-08-14T14:02:54+00:00", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -4181,6 +10013,24 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "continuousexport.discovery.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/continuousexport.discovery.amazonaws.com/AWSServiceRoleForApplicationDiscoveryServiceContinuousExport*" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/continuousexport.discovery.amazonaws.com/AWSServiceRoleForApplicationDiscoveryServiceContinuousExport*" } ], "Version": "2012-10-17" @@ -4188,10 +10038,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ4A2SZKHUYHDYIGOK", "PolicyName": "AWSMigrationHubFullAccess", - "UpdateDate": "2017-08-14T14:09:27+00:00", - "VersionId": "v2" + "UpdateDate": "2018-08-16T20:29:37+00:00", + "VersionId": "v3" }, "AWSMigrationHubSMSAccess": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSMigrationHubSMSAccess", @@ -4238,6 +10089,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIWQYYT6TSVIRJO4TY", "PolicyName": "AWSMigrationHubSMSAccess", "UpdateDate": "2017-08-14T13:57:54+00:00", @@ -4246,8 +10098,8 @@ aws_managed_policies_data = """ "AWSMobileHub_FullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSMobileHub_FullAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-10T22:23:47+00:00", - "DefaultVersionId": "v10", + "CreateDate": "2016-01-05T19:56:01+00:00", + "DefaultVersionId": "v13", "Document": { "Statement": [ { @@ -4257,6 +10109,15 @@ aws_managed_policies_data = """ "apigateway:GetResources", "apigateway:POST", "apigateway:TestInvokeMethod", + "cloudfront:GetDistribution", + "devicefarm:CreateProject", + "devicefarm:ListJobs", + "devicefarm:ListRuns", + "devicefarm:GetProject", + "devicefarm:GetRun", + "devicefarm:ListArtifacts", + "devicefarm:ListProjects", + "devicefarm:ScheduleRun", "dynamodb:DescribeTable", "ec2:DescribeSecurityGroups", "ec2:DescribeSubnets", @@ -4281,6 +10142,8 @@ aws_managed_policies_data = """ "mobilehub:GenerateProjectParameters", "mobilehub:GetProject", "mobilehub:GetProjectSnapshot", + "mobilehub:ListProjectSnapshots", + "mobilehub:DeleteProjectSnapshot", "mobilehub:ListAvailableConnectors", "mobilehub:ListAvailableFeatures", "mobilehub:ListAvailableRegions", @@ -4300,6 +10163,20 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "arn:aws:s3:::*/aws-my-sample-app*.zip" + }, + { + "Action": [ + "s3:PutObject" + ], + "Effect": "Allow", + "Resource": "arn:aws:s3:::*-mobilehub-*/*" + }, + { + "Action": [ + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": "arn:aws:s3:::*-mobilehub-*" } ], "Version": "2012-10-17" @@ -4307,16 +10184,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIJLU43R6AGRBK76DM", "PolicyName": "AWSMobileHub_FullAccess", - "UpdateDate": "2017-08-10T22:23:47+00:00", - "VersionId": "v10" + "UpdateDate": "2018-02-05T23:44:29+00:00", + "VersionId": "v13" }, "AWSMobileHub_ReadOnly": { "Arn": "arn:aws:iam::aws:policy/AWSMobileHub_ReadOnly", "AttachmentCount": 0, - "CreateDate": "2017-08-10T22:08:23+00:00", - "DefaultVersionId": "v8", + "CreateDate": "2016-01-05T19:55:48+00:00", + "DefaultVersionId": "v10", "Document": { "Statement": [ { @@ -4336,7 +10214,9 @@ aws_managed_policies_data = """ "mobilehub:ExportProject", "mobilehub:GenerateProjectParameters", "mobilehub:GetProject", + "mobilehub:SynchronizeProject", "mobilehub:GetProjectSnapshot", + "mobilehub:ListProjectSnapshots", "mobilehub:ListAvailableConnectors", "mobilehub:ListAvailableFeatures", "mobilehub:ListAvailableRegions", @@ -4363,280 +10243,29 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIBXVYVL3PWQFBZFGW", "PolicyName": "AWSMobileHub_ReadOnly", - "UpdateDate": "2017-08-10T22:08:23+00:00", - "VersionId": "v8" + "UpdateDate": "2018-07-23T21:59:05+00:00", + "VersionId": "v10" }, - "AWSMobileHub_ServiceUseOnly": { - "Arn": "arn:aws:iam::aws:policy/service-role/AWSMobileHub_ServiceUseOnly", + "AWSOpsWorksCMInstanceProfileRole": { + "Arn": "arn:aws:iam::aws:policy/AWSOpsWorksCMInstanceProfileRole", "AttachmentCount": 0, - "CreateDate": "2017-06-02T23:35:49+00:00", - "DefaultVersionId": "v23", + "CreateDate": "2016-11-24T09:48:22+00:00", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ - "cloudformation:CreateUploadBucket", - "cloudformation:ValidateTemplate", - "cloudfront:CreateDistribution", - "cloudfront:DeleteDistribution", - "cloudfront:GetDistribution", - "cloudfront:GetDistributionConfig", - "cloudfront:UpdateDistribution", - "cognito-identity:CreateIdentityPool", - "cognito-identity:UpdateIdentityPool", - "cognito-identity:DeleteIdentityPool", - "cognito-identity:SetIdentityPoolRoles", - "cognito-idp:CreateUserPool", - "dynamodb:CreateTable", - "dynamodb:DeleteTable", - "dynamodb:DescribeTable", - "dynamodb:UpdateTable", - "iam:AddClientIDToOpenIDConnectProvider", - "iam:CreateOpenIDConnectProvider", - "iam:GetOpenIDConnectProvider", - "iam:ListOpenIDConnectProviders", - "iam:CreateSAMLProvider", - "iam:GetSAMLProvider", - "iam:ListSAMLProvider", - "iam:UpdateSAMLProvider", - "lambda:CreateFunction", - "lambda:DeleteFunction", - "lambda:GetFunction", - "mobileanalytics:CreateApp", - "mobileanalytics:DeleteApp", - "sns:CreateTopic", - "sns:DeleteTopic", - "sns:ListPlatformApplications", - "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets", - "ec2:DescribeVpcs", - "lex:PutIntent", - "lex:GetIntent", - "lex:GetIntents", - "lex:PutSlotType", - "lex:GetSlotType", - "lex:GetSlotTypes", - "lex:PutBot", - "lex:GetBot", - "lex:GetBots", - "lex:GetBotAlias", - "lex:GetBotAliases" + "cloudformation:DescribeStackResource", + "cloudformation:SignalResource" ], "Effect": "Allow", "Resource": [ "*" ] }, - { - "Action": [ - "sns:CreatePlatformApplication", - "sns:DeletePlatformApplication", - "sns:GetPlatformApplicationAttributes", - "sns:SetPlatformApplicationAttributes" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:sns:*:*:app/*_MOBILEHUB_*" - ] - }, - { - "Action": [ - "s3:CreateBucket", - "s3:DeleteBucket", - "s3:DeleteBucketPolicy", - "s3:DeleteBucketWebsite", - "s3:ListBucket", - "s3:ListBucketVersions", - "s3:GetBucketLocation", - "s3:GetBucketVersioning", - "s3:PutBucketVersioning", - "s3:PutBucketWebsite", - "s3:PutBucketPolicy", - "s3:SetBucketCrossOriginConfiguration" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:s3:::*-userfiles-mobilehub-*", - "arn:aws:s3:::*-contentdelivery-mobilehub-*", - "arn:aws:s3:::*-hosting-mobilehub-*", - "arn:aws:s3:::*-deployments-mobilehub-*" - ] - }, - { - "Action": [ - "s3:DeleteObject", - "s3:DeleteVersion", - "s3:DeleteObjectVersion", - "s3:GetObject", - "s3:GetObjectVersion", - "s3:PutObject", - "s3:PutObjectAcl" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:s3:::*-userfiles-mobilehub-*/*", - "arn:aws:s3:::*-contentdelivery-mobilehub-*/*", - "arn:aws:s3:::*-hosting-mobilehub-*/*", - "arn:aws:s3:::*-deployments-mobilehub-*/*" - ] - }, - { - "Action": [ - "lambda:AddPermission", - "lambda:CreateAlias", - "lambda:DeleteAlias", - "lambda:UpdateAlias", - "lambda:GetFunctionConfiguration", - "lambda:GetPolicy", - "lambda:RemovePermission", - "lambda:UpdateFunctionCode", - "lambda:UpdateFunctionConfiguration" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:lambda:*:*:function:*-mobilehub-*" - ] - }, - { - "Action": [ - "iam:CreateRole", - "iam:DeleteRole", - "iam:DeleteRolePolicy", - "iam:GetRole", - "iam:GetRolePolicy", - "iam:ListRolePolicies", - "iam:PassRole", - "iam:PutRolePolicy", - "iam:UpdateAssumeRolePolicy", - "iam:AttachRolePolicy", - "iam:DetachRolePolicy" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:iam::*:role/*_unauth_MOBILEHUB_*", - "arn:aws:iam::*:role/*_auth_MOBILEHUB_*", - "arn:aws:iam::*:role/*_consolepush_MOBILEHUB_*", - "arn:aws:iam::*:role/*_lambdaexecutionrole_MOBILEHUB_*", - "arn:aws:iam::*:role/*_smsverification_MOBILEHUB_*", - "arn:aws:iam::*:role/*_botexecutionrole_MOBILEHUB_*", - "arn:aws:iam::*:role/pinpoint-events", - "arn:aws:iam::*:role/MOBILEHUB-*-lambdaexecution*", - "arn:aws:iam::*:role/MobileHub_Service_Role" - ] - }, - { - "Action": [ - "iam:CreateServiceLinkedRole", - "iam:GetRole" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots" - ] - }, - { - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:logs:*:*:log-group:/aws/mobilehub/*:log-stream:*" - ] - }, - { - "Action": [ - "iam:ListAttachedRolePolicies" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:iam::*:role/MobileHub_Service_Role" - ] - }, - { - "Action": [ - "cloudformation:CreateStack", - "cloudformation:DeleteStack", - "cloudformation:DescribeStacks", - "cloudformation:DescribeStackEvents", - "cloudformation:DescribeStackResource", - "cloudformation:GetTemplate", - "cloudformation:ListStackResources", - "cloudformation:ListStacks", - "cloudformation:UpdateStack" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:cloudformation:*:*:stack/MOBILEHUB-*" - ] - }, - { - "Action": [ - "apigateway:DELETE", - "apigateway:GET", - "apigateway:HEAD", - "apigateway:OPTIONS", - "apigateway:PATCH", - "apigateway:POST", - "apigateway:PUT" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:apigateway:*::/restapis*" - ] - }, - { - "Action": [ - "cognito-idp:DeleteUserPool", - "cognito-idp:DescribeUserPool", - "cognito-idp:CreateUserPoolClient", - "cognito-idp:DescribeUserPoolClient", - "cognito-idp:DeleteUserPoolClient" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:cognito-idp:*:*:userpool/*" - ] - }, - { - "Action": [ - "mobiletargeting:UpdateApnsChannel", - "mobiletargeting:UpdateApnsSandboxChannel", - "mobiletargeting:UpdateEmailChannel", - "mobiletargeting:UpdateGcmChannel", - "mobiletargeting:UpdateSmsChannel", - "mobiletargeting:DeleteApnsChannel", - "mobiletargeting:DeleteApnsSandboxChannel", - "mobiletargeting:DeleteEmailChannel", - "mobiletargeting:DeleteGcmChannel", - "mobiletargeting:DeleteSmsChannel" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:mobiletargeting:*:*:apps/*/channels/*" - ] - } - ], - "Version": "2012-10-17" - }, - "IsAttachable": true, - "IsDefaultVersion": true, - "Path": "/service-role/", - "PolicyId": "ANPAIUHPQXBDZUWOP3PSK", - "PolicyName": "AWSMobileHub_ServiceUseOnly", - "UpdateDate": "2017-06-02T23:35:49+00:00", - "VersionId": "v23" - }, - "AWSOpsWorksCMInstanceProfileRole": { - "Arn": "arn:aws:iam::aws:policy/AWSOpsWorksCMInstanceProfileRole", - "AttachmentCount": 0, - "CreateDate": "2016-11-24T09:48:22+00:00", - "DefaultVersionId": "v1", - "Document": { - "Statement": [ { "Action": [ "s3:AbortMultipartUpload", @@ -4656,16 +10285,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAICSU3OSHCURP2WIZW", "PolicyName": "AWSOpsWorksCMInstanceProfileRole", - "UpdateDate": "2016-11-24T09:48:22+00:00", - "VersionId": "v1" + "UpdateDate": "2017-11-03T12:01:32+00:00", + "VersionId": "v2" }, "AWSOpsWorksCMServiceRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSOpsWorksCMServiceRole", "AttachmentCount": 0, - "CreateDate": "2017-04-03T12:00:07+00:00", - "DefaultVersionId": "v6", + "CreateDate": "2016-11-24T09:49:46+00:00", + "DefaultVersionId": "v8", "Document": { "Statement": [ { @@ -4677,7 +10307,8 @@ aws_managed_policies_data = """ "s3:HeadBucket", "s3:ListBucket", "s3:ListObjects", - "s3:PutBucketPolicy" + "s3:PutBucketPolicy", + "s3:PutObject" ], "Effect": "Allow", "Resource": [ @@ -4752,7 +10383,8 @@ aws_managed_policies_data = """ }, { "Action": [ - "ec2:TerminateInstances" + "ec2:TerminateInstances", + "ec2:RebootInstances" ], "Condition": { "StringLike": { @@ -4764,6 +10396,16 @@ aws_managed_policies_data = """ "*" ] }, + { + "Action": [ + "opsworks-cm:DeleteServer", + "opsworks-cm:StartMaintenance" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:opsworks-cm:*:*:server/*" + ] + }, { "Action": [ "cloudformation:CreateStack", @@ -4794,10 +10436,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ6I6MPGJE62URSHCO", "PolicyName": "AWSOpsWorksCMServiceRole", - "UpdateDate": "2017-04-03T12:00:07+00:00", - "VersionId": "v6" + "UpdateDate": "2019-02-21T15:15:07+00:00", + "VersionId": "v8" }, "AWSOpsWorksCloudWatchLogs": { "Arn": "arn:aws:iam::aws:policy/AWSOpsWorksCloudWatchLogs", @@ -4824,6 +10467,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJXFIK7WABAY5CPXM4", "PolicyName": "AWSOpsWorksCloudWatchLogs", "UpdateDate": "2017-03-30T17:47:19+00:00", @@ -4864,6 +10508,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAICN26VXMXASXKOQCG", "PolicyName": "AWSOpsWorksFullAccess", "UpdateDate": "2015-02-06T18:40:48+00:00", @@ -4893,6 +10538,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJG3LCPVNI4WDZCIMU", "PolicyName": "AWSOpsWorksInstanceRegistration", "UpdateDate": "2016-06-03T14:23:15+00:00", @@ -4951,6 +10597,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ3AB5ZBFPCQGTVDU4", "PolicyName": "AWSOpsWorksRegisterCLI", "UpdateDate": "2015-02-06T18:40:49+00:00", @@ -4994,11 +10641,164 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIDUTMOKHJFAPJV45W", "PolicyName": "AWSOpsWorksRole", "UpdateDate": "2015-02-06T18:41:27+00:00", "VersionId": "v1" }, + "AWSOrganizationsFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSOrganizationsFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-06T20:31:57+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": "organizations:*", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJZXBNRCJKNLQHSB5M", + "PolicyName": "AWSOrganizationsFullAccess", + "UpdateDate": "2018-11-06T20:31:57+00:00", + "VersionId": "v1" + }, + "AWSOrganizationsReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSOrganizationsReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-06T20:32:38+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "organizations:Describe*", + "organizations:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJY5RQATUV77PEPVOM", + "PolicyName": "AWSOrganizationsReadOnlyAccess", + "UpdateDate": "2018-11-06T20:32:38+00:00", + "VersionId": "v1" + }, + "AWSOrganizationsServiceTrustPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSOrganizationsServiceTrustPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-10T23:04:07+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "iam:DeleteRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/organizations.amazonaws.com/*" + ], + "Sid": "AllowDeletionOfServiceLinkedRoleForOrganizations" + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "AllowCreationOfServiceLinkedRoles" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIQH6ROMVVECFVRJPK", + "PolicyName": "AWSOrganizationsServiceTrustPolicy", + "UpdateDate": "2017-11-01T06:01:18+00:00", + "VersionId": "v2" + }, + "AWSPriceListServiceFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSPriceListServiceFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-22T00:36:27+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "pricing:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIADJ4GBYNHKABML3Q", + "PolicyName": "AWSPriceListServiceFullAccess", + "UpdateDate": "2017-11-22T00:36:27+00:00", + "VersionId": "v1" + }, + "AWSPrivateMarketplaceAdminFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSPrivateMarketplaceAdminFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T16:32:32+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "aws-marketplace:CreatePrivateMarketplace", + "aws-marketplace:CreatePrivateMarketplaceProfile", + "aws-marketplace:UpdatePrivateMarketplaceProfile", + "aws-marketplace:StartPrivateMarketplace", + "aws-marketplace:StopPrivateMarketplace", + "aws-marketplace:AssociateProductsWithPrivateMarketplace", + "aws-marketplace:DisassociateProductsFromPrivateMarketplace", + "aws-marketplace:DescribePrivateMarketplaceProfile", + "aws-marketplace:DescribePrivateMarketplaceStatus", + "aws-marketplace:ListPrivateMarketplaceProducts", + "aws-marketplace:DescribePrivateMarketplaceProducts" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ6VRZDDCYDOVCOCEI", + "PolicyName": "AWSPrivateMarketplaceAdminFullAccess", + "UpdateDate": "2018-11-27T16:32:32+00:00", + "VersionId": "v1" + }, "AWSQuickSightDescribeRDS": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSQuickSightDescribeRDS", "AttachmentCount": 0, @@ -5019,6 +10819,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJU5J6OAMCJD3OO76O", "PolicyName": "AWSQuickSightDescribeRDS", "UpdateDate": "2015-11-10T23:24:50+00:00", @@ -5044,11 +10845,40 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJFEM6MLSLTW4ZNBW2", "PolicyName": "AWSQuickSightDescribeRedshift", "UpdateDate": "2015-11-10T23:25:01+00:00", "VersionId": "v1" }, + "AWSQuickSightIoTAnalyticsAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSQuickSightIoTAnalyticsAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T17:00:54+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iotanalytics:ListDatasets", + "iotanalytics:DescribeDataset", + "iotanalytics:GetDatasetContent" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJIZNDRUTKCN5HLZOE", + "PolicyName": "AWSQuickSightIoTAnalyticsAccess", + "UpdateDate": "2017-11-29T17:00:54+00:00", + "VersionId": "v1" + }, "AWSQuickSightListIAM": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSQuickSightListIAM", "AttachmentCount": 0, @@ -5069,6 +10899,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI3CH5UUWZN4EKGILO", "PolicyName": "AWSQuickSightListIAM", "UpdateDate": "2015-11-10T23:25:07+00:00", @@ -5077,8 +10908,8 @@ aws_managed_policies_data = """ "AWSQuicksightAthenaAccess": { "Arn": "arn:aws:iam::aws:policy/service-role/AWSQuicksightAthenaAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-11T23:37:32+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2016-12-09T02:31:03+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -5093,6 +10924,7 @@ aws_managed_policies_data = """ "athena:GetQueryExecution", "athena:GetQueryExecutions", "athena:GetQueryResults", + "athena:GetQueryResultsStream", "athena:GetTable", "athena:GetTables", "athena:ListQueryExecutions", @@ -5154,15 +10986,1124 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI4JB77JXFQXDWNRPM", "PolicyName": "AWSQuicksightAthenaAccess", - "UpdateDate": "2017-08-11T23:37:32+00:00", + "UpdateDate": "2018-08-07T20:24:55+00:00", + "VersionId": "v4" + }, + "AWSResourceAccessManagerServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSResourceAccessManagerServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-14T19:28:28+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "organizations:DescribeAccount", + "organizations:DescribeOrganization", + "organizations:DescribeOrganizationalUnit", + "organizations:ListAccounts", + "organizations:ListAccountsForParent", + "organizations:ListChildren", + "organizations:ListOrganizationalUnitsForParent", + "organizations:ListParents", + "organizations:ListRoots" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:DeleteRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/ram.amazonaws.com/*" + ], + "Sid": "AllowDeletionOfServiceLinkedRoleForResourceAccessManager" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJU667A3V5UAXC4YNE", + "PolicyName": "AWSResourceAccessManagerServiceRolePolicy", + "UpdateDate": "2018-11-14T19:28:28+00:00", + "VersionId": "v1" + }, + "AWSResourceGroupsReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSResourceGroupsReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-03-07T10:27:04+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "resource-groups:Get*", + "resource-groups:List*", + "resource-groups:Search*", + "tag:Get*", + "cloudformation:DescribeStacks", + "cloudformation:ListStackResources", + "ec2:DescribeInstances", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSnapshots", + "ec2:DescribeVolumes", + "ec2:DescribeVpcs", + "elasticache:DescribeCacheClusters", + "elasticache:DescribeSnapshots", + "elasticache:ListTagsForResource", + "elasticbeanstalk:DescribeEnvironments", + "elasticmapreduce:DescribeCluster", + "elasticmapreduce:ListClusters", + "glacier:ListVaults", + "glacier:DescribeVault", + "glacier:ListTagsForVault", + "kinesis:ListStreams", + "kinesis:DescribeStream", + "kinesis:ListTagsForStream", + "opsworks:DescribeStacks", + "opsworks:ListTags", + "rds:DescribeDBInstances", + "rds:DescribeDBSnapshots", + "rds:ListTagsForResource", + "redshift:DescribeClusters", + "redshift:DescribeTags", + "route53domains:ListDomains", + "route53:ListHealthChecks", + "route53:GetHealthCheck", + "route53:ListHostedZones", + "route53:GetHostedZone", + "route53:ListTagsForResource", + "storagegateway:ListGateways", + "storagegateway:DescribeGatewayInformation", + "storagegateway:ListTagsForResource", + "s3:ListAllMyBuckets", + "s3:GetBucketTagging", + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeTags", + "ssm:ListDocuments" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIXFKM2WGBJAEWMFEG", + "PolicyName": "AWSResourceGroupsReadOnlyAccess", + "UpdateDate": "2019-02-05T17:56:25+00:00", + "VersionId": "v2" + }, + "AWSRoboMakerFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSRoboMakerFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T05:28:10+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "s3:GetObject", + "robomaker:*" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "VisualEditor0" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "robomaker.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIG7WQVUX3AGSKGBAO", + "PolicyName": "AWSRoboMakerFullAccess", + "UpdateDate": "2018-11-26T05:28:10+00:00", + "VersionId": "v1" + }, + "AWSRoboMakerReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSRoboMakerReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T05:30:50+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "robomaker:ListDeploymentJobs", + "robomaker:BatchDescribeSimulationJob", + "robomaker:DescribeFleet", + "robomaker:DescribeSimulationApplication", + "robomaker:DescribeRobotApplication", + "robomaker:ListFleets", + "robomaker:ListSimulationJobs", + "robomaker:DescribeDeploymentJob", + "robomaker:DescribeSimulationJob", + "robomaker:DescribeRobot", + "robomaker:ListRobots", + "robomaker:ListRobotApplications", + "robomaker:ListSimulationApplications" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "VisualEditor0" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIXFHP2ALXXGGECYJI", + "PolicyName": "AWSRoboMakerReadOnlyAccess", + "UpdateDate": "2018-11-26T05:30:50+00:00", + "VersionId": "v1" + }, + "AWSRoboMakerServicePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSRoboMakerServicePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T06:30:08+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterfacePermission", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:DescribeSecurityGroups", + "greengrass:CreateDeployment", + "greengrass:CreateGroupVersion", + "greengrass:CreateFunctionDefinition", + "greengrass:CreateFunctionDefinitionVersion", + "greengrass:GetDeploymentStatus", + "greengrass:GetGroup", + "greengrass:GetGroupVersion", + "greengrass:GetCoreDefinitionVersion", + "greengrass:GetFunctionDefinitionVersion", + "greengrass:GetAssociatedRole", + "lambda:CreateFunction" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:UpdateFunctionCode", + "lambda:GetFunction", + "lambda:UpdateFunctionConfiguration", + "lambda:DeleteFunction", + "lambda:ListVersionsByFunction", + "lambda:GetAlias", + "lambda:UpdateAlias", + "lambda:CreateAlias", + "lambda:DeleteAlias" + ], + "Effect": "Allow", + "Resource": "arn:aws:lambda:*:*:function:aws-robomaker-*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringEqualsIfExists": { + "iam:PassedToService": "lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJYLVVUUQMAEEZ3ZNY", + "PolicyName": "AWSRoboMakerServicePolicy", + "UpdateDate": "2019-04-04T22:15:35+00:00", + "VersionId": "v2" + }, + "AWSRoboMakerServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/AWSRoboMakerServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T05:33:19+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterfacePermission", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:DescribeSecurityGroups", + "greengrass:CreateDeployment", + "greengrass:CreateGroupVersion", + "greengrass:CreateFunctionDefinition", + "greengrass:CreateFunctionDefinitionVersion", + "greengrass:GetDeploymentStatus", + "greengrass:GetGroup", + "greengrass:GetGroupVersion", + "greengrass:GetCoreDefinitionVersion", + "greengrass:GetFunctionDefinitionVersion", + "greengrass:GetAssociatedRole", + "lambda:CreateFunction" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:UpdateFunctionCode", + "lambda:GetFunction", + "lambda:UpdateFunctionConfiguration" + ], + "Effect": "Allow", + "Resource": "arn:aws:lambda:*:*:function:aws-robomaker-*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringEqualsIfExists": { + "iam:PassedToService": "lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIOSFFLBBLCTKS3ATC", + "PolicyName": "AWSRoboMakerServiceRolePolicy", + "UpdateDate": "2018-11-26T05:33:19+00:00", + "VersionId": "v1" + }, + "AWSSSODirectoryAdministrator": { + "Arn": "arn:aws:iam::aws:policy/AWSSSODirectoryAdministrator", + "AttachmentCount": 0, + "CreateDate": "2018-10-31T23:54:00+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "sso-directory:*" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "AWSSSODirectoryAdministrator" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI2TCZRD7WRD5D2E2Q", + "PolicyName": "AWSSSODirectoryAdministrator", + "UpdateDate": "2018-10-31T23:54:00+00:00", + "VersionId": "v1" + }, + "AWSSSODirectoryReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AWSSSODirectoryReadOnly", + "AttachmentCount": 0, + "CreateDate": "2018-10-31T23:49:32+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "sso-directory:Search*", + "sso-directory:Describe*", + "sso-directory:List*" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "AWSSSODirectoryReadOnly" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJDPMQELJXZD2NC6JG", + "PolicyName": "AWSSSODirectoryReadOnly", + "UpdateDate": "2018-10-31T23:49:32+00:00", + "VersionId": "v1" + }, + "AWSSSOMasterAccountAdministrator": { + "Arn": "arn:aws:iam::aws:policy/AWSSSOMasterAccountAdministrator", + "AttachmentCount": 0, + "CreateDate": "2018-06-27T20:36:51+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": "sso.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/sso.amazonaws.com/AWSServiceRoleForSSO", + "Sid": "AWSSSOMasterAccountAdministrator" + }, + { + "Action": [ + "ds:DescribeTrusts", + "ds:UnauthorizeApplication", + "ds:DescribeDirectories", + "ds:AuthorizeApplication", + "iam:ListPolicies", + "organizations:EnableAWSServiceAccess", + "organizations:ListRoots", + "organizations:ListAccounts", + "organizations:ListOrganizationalUnitsForParent", + "organizations:ListAccountsForParent", + "organizations:DescribeOrganization", + "organizations:ListChildren", + "organizations:DescribeAccount", + "organizations:ListParents", + "sso:*", + "sso-directory:DescribeDirectory", + "ds:CreateAlias" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "AWSSSOMemberAccountAdministrator" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIHXAQZIS3GOYIETUC", + "PolicyName": "AWSSSOMasterAccountAdministrator", + "UpdateDate": "2018-10-17T20:41:20+00:00", + "VersionId": "v3" + }, + "AWSSSOMemberAccountAdministrator": { + "Arn": "arn:aws:iam::aws:policy/AWSSSOMemberAccountAdministrator", + "AttachmentCount": 0, + "CreateDate": "2018-06-27T20:45:42+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ds:DescribeDirectories", + "ds:AuthorizeApplication", + "ds:UnauthorizeApplication", + "ds:DescribeTrusts", + "iam:ListPolicies", + "organizations:EnableAWSServiceAccess", + "organizations:DescribeOrganization", + "organizations:DescribeAccount", + "organizations:ListRoots", + "organizations:ListAccounts", + "organizations:ListAccountsForParent", + "organizations:ListParents", + "organizations:ListChildren", + "organizations:ListOrganizationalUnitsForParent", + "sso:*", + "sso-directory:DescribeDirectory", + "ds:CreateAlias" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "AWSSSOMemberAccountAdministrator" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIQYHEY7KJWXZFNDPY", + "PolicyName": "AWSSSOMemberAccountAdministrator", + "UpdateDate": "2018-10-17T20:35:52+00:00", + "VersionId": "v2" + }, + "AWSSSOReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AWSSSOReadOnly", + "AttachmentCount": 0, + "CreateDate": "2018-06-27T20:24:34+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "ds:DescribeDirectories", + "ds:DescribeTrusts", + "iam:ListPolicies", + "organizations:DescribeOrganization", + "organizations:DescribeAccount", + "organizations:ListParents", + "organizations:ListChildren", + "organizations:ListAccounts", + "organizations:ListRoots", + "organizations:ListAccountsForParent", + "organizations:ListOrganizationalUnitsForParent", + "sso:DescribePermissionsPolicies", + "sso:GetApplicationTemplate", + "sso:GetApplicationInstance", + "sso:GetPermissionSet", + "sso:GetProfile", + "sso:GetPermissionsPolicy", + "sso:GetSSOStatus", + "sso:GetSSOConfiguration", + "sso:GetTrust", + "sso:ListPermissionSets", + "sso:ListDirectoryAssociations", + "sso:ListProfiles", + "sso:ListApplicationInstances", + "sso:ListApplicationInstanceCertificates", + "sso:ListApplicationTemplates", + "sso:ListApplications", + "sso:ListProfileAssociations", + "sso:Search*", + "sso-directory:DescribeDirectory" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "AWSSSOReadOnly" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJBSMEEZXFDMKMY43I", + "PolicyName": "AWSSSOReadOnly", + "UpdateDate": "2018-12-19T20:17:58+00:00", + "VersionId": "v3" + }, + "AWSSSOServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSSSOServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-12-05T18:36:15+00:00", + "DefaultVersionId": "v6", + "Document": { + "Statement": [ + { + "Action": [ + "iam:AttachRolePolicy", + "iam:CreateRole", + "iam:DeleteRole", + "iam:DeleteRolePolicy", + "iam:DetachRolePolicy", + "iam:GetRole", + "iam:ListRolePolicies", + "iam:PutRolePolicy", + "iam:ListAttachedRolePolicies", + "iam:UpdateRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-reserved/sso.amazonaws.com/*" + ] + }, + { + "Action": [ + "iam:ListRoles" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "ListRolesInTheAccount" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus", + "iam:DeleteRole", + "iam:GetRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/sso.amazonaws.com/AWSServiceRoleForSSO" + ], + "Sid": "AllowDeletionOfServiceLinkedRoleForSSO" + }, + { + "Action": [ + "iam:CreateSAMLProvider", + "iam:GetSAMLProvider", + "iam:UpdateSAMLProvider", + "iam:DeleteSAMLProvider" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:saml-provider/AWSSSO_*" + ] + }, + { + "Action": [ + "organizations:DescribeAccount", + "organizations:DescribeOrganization", + "organizations:ListAccounts" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "ds:UnauthorizeApplication" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "AllowUnauthAppForDirectory" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIJ52KSWOD4GI54XP2", + "PolicyName": "AWSSSOServiceRolePolicy", + "UpdateDate": "2019-05-15T20:45:42+00:00", + "VersionId": "v6" + }, + "AWSSecurityHubFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSSecurityHubFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T23:54:34+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": "securityhub:*", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "securityhub.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ4262VZCA4HPBZSO6", + "PolicyName": "AWSSecurityHubFullAccess", + "UpdateDate": "2018-11-27T23:54:34+00:00", + "VersionId": "v1" + }, + "AWSSecurityHubReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSSecurityHubReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T01:34:29+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "securityhub:Get*", + "securityhub:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIEBAQNOFUCLFJ3UHG", + "PolicyName": "AWSSecurityHubReadOnlyAccess", + "UpdateDate": "2018-11-28T01:34:29+00:00", + "VersionId": "v1" + }, + "AWSSecurityHubServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSSecurityHubServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T23:47:51+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudtrail:DescribeTrails", + "cloudtrail:GetTrailStatus", + "cloudtrail:GetEventSelectors", + "cloudwatch:DescribeAlarms", + "logs:DescribeMetricFilters", + "sns:ListSubscriptionsByTopic", + "config:DescribeConfigurationRecorders", + "config:DescribeConfigurationRecorderStatus", + "config:DescribeConfigRules", + "config:BatchGetResourceConfig" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "config:PutConfigRule", + "config:DeleteConfigRule", + "config:GetComplianceDetailsByConfigRule" + ], + "Effect": "Allow", + "Resource": "arn:aws:config:*:*:config-rule/aws-service-rule/*securityhub*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJQPCESDDYDLLSOGYO", + "PolicyName": "AWSSecurityHubServiceRolePolicy", + "UpdateDate": "2018-11-27T23:47:51+00:00", + "VersionId": "v1" + }, + "AWSServiceCatalogAdminFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSServiceCatalogAdminFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-02-15T17:19:40+00:00", + "DefaultVersionId": "v5", + "Document": { + "Statement": [ + { + "Action": [ + "cloudformation:CreateStack", + "cloudformation:DeleteStack", + "cloudformation:DescribeStackEvents", + "cloudformation:DescribeStacks", + "cloudformation:SetStackPolicy", + "cloudformation:UpdateStack", + "cloudformation:CreateChangeSet", + "cloudformation:DescribeChangeSet", + "cloudformation:ExecuteChangeSet", + "cloudformation:ListChangeSets", + "cloudformation:DeleteChangeSet", + "cloudformation:ListStackResources", + "cloudformation:TagResource", + "cloudformation:CreateStackSet", + "cloudformation:CreateStackInstances", + "cloudformation:UpdateStackSet", + "cloudformation:UpdateStackInstances", + "cloudformation:DeleteStackSet", + "cloudformation:DeleteStackInstances", + "cloudformation:DescribeStackSet", + "cloudformation:DescribeStackInstance", + "cloudformation:DescribeStackSetOperation", + "cloudformation:ListStackInstances", + "cloudformation:ListStackSetOperations", + "cloudformation:ListStackSetOperationResults" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:cloudformation:*:*:stack/SC-*", + "arn:aws:cloudformation:*:*:stack/StackSet-SC-*", + "arn:aws:cloudformation:*:*:changeSet/SC-*", + "arn:aws:cloudformation:*:*:stackset/SC-*" + ] + }, + { + "Action": [ + "cloudformation:CreateUploadBucket", + "cloudformation:GetTemplateSummary", + "cloudformation:ValidateTemplate", + "iam:GetGroup", + "iam:GetRole", + "iam:GetUser", + "iam:ListGroups", + "iam:ListRoles", + "iam:ListUsers", + "servicecatalog:*", + "ssm:DescribeDocument", + "ssm:GetAutomationExecution", + "ssm:ListDocuments", + "ssm:ListDocumentVersions", + "config:DescribeConfigurationRecorders", + "config:DescribeConfigurationRecorderStatus" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringEquals": { + "iam:PassedToService": "servicecatalog.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJWLJU4BZ7AQUJSBVM", + "PolicyName": "AWSServiceCatalogAdminFullAccess", + "UpdateDate": "2019-02-06T01:57:54+00:00", + "VersionId": "v5" + }, + "AWSServiceCatalogEndUserFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSServiceCatalogEndUserFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-02-15T17:22:32+00:00", + "DefaultVersionId": "v5", + "Document": { + "Statement": [ + { + "Action": [ + "cloudformation:CreateStack", + "cloudformation:DeleteStack", + "cloudformation:DescribeStackEvents", + "cloudformation:DescribeStacks", + "cloudformation:SetStackPolicy", + "cloudformation:ValidateTemplate", + "cloudformation:UpdateStack", + "cloudformation:CreateChangeSet", + "cloudformation:DescribeChangeSet", + "cloudformation:ExecuteChangeSet", + "cloudformation:ListChangeSets", + "cloudformation:DeleteChangeSet", + "cloudformation:TagResource", + "cloudformation:CreateStackSet", + "cloudformation:CreateStackInstances", + "cloudformation:UpdateStackSet", + "cloudformation:UpdateStackInstances", + "cloudformation:DeleteStackSet", + "cloudformation:DeleteStackInstances", + "cloudformation:DescribeStackSet", + "cloudformation:DescribeStackInstance", + "cloudformation:DescribeStackSetOperation", + "cloudformation:ListStackInstances", + "cloudformation:ListStackResources", + "cloudformation:ListStackSetOperations", + "cloudformation:ListStackSetOperationResults" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:cloudformation:*:*:stack/SC-*", + "arn:aws:cloudformation:*:*:stack/StackSet-SC-*", + "arn:aws:cloudformation:*:*:changeSet/SC-*", + "arn:aws:cloudformation:*:*:stackset/SC-*" + ] + }, + { + "Action": [ + "cloudformation:GetTemplateSummary", + "servicecatalog:DescribeProduct", + "servicecatalog:DescribeProductView", + "servicecatalog:DescribeProvisioningParameters", + "servicecatalog:ListLaunchPaths", + "servicecatalog:ProvisionProduct", + "servicecatalog:SearchProducts", + "ssm:DescribeDocument", + "ssm:GetAutomationExecution", + "config:DescribeConfigurationRecorders", + "config:DescribeConfigurationRecorderStatus" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "servicecatalog:DescribeProvisionedProduct", + "servicecatalog:DescribeRecord", + "servicecatalog:ListRecordHistory", + "servicecatalog:ScanProvisionedProducts", + "servicecatalog:TerminateProvisionedProduct", + "servicecatalog:UpdateProvisionedProduct", + "servicecatalog:SearchProvisionedProducts", + "servicecatalog:CreateProvisionedProductPlan", + "servicecatalog:DescribeProvisionedProductPlan", + "servicecatalog:ExecuteProvisionedProductPlan", + "servicecatalog:DeleteProvisionedProductPlan", + "servicecatalog:ListProvisionedProductPlans", + "servicecatalog:ListServiceActionsForProvisioningArtifact", + "servicecatalog:ExecuteProvisionedProductServiceAction" + ], + "Condition": { + "StringEquals": { + "servicecatalog:userLevel": "self" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJTLLC4DGDMTZB54M4", + "PolicyName": "AWSServiceCatalogEndUserFullAccess", + "UpdateDate": "2019-02-06T02:00:22+00:00", + "VersionId": "v5" + }, + "AWSServiceRoleForEC2ScheduledInstances": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSServiceRoleForEC2ScheduledInstances", + "AttachmentCount": 0, + "CreateDate": "2017-10-12T18:31:55+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateTags" + ], + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:ec2sri:scheduledInstanceId" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:instance/*" + ] + }, + { + "Action": [ + "ec2:TerminateInstances" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/aws:ec2sri:scheduledInstanceId": "*" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7Y4TT63D6QBKCY4O", + "PolicyName": "AWSServiceRoleForEC2ScheduledInstances", + "UpdateDate": "2017-10-12T18:31:55+00:00", + "VersionId": "v1" + }, + "AWSServiceRoleForIoTSiteWise": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSServiceRoleForIoTSiteWise", + "AttachmentCount": 0, + "CreateDate": "2018-11-14T19:19:17+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": "iotanalytics:ExecuteQuery", + "Effect": "Allow", + "Resource": "arn:aws:iotanalytics:*:*:datastore-index/*" + }, + { + "Action": [ + "greengrass:CreateCoreDefinitionVersion", + "greengrass:CreateDeployment", + "greengrass:CreateFunctionDefinition", + "greengrass:CreateFunctionDefinitionVersion", + "greengrass:CreateGroupVersion", + "greengrass:CreateLoggerDefinition", + "greengrass:CreateLoggerDefinitionVersion", + "greengrass:CreateResourceDefinition", + "greengrass:CreateResourceDefinitionVersion", + "greengrass:GetAssociatedRole", + "greengrass:GetCoreDefinition", + "greengrass:GetCoreDefinitionVersion", + "greengrass:GetDeploymentStatus", + "greengrass:GetFunctionDefinition", + "greengrass:GetFunctionDefinitionVersion", + "greengrass:GetGroup", + "greengrass:GetGroupVersion", + "greengrass:GetLoggerDefinition", + "greengrass:GetLoggerDefinitionVersion", + "greengrass:GetResourceDefinition", + "greengrass:GetResourceDefinitionVersion", + "greengrass:ListCoreDefinitions", + "greengrass:UpdateCoreDefinition", + "greengrass:UpdateFunctionDefinition", + "greengrass:UpdateLoggerDefinition", + "greengrass:UpdateResourceDefinition" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:CreateAlias", + "lambda:CreateFunction", + "lambda:GetFunction", + "lambda:ListVersionsByFunction", + "lambda:UpdateFunctionCode", + "lambda:PublishVersion", + "lambda:UpdateAlias" + ], + "Effect": "Allow", + "Resource": "arn:aws:lambda:*:*:function:AWSIoTSiteWise*" + }, + { + "Action": [ + "iot:GetThingShadow", + "iot:UpdateThingShadow" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLikeIfExists": { + "iam:PassedToService": "lambda.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJGQU4DZIQP6HLYQPE", + "PolicyName": "AWSServiceRoleForIoTSiteWise", + "UpdateDate": "2019-02-11T20:49:09+00:00", + "VersionId": "v3" + }, + "AWSShieldDRTAccessPolicy": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSShieldDRTAccessPolicy", + "AttachmentCount": 0, + "CreateDate": "2018-06-05T22:29:39+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "cloudfront:List*", + "elasticloadbalancing:List*", + "route53:List*", + "cloudfront:Describe*", + "elasticloadbalancing:Describe*", + "route53:Describe*", + "cloudwatch:Describe*", + "cloudwatch:Get*", + "cloudwatch:List*", + "cloudfront:GetDistribution*", + "globalaccelerator:ListAccelerators", + "globalaccelerator:DescribeAccelerator" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:elasticloadbalancing:*:*:*", + "arn:aws:cloudfront::*:*", + "arn:aws:route53:::hostedzone/*", + "arn:aws:cloudwatch:*:*:*:*", + "arn:aws:globalaccelerator::*:*" + ], + "Sid": "DRTAccessProtectedResources" + }, + { + "Action": [ + "waf:*", + "waf-regional:*" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:waf:*", + "arn:aws:waf-regional:*" + ], + "Sid": "DRTManageMitigations" + }, + { + "Action": [ + "shield:*" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "DRTManageProtections" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJWNCSZ4PARLO37VVY", + "PolicyName": "AWSShieldDRTAccessPolicy", + "UpdateDate": "2019-02-11T17:08:57+00:00", "VersionId": "v3" }, "AWSStepFunctionsConsoleFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSStepFunctionsConsoleFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-01-12T00:19:34+00:00", + "CreateDate": "2017-01-11T21:54:31+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -5192,6 +12133,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJIYC52YWRX6OSMJWK", "PolicyName": "AWSStepFunctionsConsoleFullAccess", "UpdateDate": "2017-01-12T00:19:34+00:00", @@ -5215,6 +12157,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJXKA6VP3UFBVHDPPA", "PolicyName": "AWSStepFunctionsFullAccess", "UpdateDate": "2017-01-11T21:51:32+00:00", @@ -5224,7 +12167,7 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AWSStepFunctionsReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2017-01-11T21:46:19+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -5232,6 +12175,7 @@ aws_managed_policies_data = """ "states:ListStateMachines", "states:ListActivities", "states:DescribeStateMachine", + "states:DescribeStateMachineForExecution", "states:ListExecutions", "states:DescribeExecution", "states:GetExecutionHistory", @@ -5246,10 +12190,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJONHB2TJQDJPFW5TM", "PolicyName": "AWSStepFunctionsReadOnlyAccess", - "UpdateDate": "2017-01-11T21:46:19+00:00", - "VersionId": "v1" + "UpdateDate": "2017-11-10T22:03:49+00:00", + "VersionId": "v2" }, "AWSStorageGatewayFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSStorageGatewayFullAccess", @@ -5279,6 +12224,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJG5SSPAVOGK3SIDGU", "PolicyName": "AWSStorageGatewayFullAccess", "UpdateDate": "2015-02-06T18:41:09+00:00", @@ -5312,6 +12258,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIFKCTUVOPD5NICXJK", "PolicyName": "AWSStorageGatewayReadOnlyAccess", "UpdateDate": "2015-02-06T18:41:10+00:00", @@ -5337,15 +12284,1388 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJSNKQX2OW67GF4S7E", "PolicyName": "AWSSupportAccess", "UpdateDate": "2015-02-06T18:41:11+00:00", "VersionId": "v1" }, + "AWSSupportServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSSupportServiceRolePolicy", + "AttachmentCount": 1, + "CreateDate": "2018-04-19T18:04:44+00:00", + "DefaultVersionId": "v4", + "Document": { + "Statement": [ + { + "Action": [ + "apigateway:GET" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:apigateway:*::/account", + "arn:aws:apigateway:*::/clientcertificates", + "arn:aws:apigateway:*::/clientcertificates/*", + "arn:aws:apigateway:*::/domainnames", + "arn:aws:apigateway:*::/domainnames/*", + "arn:aws:apigateway:*::/domainnames/*/basepathmappings", + "arn:aws:apigateway:*::/domainnames/*/basepathmappings/*", + "arn:aws:apigateway:*::/restapis", + "arn:aws:apigateway:*::/restapis/*", + "arn:aws:apigateway:*::/restapis/*/authorizers", + "arn:aws:apigateway:*::/restapis/*/authorizers/*", + "arn:aws:apigateway:*::/restapis/*/deployments", + "arn:aws:apigateway:*::/restapis/*/deployments/*", + "arn:aws:apigateway:*::/restapis/*/models", + "arn:aws:apigateway:*::/restapis/*/models/*", + "arn:aws:apigateway:*::/restapis/*/models/*/default_template", + "arn:aws:apigateway:*::/restapis/*/resources", + "arn:aws:apigateway:*::/restapis/*/resources/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration/responses/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/responses/*", + "arn:aws:apigateway:*::/restapis/*/stages/*/sdks/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*/integration", + "arn:aws:apigateway:*::/restapis/*/stages", + "arn:aws:apigateway:*::/restapis/*/stages/*" + ] + }, + { + "Action": [ + "iam:DeleteRole" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/support.amazonaws.com/AWSServiceRoleForSupport" + ] + }, + { + "Action": [ + "a4b:getDevice", + "a4b:getProfile", + "a4b:getRoom", + "a4b:getRoomSkillParameter", + "a4b:getSkillGroup", + "a4b:searchDevices", + "a4b:searchProfiles", + "a4b:searchRooms", + "a4b:searchSkillGroups", + "acm-pca:describeCertificateAuthority", + "acm-pca:describeCertificateAuthorityAuditReport", + "acm-pca:getCertificate", + "acm-pca:getCertificateAuthorityCertificate", + "acm-pca:getCertificateAuthorityCsr", + "acm-pca:listCertificateAuthorities", + "acm-pca:listTags", + "acm:describeCertificate", + "acm:getCertificate", + "acm:listCertificates", + "acm:listTagsForCertificate", + "application-autoscaling:describeScalableTargets", + "application-autoscaling:describeScalingActivities", + "application-autoscaling:describeScalingPolicies", + "appstream:describeDirectoryConfigs", + "appstream:describeFleets", + "appstream:describeImageBuilders", + "appstream:describeImages", + "appstream:describeSessions", + "appstream:describeStacks", + "appstream:listAssociatedFleets", + "appstream:listAssociatedStacks", + "appstream:listTagsForResource", + "appsync:getFunction", + "appsync:getGraphqlApi", + "appsync:getIntrospectionSchema", + "appsync:getResolver", + "appsync:getSchemaCreationStatus", + "appsync:getType", + "appsync:listDataSources", + "appsync:listFunctions", + "appsync:listGraphqlApis", + "appsync:listResolvers", + "appsync:listTypes", + "athena:batchGetNamedQuery", + "athena:batchGetQueryExecution", + "athena:getNamedQuery", + "athena:getQueryExecution", + "athena:listNamedQueries", + "athena:listQueryExecutions", + "autoscaling-plans:describeScalingPlanResources", + "autoscaling-plans:describeScalingPlans", + "autoscaling-plans:getScalingPlanResourceForecastData", + "autoscaling:describeAccountLimits", + "autoscaling:describeAdjustmentTypes", + "autoscaling:describeAutoScalingGroups", + "autoscaling:describeAutoScalingInstances", + "autoscaling:describeAutoScalingNotificationTypes", + "autoscaling:describeLaunchConfigurations", + "autoscaling:describeLifecycleHooks", + "autoscaling:describeLifecycleHookTypes", + "autoscaling:describeLoadBalancers", + "autoscaling:describeLoadBalancerTargetGroups", + "autoscaling:describeMetricCollectionTypes", + "autoscaling:describeNotificationConfigurations", + "autoscaling:describePolicies", + "autoscaling:describeScalingActivities", + "autoscaling:describeScalingProcessTypes", + "autoscaling:describeScheduledActions", + "autoscaling:describeTags", + "autoscaling:describeTerminationPolicyTypes", + "batch:describeComputeEnvironments", + "batch:describeJobDefinitions", + "batch:describeJobQueues", + "batch:describeJobs", + "batch:listJobs", + "cloud9:describeEnvironmentMemberships", + "cloud9:describeEnvironments", + "cloud9:listEnvironments", + "clouddirectory:getDirectory", + "clouddirectory:listDirectories", + "cloudformation:describeAccountLimits", + "cloudformation:describeChangeSet", + "cloudformation:describeStackEvents", + "cloudformation:describeStackInstance", + "cloudformation:describeStackResource", + "cloudformation:describeStackResources", + "cloudformation:describeStacks", + "cloudformation:describeStackSet", + "cloudformation:describeStackSetOperation", + "cloudformation:estimateTemplateCost", + "cloudformation:getStackPolicy", + "cloudformation:getTemplate", + "cloudformation:getTemplateSummary", + "cloudformation:listChangeSets", + "cloudformation:listExports", + "cloudformation:listImports", + "cloudformation:listStackInstances", + "cloudformation:listStackResources", + "cloudformation:listStacks", + "cloudformation:listStackSetOperationResults", + "cloudformation:listStackSetOperations", + "cloudformation:listStackSets", + "cloudfront:getCloudFrontOriginAccessIdentity", + "cloudfront:getCloudFrontOriginAccessIdentityConfig", + "cloudfront:getDistribution", + "cloudfront:getDistributionConfig", + "cloudfront:getInvalidation", + "cloudfront:getStreamingDistribution", + "cloudfront:getStreamingDistributionConfig", + "cloudfront:listCloudFrontOriginAccessIdentities", + "cloudfront:listDistributions", + "cloudfront:listDistributionsByWebACLId", + "cloudfront:listInvalidations", + "cloudfront:listStreamingDistributions", + "cloudhsm:describeBackups", + "cloudhsm:describeClusters", + "cloudsearch:describeAnalysisSchemes", + "cloudsearch:describeAvailabilityOptions", + "cloudsearch:describeDomains", + "cloudsearch:describeExpressions", + "cloudsearch:describeIndexFields", + "cloudsearch:describeScalingParameters", + "cloudsearch:describeServiceAccessPolicies", + "cloudsearch:describeSuggesters", + "cloudsearch:listDomainNames", + "cloudtrail:describeTrails", + "cloudtrail:getEventSelectors", + "cloudtrail:getTrailStatus", + "cloudtrail:listPublicKeys", + "cloudtrail:listTags", + "cloudtrail:lookupEvents", + "cloudwatch:describeAlarmHistory", + "cloudwatch:describeAlarms", + "cloudwatch:describeAlarmsForMetric", + "cloudwatch:getDashboard", + "cloudwatch:getMetricData", + "cloudwatch:getMetricStatistics", + "cloudwatch:listDashboards", + "cloudwatch:listMetrics", + "codebuild:batchGetBuilds", + "codebuild:batchGetProjects", + "codebuild:listBuilds", + "codebuild:listBuildsForProject", + "codebuild:listCuratedEnvironmentImages", + "codebuild:listProjects", + "codecommit:batchGetRepositories", + "codecommit:getBranch", + "codecommit:getRepository", + "codecommit:getRepositoryTriggers", + "codecommit:listBranches", + "codecommit:listRepositories", + "codedeploy:batchGetApplications", + "codedeploy:batchGetDeployments", + "codedeploy:batchGetOnPremisesInstances", + "codedeploy:getApplication", + "codedeploy:getApplicationRevision", + "codedeploy:getDeployment", + "codedeploy:getDeploymentConfig", + "codedeploy:getDeploymentGroup", + "codedeploy:getDeploymentInstance", + "codedeploy:getOnPremisesInstance", + "codedeploy:listApplicationRevisions", + "codedeploy:listApplications", + "codedeploy:listDeploymentConfigs", + "codedeploy:listDeploymentGroups", + "codedeploy:listDeploymentInstances", + "codedeploy:listDeployments", + "codedeploy:listOnPremisesInstances", + "codepipeline:getJobDetails", + "codepipeline:getPipeline", + "codepipeline:getPipelineExecution", + "codepipeline:getPipelineState", + "codepipeline:listActionTypes", + "codepipeline:listPipelines", + "codestar:describeProject", + "codestar:listProjects", + "codestar:listResources", + "codestar:listTeamMembers", + "codestar:listUserProfiles", + "cognito-identity:describeIdentityPool", + "cognito-identity:getIdentityPoolRoles", + "cognito-identity:listIdentities", + "cognito-identity:listIdentityPools", + "cognito-idp:adminGetUser", + "cognito-idp:describeIdentityProvider", + "cognito-idp:describeResourceServer", + "cognito-idp:describeRiskConfiguration", + "cognito-idp:describeUserImportJob", + "cognito-idp:describeUserPool", + "cognito-idp:describeUserPoolClient", + "cognito-idp:describeUserPoolDomain", + "cognito-idp:getGroup", + "cognito-idp:getUICustomization", + "cognito-idp:getUser", + "cognito-idp:getUserPoolMfaConfig", + "cognito-idp:listGroups", + "cognito-idp:listIdentityProviders", + "cognito-idp:listResourceServers", + "cognito-idp:listUserImportJobs", + "cognito-idp:listUserPoolClients", + "cognito-idp:listUserPools", + "cognito-sync:describeDataset", + "cognito-sync:describeIdentityPoolUsage", + "cognito-sync:describeIdentityUsage", + "cognito-sync:getCognitoEvents", + "cognito-sync:getIdentityPoolConfiguration", + "cognito-sync:listDatasets", + "cognito-sync:listIdentityPoolUsage", + "config:describeConfigRuleEvaluationStatus", + "config:describeConfigRules", + "config:describeConfigurationRecorders", + "config:describeConfigurationRecorderStatus", + "config:describeDeliveryChannels", + "config:describeDeliveryChannelStatus", + "config:getResourceConfigHistory", + "config:listDiscoveredResources", + "datapipeline:describeObjects", + "datapipeline:describePipelines", + "datapipeline:getPipelineDefinition", + "datapipeline:listPipelines", + "datapipeline:queryObjects", + "dax:describeClusters", + "dax:describeDefaultParameters", + "dax:describeEvents", + "dax:describeParameterGroups", + "dax:describeParameters", + "dax:describeSubnetGroups", + "devicefarm:getAccountSettings", + "devicefarm:getDevice", + "devicefarm:getDevicePool", + "devicefarm:getDevicePoolCompatibility", + "devicefarm:getJob", + "devicefarm:getProject", + "devicefarm:getRemoteAccessSession", + "devicefarm:getRun", + "devicefarm:getSuite", + "devicefarm:getTest", + "devicefarm:getUpload", + "devicefarm:listArtifacts", + "devicefarm:listDevicePools", + "devicefarm:listDevices", + "devicefarm:listJobs", + "devicefarm:listProjects", + "devicefarm:listRemoteAccessSessions", + "devicefarm:listRuns", + "devicefarm:listSamples", + "devicefarm:listSuites", + "devicefarm:listTests", + "devicefarm:listUniqueProblems", + "devicefarm:listUploads", + "directconnect:describeConnections", + "directconnect:describeConnectionsOnInterconnect", + "directconnect:describeInterconnects", + "directconnect:describeLocations", + "directconnect:describeVirtualGateways", + "directconnect:describeVirtualInterfaces", + "dlm:getLifecyclePolicies", + "dlm:getLifecyclePolicy", + "dms:describeAccountAttributes", + "dms:describeConnections", + "dms:describeEndpoints", + "dms:describeEndpointTypes", + "dms:describeOrderableReplicationInstances", + "dms:describeRefreshSchemasStatus", + "dms:describeReplicationInstances", + "dms:describeReplicationSubnetGroups", + "ds:describeConditionalForwarders", + "ds:describeDirectories", + "ds:describeEventTopics", + "ds:describeSnapshots", + "ds:describeTrusts", + "ds:getDirectoryLimits", + "ds:getSnapshotLimits", + "ds:listIpRoutes", + "ds:listSchemaExtensions", + "ds:listTagsForResource", + "dynamodb:describeBackup", + "dynamodb:describeContinuousBackups", + "dynamodb:describeGlobalTable", + "dynamodb:describeLimits", + "dynamodb:describeStream", + "dynamodb:describeTable", + "dynamodb:describeTimeToLive", + "dynamodb:listBackups", + "dynamodb:listGlobalTables", + "dynamodb:listStreams", + "dynamodb:listTables", + "dynamodb:listTagsOfResource", + "ec2:acceptReservedInstancesExchangeQuote", + "ec2:cancelReservedInstancesListing", + "ec2:createReservedInstancesListing", + "ec2:describeAccountAttributes", + "ec2:describeAddresses", + "ec2:describeAvailabilityZones", + "ec2:describeBundleTasks", + "ec2:describeByoipCidrs", + "ec2:describeClassicLinkInstances", + "ec2:describeConversionTasks", + "ec2:describeCustomerGateways", + "ec2:describeDhcpOptions", + "ec2:describeElasticGpus", + "ec2:describeExportTasks", + "ec2:describeFlowLogs", + "ec2:describeHostReservationOfferings", + "ec2:describeHostReservations", + "ec2:describeHosts", + "ec2:describeIdentityIdFormat", + "ec2:describeIdFormat", + "ec2:describeImageAttribute", + "ec2:describeImages", + "ec2:describeImportImageTasks", + "ec2:describeImportSnapshotTasks", + "ec2:describeInstanceAttribute", + "ec2:describeInstances", + "ec2:describeInstanceStatus", + "ec2:describeInternetGateways", + "ec2:describeKeyPairs", + "ec2:describeLaunchTemplates", + "ec2:describeLaunchTemplateVersions", + "ec2:describeMovingAddresses", + "ec2:describeNatGateways", + "ec2:describeNetworkAcls", + "ec2:describeNetworkInterfaceAttribute", + "ec2:describeNetworkInterfaces", + "ec2:describePlacementGroups", + "ec2:describePrefixLists", + "ec2:describePublicIpv4Pools", + "ec2:describeRegions", + "ec2:describeReservedInstances", + "ec2:describeReservedInstancesListings", + "ec2:describeReservedInstancesModifications", + "ec2:describeReservedInstancesOfferings", + "ec2:describeRouteTables", + "ec2:describeScheduledInstances", + "ec2:describeSecurityGroups", + "ec2:describeSnapshotAttribute", + "ec2:describeSnapshots", + "ec2:describeSpotDatafeedSubscription", + "ec2:describeSpotFleetInstances", + "ec2:describeSpotFleetRequestHistory", + "ec2:describeSpotFleetRequests", + "ec2:describeSpotInstanceRequests", + "ec2:describeSpotPriceHistory", + "ec2:describeSubnets", + "ec2:describeTags", + "ec2:describeVolumeAttribute", + "ec2:describeVolumes", + "ec2:describeVolumesModifications", + "ec2:describeVolumeStatus", + "ec2:describeVpcAttribute", + "ec2:describeVpcClassicLink", + "ec2:describeVpcClassicLinkDnsSupport", + "ec2:describeVpcEndpointConnectionNotifications", + "ec2:describeVpcEndpointConnections", + "ec2:describeVpcEndpoints", + "ec2:describeVpcEndpointServiceConfigurations", + "ec2:describeVpcEndpointServicePermissions", + "ec2:describeVpcEndpointServices", + "ec2:describeVpcPeeringConnections", + "ec2:describeVpcs", + "ec2:describeVpnConnections", + "ec2:describeVpnGateways", + "ec2:getConsoleScreenshot", + "ec2:getReservedInstancesExchangeQuote", + "ec2:modifyReservedInstances", + "ec2:purchaseReservedInstancesOffering", + "ecr:batchCheckLayerAvailability", + "ecr:describeImages", + "ecr:describeRepositories", + "ecr:getRepositoryPolicy", + "ecr:listImages", + "ecs:describeClusters", + "ecs:describeContainerInstances", + "ecs:describeServices", + "ecs:describeTaskDefinition", + "ecs:describeTasks", + "ecs:listClusters", + "ecs:listContainerInstances", + "ecs:listServices", + "ecs:listTaskDefinitions", + "ecs:listTasks", + "eks:describeCluster", + "eks:listClusters", + "elasticache:describeCacheClusters", + "elasticache:describeCacheEngineVersions", + "elasticache:describeCacheParameterGroups", + "elasticache:describeCacheParameters", + "elasticache:describeCacheSecurityGroups", + "elasticache:describeCacheSubnetGroups", + "elasticache:describeEngineDefaultParameters", + "elasticache:describeEvents", + "elasticache:describeReplicationGroups", + "elasticache:describeReservedCacheNodes", + "elasticache:describeReservedCacheNodesOfferings", + "elasticache:describeSnapshots", + "elasticache:listAllowedNodeTypeModifications", + "elasticache:listTagsForResource", + "elasticbeanstalk:checkDNSAvailability", + "elasticbeanstalk:describeApplications", + "elasticbeanstalk:describeApplicationVersions", + "elasticbeanstalk:describeConfigurationOptions", + "elasticbeanstalk:describeConfigurationSettings", + "elasticbeanstalk:describeEnvironmentHealth", + "elasticbeanstalk:describeEnvironmentManagedActionHistory", + "elasticbeanstalk:describeEnvironmentManagedActions", + "elasticbeanstalk:describeEnvironmentResources", + "elasticbeanstalk:describeEnvironments", + "elasticbeanstalk:describeEvents", + "elasticbeanstalk:describeInstancesHealth", + "elasticbeanstalk:describePlatformVersion", + "elasticbeanstalk:listAvailableSolutionStacks", + "elasticbeanstalk:listPlatformVersions", + "elasticbeanstalk:validateConfigurationSettings", + "elasticfilesystem:describeFileSystems", + "elasticfilesystem:describeMountTargets", + "elasticfilesystem:describeMountTargetSecurityGroups", + "elasticfilesystem:describeTags", + "elasticloadbalancing:describeInstanceHealth", + "elasticloadbalancing:describeListenerCertificates", + "elasticloadbalancing:describeListeners", + "elasticloadbalancing:describeLoadBalancerAttributes", + "elasticloadbalancing:describeLoadBalancerPolicies", + "elasticloadbalancing:describeLoadBalancerPolicyTypes", + "elasticloadbalancing:describeLoadBalancers", + "elasticloadbalancing:describeRules", + "elasticloadbalancing:describeSSLPolicies", + "elasticloadbalancing:describeTags", + "elasticloadbalancing:describeTargetGroupAttributes", + "elasticloadbalancing:describeTargetGroups", + "elasticloadbalancing:describeTargetHealth", + "elasticmapreduce:describeCluster", + "elasticmapreduce:describeSecurityConfiguration", + "elasticmapreduce:describeStep", + "elasticmapreduce:listBootstrapActions", + "elasticmapreduce:listClusters", + "elasticmapreduce:listInstanceGroups", + "elasticmapreduce:listInstances", + "elasticmapreduce:listSecurityConfigurations", + "elasticmapreduce:listSteps", + "elastictranscoder:listJobsByPipeline", + "elastictranscoder:listJobsByStatus", + "elastictranscoder:listPipelines", + "elastictranscoder:listPresets", + "elastictranscoder:readPipeline", + "elastictranscoder:readPreset", + "es:describeElasticsearchDomain", + "es:describeElasticsearchDomainConfig", + "es:describeElasticsearchDomains", + "es:listDomainNames", + "es:listTags", + "events:describeEventBus", + "events:describeRule", + "events:listRuleNamesByTarget", + "events:listRules", + "events:listTargetsByRule", + "events:testEventPattern", + "firehose:describeDeliveryStream", + "firehose:listDeliveryStreams", + "glacier:describeJob", + "glacier:describeVault", + "glacier:getDataRetrievalPolicy", + "glacier:getVaultAccessPolicy", + "glacier:getVaultLock", + "glacier:getVaultNotifications", + "glacier:listJobs", + "glacier:listTagsForVault", + "glacier:listVaults", + "glue:batchGetPartition", + "glue:getCatalogImportStatus", + "glue:getClassifier", + "glue:getClassifiers", + "glue:getCrawler", + "glue:getCrawlerMetrics", + "glue:getCrawlers", + "glue:getDatabase", + "glue:getDatabases", + "glue:getDataflowGraph", + "glue:getDevEndpoint", + "glue:getDevEndpoints", + "glue:getJob", + "glue:getJobRun", + "glue:getJobRuns", + "glue:getJobs", + "glue:getMapping", + "glue:getPartition", + "glue:getPartitions", + "glue:getTable", + "glue:getTables", + "glue:getTableVersions", + "glue:getTrigger", + "glue:getTriggers", + "glue:getUserDefinedFunction", + "glue:getUserDefinedFunctions", + "greengrass:getConnectivityInfo", + "greengrass:getCoreDefinition", + "greengrass:getCoreDefinitionVersion", + "greengrass:getDeploymentStatus", + "greengrass:getDeviceDefinition", + "greengrass:getDeviceDefinitionVersion", + "greengrass:getFunctionDefinition", + "greengrass:getFunctionDefinitionVersion", + "greengrass:getGroup", + "greengrass:getGroupCertificateAuthority", + "greengrass:getGroupVersion", + "greengrass:getLoggerDefinition", + "greengrass:getLoggerDefinitionVersion", + "greengrass:getResourceDefinitionVersion", + "greengrass:getServiceRoleForAccount", + "greengrass:getSubscriptionDefinition", + "greengrass:getSubscriptionDefinitionVersion", + "greengrass:listCoreDefinitions", + "greengrass:listCoreDefinitionVersions", + "greengrass:listDeployments", + "greengrass:listDeviceDefinitions", + "greengrass:listDeviceDefinitionVersions", + "greengrass:listFunctionDefinitions", + "greengrass:listFunctionDefinitionVersions", + "greengrass:listGroups", + "greengrass:listGroupVersions", + "greengrass:listLoggerDefinitions", + "greengrass:listLoggerDefinitionVersions", + "greengrass:listResourceDefinitions", + "greengrass:listResourceDefinitionVersions", + "greengrass:listSubscriptionDefinitions", + "greengrass:listSubscriptionDefinitionVersions", + "guardduty:getDetector", + "guardduty:getFindings", + "guardduty:getFindingsStatistics", + "guardduty:getInvitationsCount", + "guardduty:getIPSet", + "guardduty:getMasterAccount", + "guardduty:getMembers", + "guardduty:getThreatIntelSet", + "guardduty:listDetectors", + "guardduty:listFindings", + "guardduty:listInvitations", + "guardduty:listIPSets", + "guardduty:listMembers", + "guardduty:listThreatIntelSets", + "health:describeAffectedEntities", + "health:describeEntityAggregates", + "health:describeEventAggregates", + "health:describeEventDetails", + "health:describeEvents", + "health:describeEventTypes", + "iam:getAccessKeyLastUsed", + "iam:getAccountAuthorizationDetails", + "iam:getAccountPasswordPolicy", + "iam:getAccountSummary", + "iam:getContextKeysForCustomPolicy", + "iam:getContextKeysForPrincipalPolicy", + "iam:getCredentialReport", + "iam:getGroup", + "iam:getGroupPolicy", + "iam:getInstanceProfile", + "iam:getLoginProfile", + "iam:getOpenIDConnectProvider", + "iam:getPolicy", + "iam:getPolicyVersion", + "iam:getRole", + "iam:getRolePolicy", + "iam:getSAMLProvider", + "iam:getServerCertificate", + "iam:getSSHPublicKey", + "iam:getUser", + "iam:getUserPolicy", + "iam:listAccessKeys", + "iam:listAccountAliases", + "iam:listAttachedGroupPolicies", + "iam:listAttachedRolePolicies", + "iam:listAttachedUserPolicies", + "iam:listEntitiesForPolicy", + "iam:listGroupPolicies", + "iam:listGroups", + "iam:listGroupsForUser", + "iam:listInstanceProfiles", + "iam:listInstanceProfilesForRole", + "iam:listMFADevices", + "iam:listOpenIDConnectProviders", + "iam:listPolicies", + "iam:listPolicyVersions", + "iam:listRolePolicies", + "iam:listRoles", + "iam:listSAMLProviders", + "iam:listServerCertificates", + "iam:listSigningCertificates", + "iam:listSSHPublicKeys", + "iam:listUserPolicies", + "iam:listUsers", + "iam:listVirtualMFADevices", + "iam:simulateCustomPolicy", + "iam:simulatePrincipalPolicy", + "importexport:getStatus", + "importexport:listJobs", + "inspector:describeAssessmentRuns", + "inspector:describeAssessmentTargets", + "inspector:describeAssessmentTemplates", + "inspector:describeCrossAccountAccessRole", + "inspector:describeResourceGroups", + "inspector:describeRulesPackages", + "inspector:getTelemetryMetadata", + "inspector:listAssessmentRunAgents", + "inspector:listAssessmentRuns", + "inspector:listAssessmentTargets", + "inspector:listAssessmentTemplates", + "inspector:listEventSubscriptions", + "inspector:listRulesPackages", + "inspector:listTagsForResource", + "iot:describeAuthorizer", + "iot:describeCACertificate", + "iot:describeCertificate", + "iot:describeDefaultAuthorizer", + "iot:describeEndpoint", + "iot:describeIndex", + "iot:describeJobExecution", + "iot:describeThing", + "iot:describeThingGroup", + "iot:getEffectivePolicies", + "iot:getIndexingConfiguration", + "iot:getLoggingOptions", + "iot:getPolicy", + "iot:getPolicyVersion", + "iot:getTopicRule", + "iot:getV2LoggingOptions", + "iot:listAttachedPolicies", + "iot:listAuthorizers", + "iot:listCACertificates", + "iot:listCertificates", + "iot:listCertificatesByCA", + "iot:listJobExecutionsForJob", + "iot:listJobExecutionsForThing", + "iot:listJobs", + "iot:listOutgoingCertificates", + "iot:listPolicies", + "iot:listPolicyPrincipals", + "iot:listPolicyVersions", + "iot:listPrincipalPolicies", + "iot:listPrincipalThings", + "iot:listRoleAliases", + "iot:listTargetsForPolicy", + "iot:listThingGroups", + "iot:listThingGroupsForThing", + "iot:listThingPrincipals", + "iot:listThingRegistrationTasks", + "iot:listThings", + "iot:listThingTypes", + "iot:listTopicRules", + "iot:listV2LoggingLevels", + "kafka:describeCluster", + "kafka:getBootstrapBrokers", + "kafka:listClusters", + "kafka:listNodes", + "kinesis:describeStream", + "kinesis:listStreams", + "kinesis:listTagsForStream", + "kinesisanalytics:describeApplication", + "kinesisanalytics:listApplications", + "kms:describeKey", + "kms:getKeyPolicy", + "kms:getKeyRotationStatus", + "kms:listAliases", + "kms:listGrants", + "kms:listKeyPolicies", + "kms:listKeys", + "kms:listResourceTags", + "kms:listRetirableGrants", + "lambda:getAccountSettings", + "lambda:getAlias", + "lambda:getEventSourceMapping", + "lambda:getFunction", + "lambda:getFunctionConfiguration", + "lambda:getPolicy", + "lambda:listAliases", + "lambda:listEventSourceMappings", + "lambda:listFunctions", + "lambda:listVersionsByFunction", + "lex:getBot", + "lex:getBotAlias", + "lex:getBotAliases", + "lex:getBotChannelAssociation", + "lex:getBotChannelAssociations", + "lex:getBots", + "lex:getBotVersions", + "lex:getBuiltinIntent", + "lex:getBuiltinIntents", + "lex:getBuiltinSlotTypes", + "lex:getIntent", + "lex:getIntents", + "lex:getIntentVersions", + "lex:getSlotType", + "lex:getSlotTypes", + "lex:getSlotTypeVersions", + "lightsail:getActiveNames", + "lightsail:getBlueprints", + "lightsail:getBundles", + "lightsail:getDomain", + "lightsail:getDomains", + "lightsail:getInstance", + "lightsail:getInstanceAccessDetails", + "lightsail:getInstanceMetricData", + "lightsail:getInstancePortStates", + "lightsail:getInstances", + "lightsail:getInstanceSnapshot", + "lightsail:getInstanceSnapshots", + "lightsail:getInstanceState", + "lightsail:getKeyPair", + "lightsail:getKeyPairs", + "lightsail:getOperation", + "lightsail:getOperations", + "lightsail:getOperationsForResource", + "lightsail:getRegions", + "lightsail:getStaticIp", + "lightsail:getStaticIps", + "logs:describeDestinations", + "logs:describeExportTasks", + "logs:describeLogGroups", + "logs:describeLogStreams", + "logs:describeMetricFilters", + "logs:describeSubscriptionFilters", + "logs:testMetricFilter", + "machinelearning:describeBatchPredictions", + "machinelearning:describeDataSources", + "machinelearning:describeEvaluations", + "machinelearning:describeMLModels", + "machinelearning:getBatchPrediction", + "machinelearning:getDataSource", + "machinelearning:getEvaluation", + "machinelearning:getMLModel", + "mediaconvert:describeEndpoints", + "mediaconvert:getJob", + "mediaconvert:getJobTemplate", + "mediaconvert:getPreset", + "mediaconvert:getQueue", + "mediaconvert:listJobs", + "mediaconvert:listJobTemplates", + "medialive:describeChannel", + "medialive:describeInput", + "medialive:describeInputSecurityGroup", + "medialive:describeOffering", + "medialive:describeReservation", + "medialive:describeSchedule", + "medialive:listChannels", + "medialive:listInputs", + "medialive:listInputSecurityGroups", + "medialive:listOfferings", + "mediapackage:describeChannel", + "mediapackage:describeOriginEndpoint", + "mediapackage:listChannels", + "mediapackage:listOriginEndpoints", + "mediastore:describeContainer", + "mediastore:getContainerPolicy", + "mediastore:listContainers", + "mobiletargeting:getApnsChannel", + "mobiletargeting:getApplicationSettings", + "mobiletargeting:getCampaign", + "mobiletargeting:getCampaignActivities", + "mobiletargeting:getCampaigns", + "mobiletargeting:getCampaignVersion", + "mobiletargeting:getCampaignVersions", + "mobiletargeting:getEndpoint", + "mobiletargeting:getGcmChannel", + "mobiletargeting:getImportJob", + "mobiletargeting:getImportJobs", + "mobiletargeting:getSegment", + "mobiletargeting:getSegmentImportJobs", + "mobiletargeting:getSegments", + "mobiletargeting:getSegmentVersion", + "mobiletargeting:getSegmentVersions", + "mq:describeBroker", + "mq:describeConfiguration", + "mq:describeConfigurationRevision", + "mq:describeUser", + "mq:listBrokers", + "mq:listConfigurationRevisions", + "mq:listConfigurations", + "mq:listUsers", + "opsworks-cm:describeAccountAttributes", + "opsworks-cm:describeBackups", + "opsworks-cm:describeEvents", + "opsworks-cm:describeNodeAssociationStatus", + "opsworks-cm:describeServers", + "opsworks:describeAgentVersions", + "opsworks:describeApps", + "opsworks:describeCommands", + "opsworks:describeDeployments", + "opsworks:describeEcsClusters", + "opsworks:describeElasticIps", + "opsworks:describeElasticLoadBalancers", + "opsworks:describeInstances", + "opsworks:describeLayers", + "opsworks:describeLoadBasedAutoScaling", + "opsworks:describeMyUserProfile", + "opsworks:describePermissions", + "opsworks:describeRaidArrays", + "opsworks:describeRdsDbInstances", + "opsworks:describeServiceErrors", + "opsworks:describeStackProvisioningParameters", + "opsworks:describeStacks", + "opsworks:describeStackSummary", + "opsworks:describeTimeBasedAutoScaling", + "opsworks:describeUserProfiles", + "opsworks:describeVolumes", + "opsworks:getHostnameSuggestion", + "polly:describeVoices", + "polly:getLexicon", + "polly:listLexicons", + "rds:describeAccountAttributes", + "rds:describeCertificates", + "rds:describeDBClusterParameterGroups", + "rds:describeDBClusterParameters", + "rds:describeDBClusters", + "rds:describeDBClusterSnapshots", + "rds:describeDBEngineVersions", + "rds:describeDBInstances", + "rds:describeDBParameterGroups", + "rds:describeDBParameters", + "rds:describeDBSecurityGroups", + "rds:describeDBSnapshotAttributes", + "rds:describeDBSnapshots", + "rds:describeDBSubnetGroups", + "rds:describeEngineDefaultClusterParameters", + "rds:describeEngineDefaultParameters", + "rds:describeEventCategories", + "rds:describeEvents", + "rds:describeEventSubscriptions", + "rds:describeOptionGroupOptions", + "rds:describeOptionGroups", + "rds:describeOrderableDBInstanceOptions", + "rds:describePendingMaintenanceActions", + "rds:describeReservedDBInstances", + "rds:describeReservedDBInstancesOfferings", + "rds:listTagsForResource", + "redshift:describeClusterParameterGroups", + "redshift:describeClusterParameters", + "redshift:describeClusters", + "redshift:describeClusterSecurityGroups", + "redshift:describeClusterSnapshots", + "redshift:describeClusterSubnetGroups", + "redshift:describeClusterVersions", + "redshift:describeDefaultClusterParameters", + "redshift:describeEventCategories", + "redshift:describeEvents", + "redshift:describeEventSubscriptions", + "redshift:describeHsmClientCertificates", + "redshift:describeHsmConfigurations", + "redshift:describeLoggingStatus", + "redshift:describeOrderableClusterOptions", + "redshift:describeReservedNodeOfferings", + "redshift:describeReservedNodes", + "redshift:describeResize", + "redshift:describeSnapshotCopyGrants", + "redshift:describeTableRestoreStatus", + "redshift:describeTags", + "rekognition:listCollections", + "rekognition:listFaces", + "robomaker:describeDeploymentJob", + "robomaker:describeFleet", + "robomaker:describeRobotApplication", + "robomaker:describeSimulationApplication", + "robomaker:describeSimulationJob", + "robomaker:listDeploymentJobs", + "robomaker:listFleets", + "robomaker:listRobotApplications", + "robomaker:listRobots", + "robomaker:listSimulationApplications", + "robomaker:listSimulationJobs", + "route53:getChange", + "route53:getCheckerIpRanges", + "route53:getGeoLocation", + "route53:getHealthCheck", + "route53:getHealthCheckCount", + "route53:getHealthCheckLastFailureReason", + "route53:getHealthCheckStatus", + "route53:getHostedZone", + "route53:getHostedZoneCount", + "route53:getReusableDelegationSet", + "route53:getTrafficPolicy", + "route53:getTrafficPolicyInstance", + "route53:getTrafficPolicyInstanceCount", + "route53:listGeoLocations", + "route53:listHealthChecks", + "route53:listHostedZones", + "route53:listHostedZonesByName", + "route53:listResourceRecordSets", + "route53:listReusableDelegationSets", + "route53:listTagsForResource", + "route53:listTagsForResources", + "route53:listTrafficPolicies", + "route53:listTrafficPolicyInstances", + "route53:listTrafficPolicyInstancesByHostedZone", + "route53:listTrafficPolicyInstancesByPolicy", + "route53:listTrafficPolicyVersions", + "route53domains:checkDomainAvailability", + "route53domains:getContactReachabilityStatus", + "route53domains:getDomainDetail", + "route53domains:getOperationDetail", + "route53domains:listDomains", + "route53domains:listOperations", + "route53domains:listTagsForDomain", + "route53domains:viewBilling", + "route53resolver:getResolverRulePolicy", + "route53resolver:listResolverEndpointIpAddresses", + "route53resolver:listResolverEndpoints", + "route53resolver:listResolverRuleAssociations", + "route53resolver:listResolverRules", + "route53resolver:listTagsForResource", + "s3:getAccelerateConfiguration", + "s3:getAnalyticsConfiguration", + "s3:getBucketAcl", + "s3:getBucketCORS", + "s3:getBucketLocation", + "s3:getBucketLogging", + "s3:getBucketNotification", + "s3:getBucketPolicy", + "s3:getBucketRequestPayment", + "s3:getBucketTagging", + "s3:getBucketVersioning", + "s3:getBucketWebsite", + "s3:getEncryptionConfiguration", + "s3:getInventoryConfiguration", + "s3:getLifecycleConfiguration", + "s3:getMetricsConfiguration", + "s3:getReplicationConfiguration", + "s3:headBucket", + "s3:listAllMyBuckets", + "s3:listBucketMultipartUploads", + "sagemaker:describeEndpoint", + "sagemaker:describeEndpointConfig", + "sagemaker:describeHyperParameterTuningJob", + "sagemaker:describeModel", + "sagemaker:describeNotebookInstance", + "sagemaker:describeNotebookInstanceLifecycleConfig", + "sagemaker:describeTrainingJob", + "sagemaker:describeTransformJob", + "sagemaker:listEndpointConfigs", + "sagemaker:listEndpoints", + "sagemaker:listHyperParameterTuningJobs", + "sagemaker:listModels", + "sagemaker:listNotebookInstanceLifecycleConfigs", + "sagemaker:listNotebookInstances", + "sagemaker:listTags", + "sagemaker:listTrainingJobs", + "sagemaker:listTrainingJobsForHyperParameterTuningJob", + "sagemaker:listTransformJobs", + "sdb:domainMetadata", + "sdb:listDomains", + "secretsmanager:describeSecret", + "secretsmanager:getResourcePolicy", + "secretsmanager:listSecrets", + "secretsmanager:listSecretVersionIds", + "servicecatalog:describeConstraint", + "servicecatalog:describePortfolio", + "servicecatalog:describeProduct", + "servicecatalog:describeProductAsAdmin", + "servicecatalog:describeProductView", + "servicecatalog:describeProvisioningArtifact", + "servicecatalog:describeProvisioningParameters", + "servicecatalog:describeRecord", + "servicecatalog:listAcceptedPortfolioShares", + "servicecatalog:listConstraintsForPortfolio", + "servicecatalog:listLaunchPaths", + "servicecatalog:listPortfolioAccess", + "servicecatalog:listPortfolios", + "servicecatalog:listPortfoliosForProduct", + "servicecatalog:listPrincipalsForPortfolio", + "servicecatalog:listProvisioningArtifacts", + "servicecatalog:listRecordHistory", + "servicecatalog:scanProvisionedProducts", + "servicecatalog:searchProducts", + "ses:describeActiveReceiptRuleSet", + "ses:describeReceiptRule", + "ses:describeReceiptRuleSet", + "ses:getIdentityDkimAttributes", + "ses:getIdentityMailFromDomainAttributes", + "ses:getIdentityNotificationAttributes", + "ses:getIdentityPolicies", + "ses:getIdentityVerificationAttributes", + "ses:getSendQuota", + "ses:getSendStatistics", + "ses:listIdentities", + "ses:listIdentityPolicies", + "ses:listReceiptFilters", + "ses:listReceiptRuleSets", + "ses:listVerifiedEmailAddresses", + "shield:describeAttack", + "shield:describeProtection", + "shield:describeSubscription", + "shield:listAttacks", + "shield:listProtections", + "sms:getConnectors", + "sms:getReplicationJobs", + "sms:getReplicationRuns", + "sms:getServers", + "snowball:describeAddress", + "snowball:describeAddresses", + "snowball:describeJob", + "snowball:getSnowballUsage", + "snowball:listJobs", + "sns:checkIfPhoneNumberIsOptedOut", + "sns:getEndpointAttributes", + "sns:getPlatformApplicationAttributes", + "sns:getSMSAttributes", + "sns:getSubscriptionAttributes", + "sns:getTopicAttributes", + "sns:listEndpointsByPlatformApplication", + "sns:listPhoneNumbersOptedOut", + "sns:listPlatformApplications", + "sns:listSubscriptions", + "sns:listSubscriptionsByTopic", + "sns:listTopics", + "sqs:getQueueAttributes", + "sqs:getQueueUrl", + "sqs:listDeadLetterSourceQueues", + "sqs:listQueues", + "ssm:describeActivations", + "ssm:describeAssociation", + "ssm:describeAutomationExecutions", + "ssm:describeAvailablePatches", + "ssm:describeDocument", + "ssm:describeDocumentPermission", + "ssm:describeEffectiveInstanceAssociations", + "ssm:describeEffectivePatchesForPatchBaseline", + "ssm:describeInstanceAssociationsStatus", + "ssm:describeInstanceInformation", + "ssm:describeInstancePatches", + "ssm:describeInstancePatchStates", + "ssm:describeInstancePatchStatesForPatchGroup", + "ssm:describeMaintenanceWindowExecutions", + "ssm:describeMaintenanceWindowExecutionTaskInvocations", + "ssm:describeMaintenanceWindowExecutionTasks", + "ssm:describeMaintenanceWindows", + "ssm:describeMaintenanceWindowTargets", + "ssm:describeMaintenanceWindowTasks", + "ssm:describeParameters", + "ssm:describePatchBaselines", + "ssm:describePatchGroups", + "ssm:describePatchGroupState", + "ssm:getAutomationExecution", + "ssm:getCommandInvocation", + "ssm:getDefaultPatchBaseline", + "ssm:getDeployablePatchSnapshotForInstance", + "ssm:getDocument", + "ssm:getInventory", + "ssm:getInventorySchema", + "ssm:getMaintenanceWindow", + "ssm:getMaintenanceWindowExecution", + "ssm:getMaintenanceWindowExecutionTask", + "ssm:getParameterHistory", + "ssm:getParameters", + "ssm:getPatchBaseline", + "ssm:getPatchBaselineForPatchGroup", + "ssm:listAssociations", + "ssm:listCommandInvocations", + "ssm:listCommands", + "ssm:listDocuments", + "ssm:listDocumentVersions", + "ssm:listInventoryEntries", + "ssm:listTagsForResource", + "states:describeActivity", + "states:describeExecution", + "states:describeStateMachine", + "states:getExecutionHistory", + "states:listActivities", + "states:listExecutions", + "states:listStateMachines", + "storagegateway:describeBandwidthRateLimit", + "storagegateway:describeCache", + "storagegateway:describeCachediSCSIVolumes", + "storagegateway:describeGatewayInformation", + "storagegateway:describeMaintenanceStartTime", + "storagegateway:describeNFSFileShares", + "storagegateway:describeSMBFileShares", + "storagegateway:describeSMBSettings", + "storagegateway:describeSnapshotSchedule", + "storagegateway:describeStorediSCSIVolumes", + "storagegateway:describeTapeArchives", + "storagegateway:describeTapeRecoveryPoints", + "storagegateway:describeTapes", + "storagegateway:describeUploadBuffer", + "storagegateway:describeVTLDevices", + "storagegateway:describeWorkingStorage", + "storagegateway:listFileShares", + "storagegateway:listGateways", + "storagegateway:listLocalDisks", + "storagegateway:listTagsForResource", + "storagegateway:listTapes", + "storagegateway:listVolumeInitiators", + "storagegateway:listVolumeRecoveryPoints", + "storagegateway:listVolumes", + "swf:describeActivityType", + "swf:describeDomain", + "swf:describeWorkflowExecution", + "swf:describeWorkflowType", + "swf:getWorkflowExecutionHistory", + "swf:listActivityTypes", + "swf:listClosedWorkflowExecutions", + "swf:listDomains", + "swf:listOpenWorkflowExecutions", + "swf:listWorkflowTypes", + "transfer:describeServer", + "transfer:describeUser", + "transfer:listServers", + "transfer:listTagsForResource", + "transfer:listUsers", + "waf-regional:getByteMatchSet", + "waf-regional:getChangeTokenStatus", + "waf-regional:getIPSet", + "waf-regional:getRule", + "waf-regional:getSqlInjectionMatchSet", + "waf-regional:getWebACL", + "waf-regional:getWebACLForResource", + "waf-regional:listByteMatchSets", + "waf-regional:listIPSets", + "waf-regional:listResourcesForWebACL", + "waf-regional:listRules", + "waf-regional:listSqlInjectionMatchSets", + "waf-regional:listWebACLs", + "waf:getByteMatchSet", + "waf:getChangeTokenStatus", + "waf:getIPSet", + "waf:getRule", + "waf:getSampledRequests", + "waf:getSizeConstraintSet", + "waf:getSqlInjectionMatchSet", + "waf:getWebACL", + "waf:getXssMatchSet", + "waf:listByteMatchSets", + "waf:listIPSets", + "waf:listRules", + "waf:listSizeConstraintSets", + "waf:listSqlInjectionMatchSets", + "waf:listWebACLs", + "waf:listXssMatchSets", + "workdocs:checkAlias", + "workdocs:describeAvailableDirectories", + "workdocs:describeInstances", + "workspaces:describeTags", + "workspaces:describeWorkspaceBundles", + "workspaces:describeWorkspaceDirectories", + "workspaces:describeWorkspaces", + "workspaces:describeWorkspacesConnectionStatus" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": false, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7W6266ELXF5MISDS", + "PolicyName": "AWSSupportServiceRolePolicy", + "UpdateDate": "2019-02-06T18:06:11+00:00", + "VersionId": "v4" + }, + "AWSTransferLoggingAccess": { + "Arn": "arn:aws:iam::aws:policy/service-role/AWSTransferLoggingAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-14T15:32:50+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:CreateLogGroup", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAISIP5WGJX7VKXRQZO", + "PolicyName": "AWSTransferLoggingAccess", + "UpdateDate": "2019-01-14T15:32:50+00:00", + "VersionId": "v1" + }, + "AWSTrustedAdvisorServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSTrustedAdvisorServiceRolePolicy", + "AttachmentCount": 1, + "CreateDate": "2018-02-22T21:24:25+00:00", + "DefaultVersionId": "v5", + "Document": { + "Statement": [ + { + "Action": [ + "autoscaling:DescribeAccountLimits", + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:DescribeLaunchConfigurations", + "cloudformation:DescribeAccountLimits", + "cloudformation:DescribeStacks", + "cloudformation:ListStacks", + "cloudfront:ListDistributions", + "cloudtrail:DescribeTrails", + "cloudtrail:GetTrailStatus", + "dynamodb:DescribeLimits", + "dynamodb:DescribeTable", + "dynamodb:ListTables", + "ec2:DescribeAddresses", + "ec2:DescribeReservedInstances", + "ec2:DescribeInstances", + "ec2:DescribeVpcs", + "ec2:DescribeInternetGateways", + "ec2:DescribeImages", + "ec2:DescribeVolumes", + "ec2:DescribeSecurityGroups", + "ec2:DescribeReservedInstancesOfferings", + "ec2:DescribeSnapshots", + "ec2:DescribeVpnConnections", + "ec2:DescribeVpnGateways", + "ec2:DescribeLaunchTemplateVersions", + "elasticloadbalancing:DescribeInstanceHealth", + "elasticloadbalancing:DescribeLoadBalancerAttributes", + "elasticloadbalancing:DescribeLoadBalancerPolicies", + "elasticloadbalancing:DescribeLoadBalancerPolicyTypes", + "elasticloadbalancing:DescribeLoadBalancers", + "iam:GenerateCredentialReport", + "iam:GetAccountPasswordPolicy", + "iam:GetAccountSummary", + "iam:GetCredentialReport", + "iam:GetServerCertificate", + "iam:ListServerCertificates", + "kinesis:DescribeLimits", + "rds:DescribeAccountAttributes", + "rds:DescribeDBClusters", + "rds:DescribeDBEngineVersions", + "rds:DescribeDBInstances", + "rds:DescribeDBParameterGroups", + "rds:DescribeDBParameters", + "rds:DescribeDBSecurityGroups", + "rds:DescribeDBSnapshots", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEngineDefaultParameters", + "rds:DescribeEvents", + "rds:DescribeOptionGroupOptions", + "rds:DescribeOptionGroups", + "rds:DescribeOrderableDBInstanceOptions", + "rds:DescribeReservedDBInstances", + "rds:DescribeReservedDBInstancesOfferings", + "rds:ListTagsForResource", + "redshift:DescribeClusters", + "redshift:DescribeReservedNodeOfferings", + "redshift:DescribeReservedNodes", + "route53:GetAccountLimit", + "route53:GetHealthCheck", + "route53:GetHostedZone", + "route53:ListHealthChecks", + "route53:ListHostedZones", + "route53:ListHostedZonesByName", + "route53:ListResourceRecordSets", + "s3:GetBucketAcl", + "s3:GetBucketPolicy", + "s3:GetBucketPolicyStatus", + "s3:GetBucketLocation", + "s3:GetBucketLogging", + "s3:GetBucketVersioning", + "s3:GetBucketPublicAccessBlock", + "s3:ListBucket", + "s3:ListObjects", + "s3:ListAllMyBuckets", + "ses:GetSendQuota", + "sqs:ListQueues", + "cloudwatch:GetMetricStatistics" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJH4QJ2WMHBOB47BUE", + "PolicyName": "AWSTrustedAdvisorServiceRolePolicy", + "UpdateDate": "2019-01-22T19:58:36+00:00", + "VersionId": "v5" + }, + "AWSVPCTransitGatewayServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AWSVPCTransitGatewayServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T16:21:17+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DeleteNetworkInterface", + "ec2:CreateNetworkInterfacePermission" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "0" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJS2PBJSYV2EZW3MIQ", + "PolicyName": "AWSVPCTransitGatewayServiceRolePolicy", + "UpdateDate": "2018-11-26T16:21:17+00:00", + "VersionId": "v1" + }, "AWSWAFFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSWAFFullAccess", "AttachmentCount": 0, - "CreateDate": "2016-12-07T21:33:25+00:00", + "CreateDate": "2015-10-06T20:44:00+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -5364,6 +13684,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJMIKIAFXZEGOLRH7C", "PolicyName": "AWSWAFFullAccess", "UpdateDate": "2016-12-07T21:33:25+00:00", @@ -5372,7 +13693,7 @@ aws_managed_policies_data = """ "AWSWAFReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSWAFReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-12-07T21:30:54+00:00", + "CreateDate": "2015-10-06T20:43:45+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -5392,11 +13713,44 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAINZVDMX2SBF7EU2OC", "PolicyName": "AWSWAFReadOnlyAccess", "UpdateDate": "2016-12-07T21:30:54+00:00", "VersionId": "v2" }, + "AWSXRayDaemonWriteAccess": { + "Arn": "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess", + "AttachmentCount": 0, + "CreateDate": "2018-08-28T23:00:33+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "xray:PutTraceSegments", + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + "xray:GetSamplingStatisticSummaries" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIOE47HSUE5AVBNEDM", + "PolicyName": "AWSXRayDaemonWriteAccess", + "UpdateDate": "2018-08-28T23:00:33+00:00", + "VersionId": "v1" + }, "AWSXrayFullAccess": { "Arn": "arn:aws:iam::aws:policy/AWSXrayFullAccess", "AttachmentCount": 0, @@ -5419,6 +13773,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJQBYG45NSJMVQDB2K", "PolicyName": "AWSXrayFullAccess", "UpdateDate": "2016-12-01T18:30:55+00:00", @@ -5428,15 +13783,21 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AWSXrayReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2016-12-01T18:27:02+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v4", "Document": { "Statement": [ { "Action": [ + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + "xray:GetSamplingStatisticSummaries", "xray:BatchGetTraces", "xray:GetServiceGraph", "xray:GetTraceGraph", - "xray:GetTraceSummaries" + "xray:GetTraceSummaries", + "xray:GetGroups", + "xray:GetGroup", + "xray:GetTimeSeriesServiceStatistics" ], "Effect": "Allow", "Resource": [ @@ -5449,22 +13810,26 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIH4OFXWPS6ZX6OPGQ", "PolicyName": "AWSXrayReadOnlyAccess", - "UpdateDate": "2016-12-01T18:27:02+00:00", - "VersionId": "v1" + "UpdateDate": "2019-04-30T18:11:46+00:00", + "VersionId": "v4" }, "AWSXrayWriteOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess", "AttachmentCount": 0, "CreateDate": "2016-12-01T18:19:53+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ "xray:PutTraceSegments", - "xray:PutTelemetryRecords" + "xray:PutTelemetryRecords", + "xray:GetSamplingRules", + "xray:GetSamplingTargets", + "xray:GetSamplingStatisticSummaries" ], "Effect": "Allow", "Resource": [ @@ -5477,14 +13842,15 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIAACM4LMYSRGBCTM6", "PolicyName": "AWSXrayWriteOnlyAccess", - "UpdateDate": "2016-12-01T18:19:53+00:00", - "VersionId": "v1" + "UpdateDate": "2018-08-28T23:03:04+00:00", + "VersionId": "v2" }, "AdministratorAccess": { "Arn": "arn:aws:iam::aws:policy/AdministratorAccess", - "AttachmentCount": 3, + "AttachmentCount": 1, "CreateDate": "2015-02-06T18:39:46+00:00", "DefaultVersionId": "v1", "Document": { @@ -5500,14 +13866,242 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIWMBCKSKIEE64ZLYK", "PolicyName": "AdministratorAccess", "UpdateDate": "2015-02-06T18:39:46+00:00", "VersionId": "v1" }, + "AlexaForBusinessDeviceSetup": { + "Arn": "arn:aws:iam::aws:policy/AlexaForBusinessDeviceSetup", + "AttachmentCount": 0, + "CreateDate": "2017-11-30T16:47:16+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "a4b:RegisterDevice", + "a4b:CompleteRegistration", + "a4b:SearchDevices", + "a4b:SearchNetworkProfiles", + "a4b:GetNetworkProfile", + "a4b:PutDeviceSetupEvents" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "secretsmanager:GetSecretValue" + ], + "Effect": "Allow", + "Resource": "arn:aws:secretsmanager:*:*:secret:A4BNetworkProfile*", + "Sid": "A4bDeviceSetupAccess" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIUEFZFUTDTY4HGFU2", + "PolicyName": "AlexaForBusinessDeviceSetup", + "UpdateDate": "2019-05-20T21:05:39+00:00", + "VersionId": "v2" + }, + "AlexaForBusinessFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AlexaForBusinessFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-30T16:47:09+00:00", + "DefaultVersionId": "v4", + "Document": { + "Statement": [ + { + "Action": [ + "a4b:*", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "*a4b.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/*a4b.amazonaws.com/AWSServiceRoleForAlexaForBusiness*" + }, + { + "Action": [ + "secretsmanager:GetSecretValue", + "secretsmanager:DeleteSecret", + "secretsmanager:UpdateSecret" + ], + "Effect": "Allow", + "Resource": "arn:aws:secretsmanager:*:*:secret:A4BNetworkProfile*" + }, + { + "Action": "secretsmanager:CreateSecret", + "Condition": { + "StringLike": { + "secretsmanager:Name": "A4BNetworkProfile*" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAILUT3JGG7WRIMVNH2", + "PolicyName": "AlexaForBusinessFullAccess", + "UpdateDate": "2019-05-20T21:32:33+00:00", + "VersionId": "v4" + }, + "AlexaForBusinessGatewayExecution": { + "Arn": "arn:aws:iam::aws:policy/AlexaForBusinessGatewayExecution", + "AttachmentCount": 0, + "CreateDate": "2017-11-30T16:47:19+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "a4b:Send*", + "a4b:Get*" + ], + "Effect": "Allow", + "Resource": "arn:aws:a4b:*:*:gateway/*" + }, + { + "Action": [ + "sqs:ReceiveMessage", + "sqs:DeleteMessage" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:sqs:*:*:dd-*", + "arn:aws:sqs:*:*:sd-*" + ] + }, + { + "Action": [ + "a4b:List*", + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:DescribeLogGroups", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI3LZ7YP7KHLG4DT2Q", + "PolicyName": "AlexaForBusinessGatewayExecution", + "UpdateDate": "2017-11-30T16:47:19+00:00", + "VersionId": "v1" + }, + "AlexaForBusinessNetworkProfileServicePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AlexaForBusinessNetworkProfileServicePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-03-13T00:53:40+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "acm-pca:GetCertificate", + "acm-pca:IssueCertificate", + "acm-pca:RevokeCertificate" + ], + "Condition": { + "StringEquals": { + "aws:ResourceTag/a4b": "enabled" + } + }, + "Effect": "Allow", + "Resource": "*", + "Sid": "A4bPcaTagAccess" + }, + { + "Action": [ + "secretsmanager:GetSecretValue" + ], + "Effect": "Allow", + "Resource": "arn:aws:secretsmanager:*:*:secret:A4BNetworkProfile*", + "Sid": "A4bNetworkProfileAccess" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI7GYBNGIZU2EDSMGQ", + "PolicyName": "AlexaForBusinessNetworkProfileServicePolicy", + "UpdateDate": "2019-04-05T21:57:56+00:00", + "VersionId": "v2" + }, + "AlexaForBusinessReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AlexaForBusinessReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-30T16:47:12+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "a4b:Get*", + "a4b:List*", + "a4b:Describe*", + "a4b:Search*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI6BKSTB4XMLPBFFJ2", + "PolicyName": "AlexaForBusinessReadOnlyAccess", + "UpdateDate": "2018-06-25T23:52:33+00:00", + "VersionId": "v2" + }, "AmazonAPIGatewayAdministrator": { "Arn": "arn:aws:iam::aws:policy/AmazonAPIGatewayAdministrator", - "AttachmentCount": 0, + "AttachmentCount": 1, "CreateDate": "2015-07-09T17:34:45+00:00", "DefaultVersionId": "v1", "Document": { @@ -5525,6 +14119,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ4PT6VY5NLKTNUYSI", "PolicyName": "AmazonAPIGatewayAdministrator", "UpdateDate": "2015-07-09T17:34:45+00:00", @@ -5534,12 +14129,13 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AmazonAPIGatewayInvokeFullAccess", "AttachmentCount": 0, "CreateDate": "2015-07-09T17:36:12+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ - "execute-api:Invoke" + "execute-api:Invoke", + "execute-api:ManageConnections" ], "Effect": "Allow", "Resource": "arn:aws:execute-api:*:*:*" @@ -5550,14 +14146,15 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIIWAX2NOOQJ4AIEQ6", "PolicyName": "AmazonAPIGatewayInvokeFullAccess", - "UpdateDate": "2015-07-09T17:36:12+00:00", - "VersionId": "v1" + "UpdateDate": "2018-12-18T18:25:10+00:00", + "VersionId": "v2" }, "AmazonAPIGatewayPushToCloudWatchLogs": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs", - "AttachmentCount": 0, + "AttachmentCount": 1, "CreateDate": "2015-11-11T23:41:46+00:00", "DefaultVersionId": "v1", "Document": { @@ -5581,6 +14178,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIK4GFO7HLKYN64ASK", "PolicyName": "AmazonAPIGatewayPushToCloudWatchLogs", "UpdateDate": "2015-11-11T23:41:46+00:00", @@ -5589,8 +14187,8 @@ aws_managed_policies_data = """ "AmazonAppStreamFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonAppStreamFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-09-07T23:56:23+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2015-02-06T18:40:09+00:00", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -5645,6 +14243,16 @@ aws_managed_policies_data = """ }, "Effect": "Allow", "Resource": "arn:aws:iam::*:role/service-role/ApplicationAutoScalingForAmazonAppStreamAccess" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "appstream.application-autoscaling.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/appstream.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_AppStreamFleet" } ], "Version": "2012-10-17" @@ -5652,15 +14260,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJLZZXU2YQVGL4QDNC", "PolicyName": "AmazonAppStreamFullAccess", - "UpdateDate": "2017-09-07T23:56:23+00:00", - "VersionId": "v2" + "UpdateDate": "2018-09-10T17:29:25+00:00", + "VersionId": "v3" }, "AmazonAppStreamReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonAppStreamReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-12-07T21:00:06+00:00", + "CreateDate": "2015-02-06T18:40:10+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -5679,6 +14288,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJXIFDGB4VBX23DX7K", "PolicyName": "AmazonAppStreamReadOnlyAccess", "UpdateDate": "2016-12-07T21:00:06+00:00", @@ -5687,8 +14297,8 @@ aws_managed_policies_data = """ "AmazonAppStreamServiceAccess": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonAppStreamServiceAccess", "AttachmentCount": 0, - "CreateDate": "2017-05-23T23:00:47+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2016-11-19T04:17:37+00:00", + "DefaultVersionId": "v5", "Document": { "Statement": [ { @@ -5703,7 +14313,8 @@ aws_managed_policies_data = """ "ec2:AssociateAddress", "ec2:DisassociateAddress", "ec2:DescribeRouteTables", - "ec2:DescribeSecurityGroups" + "ec2:DescribeSecurityGroups", + "s3:ListAllMyBuckets" ], "Effect": "Allow", "Resource": "*" @@ -5717,10 +14328,15 @@ aws_managed_policies_data = """ "s3:DeleteObject", "s3:GetObjectVersion", "s3:DeleteObjectVersion", - "s3:PutBucketPolicy" + "s3:PutBucketPolicy", + "s3:PutEncryptionConfiguration" ], "Effect": "Allow", - "Resource": "arn:aws:s3:::appstream2-36fb080bb8-*" + "Resource": [ + "arn:aws:s3:::appstream2-36fb080bb8-*", + "arn:aws:s3:::appstream-app-settings-*", + "arn:aws:s3:::appstream-logs-*" + ] } ], "Version": "2012-10-17" @@ -5728,16 +14344,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAISBRZ7LMMCBYEF3SE", "PolicyName": "AmazonAppStreamServiceAccess", - "UpdateDate": "2017-05-23T23:00:47+00:00", - "VersionId": "v3" + "UpdateDate": "2019-01-17T20:22:45+00:00", + "VersionId": "v5" }, "AmazonAthenaFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonAthenaFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-09-13T00:13:48+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2016-11-30T16:46:01+00:00", + "DefaultVersionId": "v5", "Document": { "Statement": [ { @@ -5794,12 +14411,45 @@ aws_managed_policies_data = """ }, { "Action": [ - "s3:GetObject" + "s3:GetObject", + "s3:ListBucket" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::athena-examples*" ] + }, + { + "Action": [ + "s3:ListBucket", + "s3:GetBucketLocation", + "s3:ListAllMyBuckets" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "sns:ListTopics", + "sns:GetTopicAttributes" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] } ], "Version": "2012-10-17" @@ -5807,10 +14457,156 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIPJMLMD4C7RYZ6XCK", "PolicyName": "AmazonAthenaFullAccess", - "UpdateDate": "2017-09-13T00:13:48+00:00", - "VersionId": "v3" + "UpdateDate": "2019-02-19T00:13:03+00:00", + "VersionId": "v5" + }, + "AmazonChimeFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonChimeFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-01T22:15:43+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "chime:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIUJFSAKUERNORYRWO", + "PolicyName": "AmazonChimeFullAccess", + "UpdateDate": "2017-11-01T22:15:43+00:00", + "VersionId": "v1" + }, + "AmazonChimeReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AmazonChimeReadOnly", + "AttachmentCount": 0, + "CreateDate": "2017-11-01T22:04:17+00:00", + "DefaultVersionId": "v6", + "Document": { + "Statement": [ + { + "Action": [ + "chime:ListAccounts", + "chime:GetAccount", + "chime:GetAccountSettings", + "chime:ListUsers", + "chime:GetUser", + "chime:GetUserByEmail", + "chime:ListDomains", + "chime:GetDomain", + "chime:ListGroups", + "chime:ListDirectories", + "chime:ListCDRBucket", + "chime:GetCDRBucket", + "chime:ListDelegates", + "chime:GetAccountResource", + "chime:ValidateDelegate", + "chime:ListAccountUsageReportData", + "chime:GetUserActivityReportData", + "chime:GetGlobalSettings", + "chime:GetPhoneNumber", + "chime:GetPhoneNumberOrder", + "chime:GetUserSettings", + "chime:GetVoiceConnector", + "chime:GetVoiceConnectorOrigination", + "chime:GetVoiceConnectorTermination", + "chime:GetVoiceConnectorTerminationHealth", + "chime:ListPhoneNumberOrders", + "chime:ListPhoneNumbers", + "chime:ListVoiceConnectorTerminationCredentials", + "chime:ListVoiceConnectors", + "chime:SearchAvailablePhoneNumbers", + "chime:GetTelephonyLimits", + "chime:ListCallingRegions", + "chime:GetBot", + "chime:ListBots", + "chime:GetEventsConfiguration" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJLBFZZFABRXVWRTCI", + "PolicyName": "AmazonChimeReadOnly", + "UpdateDate": "2019-05-13T20:34:08+00:00", + "VersionId": "v6" + }, + "AmazonChimeUserManagement": { + "Arn": "arn:aws:iam::aws:policy/AmazonChimeUserManagement", + "AttachmentCount": 0, + "CreateDate": "2017-11-01T22:17:26+00:00", + "DefaultVersionId": "v6", + "Document": { + "Statement": [ + { + "Action": [ + "chime:ListAccounts", + "chime:GetAccount", + "chime:GetAccountSettings", + "chime:UpdateAccountSettings", + "chime:ListUsers", + "chime:GetUser", + "chime:GetUserByEmail", + "chime:InviteUsers", + "chime:SuspendUsers", + "chime:ActivateUsers", + "chime:UpdateUserLicenses", + "chime:ResetPersonalPIN", + "chime:LogoutUser", + "chime:ListDomains", + "chime:GetDomain", + "chime:ListDirectories", + "chime:ListGroups", + "chime:SubmitSupportRequest", + "chime:ListDelegates", + "chime:ListAccountUsageReportData", + "chime:GetMeetingDetail", + "chime:ListMeetingEvents", + "chime:ListMeetingsReportData", + "chime:GetUserActivityReportData", + "chime:UpdateUser", + "chime:BatchUpdateUser", + "chime:BatchSuspendUser", + "chime:BatchUnsuspendUser", + "chime:AssociatePhoneNumberWithUser", + "chime:DisassociatePhoneNumberFromUser", + "chime:GetPhoneNumber", + "chime:ListPhoneNumbers", + "chime:GetUserSettings", + "chime:UpdateUserSettings" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJGLHVUHNMQPSDGSOO", + "PolicyName": "AmazonChimeUserManagement", + "UpdateDate": "2019-03-18T12:17:58+00:00", + "VersionId": "v6" }, "AmazonCloudDirectoryFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonCloudDirectoryFullAccess", @@ -5834,6 +14630,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJG3XQK77ATFLCF2CK", "PolicyName": "AmazonCloudDirectoryFullAccess", "UpdateDate": "2017-02-25T00:41:39+00:00", @@ -5864,6 +14661,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAICMSZQGR3O62KMD6M", "PolicyName": "AmazonCloudDirectoryReadOnlyAccess", "UpdateDate": "2017-02-28T23:42:06+00:00", @@ -5892,16 +14690,51 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIQOKZ5BGKLCMTXH4W", "PolicyName": "AmazonCognitoDeveloperAuthenticatedIdentities", "UpdateDate": "2015-03-24T17:22:23+00:00", "VersionId": "v1" }, + "AmazonCognitoIdpEmailServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonCognitoIdpEmailServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-03-21T21:32:25+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ses:SendEmail", + "ses:SendRawEmail" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ses:List*" + ], + "Effect": "Deny", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIX7PW362PLAQFKBHM", + "PolicyName": "AmazonCognitoIdpEmailServiceRolePolicy", + "UpdateDate": "2019-03-21T21:32:25+00:00", + "VersionId": "v1" + }, "AmazonCognitoPowerUser": { "Arn": "arn:aws:iam::aws:policy/AmazonCognitoPowerUser", "AttachmentCount": 0, - "CreateDate": "2016-06-02T16:57:56+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2015-03-24T17:14:56+00:00", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -5915,6 +14748,24 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "email.cognito-idp.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/email.cognito-idp.amazonaws.com/AWSServiceRoleForAmazonCognitoIdpEmail*" } ], "Version": "2012-10-17" @@ -5922,16 +14773,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJKW5H2HNCPGCYGR6Y", "PolicyName": "AmazonCognitoPowerUser", - "UpdateDate": "2016-06-02T16:57:56+00:00", - "VersionId": "v2" + "UpdateDate": "2019-03-29T22:06:46+00:00", + "VersionId": "v3" }, "AmazonCognitoReadOnly": { "Arn": "arn:aws:iam::aws:policy/AmazonCognitoReadOnly", "AttachmentCount": 0, - "CreateDate": "2016-06-02T17:30:24+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2015-03-24T17:06:46+00:00", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -5941,6 +14793,7 @@ aws_managed_policies_data = """ "cognito-identity:List*", "cognito-idp:Describe*", "cognito-idp:AdminGetUser", + "cognito-idp:AdminList*", "cognito-idp:List*", "cognito-sync:Describe*", "cognito-sync:Get*", @@ -5958,9 +14811,141 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJBFTRZD2GQGJHSVQK", "PolicyName": "AmazonCognitoReadOnly", - "UpdateDate": "2016-06-02T17:30:24+00:00", + "UpdateDate": "2019-02-16T00:18:11+00:00", + "VersionId": "v3" + }, + "AmazonConnectFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonConnectFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-10-17T20:59:39+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "connect:*", + "ds:CreateAlias", + "ds:AuthorizeApplication", + "ds:CreateIdentityPoolDirectory", + "ds:DeleteDirectory", + "ds:DescribeDirectories", + "ds:UnauthorizeApplication", + "firehose:DescribeDeliveryStream", + "firehose:ListDeliveryStreams", + "kinesis:DescribeStream", + "kinesis:ListStreams", + "kms:DescribeKey", + "kms:CreateGrant", + "kms:ListAliases", + "lex:GetBots", + "logs:CreateLogGroup", + "s3:CreateBucket", + "s3:GetBucketLocation", + "s3:ListAllMyBuckets" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "connect.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:PutRolePolicy" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/connect.amazonaws.com/AWSServiceRoleForAmazonConnect*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIPZZCFFD55NYGBAJI", + "PolicyName": "AmazonConnectFullAccess", + "UpdateDate": "2018-10-17T22:28:01+00:00", + "VersionId": "v2" + }, + "AmazonConnectReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonConnectReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-10-17T21:00:44+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "connect:Get*", + "connect:Describe*", + "connect:List*", + "ds:DescribeDirectories" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "connect:GetFederationTokens", + "Effect": "Deny", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIVZMH7VU6YYKRY6ZU", + "PolicyName": "AmazonConnectReadOnlyAccess", + "UpdateDate": "2018-10-17T21:00:44+00:00", + "VersionId": "v1" + }, + "AmazonConnectServiceLinkedRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonConnectServiceLinkedRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-09-07T00:21:43+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "connect:*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "iam:DeleteRole" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/connect.amazonaws.com/AWSServiceRoleForAmazonConnect_*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ6R6FMTSRUJSKI72Y", + "PolicyName": "AmazonConnectServiceLinkedRolePolicy", + "UpdateDate": "2018-09-25T21:29:18+00:00", "VersionId": "v2" }, "AmazonDMSCloudWatchLogsRole": { @@ -6026,6 +15011,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJBG7UXZZXUJD3TDJE", "PolicyName": "AmazonDMSCloudWatchLogsRole", "UpdateDate": "2016-01-07T23:44:53+00:00", @@ -6061,6 +15047,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI3CCUQ4U5WNC5F6B6", "PolicyName": "AmazonDMSRedshiftS3Role", "UpdateDate": "2016-04-20T17:05:56+00:00", @@ -6069,7 +15056,7 @@ aws_managed_policies_data = """ "AmazonDMSVPCManagementRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole", "AttachmentCount": 0, - "CreateDate": "2016-05-23T16:29:57+00:00", + "CreateDate": "2015-11-18T16:33:19+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -6093,6 +15080,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJHKIGMBQI4AEFFSYO", "PolicyName": "AmazonDMSVPCManagementRole", "UpdateDate": "2016-05-23T16:29:57+00:00", @@ -6130,16 +15118,394 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJPXIBTTZMBEFEX6UA", "PolicyName": "AmazonDRSVPCManagement", "UpdateDate": "2015-09-02T00:09:20+00:00", "VersionId": "v1" }, + "AmazonDocDBConsoleFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonDocDBConsoleFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-09T20:37:28+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "rds:AddRoleToDBCluster", + "rds:AddSourceIdentifierToSubscription", + "rds:AddTagsToResource", + "rds:ApplyPendingMaintenanceAction", + "rds:CopyDBClusterParameterGroup", + "rds:CopyDBClusterSnapshot", + "rds:CopyDBParameterGroup", + "rds:CreateDBCluster", + "rds:CreateDBClusterParameterGroup", + "rds:CreateDBClusterSnapshot", + "rds:CreateDBInstance", + "rds:CreateDBParameterGroup", + "rds:CreateDBSubnetGroup", + "rds:CreateEventSubscription", + "rds:DeleteDBCluster", + "rds:DeleteDBClusterParameterGroup", + "rds:DeleteDBClusterSnapshot", + "rds:DeleteDBInstance", + "rds:DeleteDBParameterGroup", + "rds:DeleteDBSubnetGroup", + "rds:DeleteEventSubscription", + "rds:DescribeAccountAttributes", + "rds:DescribeCertificates", + "rds:DescribeDBClusterParameterGroups", + "rds:DescribeDBClusterParameters", + "rds:DescribeDBClusterSnapshotAttributes", + "rds:DescribeDBClusterSnapshots", + "rds:DescribeDBClusters", + "rds:DescribeDBEngineVersions", + "rds:DescribeDBInstances", + "rds:DescribeDBLogFiles", + "rds:DescribeDBParameterGroups", + "rds:DescribeDBParameters", + "rds:DescribeDBSecurityGroups", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEngineDefaultClusterParameters", + "rds:DescribeEngineDefaultParameters", + "rds:DescribeEventCategories", + "rds:DescribeEventSubscriptions", + "rds:DescribeEvents", + "rds:DescribeOptionGroups", + "rds:DescribeOrderableDBInstanceOptions", + "rds:DescribePendingMaintenanceActions", + "rds:DescribeValidDBInstanceModifications", + "rds:DownloadDBLogFilePortion", + "rds:FailoverDBCluster", + "rds:ListTagsForResource", + "rds:ModifyDBCluster", + "rds:ModifyDBClusterParameterGroup", + "rds:ModifyDBClusterSnapshotAttribute", + "rds:ModifyDBInstance", + "rds:ModifyDBParameterGroup", + "rds:ModifyDBSubnetGroup", + "rds:ModifyEventSubscription", + "rds:PromoteReadReplicaDBCluster", + "rds:RebootDBInstance", + "rds:RemoveRoleFromDBCluster", + "rds:RemoveSourceIdentifierFromSubscription", + "rds:RemoveTagsFromResource", + "rds:ResetDBClusterParameterGroup", + "rds:ResetDBParameterGroup", + "rds:RestoreDBClusterFromSnapshot", + "rds:RestoreDBClusterToPointInTime" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "iam:GetRole", + "cloudwatch:GetMetricData", + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics", + "ec2:AllocateAddress", + "ec2:AssignIpv6Addresses", + "ec2:AssignPrivateIpAddresses", + "ec2:AssociateAddress", + "ec2:AssociateRouteTable", + "ec2:AssociateSubnetCidrBlock", + "ec2:AssociateVpcCidrBlock", + "ec2:AttachInternetGateway", + "ec2:AttachNetworkInterface", + "ec2:CreateCustomerGateway", + "ec2:CreateDefaultSubnet", + "ec2:CreateDefaultVpc", + "ec2:CreateInternetGateway", + "ec2:CreateNatGateway", + "ec2:CreateNetworkInterface", + "ec2:CreateRoute", + "ec2:CreateRouteTable", + "ec2:CreateSecurityGroup", + "ec2:CreateSubnet", + "ec2:CreateVpc", + "ec2:CreateVpcEndpoint", + "ec2:DescribeAccountAttributes", + "ec2:DescribeAddresses", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeCustomerGateways", + "ec2:DescribeInstances", + "ec2:DescribeNatGateways", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribePrefixLists", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroupReferences", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:ModifySubnetAttribute", + "ec2:ModifyVpcAttribute", + "ec2:ModifyVpcEndpoint", + "kms:DescribeKey", + "kms:ListAliases", + "kms:ListKeyPolicies", + "kms:ListKeys", + "kms:ListKeysForService", + "kms:ListRetirableGrants", + "logs:DescribeLogStreams", + "logs:GetLogEvents", + "sns:ListSubscriptions", + "sns:ListTopics", + "sns:Publish" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "rds.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJHV6VMSNDDHJ3ESNI", + "PolicyName": "AmazonDocDBConsoleFullAccess", + "UpdateDate": "2019-01-09T20:37:28+00:00", + "VersionId": "v1" + }, + "AmazonDocDBFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonDocDBFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-09T20:21:44+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "rds:AddRoleToDBCluster", + "rds:AddSourceIdentifierToSubscription", + "rds:AddTagsToResource", + "rds:ApplyPendingMaintenanceAction", + "rds:CopyDBClusterParameterGroup", + "rds:CopyDBClusterSnapshot", + "rds:CopyDBParameterGroup", + "rds:CreateDBCluster", + "rds:CreateDBClusterParameterGroup", + "rds:CreateDBClusterSnapshot", + "rds:CreateDBInstance", + "rds:CreateDBParameterGroup", + "rds:CreateDBSubnetGroup", + "rds:CreateEventSubscription", + "rds:DeleteDBCluster", + "rds:DeleteDBClusterParameterGroup", + "rds:DeleteDBClusterSnapshot", + "rds:DeleteDBInstance", + "rds:DeleteDBParameterGroup", + "rds:DeleteDBSubnetGroup", + "rds:DeleteEventSubscription", + "rds:DescribeAccountAttributes", + "rds:DescribeCertificates", + "rds:DescribeDBClusterParameterGroups", + "rds:DescribeDBClusterParameters", + "rds:DescribeDBClusterSnapshotAttributes", + "rds:DescribeDBClusterSnapshots", + "rds:DescribeDBClusters", + "rds:DescribeDBEngineVersions", + "rds:DescribeDBInstances", + "rds:DescribeDBLogFiles", + "rds:DescribeDBParameterGroups", + "rds:DescribeDBParameters", + "rds:DescribeDBSecurityGroups", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEngineDefaultClusterParameters", + "rds:DescribeEngineDefaultParameters", + "rds:DescribeEventCategories", + "rds:DescribeEventSubscriptions", + "rds:DescribeEvents", + "rds:DescribeOptionGroups", + "rds:DescribeOrderableDBInstanceOptions", + "rds:DescribePendingMaintenanceActions", + "rds:DescribeValidDBInstanceModifications", + "rds:DownloadDBLogFilePortion", + "rds:FailoverDBCluster", + "rds:ListTagsForResource", + "rds:ModifyDBCluster", + "rds:ModifyDBClusterParameterGroup", + "rds:ModifyDBClusterSnapshotAttribute", + "rds:ModifyDBInstance", + "rds:ModifyDBParameterGroup", + "rds:ModifyDBSubnetGroup", + "rds:ModifyEventSubscription", + "rds:PromoteReadReplicaDBCluster", + "rds:RebootDBInstance", + "rds:RemoveRoleFromDBCluster", + "rds:RemoveSourceIdentifierFromSubscription", + "rds:RemoveTagsFromResource", + "rds:ResetDBClusterParameterGroup", + "rds:ResetDBParameterGroup", + "rds:RestoreDBClusterFromSnapshot", + "rds:RestoreDBClusterToPointInTime" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics", + "ec2:DescribeAccountAttributes", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "kms:ListAliases", + "kms:ListKeyPolicies", + "kms:ListKeys", + "kms:ListRetirableGrants", + "logs:DescribeLogStreams", + "logs:GetLogEvents", + "sns:ListSubscriptions", + "sns:ListTopics", + "sns:Publish" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "rds.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIQKACUF6JJHALEG5K", + "PolicyName": "AmazonDocDBFullAccess", + "UpdateDate": "2019-01-09T20:21:44+00:00", + "VersionId": "v1" + }, + "AmazonDocDBReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonDocDBReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-09T20:30:28+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "rds:DescribeAccountAttributes", + "rds:DescribeCertificates", + "rds:DescribeDBClusterParameterGroups", + "rds:DescribeDBClusterParameters", + "rds:DescribeDBClusterSnapshotAttributes", + "rds:DescribeDBClusterSnapshots", + "rds:DescribeDBClusters", + "rds:DescribeDBEngineVersions", + "rds:DescribeDBInstances", + "rds:DescribeDBLogFiles", + "rds:DescribeDBParameterGroups", + "rds:DescribeDBParameters", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEventCategories", + "rds:DescribeEventSubscriptions", + "rds:DescribeEvents", + "rds:DescribeOrderableDBInstanceOptions", + "rds:DescribePendingMaintenanceActions", + "rds:DownloadDBLogFilePortion", + "rds:ListTagsForResource" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DescribeAccountAttributes", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInternetGateways", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "kms:ListKeys", + "kms:ListRetirableGrants", + "kms:ListAliases", + "kms:ListKeyPolicies" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:DescribeLogStreams", + "logs:GetLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/rds/*:log-stream:*", + "arn:aws:logs:*:*:log-group:/aws/docdb/*:log-stream:*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI477RMVACLTLWY5RQ", + "PolicyName": "AmazonDocDBReadOnlyAccess", + "UpdateDate": "2019-01-09T20:30:28+00:00", + "VersionId": "v1" + }, "AmazonDynamoDBFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-06-28T23:23:34+00:00", - "DefaultVersionId": "v5", + "CreateDate": "2015-02-06T18:40:11+00:00", + "DefaultVersionId": "v9", "Document": { "Statement": [ { @@ -6188,7 +15554,14 @@ aws_managed_policies_data = """ "lambda:CreateEventSourceMapping", "lambda:DeleteEventSourceMapping", "lambda:GetFunctionConfiguration", - "lambda:DeleteFunction" + "lambda:DeleteFunction", + "resource-groups:ListGroups", + "resource-groups:ListGroupResources", + "resource-groups:GetGroup", + "resource-groups:GetGroupQuery", + "resource-groups:DeleteGroup", + "resource-groups:CreateGroup", + "tag:GetResources" ], "Effect": "Allow", "Resource": "*" @@ -6207,6 +15580,22 @@ aws_managed_policies_data = """ }, "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringEquals": { + "iam:AWSServiceName": [ + "replication.dynamodb.amazonaws.com", + "dax.amazonaws.com", + "dynamodb.application-autoscaling.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -6214,15 +15603,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAINUGF2JSOSUY76KYA", "PolicyName": "AmazonDynamoDBFullAccess", - "UpdateDate": "2017-06-28T23:23:34+00:00", - "VersionId": "v5" + "UpdateDate": "2019-05-08T21:20:48+00:00", + "VersionId": "v9" }, "AmazonDynamoDBFullAccesswithDataPipeline": { "Arn": "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccesswithDataPipeline", "AttachmentCount": 0, - "CreateDate": "2015-11-12T02:17:42+00:00", + "CreateDate": "2015-02-06T18:40:14+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -6312,6 +15702,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ3ORT7KDISSXGHJXA", "PolicyName": "AmazonDynamoDBFullAccesswithDataPipeline", "UpdateDate": "2015-11-12T02:17:42+00:00", @@ -6320,8 +15711,8 @@ aws_managed_policies_data = """ "AmazonDynamoDBReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-06-12T21:11:40+00:00", - "DefaultVersionId": "v5", + "CreateDate": "2015-02-06T18:40:12+00:00", + "DefaultVersionId": "v8", "Document": { "Statement": [ { @@ -6340,23 +15731,32 @@ aws_managed_policies_data = """ "datapipeline:ListPipelines", "datapipeline:QueryObjects", "dynamodb:BatchGetItem", - "dynamodb:DescribeTable", + "dynamodb:Describe*", + "dynamodb:List*", "dynamodb:GetItem", - "dynamodb:ListTables", "dynamodb:Query", "dynamodb:Scan", - "dynamodb:DescribeReservedCapacity", - "dynamodb:DescribeReservedCapacityOfferings", - "dynamodb:ListTagsOfResource", - "dynamodb:DescribeTimeToLive", - "dynamodb:DescribeLimits", + "dax:Describe*", + "dax:List*", + "dax:GetItem", + "dax:BatchGetItem", + "dax:Query", + "dax:Scan", + "ec2:DescribeVpcs", + "ec2:DescribeSubnets", + "ec2:DescribeSecurityGroups", "iam:GetRole", "iam:ListRoles", "sns:ListSubscriptionsByTopic", "sns:ListTopics", "lambda:ListFunctions", "lambda:ListEventSourceMappings", - "lambda:GetFunctionConfiguration" + "lambda:GetFunctionConfiguration", + "resource-groups:ListGroups", + "resource-groups:ListGroupResources", + "resource-groups:GetGroup", + "resource-groups:GetGroupQuery", + "tag:GetResources" ], "Effect": "Allow", "Resource": "*" @@ -6367,21 +15767,23 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIY2XFNA232XJ6J7X2", "PolicyName": "AmazonDynamoDBReadOnlyAccess", - "UpdateDate": "2017-06-12T21:11:40+00:00", - "VersionId": "v5" + "UpdateDate": "2019-05-08T21:15:48+00:00", + "VersionId": "v8" }, "AmazonEC2ContainerRegistryFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess", "AttachmentCount": 0, "CreateDate": "2015-12-21T17:06:48+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ - "ecr:*" + "ecr:*", + "cloudtrail:LookupEvents" ], "Effect": "Allow", "Resource": "*" @@ -6392,15 +15794,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIESRL7KD7IIVF6V4W", "PolicyName": "AmazonEC2ContainerRegistryFullAccess", - "UpdateDate": "2015-12-21T17:06:48+00:00", - "VersionId": "v1" + "UpdateDate": "2017-11-10T17:54:49+00:00", + "VersionId": "v2" }, "AmazonEC2ContainerRegistryPowerUser": { "Arn": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser", "AttachmentCount": 0, - "CreateDate": "2016-10-11T22:28:07+00:00", + "CreateDate": "2015-12-21T17:05:33+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -6428,6 +15831,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJDNE5PIHROIBGGDDW", "PolicyName": "AmazonEC2ContainerRegistryPowerUser", "UpdateDate": "2016-10-11T22:28:07+00:00", @@ -6436,7 +15840,7 @@ aws_managed_policies_data = """ "AmazonEC2ContainerRegistryReadOnly": { "Arn": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", "AttachmentCount": 0, - "CreateDate": "2016-10-11T22:08:43+00:00", + "CreateDate": "2015-12-21T17:04:15+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -6460,6 +15864,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIFYZPA37OOHVIH7KQ", "PolicyName": "AmazonEC2ContainerRegistryReadOnly", "UpdateDate": "2016-10-11T22:08:43+00:00", @@ -6467,9 +15872,9 @@ aws_managed_policies_data = """ }, "AmazonEC2ContainerServiceAutoscaleRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceAutoscaleRole", - "AttachmentCount": 1, + "AttachmentCount": 0, "CreateDate": "2016-05-12T23:25:44+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -6484,7 +15889,8 @@ aws_managed_policies_data = """ }, { "Action": [ - "cloudwatch:DescribeAlarms" + "cloudwatch:DescribeAlarms", + "cloudwatch:PutMetricAlarm" ], "Effect": "Allow", "Resource": [ @@ -6497,16 +15903,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIUAP3EGGGXXCPDQKK", "PolicyName": "AmazonEC2ContainerServiceAutoscaleRole", - "UpdateDate": "2016-05-12T23:25:44+00:00", - "VersionId": "v1" + "UpdateDate": "2018-02-05T19:15:15+00:00", + "VersionId": "v2" }, "AmazonEC2ContainerServiceEventsRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceEventsRole", "AttachmentCount": 0, "CreateDate": "2017-05-30T16:51:35+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -6517,6 +15924,18 @@ aws_managed_policies_data = """ "Resource": [ "*" ] + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": "ecs-tasks.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] } ], "Version": "2012-10-17" @@ -6524,15 +15943,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAITKFNIUAG27VSYNZ4", "PolicyName": "AmazonEC2ContainerServiceEventsRole", - "UpdateDate": "2017-05-30T16:51:35+00:00", - "VersionId": "v1" + "UpdateDate": "2018-05-22T19:13:11+00:00", + "VersionId": "v2" }, "AmazonEC2ContainerServiceFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonEC2ContainerServiceFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-06-08T00:18:56+00:00", + "CreateDate": "2015-04-24T16:54:35+00:00", "DefaultVersionId": "v4", "Document": { "Statement": [ @@ -6568,6 +15988,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJALOYVTPDZEMIACSM", "PolicyName": "AmazonEC2ContainerServiceFullAccess", "UpdateDate": "2017-06-08T00:18:56+00:00", @@ -6575,8 +15996,8 @@ aws_managed_policies_data = """ }, "AmazonEC2ContainerServiceRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole", - "AttachmentCount": 1, - "CreateDate": "2016-08-11T13:08:01+00:00", + "AttachmentCount": 0, + "CreateDate": "2015-04-09T16:14:19+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -6599,6 +16020,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJO53W2XHNACG7V77Q", "PolicyName": "AmazonEC2ContainerServiceRole", "UpdateDate": "2016-08-11T13:08:01+00:00", @@ -6606,8 +16028,8 @@ aws_managed_policies_data = """ }, "AmazonEC2ContainerServiceforEC2Role": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role", - "AttachmentCount": 1, - "CreateDate": "2017-05-17T23:09:13+00:00", + "AttachmentCount": 0, + "CreateDate": "2015-03-19T18:45:18+00:00", "DefaultVersionId": "v5", "Document": { "Statement": [ @@ -6637,6 +16059,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJLYJCVHC7TQHCSQDS", "PolicyName": "AmazonEC2ContainerServiceforEC2Role", "UpdateDate": "2017-05-17T23:09:13+00:00", @@ -6644,9 +16067,9 @@ aws_managed_policies_data = """ }, "AmazonEC2FullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonEC2FullAccess", - "AttachmentCount": 1, + "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:15+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v5", "Document": { "Statement": [ { @@ -6668,6 +16091,23 @@ aws_managed_policies_data = """ "Action": "autoscaling:*", "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": [ + "autoscaling.amazonaws.com", + "ec2scheduled.amazonaws.com", + "elasticloadbalancing.amazonaws.com", + "spot.amazonaws.com", + "spotfleet.amazonaws.com", + "transitgateway.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -6675,10 +16115,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI3VAJF5ZCRZ7MCQE6", "PolicyName": "AmazonEC2FullAccess", - "UpdateDate": "2015-02-06T18:40:15+00:00", - "VersionId": "v1" + "UpdateDate": "2018-11-27T02:16:56+00:00", + "VersionId": "v5" }, "AmazonEC2ReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess", @@ -6717,6 +16158,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIGDT4SV4GSETWTBZK", "PolicyName": "AmazonEC2ReadOnlyAccess", "UpdateDate": "2015-02-06T18:40:17+00:00", @@ -6740,6 +16182,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIU6NBZVF2PCRW36ZW", "PolicyName": "AmazonEC2ReportsAccess", "UpdateDate": "2015-02-06T18:40:16+00:00", @@ -6748,7 +16191,7 @@ aws_managed_policies_data = """ "AmazonEC2RoleforAWSCodeDeploy": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforAWSCodeDeploy", "AttachmentCount": 0, - "CreateDate": "2017-03-20T17:14:10+00:00", + "CreateDate": "2015-05-19T18:10:14+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -6767,6 +16210,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIAZKXZ27TAJ4PVWGK", "PolicyName": "AmazonEC2RoleforAWSCodeDeploy", "UpdateDate": "2017-03-20T17:14:10+00:00", @@ -6775,7 +16219,7 @@ aws_managed_policies_data = """ "AmazonEC2RoleforDataPipelineRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforDataPipelineRole", "AttachmentCount": 0, - "CreateDate": "2016-02-22T17:24:05+00:00", + "CreateDate": "2015-02-06T18:41:25+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -6808,6 +16252,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ3Z5I2WAJE5DN2J36", "PolicyName": "AmazonEC2RoleforDataPipelineRole", "UpdateDate": "2016-02-22T17:24:05+00:00", @@ -6816,8 +16261,8 @@ aws_managed_policies_data = """ "AmazonEC2RoleforSSM": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM", "AttachmentCount": 0, - "CreateDate": "2017-08-10T20:49:08+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2015-05-29T17:48:35+00:00", + "DefaultVersionId": "v8", "Document": { "Statement": [ { @@ -6825,11 +16270,14 @@ aws_managed_policies_data = """ "ssm:DescribeAssociation", "ssm:GetDeployablePatchSnapshotForInstance", "ssm:GetDocument", + "ssm:DescribeDocument", + "ssm:GetManifest", "ssm:GetParameters", "ssm:ListAssociations", "ssm:ListInstanceAssociations", "ssm:PutInventory", "ssm:PutComplianceItems", + "ssm:PutConfigurePackageResult", "ssm:UpdateAssociationStatus", "ssm:UpdateInstanceAssociationStatus", "ssm:UpdateInstanceInformation" @@ -6837,6 +16285,16 @@ aws_managed_policies_data = """ "Effect": "Allow", "Resource": "*" }, + { + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Effect": "Allow", + "Resource": "*" + }, { "Action": [ "ec2messages:AcknowledgeMessage", @@ -6884,21 +16342,17 @@ aws_managed_policies_data = """ }, { "Action": [ + "s3:GetBucketLocation", "s3:PutObject", "s3:GetObject", + "s3:GetEncryptionConfiguration", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts", + "s3:ListBucket", "s3:ListBucketMultipartUploads" ], "Effect": "Allow", "Resource": "*" - }, - { - "Action": [ - "s3:ListBucket" - ], - "Effect": "Allow", - "Resource": "arn:aws:s3:::amazon-ssm-packages-*" } ], "Version": "2012-10-17" @@ -6906,16 +16360,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI6TL3SMY22S4KMMX6", "PolicyName": "AmazonEC2RoleforSSM", - "UpdateDate": "2017-08-10T20:49:08+00:00", - "VersionId": "v4" + "UpdateDate": "2019-01-24T19:20:51+00:00", + "VersionId": "v8" }, "AmazonEC2SpotFleetAutoscaleRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetAutoscaleRole", "AttachmentCount": 0, "CreateDate": "2016-08-19T18:27:22+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -6930,12 +16385,24 @@ aws_managed_policies_data = """ }, { "Action": [ - "cloudwatch:DescribeAlarms" + "cloudwatch:DescribeAlarms", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DeleteAlarms" ], "Effect": "Allow", "Resource": [ "*" ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "ec2.application-autoscaling.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/ec2.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_EC2SpotFleetRequest" } ], "Version": "2012-10-17" @@ -6943,16 +16410,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIMFFRMIOBGDP2TAVE", "PolicyName": "AmazonEC2SpotFleetAutoscaleRole", - "UpdateDate": "2016-08-19T18:27:22+00:00", - "VersionId": "v1" + "UpdateDate": "2019-02-18T19:17:03+00:00", + "VersionId": "v3" }, "AmazonEC2SpotFleetRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetRole", "AttachmentCount": 0, - "CreateDate": "2016-11-10T21:19:35+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2015-05-18T23:28:05+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -6968,6 +16436,24 @@ aws_managed_policies_data = """ "Resource": [ "*" ] + }, + { + "Action": [ + "elasticloadbalancing:RegisterInstancesWithLoadBalancer" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:elasticloadbalancing:*:*:loadbalancer/*" + ] + }, + { + "Action": [ + "elasticloadbalancing:RegisterTargets" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] } ], "Version": "2012-10-17" @@ -6975,16 +16461,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIMRTKHWK7ESSNETSW", "PolicyName": "AmazonEC2SpotFleetRole", - "UpdateDate": "2016-11-10T21:19:35+00:00", - "VersionId": "v3" + "UpdateDate": "2017-11-07T19:14:10+00:00", + "VersionId": "v4" }, "AmazonEC2SpotFleetTaggingRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetTaggingRole", "AttachmentCount": 0, - "CreateDate": "2017-07-26T19:10:35+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2017-06-29T18:19:29+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -7005,13 +16492,34 @@ aws_managed_policies_data = """ "Action": "iam:PassRole", "Condition": { "StringEquals": { - "iam:PassedToService": "ec2.amazonaws.com" + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ec2.amazonaws.com.cn" + ] } }, "Effect": "Allow", "Resource": [ "*" ] + }, + { + "Action": [ + "elasticloadbalancing:RegisterInstancesWithLoadBalancer" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:elasticloadbalancing:*:*:loadbalancer/*" + ] + }, + { + "Action": [ + "elasticloadbalancing:RegisterTargets" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] } ], "Version": "2012-10-17" @@ -7019,11 +16527,633 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ5U6UMLCEYLX5OLC4", "PolicyName": "AmazonEC2SpotFleetTaggingRole", - "UpdateDate": "2017-07-26T19:10:35+00:00", + "UpdateDate": "2017-11-17T22:51:17+00:00", + "VersionId": "v4" + }, + "AmazonECSServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonECSServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-10-14T01:18:58+00:00", + "DefaultVersionId": "v5", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AttachNetworkInterface", + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", + "ec2:Describe*", + "ec2:DetachNetworkInterface", + "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", + "elasticloadbalancing:DeregisterTargets", + "elasticloadbalancing:Describe*", + "elasticloadbalancing:RegisterInstancesWithLoadBalancer", + "elasticloadbalancing:RegisterTargets", + "route53:ChangeResourceRecordSets", + "route53:CreateHealthCheck", + "route53:DeleteHealthCheck", + "route53:Get*", + "route53:List*", + "route53:UpdateHealthCheck", + "servicediscovery:DeregisterInstance", + "servicediscovery:Get*", + "servicediscovery:List*", + "servicediscovery:RegisterInstance", + "servicediscovery:UpdateInstanceCustomHealthStatus" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "ECSTaskManagement" + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Effect": "Allow", + "Resource": "arn:aws:ec2:*:*:network-interface/*", + "Sid": "ECSTagging" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIVUWKCAI7URU4WUEI", + "PolicyName": "AmazonECSServiceRolePolicy", + "UpdateDate": "2018-10-18T23:18:18+00:00", + "VersionId": "v5" + }, + "AmazonECSTaskExecutionRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-16T18:48:22+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJG4T4G4PV56DE72PY", + "PolicyName": "AmazonECSTaskExecutionRolePolicy", + "UpdateDate": "2017-11-16T18:48:22+00:00", + "VersionId": "v1" + }, + "AmazonECS_FullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonECS_FullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-07T21:36:54+00:00", + "DefaultVersionId": "v15", + "Document": { + "Statement": [ + { + "Action": [ + "application-autoscaling:DeleteScalingPolicy", + "application-autoscaling:DeregisterScalableTarget", + "application-autoscaling:DescribeScalableTargets", + "application-autoscaling:DescribeScalingActivities", + "application-autoscaling:DescribeScalingPolicies", + "application-autoscaling:PutScalingPolicy", + "application-autoscaling:RegisterScalableTarget", + "autoscaling:UpdateAutoScalingGroup", + "autoscaling:CreateAutoScalingGroup", + "autoscaling:CreateLaunchConfiguration", + "autoscaling:DeleteAutoScalingGroup", + "autoscaling:DeleteLaunchConfiguration", + "autoscaling:Describe*", + "cloudformation:CreateStack", + "cloudformation:DeleteStack", + "cloudformation:DescribeStack*", + "cloudformation:UpdateStack", + "cloudwatch:DescribeAlarms", + "cloudwatch:DeleteAlarms", + "cloudwatch:GetMetricStatistics", + "cloudwatch:PutMetricAlarm", + "codedeploy:CreateApplication", + "codedeploy:CreateDeployment", + "codedeploy:CreateDeploymentGroup", + "codedeploy:GetApplication", + "codedeploy:GetDeployment", + "codedeploy:GetDeploymentGroup", + "codedeploy:ListApplications", + "codedeploy:ListDeploymentGroups", + "codedeploy:ListDeployments", + "codedeploy:StopDeployment", + "codedeploy:GetDeploymentTarget", + "codedeploy:ListDeploymentTargets", + "codedeploy:GetDeploymentConfig", + "codedeploy:GetApplicationRevision", + "codedeploy:RegisterApplicationRevision", + "codedeploy:BatchGetApplicationRevisions", + "codedeploy:BatchGetDeploymentGroups", + "codedeploy:BatchGetDeployments", + "codedeploy:BatchGetApplications", + "codedeploy:ListApplicationRevisions", + "codedeploy:ListDeploymentConfigs", + "codedeploy:ContinueDeployment", + "sns:ListTopics", + "lambda:ListFunctions", + "ec2:AssociateRouteTable", + "ec2:AttachInternetGateway", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CancelSpotFleetRequests", + "ec2:CreateInternetGateway", + "ec2:CreateLaunchTemplate", + "ec2:CreateRoute", + "ec2:CreateRouteTable", + "ec2:CreateSecurityGroup", + "ec2:CreateSubnet", + "ec2:CreateVpc", + "ec2:DeleteLaunchTemplate", + "ec2:DeleteSubnet", + "ec2:DeleteVpc", + "ec2:Describe*", + "ec2:DetachInternetGateway", + "ec2:DisassociateRouteTable", + "ec2:ModifySubnetAttribute", + "ec2:ModifyVpcAttribute", + "ec2:RunInstances", + "ec2:RequestSpotFleet", + "elasticloadbalancing:CreateListener", + "elasticloadbalancing:CreateLoadBalancer", + "elasticloadbalancing:CreateRule", + "elasticloadbalancing:CreateTargetGroup", + "elasticloadbalancing:DeleteListener", + "elasticloadbalancing:DeleteLoadBalancer", + "elasticloadbalancing:DeleteRule", + "elasticloadbalancing:DeleteTargetGroup", + "elasticloadbalancing:DescribeListeners", + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeRules", + "elasticloadbalancing:DescribeTargetGroups", + "ecs:*", + "events:DescribeRule", + "events:DeleteRule", + "events:ListRuleNamesByTarget", + "events:ListTargetsByRule", + "events:PutRule", + "events:PutTargets", + "events:RemoveTargets", + "iam:ListAttachedRolePolicies", + "iam:ListInstanceProfiles", + "iam:ListRoles", + "logs:CreateLogGroup", + "logs:DescribeLogGroups", + "logs:FilterLogEvents", + "route53:GetHostedZone", + "route53:ListHostedZonesByName", + "route53:CreateHostedZone", + "route53:DeleteHostedZone", + "route53:GetHealthCheck", + "servicediscovery:CreatePrivateDnsNamespace", + "servicediscovery:CreateService", + "servicediscovery:GetNamespace", + "servicediscovery:GetOperation", + "servicediscovery:GetService", + "servicediscovery:ListNamespaces", + "servicediscovery:ListServices", + "servicediscovery:UpdateService", + "servicediscovery:DeleteService" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "ssm:GetParametersByPath", + "ssm:GetParameters", + "ssm:GetParameter" + ], + "Effect": "Allow", + "Resource": "arn:aws:ssm:*:*:parameter/aws/service/ecs*" + }, + { + "Action": [ + "ec2:DeleteInternetGateway", + "ec2:DeleteRoute", + "ec2:DeleteRouteTable", + "ec2:DeleteSecurityGroup" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/aws:cloudformation:stack-name": "EC2ContainerService-*" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": "ecs-tasks.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "ec2.amazonaws.com", + "ec2.amazonaws.com.cn" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/ecsInstanceRole*" + ] + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "application-autoscaling.amazonaws.com", + "application-autoscaling.amazonaws.com.cn" + ] + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/ecsAutoscaleRole*" + ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "ecs.amazonaws.com", + "spot.amazonaws.com", + "spotfleet.amazonaws.com", + "ecs.application-autoscaling.amazonaws.com", + "autoscaling.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7S7AN6YQPTJC7IFS", + "PolicyName": "AmazonECS_FullAccess", + "UpdateDate": "2019-02-04T18:44:48+00:00", + "VersionId": "v15" + }, + "AmazonEKSClusterPolicy": { + "Arn": "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy", + "AttachmentCount": 0, + "CreateDate": "2018-05-27T21:06:14+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "autoscaling:DescribeAutoScalingGroups", + "autoscaling:UpdateAutoScalingGroup", + "ec2:AttachVolume", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateRoute", + "ec2:CreateSecurityGroup", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:DeleteRoute", + "ec2:DeleteSecurityGroup", + "ec2:DeleteVolume", + "ec2:DescribeInstances", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVolumes", + "ec2:DescribeVolumesModifications", + "ec2:DescribeVpcs", + "ec2:DescribeDhcpOptions", + "ec2:DetachVolume", + "ec2:ModifyInstanceAttribute", + "ec2:ModifyVolume", + "ec2:RevokeSecurityGroupIngress", + "elasticloadbalancing:AddTags", + "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer", + "elasticloadbalancing:AttachLoadBalancerToSubnets", + "elasticloadbalancing:ConfigureHealthCheck", + "elasticloadbalancing:CreateListener", + "elasticloadbalancing:CreateLoadBalancer", + "elasticloadbalancing:CreateLoadBalancerListeners", + "elasticloadbalancing:CreateLoadBalancerPolicy", + "elasticloadbalancing:CreateTargetGroup", + "elasticloadbalancing:DeleteListener", + "elasticloadbalancing:DeleteLoadBalancer", + "elasticloadbalancing:DeleteLoadBalancerListeners", + "elasticloadbalancing:DeleteTargetGroup", + "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", + "elasticloadbalancing:DeregisterTargets", + "elasticloadbalancing:DescribeListeners", + "elasticloadbalancing:DescribeLoadBalancerAttributes", + "elasticloadbalancing:DescribeLoadBalancerPolicies", + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeTargetGroupAttributes", + "elasticloadbalancing:DescribeTargetGroups", + "elasticloadbalancing:DescribeTargetHealth", + "elasticloadbalancing:DetachLoadBalancerFromSubnets", + "elasticloadbalancing:ModifyListener", + "elasticloadbalancing:ModifyLoadBalancerAttributes", + "elasticloadbalancing:ModifyTargetGroup", + "elasticloadbalancing:ModifyTargetGroupAttributes", + "elasticloadbalancing:RegisterInstancesWithLoadBalancer", + "elasticloadbalancing:RegisterTargets", + "elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer", + "elasticloadbalancing:SetLoadBalancerPoliciesOfListener", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "elasticloadbalancing.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIBTLDQMIC6UOIGFWA", + "PolicyName": "AmazonEKSClusterPolicy", + "UpdateDate": "2019-05-22T22:04:46+00:00", + "VersionId": "v3" + }, + "AmazonEKSServicePolicy": { + "Arn": "arn:aws:iam::aws:policy/AmazonEKSServicePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-05-27T21:08:21+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterface", + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute", + "iam:ListAttachedRolePolicies" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateTags", + "ec2:DeleteTags" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:vpc/*", + "arn:aws:ec2:*:*:subnet/*" + ] + }, + { + "Action": "route53:AssociateVPCWithHostedZone", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "logs:CreateLogGroup", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:DescribeLogStreams" + ], + "Effect": "Allow", + "Resource": "arn:aws:logs:*:*:log-group:/aws/eks/*:*" + }, + { + "Action": "logs:PutLogEvents", + "Effect": "Allow", + "Resource": "arn:aws:logs:*:*:log-group:/aws/eks/*:*:*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJFCNXU6HPGCIVXYDI", + "PolicyName": "AmazonEKSServicePolicy", + "UpdateDate": "2019-02-26T21:01:48+00:00", + "VersionId": "v3" + }, + "AmazonEKSWorkerNodePolicy": { + "Arn": "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-05-27T21:09:01+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVolumes", + "ec2:DescribeVolumesModifications", + "ec2:DescribeVpcs", + "eks:DescribeCluster" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIBVMOY52IPQ6HD3PO", + "PolicyName": "AmazonEKSWorkerNodePolicy", + "UpdateDate": "2018-05-27T21:09:01+00:00", + "VersionId": "v1" + }, + "AmazonEKS_CNI_Policy": { + "Arn": "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", + "AttachmentCount": 0, + "CreateDate": "2018-05-27T21:07:42+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AssignPrivateIpAddresses", + "ec2:AttachNetworkInterface", + "ec2:CreateNetworkInterface", + "ec2:DeleteNetworkInterface", + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:DetachNetworkInterface", + "ec2:ModifyNetworkInterfaceAttribute" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:network-interface/*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJWLAS474LDBXNNTM4", + "PolicyName": "AmazonEKS_CNI_Policy", + "UpdateDate": "2018-05-31T22:16:00+00:00", "VersionId": "v2" }, + "AmazonEMRCleanupPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonEMRCleanupPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-09-26T23:54:19+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeSpotInstanceRequests", + "ec2:ModifyInstanceAttribute", + "ec2:TerminateInstances", + "ec2:CancelSpotInstanceRequests", + "ec2:DeleteNetworkInterface", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeVolumeStatus", + "ec2:DescribeVolumes", + "ec2:DetachVolume", + "ec2:DeleteVolume" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI4YEZURRMKACW56EA", + "PolicyName": "AmazonEMRCleanupPolicy", + "UpdateDate": "2017-09-26T23:54:19+00:00", + "VersionId": "v1" + }, + "AmazonESCognitoAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonESCognitoAccess", + "AttachmentCount": 0, + "CreateDate": "2018-02-28T22:29:18+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cognito-idp:DescribeUserPool", + "cognito-idp:CreateUserPoolClient", + "cognito-idp:DeleteUserPoolClient", + "cognito-idp:DescribeUserPoolClient", + "cognito-idp:AdminInitiateAuth", + "cognito-idp:AdminUserGlobalSignOut", + "cognito-idp:ListUserPoolClients", + "cognito-identity:DescribeIdentityPool", + "cognito-identity:UpdateIdentityPool", + "cognito-identity:SetIdentityPoolRoles", + "cognito-identity:GetIdentityPoolRoles" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": "cognito-identity.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJL2FUMODIGNDPTZHO", + "PolicyName": "AmazonESCognitoAccess", + "UpdateDate": "2018-02-28T22:29:18+00:00", + "VersionId": "v1" + }, "AmazonESFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonESFullAccess", "AttachmentCount": 0, @@ -7044,6 +17174,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJM6ZTCU24QL5PZCGC", "PolicyName": "AmazonESFullAccess", "UpdateDate": "2015-10-01T19:14:00+00:00", @@ -7053,13 +17184,14 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AmazonESReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2015-10-01T19:18:24+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ "es:Describe*", - "es:List*" + "es:List*", + "es:Get*" ], "Effect": "Allow", "Resource": "*" @@ -7070,22 +17202,33 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJUDMRLOQ7FPAR46FQ", "PolicyName": "AmazonESReadOnlyAccess", - "UpdateDate": "2015-10-01T19:18:24+00:00", - "VersionId": "v1" + "UpdateDate": "2018-10-03T03:32:56+00:00", + "VersionId": "v2" }, "AmazonElastiCacheFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonElastiCacheFullAccess", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:20+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": "elasticache:*", "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "elasticache.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/elasticache.amazonaws.com/AWSServiceRoleForElastiCache" } ], "Version": "2012-10-17" @@ -7093,10 +17236,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIA2V44CPHAUAAECKG", "PolicyName": "AmazonElastiCacheFullAccess", - "UpdateDate": "2015-02-06T18:40:20+00:00", - "VersionId": "v1" + "UpdateDate": "2017-12-07T17:48:26+00:00", + "VersionId": "v2" }, "AmazonElastiCacheReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonElastiCacheReadOnlyAccess", @@ -7118,6 +17262,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIPDACSNQHSENWAKM2", "PolicyName": "AmazonElastiCacheReadOnlyAccess", "UpdateDate": "2015-02-06T18:40:21+00:00", @@ -7126,7 +17271,7 @@ aws_managed_policies_data = """ "AmazonElasticFileSystemFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonElasticFileSystemFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-14T10:18:34+00:00", + "CreateDate": "2015-05-27T16:22:28+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -7155,6 +17300,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJKXTMNVQGIDNCKPBC", "PolicyName": "AmazonElasticFileSystemFullAccess", "UpdateDate": "2017-08-14T10:18:34+00:00", @@ -7163,7 +17309,7 @@ aws_managed_policies_data = """ "AmazonElasticFileSystemReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonElasticFileSystemReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-14T10:09:49+00:00", + "CreateDate": "2015-05-27T16:25:25+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -7188,16 +17334,71 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIPN5S4NE5JJOKVC4Y", "PolicyName": "AmazonElasticFileSystemReadOnlyAccess", "UpdateDate": "2017-08-14T10:09:49+00:00", "VersionId": "v3" }, + "AmazonElasticMapReduceEditorsRole": { + "Arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceEditorsRole", + "AttachmentCount": 0, + "CreateDate": "2018-11-16T21:55:25+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateSecurityGroup", + "ec2:DescribeSecurityGroups", + "ec2:RevokeSecurityGroupEgress", + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", + "ec2:DescribeNetworkInterfaces", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DescribeTags", + "ec2:DescribeInstances", + "ec2:DescribeSubnets", + "elasticmapreduce:ListInstances", + "elasticmapreduce:DescribeCluster" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "ec2:CreateTags", + "Condition": { + "ForAllValues:StringEquals": { + "aws:TagKeys": [ + "aws:elasticmapreduce:editor-id", + "aws:elasticmapreduce:job-flow-id" + ] + } + }, + "Effect": "Allow", + "Resource": "arn:aws:ec2:*:*:network-interface/*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIBI5CIE6OHUIGLYVG", + "PolicyName": "AmazonElasticMapReduceEditorsRole", + "UpdateDate": "2018-11-16T21:55:25+00:00", + "VersionId": "v1" + }, "AmazonElasticMapReduceFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonElasticMapReduceFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-09-20T19:27:37+00:00", - "DefaultVersionId": "v5", + "CreateDate": "2015-02-06T18:40:22+00:00", + "DefaultVersionId": "v6", "Document": { "Statement": [ { @@ -7253,11 +17454,14 @@ aws_managed_policies_data = """ "Action": "iam:CreateServiceLinkedRole", "Condition": { "StringLike": { - "iam:AWSServiceName": "elasticmapreduce.amazonaws.com" + "iam:AWSServiceName": [ + "elasticmapreduce.amazonaws.com", + "elasticmapreduce.amazonaws.com.cn" + ] } }, "Effect": "Allow", - "Resource": "arn:aws:iam::*:role/aws-service-role/elasticmapreduce.amazonaws.com/AWSServiceRoleForEMRCleanup" + "Resource": "*" } ], "Version": "2012-10-17" @@ -7265,15 +17469,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIZP5JFP3AMSGINBB2", "PolicyName": "AmazonElasticMapReduceFullAccess", - "UpdateDate": "2017-09-20T19:27:37+00:00", - "VersionId": "v5" + "UpdateDate": "2018-01-23T19:40:00+00:00", + "VersionId": "v6" }, "AmazonElasticMapReduceReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonElasticMapReduceReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-05-22T23:00:19+00:00", + "CreateDate": "2015-02-06T18:40:23+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -7297,6 +17502,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIHP6NH2S6GYFCOINC", "PolicyName": "AmazonElasticMapReduceReadOnlyAccess", "UpdateDate": "2017-05-22T23:00:19+00:00", @@ -7305,8 +17511,8 @@ aws_managed_policies_data = """ "AmazonElasticMapReduceRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceRole", "AttachmentCount": 0, - "CreateDate": "2017-07-17T21:29:50+00:00", - "DefaultVersionId": "v8", + "CreateDate": "2015-02-06T18:41:20+00:00", + "DefaultVersionId": "v9", "Document": { "Statement": [ { @@ -7377,6 +17583,16 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "spot.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot*" } ], "Version": "2012-10-17" @@ -7384,10 +17600,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIDI2BQT2LKXZG36TW", "PolicyName": "AmazonElasticMapReduceRole", - "UpdateDate": "2017-07-17T21:29:50+00:00", - "VersionId": "v8" + "UpdateDate": "2017-12-12T00:47:45+00:00", + "VersionId": "v9" }, "AmazonElasticMapReduceforAutoScalingRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforAutoScalingRole", @@ -7411,6 +17628,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJSVXG6QHPE6VHDZ4Q", "PolicyName": "AmazonElasticMapReduceforAutoScalingRole", "UpdateDate": "2016-11-18T01:09:10+00:00", @@ -7419,7 +17637,7 @@ aws_managed_policies_data = """ "AmazonElasticMapReduceforEC2Role": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role", "AttachmentCount": 0, - "CreateDate": "2017-08-11T23:57:30+00:00", + "CreateDate": "2015-02-06T18:41:21+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -7481,108 +17699,12 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIGALS5RCDLZLB3PGS", "PolicyName": "AmazonElasticMapReduceforEC2Role", "UpdateDate": "2017-08-11T23:57:30+00:00", "VersionId": "v3" }, - "AmazonElasticTranscoderFullAccess": { - "Arn": "arn:aws:iam::aws:policy/AmazonElasticTranscoderFullAccess", - "AttachmentCount": 0, - "CreateDate": "2015-02-06T18:40:24+00:00", - "DefaultVersionId": "v1", - "Document": { - "Statement": [ - { - "Action": [ - "elastictranscoder:*", - "cloudfront:*", - "s3:List*", - "s3:Put*", - "s3:Get*", - "s3:*MultipartUpload*", - "iam:CreateRole", - "iam:GetRolePolicy", - "iam:PassRole", - "iam:PutRolePolicy", - "iam:List*", - "sns:CreateTopic", - "sns:List*" - ], - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "IsAttachable": true, - "IsDefaultVersion": true, - "Path": "/", - "PolicyId": "ANPAJ4D5OJU75P5ZJZVNY", - "PolicyName": "AmazonElasticTranscoderFullAccess", - "UpdateDate": "2015-02-06T18:40:24+00:00", - "VersionId": "v1" - }, - "AmazonElasticTranscoderJobsSubmitter": { - "Arn": "arn:aws:iam::aws:policy/AmazonElasticTranscoderJobsSubmitter", - "AttachmentCount": 0, - "CreateDate": "2015-02-06T18:40:25+00:00", - "DefaultVersionId": "v1", - "Document": { - "Statement": [ - { - "Action": [ - "elastictranscoder:Read*", - "elastictranscoder:List*", - "elastictranscoder:*Job", - "elastictranscoder:*Preset", - "s3:List*", - "iam:List*", - "sns:List*" - ], - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "IsAttachable": true, - "IsDefaultVersion": true, - "Path": "/", - "PolicyId": "ANPAIN5WGARIKZ3E2UQOU", - "PolicyName": "AmazonElasticTranscoderJobsSubmitter", - "UpdateDate": "2015-02-06T18:40:25+00:00", - "VersionId": "v1" - }, - "AmazonElasticTranscoderReadOnlyAccess": { - "Arn": "arn:aws:iam::aws:policy/AmazonElasticTranscoderReadOnlyAccess", - "AttachmentCount": 0, - "CreateDate": "2015-02-06T18:40:26+00:00", - "DefaultVersionId": "v1", - "Document": { - "Statement": [ - { - "Action": [ - "elastictranscoder:Read*", - "elastictranscoder:List*", - "s3:List*", - "iam:List*", - "sns:List*" - ], - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "IsAttachable": true, - "IsDefaultVersion": true, - "Path": "/", - "PolicyId": "ANPAJGPP7GPMJRRJMEP3Q", - "PolicyName": "AmazonElasticTranscoderReadOnlyAccess", - "UpdateDate": "2015-02-06T18:40:26+00:00", - "VersionId": "v1" - }, "AmazonElasticTranscoderRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonElasticTranscoderRole", "AttachmentCount": 0, @@ -7633,16 +17755,128 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJNW3WMKVXFJ2KPIQ2", "PolicyName": "AmazonElasticTranscoderRole", "UpdateDate": "2015-02-06T18:41:26+00:00", "VersionId": "v1" }, + "AmazonElasticTranscoder_FullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonElasticTranscoder_FullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-04-27T18:59:35+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "elastictranscoder:*", + "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:ListObjects", + "iam:ListRoles", + "sns:ListTopics" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": [ + "elastictranscoder.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAICFT6XVF3RSR4E7JG", + "PolicyName": "AmazonElasticTranscoder_FullAccess", + "UpdateDate": "2018-04-27T18:59:35+00:00", + "VersionId": "v1" + }, + "AmazonElasticTranscoder_JobsSubmitter": { + "Arn": "arn:aws:iam::aws:policy/AmazonElasticTranscoder_JobsSubmitter", + "AttachmentCount": 0, + "CreateDate": "2018-06-07T21:12:16+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "elastictranscoder:Read*", + "elastictranscoder:List*", + "elastictranscoder:*Job", + "elastictranscoder:*Preset", + "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:ListObjects", + "iam:ListRoles", + "sns:ListTopics" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7AUMMRQOVZRI734S", + "PolicyName": "AmazonElasticTranscoder_JobsSubmitter", + "UpdateDate": "2018-06-07T21:12:16+00:00", + "VersionId": "v1" + }, + "AmazonElasticTranscoder_ReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonElasticTranscoder_ReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-06-07T21:09:56+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "elastictranscoder:Read*", + "elastictranscoder:List*", + "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:ListObjects", + "iam:ListRoles", + "sns:ListTopics" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI3R3CR6KVEWD4DPFY", + "PolicyName": "AmazonElasticTranscoder_ReadOnlyAccess", + "UpdateDate": "2018-06-07T21:09:56+00:00", + "VersionId": "v1" + }, "AmazonElasticsearchServiceRolePolicy": { "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonElasticsearchServiceRolePolicy", "AttachmentCount": 0, "CreateDate": "2017-07-07T00:15:31+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -7652,7 +17886,8 @@ aws_managed_policies_data = """ "ec2:DescribeNetworkInterfaces", "ec2:ModifyNetworkInterfaceAttribute", "ec2:DescribeSecurityGroups", - "ec2:DescribeSubnets" + "ec2:DescribeSubnets", + "ec2:DescribeVpcs" ], "Effect": "Allow", "Resource": "*", @@ -7664,9 +17899,347 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJFEWZPHXKLCVHEUIC", "PolicyName": "AmazonElasticsearchServiceRolePolicy", - "UpdateDate": "2017-07-07T00:15:31+00:00", + "UpdateDate": "2018-02-08T21:38:27+00:00", + "VersionId": "v2" + }, + "AmazonFSxConsoleFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonFSxConsoleFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T16:36:05+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ds:DescribeDirectories", + "ec2:DescribeNetworkInterfaceAttribute", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "fsx:*", + "kms:ListAliases", + "s3:HeadBucket" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "fsx.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "s3.data-source.lustre.fsx.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAITDDJ23Y5UZ2WCZRQ", + "PolicyName": "AmazonFSxConsoleFullAccess", + "UpdateDate": "2018-11-28T16:36:05+00:00", + "VersionId": "v1" + }, + "AmazonFSxConsoleReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonFSxConsoleReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T16:35:24+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ds:DescribeDirectories", + "ec2:DescribeNetworkInterfaceAttribute", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "fsx:Describe*", + "fsx:ListTagsForResource", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJQUISIZNHGLA6YQFM", + "PolicyName": "AmazonFSxConsoleReadOnlyAccess", + "UpdateDate": "2018-11-28T16:35:24+00:00", + "VersionId": "v1" + }, + "AmazonFSxFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonFSxFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T16:34:43+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ds:DescribeDirectories", + "fsx:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "fsx.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "s3.data-source.lustre.fsx.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIEUV6Z2X4VNZRVB5I", + "PolicyName": "AmazonFSxFullAccess", + "UpdateDate": "2018-11-28T16:34:43+00:00", + "VersionId": "v1" + }, + "AmazonFSxReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonFSxReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T16:33:32+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "fsx:Describe*", + "fsx:ListTagsForResource" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ4ICPKXR6KK32HT52", + "PolicyName": "AmazonFSxReadOnlyAccess", + "UpdateDate": "2018-11-28T16:33:32+00:00", + "VersionId": "v1" + }, + "AmazonFSxServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonFSxServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T10:38:37+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudwatch:PutMetricData", + "ds:AuthorizeApplication", + "ds:UnauthorizeApplication", + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "route53:AssociateVPCWithHostedZone" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIVQ24YKVRBV5IYQ5G", + "PolicyName": "AmazonFSxServiceRolePolicy", + "UpdateDate": "2018-11-28T10:38:37+00:00", + "VersionId": "v1" + }, + "AmazonForecastFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonForecastFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-18T01:52:29+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "forecast:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": "forecast.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIAKOTFNTUECQVU7C4", + "PolicyName": "AmazonForecastFullAccess", + "UpdateDate": "2019-01-18T01:52:29+00:00", + "VersionId": "v1" + }, + "AmazonFreeRTOSFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonFreeRTOSFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T15:32:51+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "freertos:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJAN6PSDCOH6HXG2SE", + "PolicyName": "AmazonFreeRTOSFullAccess", + "UpdateDate": "2017-11-29T15:32:51+00:00", + "VersionId": "v1" + }, + "AmazonFreeRTOSOTAUpdate": { + "Arn": "arn:aws:iam::aws:policy/service-role/AmazonFreeRTOSOTAUpdate", + "AttachmentCount": 0, + "CreateDate": "2018-08-27T22:43:07+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "s3:GetObjectVersion", + "s3:PutObject", + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": "arn:aws:s3:::afr-ota*" + }, + { + "Action": [ + "signer:StartSigningJob", + "signer:DescribeSigningJob", + "signer:GetSigningProfile", + "signer:PutSigningProfile" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:ListBucket", + "s3:ListAllMyBuckets", + "s3:GetBucketLocation" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iot:DeleteJob" + ], + "Effect": "Allow", + "Resource": "arn:aws:iot:*:*:job/AFR_OTA*" + }, + { + "Action": [ + "iot:DeleteStream" + ], + "Effect": "Allow", + "Resource": "arn:aws:iot:*:*:stream/AFR_OTA*" + }, + { + "Action": [ + "iot:CreateStream", + "iot:CreateJob" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAINC2TXHAYDOK3SWMU", + "PolicyName": "AmazonFreeRTOSOTAUpdate", + "UpdateDate": "2018-08-27T22:43:07+00:00", "VersionId": "v1" }, "AmazonGlacierFullAccess": { @@ -7687,6 +18260,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJQSTZJWB2AXXAKHVQ", "PolicyName": "AmazonGlacierFullAccess", "UpdateDate": "2015-02-06T18:40:28+00:00", @@ -7695,7 +18269,7 @@ aws_managed_policies_data = """ "AmazonGlacierReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonGlacierReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-05-05T18:46:10+00:00", + "CreateDate": "2015-02-06T18:40:27+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -7723,16 +18297,105 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI2D5NJKMU274MET4E", "PolicyName": "AmazonGlacierReadOnlyAccess", "UpdateDate": "2016-05-05T18:46:10+00:00", "VersionId": "v2" }, + "AmazonGuardDutyFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonGuardDutyFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-28T22:31:30+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": "guardduty:*", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "guardduty.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIKUTKSN4KC63VDQUM", + "PolicyName": "AmazonGuardDutyFullAccess", + "UpdateDate": "2017-11-28T22:31:30+00:00", + "VersionId": "v1" + }, + "AmazonGuardDutyReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonGuardDutyReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-28T22:29:40+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "guardduty:Get*", + "guardduty:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIVMCEDV336RWUSNHG", + "PolicyName": "AmazonGuardDutyReadOnlyAccess", + "UpdateDate": "2018-04-25T21:07:17+00:00", + "VersionId": "v2" + }, + "AmazonGuardDutyServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonGuardDutyServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-28T20:12:59+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeImages" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIHZREZOWNSSA6FWQO", + "PolicyName": "AmazonGuardDutyServiceRolePolicy", + "UpdateDate": "2017-11-28T20:12:59+00:00", + "VersionId": "v1" + }, "AmazonInspectorFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonInspectorFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-09-12T17:42:57+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2015-10-07T17:08:04+00:00", + "DefaultVersionId": "v5", "Document": { "Statement": [ { @@ -7746,6 +18409,30 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "inspector.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "inspector.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/inspector.amazonaws.com/AWSServiceRoleForAmazonInspector" } ], "Version": "2012-10-17" @@ -7753,15 +18440,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI7Y6NTA27NWNA5U5E", "PolicyName": "AmazonInspectorFullAccess", - "UpdateDate": "2017-09-12T17:42:57+00:00", - "VersionId": "v3" + "UpdateDate": "2017-12-21T14:53:31+00:00", + "VersionId": "v5" }, "AmazonInspectorReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonInspectorReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-09-12T16:53:06+00:00", + "CreateDate": "2015-10-07T17:08:01+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -7787,11 +18475,69 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJXQNTHTEJ2JFRN2SE", "PolicyName": "AmazonInspectorReadOnlyAccess", "UpdateDate": "2017-09-12T16:53:06+00:00", "VersionId": "v3" }, + "AmazonInspectorServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonInspectorServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-21T15:48:27+00:00", + "DefaultVersionId": "v4", + "Document": { + "Statement": [ + { + "Action": [ + "directconnect:DescribeConnections", + "directconnect:DescribeDirectConnectGateways", + "directconnect:DescribeDirectConnectGatewayAssociations", + "directconnect:DescribeDirectConnectGatewayAttachments", + "directconnect:DescribeVirtualGateways", + "directconnect:DescribeVirtualInterfaces", + "directconnect:DescribeTags", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeCustomerGateways", + "ec2:DescribeInstances", + "ec2:DescribeTags", + "ec2:DescribeInternetGateways", + "ec2:DescribeNatGateways", + "ec2:DescribeNetworkAcls", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribePrefixLists", + "ec2:DescribeRegions", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcPeeringConnections", + "ec2:DescribeVpcs", + "ec2:DescribeVpnConnections", + "ec2:DescribeVpnGateways", + "elasticloadbalancing:DescribeListeners", + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeLoadBalancerAttributes", + "elasticloadbalancing:DescribeRules", + "elasticloadbalancing:DescribeTags", + "elasticloadbalancing:DescribeTargetGroups", + "elasticloadbalancing:DescribeTargetHealth" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJKBMSBWLU2TGXHHUQ", + "PolicyName": "AmazonInspectorServiceRolePolicy", + "UpdateDate": "2018-05-10T18:36:01+00:00", + "VersionId": "v4" + }, "AmazonKinesisAnalyticsFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonKinesisAnalyticsFullAccess", "AttachmentCount": 0, @@ -7856,6 +18602,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJQOSKHTXP43R7P5AC", "PolicyName": "AmazonKinesisAnalyticsFullAccess", "UpdateDate": "2016-09-21T19:01:14+00:00", @@ -7920,6 +18667,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIJIEXZAFUK43U7ARK", "PolicyName": "AmazonKinesisAnalyticsReadOnly", "UpdateDate": "2016-09-21T18:16:43+00:00", @@ -7945,6 +18693,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJMZQMTZ7FRBFHHAHI", "PolicyName": "AmazonKinesisFirehoseFullAccess", "UpdateDate": "2015-10-07T18:45:26+00:00", @@ -7971,6 +18720,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ36NT645INW4K24W6", "PolicyName": "AmazonKinesisFirehoseReadOnlyAccess", "UpdateDate": "2015-10-07T18:43:39+00:00", @@ -7994,6 +18744,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIVF32HAMOXCUYRAYE", "PolicyName": "AmazonKinesisFullAccess", "UpdateDate": "2015-02-06T18:40:29+00:00", @@ -8021,16 +18772,69 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIOCMTDT5RLKZ2CAJO", "PolicyName": "AmazonKinesisReadOnlyAccess", "UpdateDate": "2015-02-06T18:40:30+00:00", "VersionId": "v1" }, + "AmazonKinesisVideoStreamsFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonKinesisVideoStreamsFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-12-01T23:27:18+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": "kinesisvideo:*", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIZAN5AK7E7UVYIAZY", + "PolicyName": "AmazonKinesisVideoStreamsFullAccess", + "UpdateDate": "2017-12-01T23:27:18+00:00", + "VersionId": "v1" + }, + "AmazonKinesisVideoStreamsReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonKinesisVideoStreamsReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2017-12-01T23:14:32+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "kinesisvideo:Describe*", + "kinesisvideo:Get*", + "kinesisvideo:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJDS2DKUCYTEA7M6UA", + "PolicyName": "AmazonKinesisVideoStreamsReadOnlyAccess", + "UpdateDate": "2017-12-01T23:14:32+00:00", + "VersionId": "v1" + }, "AmazonLexFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonLexFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-04-14T19:45:37+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2017-04-11T23:20:36+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -8089,6 +18893,16 @@ aws_managed_policies_data = """ "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots" ] }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots" + ] + }, { "Action": [ "iam:DetachRolePolicy" @@ -8117,6 +18931,16 @@ aws_managed_policies_data = """ "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels" ] }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels" + ] + }, { "Action": [ "iam:DetachRolePolicy" @@ -8137,10 +18961,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJVLXDHKVC23HRTKSI", "PolicyName": "AmazonLexFullAccess", - "UpdateDate": "2017-04-14T19:45:37+00:00", - "VersionId": "v3" + "UpdateDate": "2017-11-15T23:55:07+00:00", + "VersionId": "v4" }, "AmazonLexReadOnly": { "Arn": "arn:aws:iam::aws:policy/AmazonLexReadOnly", @@ -8178,6 +19003,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJGBI5LSMAJNDGBNAM", "PolicyName": "AmazonLexReadOnly", "UpdateDate": "2017-04-11T23:13:33+00:00", @@ -8204,11 +19030,253 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJVZGB5CM3N6YWJHBE", "PolicyName": "AmazonLexRunBotsOnly", "UpdateDate": "2017-04-11T23:06:24+00:00", "VersionId": "v1" }, + "AmazonMQApiFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonMQApiFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-12-18T20:31:31+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "mq:*", + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", + "ec2:DetachNetworkInterface", + "ec2:DescribeInternetGateways", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeNetworkInterfacePermissions", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/amazonmq/*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI4CMO533EBV3L2GW4", + "PolicyName": "AmazonMQApiFullAccess", + "UpdateDate": "2018-12-18T20:31:31+00:00", + "VersionId": "v1" + }, + "AmazonMQApiReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonMQApiReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-12-18T20:31:13+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "mq:Describe*", + "mq:List*", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIKI5JRHKAFHXQJKMO", + "PolicyName": "AmazonMQApiReadOnlyAccess", + "UpdateDate": "2018-12-18T20:31:13+00:00", + "VersionId": "v1" + }, + "AmazonMQFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonMQFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-28T15:28:29+00:00", + "DefaultVersionId": "v4", + "Document": { + "Statement": [ + { + "Action": [ + "mq:*", + "cloudformation:CreateStack", + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", + "ec2:DetachNetworkInterface", + "ec2:DescribeInternetGateways", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeNetworkInterfacePermissions", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:CreateSecurityGroup", + "ec2:AuthorizeSecurityGroupIngress" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/amazonmq/*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJLKBROJNQYDDXOOGG", + "PolicyName": "AmazonMQFullAccess", + "UpdateDate": "2018-12-18T20:33:17+00:00", + "VersionId": "v4" + }, + "AmazonMQReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonMQReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-28T15:30:32+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "mq:Describe*", + "mq:List*", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJFH3NKGULDUU66D5C", + "PolicyName": "AmazonMQReadOnlyAccess", + "UpdateDate": "2017-11-28T19:02:03+00:00", + "VersionId": "v2" + }, + "AmazonMSKFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonMSKFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-14T22:07:52+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "kafka:*", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:DescribeSecurityGroups", + "kms:DescribeKey", + "kms:CreateGrant" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "kafka.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/kafka.amazonaws.com/AWSServiceRoleForKafka*" + }, + { + "Action": [ + "iam:AttachRolePolicy", + "iam:PutRolePolicy" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/kafka.amazonaws.com/AWSServiceRoleForKafka*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJERQQQTWI5OMENTQE", + "PolicyName": "AmazonMSKFullAccess", + "UpdateDate": "2019-01-14T22:07:52+00:00", + "VersionId": "v1" + }, + "AmazonMSKReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonMSKReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-14T22:28:45+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "kafka:Describe*", + "kafka:List*", + "kafka:Get*", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJGMUI3DP2EVP3VGYO", + "PolicyName": "AmazonMSKReadOnlyAccess", + "UpdateDate": "2019-01-14T22:28:45+00:00", + "VersionId": "v1" + }, "AmazonMachineLearningBatchPredictionsAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonMachineLearningBatchPredictionsAccess", "AttachmentCount": 0, @@ -8233,6 +19301,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAILOI4HTQSFTF3GQSC", "PolicyName": "AmazonMachineLearningBatchPredictionsAccess", "UpdateDate": "2015-04-09T17:12:19+00:00", @@ -8241,7 +19310,7 @@ aws_managed_policies_data = """ "AmazonMachineLearningCreateOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonMachineLearningCreateOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-06-29T20:55:03+00:00", + "CreateDate": "2015-04-09T17:18:09+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -8262,6 +19331,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJDRUNIC2RYAMAT3CK", "PolicyName": "AmazonMachineLearningCreateOnlyAccess", "UpdateDate": "2016-06-29T20:55:03+00:00", @@ -8287,6 +19357,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIWKW6AGSGYOQ5ERHC", "PolicyName": "AmazonMachineLearningFullAccess", "UpdateDate": "2015-04-09T17:25:41+00:00", @@ -8313,6 +19384,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJJL3PC3VCSVZP6OCI", "PolicyName": "AmazonMachineLearningManageRealTimeEndpointOnlyAccess", "UpdateDate": "2015-04-09T17:32:41+00:00", @@ -8339,6 +19411,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIW5VYBCGEX56JCINC", "PolicyName": "AmazonMachineLearningReadOnlyAccess", "UpdateDate": "2015-04-09T17:40:02+00:00", @@ -8364,6 +19437,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIWMCNQPRWMWT36GVQ", "PolicyName": "AmazonMachineLearningRealTimePredictionOnlyAccess", "UpdateDate": "2015-04-09T17:44:06+00:00", @@ -8404,6 +19478,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIQ5UDYYMNN42BM4AK", "PolicyName": "AmazonMachineLearningRoleforRedshiftDataSource", "UpdateDate": "2015-04-09T17:05:26+00:00", @@ -8413,7 +19488,7 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AmazonMacieFullAccess", "AttachmentCount": 0, "CreateDate": "2017-08-14T14:54:30+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -8422,6 +19497,16 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "macie.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -8429,9 +19514,39 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJJF2N5FR6S5TZN5OA", "PolicyName": "AmazonMacieFullAccess", - "UpdateDate": "2017-08-14T14:54:30+00:00", + "UpdateDate": "2018-06-28T15:54:57+00:00", + "VersionId": "v2" + }, + "AmazonMacieHandshakeRole": { + "Arn": "arn:aws:iam::aws:policy/service-role/AmazonMacieHandshakeRole", + "AttachmentCount": 0, + "CreateDate": "2018-06-28T15:46:10+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "ForAnyValue:StringEquals": { + "iam:AWSServiceName": "macie.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7CVEIVL347MLOVKI", + "PolicyName": "AmazonMacieHandshakeRole", + "UpdateDate": "2018-06-28T15:46:10+00:00", "VersionId": "v1" }, "AmazonMacieServiceRole": { @@ -8455,11 +19570,77 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJVV7PON3FPBL2PSGC", "PolicyName": "AmazonMacieServiceRole", "UpdateDate": "2017-08-14T14:53:26+00:00", "VersionId": "v1" }, + "AmazonMacieServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonMacieServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-06-19T22:17:38+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudtrail:DescribeTrails", + "cloudtrail:GetEventSelectors", + "cloudtrail:GetTrailStatus", + "cloudtrail:ListTags", + "cloudtrail:LookupEvents", + "iam:ListAccountAliases", + "s3:Get*", + "s3:List*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloudtrail:CreateTrail", + "cloudtrail:StartLogging", + "cloudtrail:StopLogging", + "cloudtrail:UpdateTrail", + "cloudtrail:DeleteTrail", + "cloudtrail:PutEventSelectors" + ], + "Effect": "Allow", + "Resource": "arn:aws:cloudtrail:*:*:trail/AWSMacieTrail-DO-NOT-EDIT" + }, + { + "Action": [ + "s3:CreateBucket", + "s3:DeleteBucket", + "s3:DeleteBucketPolicy", + "s3:DeleteBucketWebsite", + "s3:DeleteObject", + "s3:DeleteObjectTagging", + "s3:DeleteObjectVersion", + "s3:DeleteObjectVersionTagging", + "s3:DeleteReplicationConfiguration", + "s3:PutBucketPolicy" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::awsmacie-*", + "arn:aws:s3:::awsmacietrail-*", + "arn:aws:s3:::*-awsmacietrail-*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJPLHONRH2HP2H6TNQ", + "PolicyName": "AmazonMacieServiceRolePolicy", + "UpdateDate": "2018-06-19T22:17:38+00:00", + "VersionId": "v1" + }, "AmazonMacieSetupRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonMacieSetupRole", "AttachmentCount": 0, @@ -8520,11 +19701,172 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ5DC6UBVKND7ADSKA", "PolicyName": "AmazonMacieSetupRole", "UpdateDate": "2017-08-14T14:53:34+00:00", "VersionId": "v1" }, + "AmazonManagedBlockchainConsoleFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonManagedBlockchainConsoleFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-04-29T21:23:25+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "managedblockchain:*", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:CreateVpcEndpoint", + "kms:ListAliases", + "kms:DescribeKey" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4ONVQBFILL", + "PolicyName": "AmazonManagedBlockchainConsoleFullAccess", + "UpdateDate": "2019-04-29T21:23:25+00:00", + "VersionId": "v1" + }, + "AmazonManagedBlockchainFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonManagedBlockchainFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-04-29T21:39:29+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "managedblockchain:*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4CGBOJKRYD", + "PolicyName": "AmazonManagedBlockchainFullAccess", + "UpdateDate": "2019-04-29T21:39:29+00:00", + "VersionId": "v1" + }, + "AmazonManagedBlockchainReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonManagedBlockchainReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2019-04-30T18:17:31+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "managedblockchain:Get*", + "managedblockchain:List*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4OIIAURVWV", + "PolicyName": "AmazonManagedBlockchainReadOnlyAccess", + "UpdateDate": "2019-04-30T18:17:31+00:00", + "VersionId": "v1" + }, + "AmazonMechanicalTurkCrowdFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonMechanicalTurkCrowdFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-10-05T18:07:21+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "crowd:*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "CrowdApiFullAccess" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": "crowd.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIPM7C67S54NPAHQ4Q", + "PolicyName": "AmazonMechanicalTurkCrowdFullAccess", + "UpdateDate": "2018-09-28T21:08:53+00:00", + "VersionId": "v2" + }, + "AmazonMechanicalTurkCrowdReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonMechanicalTurkCrowdReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2017-10-05T18:10:56+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "crowd:GetTask" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "CrowdApiReadOnlyAccess" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAID5UNRAAANDGAW4CY", + "PolicyName": "AmazonMechanicalTurkCrowdReadOnlyAccess", + "UpdateDate": "2017-10-05T18:10:56+00:00", + "VersionId": "v1" + }, "AmazonMechanicalTurkFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonMechanicalTurkFullAccess", "AttachmentCount": 0, @@ -8547,6 +19889,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJDGCL5BET73H5QIQC", "PolicyName": "AmazonMechanicalTurkFullAccess", "UpdateDate": "2015-12-11T19:08:19+00:00", @@ -8555,7 +19898,7 @@ aws_managed_policies_data = """ "AmazonMechanicalTurkReadOnly": { "Arn": "arn:aws:iam::aws:policy/AmazonMechanicalTurkReadOnly", "AttachmentCount": 0, - "CreateDate": "2017-02-27T21:45:50+00:00", + "CreateDate": "2015-12-11T19:08:28+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -8576,6 +19919,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIO5IY3G3WXSX5PPRM", "PolicyName": "AmazonMechanicalTurkReadOnly", "UpdateDate": "2017-02-27T21:45:50+00:00", @@ -8602,6 +19946,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJKJHO2R27TXKCWBU4", "PolicyName": "AmazonMobileAnalyticsFinancialReportAccess", "UpdateDate": "2015-02-06T18:40:35+00:00", @@ -8625,6 +19970,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIJIKLU2IJ7WJ6DZFG", "PolicyName": "AmazonMobileAnalyticsFullAccess", "UpdateDate": "2015-02-06T18:40:34+00:00", @@ -8648,6 +19994,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIQLKQ4RXPUBBVVRDE", "PolicyName": "AmazonMobileAnalyticsNon-financialReportAccess", "UpdateDate": "2015-02-06T18:40:36+00:00", @@ -8671,11 +20018,71 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ5TAWBBQC2FAL3G6G", "PolicyName": "AmazonMobileAnalyticsWriteOnlyAccess", "UpdateDate": "2015-02-06T18:40:37+00:00", "VersionId": "v1" }, + "AmazonPersonalizeFullAccess": { + "Arn": "arn:aws:iam::aws:policy/service-role/AmazonPersonalizeFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-12-04T22:24:33+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "personalize:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloudwatch:PutMetricData", + "cloudwatch:ListMetrics" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject", + "s3:ListBucket" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*Personalize*", + "arn:aws:s3:::*personalize*" + ] + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": "personalize.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ45XBPPZNI3MMVAUK", + "PolicyName": "AmazonPersonalizeFullAccess", + "UpdateDate": "2019-05-30T23:46:59+00:00", + "VersionId": "v2" + }, "AmazonPollyFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonPollyFullAccess", "AttachmentCount": 0, @@ -8698,6 +20105,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJUZOYQU6XQYPR7EWS", "PolicyName": "AmazonPollyFullAccess", "UpdateDate": "2016-11-30T18:59:06+00:00", @@ -8707,14 +20115,16 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AmazonPollyReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2016-11-30T18:59:24+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ "polly:DescribeVoices", "polly:GetLexicon", + "polly:GetSpeechSynthesisTask", "polly:ListLexicons", + "polly:ListSpeechSynthesisTasks", "polly:SynthesizeSpeech" ], "Effect": "Allow", @@ -8728,23 +20138,153 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ5FENL3CVPL2FPDLA", "PolicyName": "AmazonPollyReadOnlyAccess", - "UpdateDate": "2016-11-30T18:59:24+00:00", - "VersionId": "v1" + "UpdateDate": "2018-07-17T16:41:07+00:00", + "VersionId": "v2" + }, + "AmazonRDSBetaServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonRDSBetaServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-05-02T19:41:04+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateNetworkInterface", + "ec2:CreateSecurityGroup", + "ec2:DeleteNetworkInterface", + "ec2:DeleteSecurityGroup", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInternetGateways", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:ModifyVpcEndpoint", + "ec2:RevokeSecurityGroupIngress", + "ec2:CreateVpcEndpoint", + "ec2:DescribeVpcEndpoints", + "ec2:DeleteVpcEndpoints" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/rds/*" + ] + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogStreams" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/rds/*:log-stream:*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ36CJAE6OYAR4YEK4", + "PolicyName": "AmazonRDSBetaServiceRolePolicy", + "UpdateDate": "2018-07-05T18:29:48+00:00", + "VersionId": "v3" + }, + "AmazonRDSDataFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonRDSDataFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-20T21:29:36+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "secretsmanager:GetSecretValue", + "secretsmanager:PutResourcePolicy", + "secretsmanager:PutSecretValue", + "secretsmanager:DeleteSecret", + "secretsmanager:DescribeSecret", + "secretsmanager:TagResource" + ], + "Effect": "Allow", + "Resource": "arn:aws:secretsmanager:*:*:secret:rds-db-credentials/*", + "Sid": "SecretsManagerDbCredentialsAccess" + }, + { + "Action": [ + "dbqms:CreateFavoriteQuery", + "dbqms:DescribeFavoriteQueries", + "dbqms:UpdateFavoriteQuery", + "dbqms:DeleteFavoriteQueries", + "dbqms:GetQueryString", + "dbqms:CreateQueryHistory", + "dbqms:DescribeQueryHistory", + "dbqms:UpdateQueryHistory", + "dbqms:DeleteQueryHistory", + "dbqms:DescribeQueryHistory", + "rds-data:ExecuteSql", + "rds-data:ExecuteStatement", + "rds-data:BatchExecuteStatement", + "rds-data:BeginTransaction", + "rds-data:CommitTransaction", + "rds-data:RollbackTransaction", + "secretsmanager:CreateSecret", + "secretsmanager:ListSecrets", + "secretsmanager:GetRandomPassword", + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "RDSDataServiceAccess" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ5HUMNZCSW4IC74T6", + "PolicyName": "AmazonRDSDataFullAccess", + "UpdateDate": "2019-05-30T17:11:26+00:00", + "VersionId": "v2" }, "AmazonRDSDirectoryServiceAccess": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonRDSDirectoryServiceAccess", "AttachmentCount": 0, "CreateDate": "2016-02-26T02:02:05+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ "ds:DescribeDirectories", "ds:AuthorizeApplication", - "ds:UnauthorizeApplication" + "ds:UnauthorizeApplication", + "ds:GetAuthorizedApplicationDetails" ], "Effect": "Allow", "Resource": "*" @@ -8755,14 +20295,15 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIL4KBY57XWMYUHKUU", "PolicyName": "AmazonRDSDirectoryServiceAccess", - "UpdateDate": "2016-02-26T02:02:05+00:00", - "VersionId": "v1" + "UpdateDate": "2019-05-15T16:51:50+00:00", + "VersionId": "v2" }, "AmazonRDSEnhancedMonitoringRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole", - "AttachmentCount": 1, + "AttachmentCount": 0, "CreateDate": "2015-11-11T19:58:29+00:00", "DefaultVersionId": "v1", "Document": { @@ -8797,6 +20338,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJV7BS425S4PTSSVGK", "PolicyName": "AmazonRDSEnhancedMonitoringRole", "UpdateDate": "2015-11-11T19:58:29+00:00", @@ -8805,15 +20347,24 @@ aws_managed_policies_data = """ "AmazonRDSFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonRDSFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-09-14T23:40:45+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2015-02-06T18:40:52+00:00", + "DefaultVersionId": "v6", "Document": { "Statement": [ { "Action": [ "rds:*", + "application-autoscaling:DeleteScalingPolicy", + "application-autoscaling:DeregisterScalableTarget", + "application-autoscaling:DescribeScalableTargets", + "application-autoscaling:DescribeScalingActivities", + "application-autoscaling:DescribeScalingPolicies", + "application-autoscaling:PutScalingPolicy", + "application-autoscaling:RegisterScalableTarget", "cloudwatch:DescribeAlarms", "cloudwatch:GetMetricStatistics", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DeleteAlarms", "ec2:DescribeAccountAttributes", "ec2:DescribeAvailabilityZones", "ec2:DescribeInternetGateways", @@ -8823,6 +20374,7 @@ aws_managed_policies_data = """ "ec2:DescribeVpcs", "sns:ListSubscriptions", "sns:ListTopics", + "sns:Publish", "logs:DescribeLogStreams", "logs:GetLogEvents" ], @@ -8833,6 +20385,19 @@ aws_managed_policies_data = """ "Action": "pi:*", "Effect": "Allow", "Resource": "arn:aws:pi:*:*:metrics/rds/*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": [ + "rds.amazonaws.com", + "rds.application-autoscaling.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -8840,15 +20405,81 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI3R4QMOG6Q5A4VWVG", "PolicyName": "AmazonRDSFullAccess", - "UpdateDate": "2017-09-14T23:40:45+00:00", - "VersionId": "v4" + "UpdateDate": "2018-04-09T17:42:48+00:00", + "VersionId": "v6" + }, + "AmazonRDSPreviewServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonRDSPreviewServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-05-31T18:02:00+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateNetworkInterface", + "ec2:CreateSecurityGroup", + "ec2:DeleteNetworkInterface", + "ec2:DeleteSecurityGroup", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInternetGateways", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:RevokeSecurityGroupIngress" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/rds/*" + ] + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogStreams" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/rds/*:log-stream:*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIZHJJBU3675JOUEMQ", + "PolicyName": "AmazonRDSPreviewServiceRolePolicy", + "UpdateDate": "2018-05-31T18:02:00+00:00", + "VersionId": "v1" }, "AmazonRDSReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonRDSReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-28T21:36:32+00:00", + "CreateDate": "2015-02-06T18:40:53+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -8882,15 +20513,107 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJKTTTYV2IIHKLZ346", "PolicyName": "AmazonRDSReadOnlyAccess", "UpdateDate": "2017-08-28T21:36:32+00:00", "VersionId": "v3" }, + "AmazonRDSServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonRDSServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-01-08T18:17:46+00:00", + "DefaultVersionId": "v6", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateNetworkInterface", + "ec2:CreateSecurityGroup", + "ec2:DeleteNetworkInterface", + "ec2:DeleteSecurityGroup", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInternetGateways", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:ModifyVpcEndpoint", + "ec2:RevokeSecurityGroupIngress", + "ec2:CreateVpcEndpoint", + "ec2:DescribeVpcEndpoints", + "ec2:DeleteVpcEndpoints", + "ec2:AssignPrivateIpAddresses", + "ec2:UnassignPrivateIpAddresses" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/rds/*", + "arn:aws:logs:*:*:log-group:/aws/docdb/*", + "arn:aws:logs:*:*:log-group:/aws/neptune/*" + ] + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogStreams" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/rds/*:log-stream:*", + "arn:aws:logs:*:*:log-group:/aws/docdb/*:log-stream:*", + "arn:aws:logs:*:*:log-group:/aws/neptune/*:log-stream:*" + ] + }, + { + "Action": [ + "kinesis:CreateStream", + "kinesis:PutRecord", + "kinesis:PutRecords", + "kinesis:DescribeStream", + "kinesis:SplitShard", + "kinesis:MergeShards", + "kinesis:DeleteStream", + "kinesis:UpdateShardCount" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:kinesis:*:*:stream/aws-rds-das-*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIPEU5ZOBJWKWHUIBA", + "PolicyName": "AmazonRDSServiceRolePolicy", + "UpdateDate": "2019-04-16T20:12:27+00:00", + "VersionId": "v6" + }, "AmazonRedshiftFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonRedshiftFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-09-19T18:27:44+00:00", + "CreateDate": "2015-02-06T18:40:50+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -8933,11 +20656,52 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAISEKCHH4YDB46B5ZO", "PolicyName": "AmazonRedshiftFullAccess", "UpdateDate": "2017-09-19T18:27:44+00:00", "VersionId": "v2" }, + "AmazonRedshiftQueryEditor": { + "Arn": "arn:aws:iam::aws:policy/AmazonRedshiftQueryEditor", + "AttachmentCount": 0, + "CreateDate": "2018-10-04T22:50:32+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "redshift:GetClusterCredentials", + "redshift:ListSchemas", + "redshift:ListTables", + "redshift:ListDatabases", + "redshift:ExecuteQuery", + "redshift:FetchResults", + "redshift:CancelQuery", + "redshift:DescribeClusters", + "redshift:DescribeQuery", + "redshift:DescribeTable", + "redshift:ViewQueriesFromConsole", + "redshift:DescribeSavedQueries", + "redshift:CreateSavedQuery", + "redshift:DeleteSavedQueries", + "redshift:ModifySavedQuery" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAINVFHHP7CWVHTGBGM", + "PolicyName": "AmazonRedshiftQueryEditor", + "UpdateDate": "2018-10-04T22:50:32+00:00", + "VersionId": "v1" + }, "AmazonRedshiftReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonRedshiftReadOnlyAccess", "AttachmentCount": 0, @@ -8971,6 +20735,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIGD46KSON64QBSEZM", "PolicyName": "AmazonRedshiftReadOnlyAccess", "UpdateDate": "2015-02-06T18:40:51+00:00", @@ -8980,7 +20745,7 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonRedshiftServiceLinkedRolePolicy", "AttachmentCount": 0, "CreateDate": "2017-09-18T19:19:45+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -8988,7 +20753,7 @@ aws_managed_policies_data = """ "ec2:DescribeVpcs", "ec2:DescribeSubnets", "ec2:DescribeNetworkInterfaces", - "ec2:DescribeAddress", + "ec2:DescribeAddresses", "ec2:AssociateAddress", "ec2:DisassociateAddress", "ec2:CreateNetworkInterface", @@ -9004,10 +20769,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJPY2VXNRUYOY3SRZS", "PolicyName": "AmazonRedshiftServiceLinkedRolePolicy", - "UpdateDate": "2017-09-18T19:19:45+00:00", - "VersionId": "v1" + "UpdateDate": "2017-09-25T21:20:15+00:00", + "VersionId": "v2" }, "AmazonRekognitionFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonRekognitionFullAccess", @@ -9029,6 +20795,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIWDAOK6AIFDVX6TT6", "PolicyName": "AmazonRekognitionFullAccess", "UpdateDate": "2016-11-30T14:40:44+00:00", @@ -9038,7 +20805,7 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AmazonRekognitionReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2016-11-30T14:58:06+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -9049,7 +20816,19 @@ aws_managed_policies_data = """ "rekognition:ListCollections", "rekognition:ListFaces", "rekognition:SearchFaces", - "rekognition:SearchFacesByImage" + "rekognition:SearchFacesByImage", + "rekognition:DetectText", + "rekognition:GetCelebrityInfo", + "rekognition:RecognizeCelebrities", + "rekognition:DetectModerationLabels", + "rekognition:GetLabelDetection", + "rekognition:GetFaceDetection", + "rekognition:GetContentModeration", + "rekognition:GetPersonTracking", + "rekognition:GetCelebrityRecognition", + "rekognition:GetFaceSearch", + "rekognition:DescribeStreamProcessor", + "rekognition:ListStreamProcessors" ], "Effect": "Allow", "Resource": "*" @@ -9060,9 +20839,158 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAILWSUHXUY4ES43SA4", "PolicyName": "AmazonRekognitionReadOnlyAccess", - "UpdateDate": "2016-11-30T14:58:06+00:00", + "UpdateDate": "2017-12-06T23:28:39+00:00", + "VersionId": "v2" + }, + "AmazonRekognitionServiceRole": { + "Arn": "arn:aws:iam::aws:policy/service-role/AmazonRekognitionServiceRole", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T16:52:13+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "arn:aws:sns:*:*:AmazonRekognition*" + }, + { + "Action": [ + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": "arn:aws:kinesis:*:*:stream/AmazonRekognition*" + }, + { + "Action": [ + "kinesisvideo:GetDataEndpoint", + "kinesisvideo:GetMedia" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJI6Q3CUQAVBJ2CTE2", + "PolicyName": "AmazonRekognitionServiceRole", + "UpdateDate": "2017-11-29T16:52:13+00:00", + "VersionId": "v1" + }, + "AmazonRoute53AutoNamingFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonRoute53AutoNamingFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-01-18T18:40:41+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "route53:GetHostedZone", + "route53:ListHostedZonesByName", + "route53:CreateHostedZone", + "route53:DeleteHostedZone", + "route53:ChangeResourceRecordSets", + "route53:CreateHealthCheck", + "route53:GetHealthCheck", + "route53:DeleteHealthCheck", + "route53:UpdateHealthCheck", + "ec2:DescribeVpcs", + "ec2:DescribeRegions", + "servicediscovery:*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJCNJBBLMJN2ZMV62Y", + "PolicyName": "AmazonRoute53AutoNamingFullAccess", + "UpdateDate": "2018-01-18T18:40:41+00:00", + "VersionId": "v1" + }, + "AmazonRoute53AutoNamingReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonRoute53AutoNamingReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-01-18T03:02:59+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "servicediscovery:Get*", + "servicediscovery:List*" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJBPMV2EFBFFKJ6SI4", + "PolicyName": "AmazonRoute53AutoNamingReadOnlyAccess", + "UpdateDate": "2018-01-18T03:02:59+00:00", + "VersionId": "v1" + }, + "AmazonRoute53AutoNamingRegistrantAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonRoute53AutoNamingRegistrantAccess", + "AttachmentCount": 0, + "CreateDate": "2018-03-12T22:33:20+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "route53:GetHostedZone", + "route53:ListHostedZonesByName", + "route53:ChangeResourceRecordSets", + "route53:CreateHealthCheck", + "route53:GetHealthCheck", + "route53:DeleteHealthCheck", + "route53:UpdateHealthCheck", + "servicediscovery:Get*", + "servicediscovery:List*", + "servicediscovery:RegisterInstance", + "servicediscovery:DeregisterInstance" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJKXLG7EKP2O5SVZW6", + "PolicyName": "AmazonRoute53AutoNamingRegistrantAccess", + "UpdateDate": "2018-03-12T22:33:20+00:00", "VersionId": "v1" }, "AmazonRoute53DomainsFullAccess": { @@ -9088,6 +21016,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIPAFBMIYUILMOKL6G", "PolicyName": "AmazonRoute53DomainsFullAccess", "UpdateDate": "2015-02-06T18:40:56+00:00", @@ -9116,6 +21045,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIDRINP6PPTRXYVQCI", "PolicyName": "AmazonRoute53DomainsReadOnlyAccess", "UpdateDate": "2015-02-06T18:40:57+00:00", @@ -9124,8 +21054,8 @@ aws_managed_policies_data = """ "AmazonRoute53FullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonRoute53FullAccess", "AttachmentCount": 0, - "CreateDate": "2017-02-14T21:25:53+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2015-02-06T18:40:54+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -9137,8 +21067,9 @@ aws_managed_policies_data = """ "elasticbeanstalk:DescribeEnvironments", "s3:ListBucket", "s3:GetBucketLocation", - "s3:GetBucketWebsiteConfiguration", + "s3:GetBucketWebsite", "ec2:DescribeVpcs", + "ec2:DescribeVpcEndpoints", "ec2:DescribeRegions", "sns:ListTopics", "sns:ListSubscriptionsByTopic", @@ -9147,6 +21078,11 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "apigateway:GET", + "Effect": "Allow", + "Resource": "arn:aws:apigateway:*::/domainnames" } ], "Version": "2012-10-17" @@ -9154,15 +21090,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJWVDLG5RPST6PHQ3A", "PolicyName": "AmazonRoute53FullAccess", - "UpdateDate": "2017-02-14T21:25:53+00:00", - "VersionId": "v2" + "UpdateDate": "2018-12-20T21:42:00+00:00", + "VersionId": "v4" }, "AmazonRoute53ReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonRoute53ReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-11-15T21:15:16+00:00", + "CreateDate": "2015-02-06T18:40:55+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -9183,14 +21120,84 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAITOYK2ZAOQFXV2JNC", "PolicyName": "AmazonRoute53ReadOnlyAccess", "UpdateDate": "2016-11-15T21:15:16+00:00", "VersionId": "v2" }, + "AmazonRoute53ResolverFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonRoute53ResolverFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-05-30T18:10:50+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "route53resolver:*", + "ec2:DescribeSubnets", + "ec2:CreateNetworkInterface", + "ec2:DeleteNetworkInterface", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DescribeNetworkInterfaces", + "ec2:CreateNetworkInterfacePermission", + "ec2:DescribeSecurityGroups", + "ec2:DescribeVpcs" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4MZN2MQCY3", + "PolicyName": "AmazonRoute53ResolverFullAccess", + "UpdateDate": "2019-05-30T18:10:50+00:00", + "VersionId": "v1" + }, + "AmazonRoute53ResolverReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonRoute53ResolverReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2019-05-30T18:11:31+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "route53resolver:Get*", + "route53resolver:List*", + "ec2:DescribeNetworkInterface", + "ec2:DescribeSecurityGroups", + "ec2:DescribeVpcs", + "ec2:DescribeSubnets" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4CARVKYCWY", + "PolicyName": "AmazonRoute53ResolverReadOnlyAccess", + "UpdateDate": "2019-05-30T18:11:31+00:00", + "VersionId": "v1" + }, "AmazonS3FullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonS3FullAccess", - "AttachmentCount": 1, + "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:58+00:00", "DefaultVersionId": "v1", "Document": { @@ -9206,6 +21213,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIFIR6V6BVTRAHWINE", "PolicyName": "AmazonS3FullAccess", "UpdateDate": "2015-02-06T18:40:58+00:00", @@ -9232,6 +21240,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIZTJ4DXE7G6AGAE6M", "PolicyName": "AmazonS3ReadOnlyAccess", "UpdateDate": "2015-02-06T18:40:59+00:00", @@ -9257,6 +21266,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ2P4NXCHAT7NDPNR4", "PolicyName": "AmazonSESFullAccess", "UpdateDate": "2015-02-06T18:41:02+00:00", @@ -9283,6 +21293,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAINV2XPFRMWJJNSCGI", "PolicyName": "AmazonSESReadOnlyAccess", "UpdateDate": "2015-02-06T18:41:03+00:00", @@ -9308,6 +21319,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJWEKLCXXUNT2SOLSG", "PolicyName": "AmazonSNSFullAccess", "UpdateDate": "2015-02-06T18:41:05+00:00", @@ -9334,6 +21346,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIZGQCQTFOFPMHSB6W", "PolicyName": "AmazonSNSReadOnlyAccess", "UpdateDate": "2015-02-06T18:41:06+00:00", @@ -9365,6 +21378,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJK5GQB7CIK7KHY2GA", "PolicyName": "AmazonSNSRole", "UpdateDate": "2015-02-06T18:41:30+00:00", @@ -9390,6 +21404,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI65L554VRJ33ECQS6", "PolicyName": "AmazonSQSFullAccess", "UpdateDate": "2015-02-06T18:41:07+00:00", @@ -9399,12 +21414,14 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AmazonSQSReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:41:08+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ "sqs:GetQueueAttributes", + "sqs:GetQueueUrl", + "sqs:ListDeadLetterSourceQueues", "sqs:ListQueues" ], "Effect": "Allow", @@ -9416,10 +21433,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIUGSSQY362XGCM6KW", "PolicyName": "AmazonSQSReadOnlyAccess", - "UpdateDate": "2015-02-06T18:41:08+00:00", - "VersionId": "v1" + "UpdateDate": "2018-08-20T23:35:49+00:00", + "VersionId": "v2" }, "AmazonSSMAutomationApproverAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonSSMAutomationApproverAccess", @@ -9445,6 +21463,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIDSSXIRWBSLWWIORC", "PolicyName": "AmazonSSMAutomationApproverAccess", "UpdateDate": "2017-08-07T23:07:28+00:00", @@ -9453,7 +21472,7 @@ aws_managed_policies_data = """ "AmazonSSMAutomationRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole", "AttachmentCount": 0, - "CreateDate": "2017-07-24T23:29:12+00:00", + "CreateDate": "2016-12-05T22:09:55+00:00", "DefaultVersionId": "v5", "Document": { "Statement": [ @@ -9516,16 +21535,44 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJIBQCTBCXD2XRNB6W", "PolicyName": "AmazonSSMAutomationRole", "UpdateDate": "2017-07-24T23:29:12+00:00", "VersionId": "v5" }, + "AmazonSSMDirectoryServiceAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonSSMDirectoryServiceAccess", + "AttachmentCount": 0, + "CreateDate": "2019-03-15T17:44:38+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ds:CreateComputer", + "ds:DescribeDirectories" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ7OJQH3CZU674ERII", + "PolicyName": "AmazonSSMDirectoryServiceAccess", + "UpdateDate": "2019-03-15T17:44:38+00:00", + "VersionId": "v1" + }, "AmazonSSMFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonSSMFullAccess", "AttachmentCount": 0, - "CreateDate": "2016-03-07T21:09:12+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2015-05-29T17:39:47+00:00", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -9540,6 +21587,24 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "ssm.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/ssm.amazonaws.com/AWSServiceRoleForAmazonSSM*" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/ssm.amazonaws.com/AWSServiceRoleForAmazonSSM*" } ], "Version": "2012-10-17" @@ -9547,15 +21612,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJA7V6HI4ISQFMDYAG", "PolicyName": "AmazonSSMFullAccess", - "UpdateDate": "2016-03-07T21:09:12+00:00", - "VersionId": "v2" + "UpdateDate": "2018-07-23T22:53:18+00:00", + "VersionId": "v3" }, "AmazonSSMMaintenanceWindowRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AmazonSSMMaintenanceWindowRole", "AttachmentCount": 0, - "CreateDate": "2017-08-09T20:49:14+00:00", + "CreateDate": "2016-12-01T15:57:54+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -9602,11 +21668,74 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJV3JNYSTZ47VOXYME", "PolicyName": "AmazonSSMMaintenanceWindowRole", "UpdateDate": "2017-08-09T20:49:14+00:00", "VersionId": "v2" }, + "AmazonSSMManagedInstanceCore": { + "Arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore", + "AttachmentCount": 0, + "CreateDate": "2019-03-15T17:22:12+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ssm:DescribeAssociation", + "ssm:GetDeployablePatchSnapshotForInstance", + "ssm:GetDocument", + "ssm:DescribeDocument", + "ssm:GetManifest", + "ssm:GetParameter", + "ssm:GetParameters", + "ssm:ListAssociations", + "ssm:ListInstanceAssociations", + "ssm:PutInventory", + "ssm:PutComplianceItems", + "ssm:PutConfigurePackageResult", + "ssm:UpdateAssociationStatus", + "ssm:UpdateInstanceAssociationStatus", + "ssm:UpdateInstanceInformation" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssmmessages:CreateControlChannel", + "ssmmessages:CreateDataChannel", + "ssmmessages:OpenControlChannel", + "ssmmessages:OpenDataChannel" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2messages:AcknowledgeMessage", + "ec2messages:DeleteMessage", + "ec2messages:FailMessage", + "ec2messages:GetEndpoint", + "ec2messages:GetMessages", + "ec2messages:SendReply" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIXSHM2BNB2D3AXXRU", + "PolicyName": "AmazonSSMManagedInstanceCore", + "UpdateDate": "2019-05-23T16:54:21+00:00", + "VersionId": "v2" + }, "AmazonSSMReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess", "AttachmentCount": 0, @@ -9629,16 +21758,589 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJODSKQGGJTHRYZ5FC", "PolicyName": "AmazonSSMReadOnlyAccess", "UpdateDate": "2015-05-29T17:44:19+00:00", "VersionId": "v1" }, + "AmazonSSMServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonSSMServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-13T19:20:08+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "ssm:CancelCommand", + "ssm:GetCommandInvocation", + "ssm:ListCommandInvocations", + "ssm:ListCommands", + "ssm:SendCommand", + "ssm:GetAutomationExecution", + "ssm:GetParameters", + "ssm:StartAutomationExecution" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:lambda:*:*:function:SSM*", + "arn:aws:lambda:*:*:function:*:SSM*" + ] + }, + { + "Action": [ + "states:DescribeExecution", + "states:StartExecution" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:states:*:*:stateMachine:SSM*", + "arn:aws:states:*:*:execution:SSM*" + ] + }, + { + "Action": [ + "resource-groups:ListGroups", + "resource-groups:ListGroupResources" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "ssm.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIXJ26NUGBA3TCV7EC", + "PolicyName": "AmazonSSMServiceRolePolicy", + "UpdateDate": "2018-07-25T22:14:20+00:00", + "VersionId": "v3" + }, + "AmazonSageMakerFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonSageMakerFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T13:07:59+00:00", + "DefaultVersionId": "v11", + "Document": { + "Statement": [ + { + "Action": [ + "sagemaker:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "application-autoscaling:DeleteScalingPolicy", + "application-autoscaling:DeleteScheduledAction", + "application-autoscaling:DeregisterScalableTarget", + "application-autoscaling:DescribeScalableTargets", + "application-autoscaling:DescribeScalingActivities", + "application-autoscaling:DescribeScalingPolicies", + "application-autoscaling:DescribeScheduledActions", + "application-autoscaling:PutScalingPolicy", + "application-autoscaling:PutScheduledAction", + "application-autoscaling:RegisterScalableTarget", + "aws-marketplace:ViewSubscriptions", + "cloudwatch:DeleteAlarms", + "cloudwatch:DescribeAlarms", + "cloudwatch:GetMetricData", + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics", + "cloudwatch:PutMetricAlarm", + "cloudwatch:PutMetricData", + "codecommit:BatchGetRepositories", + "codecommit:CreateRepository", + "codecommit:GetRepository", + "codecommit:ListBranches", + "codecommit:ListRepositories", + "cognito-idp:AdminAddUserToGroup", + "cognito-idp:AdminCreateUser", + "cognito-idp:AdminDeleteUser", + "cognito-idp:AdminDisableUser", + "cognito-idp:AdminEnableUser", + "cognito-idp:AdminRemoveUserFromGroup", + "cognito-idp:CreateGroup", + "cognito-idp:CreateUserPool", + "cognito-idp:CreateUserPoolClient", + "cognito-idp:CreateUserPoolDomain", + "cognito-idp:DescribeUserPool", + "cognito-idp:DescribeUserPoolClient", + "cognito-idp:ListGroups", + "cognito-idp:ListIdentityProviders", + "cognito-idp:ListUserPoolClients", + "cognito-idp:ListUserPools", + "cognito-idp:ListUsers", + "cognito-idp:ListUsersInGroup", + "cognito-idp:UpdateUserPool", + "cognito-idp:UpdateUserPoolClient", + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:CreateVpcEndpoint", + "ec2:DeleteNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", + "ec2:DescribeDhcpOptions", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcs", + "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:CreateRepository", + "ecr:GetAuthorizationToken", + "ecr:GetDownloadUrlForLayer", + "ecr:Describe*", + "elastic-inference:Connect", + "glue:CreateJob", + "glue:DeleteJob", + "glue:GetJob", + "glue:GetJobRun", + "glue:GetJobRuns", + "glue:GetJobs", + "glue:ResetJobBookmark", + "glue:StartJobRun", + "glue:UpdateJob", + "groundtruthlabeling:*", + "iam:ListRoles", + "kms:DescribeKey", + "kms:ListAliases", + "lambda:ListFunctions", + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:DescribeLogStreams", + "logs:GetLogEvents", + "logs:PutLogEvents", + "sns:ListTopics" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ecr:SetRepositoryPolicy", + "ecr:CompleteLayerUpload", + "ecr:BatchDeleteImage", + "ecr:UploadLayerPart", + "ecr:DeleteRepositoryPolicy", + "ecr:InitiateLayerUpload", + "ecr:DeleteRepository", + "ecr:PutImage" + ], + "Effect": "Allow", + "Resource": "arn:aws:ecr:*:*:repository/*sagemaker*" + }, + { + "Action": [ + "codecommit:GitPull", + "codecommit:GitPush" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:codecommit:*:*:*sagemaker*", + "arn:aws:codecommit:*:*:*SageMaker*", + "arn:aws:codecommit:*:*:*Sagemaker*" + ] + }, + { + "Action": [ + "secretsmanager:ListSecrets" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "secretsmanager:DescribeSecret", + "secretsmanager:GetSecretValue", + "secretsmanager:CreateSecret" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:secretsmanager:*:*:secret:AmazonSageMaker-*" + ] + }, + { + "Action": [ + "secretsmanager:DescribeSecret", + "secretsmanager:GetSecretValue" + ], + "Condition": { + "StringEquals": { + "secretsmanager:ResourceTag/SageMaker": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "robomaker:CreateSimulationApplication", + "robomaker:DescribeSimulationApplication", + "robomaker:DeleteSimulationApplication" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "robomaker:CreateSimulationJob", + "robomaker:DescribeSimulationJob", + "robomaker:CancelSimulationJob" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "s3:GetObject", + "s3:PutObject", + "s3:DeleteObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*SageMaker*", + "arn:aws:s3:::*Sagemaker*", + "arn:aws:s3:::*sagemaker*", + "arn:aws:s3:::*aws-glue*" + ] + }, + { + "Action": [ + "s3:CreateBucket", + "s3:GetBucketLocation", + "s3:ListBucket", + "s3:ListAllMyBuckets" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetObject" + ], + "Condition": { + "StringEqualsIgnoreCase": { + "s3:ExistingObjectTag/SageMaker": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:InvokeFunction" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:lambda:*:*:function:*SageMaker*", + "arn:aws:lambda:*:*:function:*sagemaker*", + "arn:aws:lambda:*:*:function:*Sagemaker*", + "arn:aws:lambda:*:*:function:*LabelingFunction*" + ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "sagemaker.application-autoscaling.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/sagemaker.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_SageMakerEndpoint" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "robomaker.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "sns:Subscribe", + "sns:CreateTopic" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:sns:*:*:*SageMaker*", + "arn:aws:sns:*:*:*Sagemaker*", + "arn:aws:sns:*:*:*sagemaker*" + ] + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": [ + "sagemaker.amazonaws.com", + "glue.amazonaws.com", + "robomaker.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJZ5IWYMXO5QDB4QOG", + "PolicyName": "AmazonSageMakerFullAccess", + "UpdateDate": "2019-05-09T04:44:05+00:00", + "VersionId": "v11" + }, + "AmazonSageMakerReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AmazonSageMakerReadOnly", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T13:07:09+00:00", + "DefaultVersionId": "v5", + "Document": { + "Statement": [ + { + "Action": [ + "application-autoscaling:DescribeScalableTargets", + "application-autoscaling:DescribeScalingActivities", + "application-autoscaling:DescribeScalingPolicies", + "application-autoscaling:DescribeScheduledActions", + "aws-marketplace:ViewSubscriptions", + "aws-marketplace:ViewSubscriptions", + "cloudwatch:DescribeAlarms", + "cognito-idp:DescribeUserPool", + "cognito-idp:DescribeUserPoolClient", + "cognito-idp:ListGroups", + "cognito-idp:ListIdentityProviders", + "cognito-idp:ListUserPoolClients", + "cognito-idp:ListUserPools", + "cognito-idp:ListUsers", + "cognito-idp:ListUsersInGroup", + "ecr:Describe*", + "sagemaker:Describe*", + "sagemaker:GetSearchSuggestions", + "sagemaker:List*", + "sagemaker:Search" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJTZ2FTFCQ6CFLQA2O", + "PolicyName": "AmazonSageMakerReadOnly", + "UpdateDate": "2019-01-04T22:22:07+00:00", + "VersionId": "v5" + }, + "AmazonSumerianFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonSumerianFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-04-24T20:14:16+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "sumerian:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJMGUENPB56MXVVGBE", + "PolicyName": "AmazonSumerianFullAccess", + "UpdateDate": "2018-04-24T20:14:16+00:00", + "VersionId": "v1" + }, + "AmazonTextractFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonTextractFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T19:07:42+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "textract:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIQDD47A7H3GBVPWOQ", + "PolicyName": "AmazonTextractFullAccess", + "UpdateDate": "2018-11-28T19:07:42+00:00", + "VersionId": "v1" + }, + "AmazonTextractServiceRole": { + "Arn": "arn:aws:iam::aws:policy/service-role/AmazonTextractServiceRole", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T19:12:16+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "arn:aws:sns:*:*:AmazonTextract*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJBDSAWESWLL34WASG", + "PolicyName": "AmazonTextractServiceRole", + "UpdateDate": "2018-11-28T19:12:16+00:00", + "VersionId": "v1" + }, + "AmazonTranscribeFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonTranscribeFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-04-04T16:06:16+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "transcribe:*" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*transcribe*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAINAV45F5NT5RMFO7K", + "PolicyName": "AmazonTranscribeFullAccess", + "UpdateDate": "2018-04-04T16:06:16+00:00", + "VersionId": "v1" + }, + "AmazonTranscribeReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonTranscribeReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-04-04T16:05:06+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "transcribe:Get*", + "transcribe:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJM6JONISXCAZKFCAO", + "PolicyName": "AmazonTranscribeReadOnlyAccess", + "UpdateDate": "2018-04-04T16:05:06+00:00", + "VersionId": "v1" + }, "AmazonVPCCrossAccountNetworkInterfaceOperations": { "Arn": "arn:aws:iam::aws:policy/AmazonVPCCrossAccountNetworkInterfaceOperations", "AttachmentCount": 0, "CreateDate": "2017-07-18T20:47:16+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -9659,8 +22361,11 @@ aws_managed_policies_data = """ "ec2:CreateNetworkInterface", "ec2:DeleteNetworkInterface", "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterfacePermission", + "ec2:DescribeNetworkInterfacePermissions", "ec2:ModifyNetworkInterfaceAttribute", "ec2:DescribeNetworkInterfaceAttribute", + "ec2:DescribeAvailabilityZones", "ec2:DescribeVpcs", "ec2:DescribeSubnets" ], @@ -9685,26 +22390,31 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ53Y4ZY5OHP4CNRJC", "PolicyName": "AmazonVPCCrossAccountNetworkInterfaceOperations", - "UpdateDate": "2017-07-18T20:47:16+00:00", - "VersionId": "v1" + "UpdateDate": "2019-01-07T19:16:23+00:00", + "VersionId": "v3" }, "AmazonVPCFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonVPCFullAccess", - "AttachmentCount": 1, - "CreateDate": "2015-12-17T17:25:44+00:00", - "DefaultVersionId": "v5", + "AttachmentCount": 0, + "CreateDate": "2015-02-06T18:41:16+00:00", + "DefaultVersionId": "v7", "Document": { "Statement": [ { "Action": [ "ec2:AcceptVpcPeeringConnection", + "ec2:AcceptVpcEndpointConnections", "ec2:AllocateAddress", + "ec2:AssignIpv6Addresses", "ec2:AssignPrivateIpAddresses", "ec2:AssociateAddress", "ec2:AssociateDhcpOptions", "ec2:AssociateRouteTable", + "ec2:AssociateSubnetCidrBlock", + "ec2:AssociateVpcCidrBlock", "ec2:AttachClassicLinkVpc", "ec2:AttachInternetGateway", "ec2:AttachNetworkInterface", @@ -9712,7 +22422,10 @@ aws_managed_policies_data = """ "ec2:AuthorizeSecurityGroupEgress", "ec2:AuthorizeSecurityGroupIngress", "ec2:CreateCustomerGateway", + "ec2:CreateDefaultSubnet", + "ec2:CreateDefaultVpc", "ec2:CreateDhcpOptions", + "ec2:CreateEgressOnlyInternetGateway", "ec2:CreateFlowLogs", "ec2:CreateInternetGateway", "ec2:CreateNatGateway", @@ -9720,6 +22433,7 @@ aws_managed_policies_data = """ "ec2:CreateNetworkAcl", "ec2:CreateNetworkAclEntry", "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", "ec2:CreateRoute", "ec2:CreateRouteTable", "ec2:CreateSecurityGroup", @@ -9727,18 +22441,22 @@ aws_managed_policies_data = """ "ec2:CreateTags", "ec2:CreateVpc", "ec2:CreateVpcEndpoint", + "ec2:CreateVpcEndpointConnectionNotification", + "ec2:CreateVpcEndpointServiceConfiguration", "ec2:CreateVpcPeeringConnection", "ec2:CreateVpnConnection", "ec2:CreateVpnConnectionRoute", "ec2:CreateVpnGateway", "ec2:DeleteCustomerGateway", "ec2:DeleteDhcpOptions", + "ec2:DeleteEgressOnlyInternetGateway", "ec2:DeleteFlowLogs", "ec2:DeleteInternetGateway", "ec2:DeleteNatGateway", "ec2:DeleteNetworkAcl", "ec2:DeleteNetworkAclEntry", "ec2:DeleteNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", "ec2:DeleteRoute", "ec2:DeleteRouteTable", "ec2:DeleteSecurityGroup", @@ -9746,15 +22464,19 @@ aws_managed_policies_data = """ "ec2:DeleteTags", "ec2:DeleteVpc", "ec2:DeleteVpcEndpoints", + "ec2:DeleteVpcEndpointConnectionNotifications", + "ec2:DeleteVpcEndpointServiceConfigurations", "ec2:DeleteVpcPeeringConnection", "ec2:DeleteVpnConnection", "ec2:DeleteVpnConnectionRoute", "ec2:DeleteVpnGateway", + "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", "ec2:DescribeAvailabilityZones", "ec2:DescribeClassicLinkInstances", "ec2:DescribeCustomerGateways", "ec2:DescribeDhcpOptions", + "ec2:DescribeEgressOnlyInternetGateways", "ec2:DescribeFlowLogs", "ec2:DescribeInstances", "ec2:DescribeInternetGateways", @@ -9763,15 +22485,23 @@ aws_managed_policies_data = """ "ec2:DescribeNatGateways", "ec2:DescribeNetworkAcls", "ec2:DescribeNetworkInterfaceAttribute", + "ec2:DescribeNetworkInterfacePermissions", "ec2:DescribeNetworkInterfaces", "ec2:DescribePrefixLists", "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroupReferences", "ec2:DescribeSecurityGroups", + "ec2:DescribeStaleSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeTags", "ec2:DescribeVpcAttribute", "ec2:DescribeVpcClassicLink", + "ec2:DescribeVpcClassicLinkDnsSupport", + "ec2:DescribeVpcEndpointConnectionNotifications", + "ec2:DescribeVpcEndpointConnections", "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcEndpointServiceConfigurations", + "ec2:DescribeVpcEndpointServicePermissions", "ec2:DescribeVpcEndpointServices", "ec2:DescribeVpcPeeringConnections", "ec2:DescribeVpcs", @@ -9783,15 +22513,25 @@ aws_managed_policies_data = """ "ec2:DetachVpnGateway", "ec2:DisableVgwRoutePropagation", "ec2:DisableVpcClassicLink", + "ec2:DisableVpcClassicLinkDnsSupport", "ec2:DisassociateAddress", "ec2:DisassociateRouteTable", + "ec2:DisassociateSubnetCidrBlock", + "ec2:DisassociateVpcCidrBlock", "ec2:EnableVgwRoutePropagation", "ec2:EnableVpcClassicLink", + "ec2:EnableVpcClassicLinkDnsSupport", "ec2:ModifyNetworkInterfaceAttribute", "ec2:ModifySubnetAttribute", "ec2:ModifyVpcAttribute", "ec2:ModifyVpcEndpoint", + "ec2:ModifyVpcEndpointConnectionNotification", + "ec2:ModifyVpcEndpointServiceConfiguration", + "ec2:ModifyVpcEndpointServicePermissions", + "ec2:ModifyVpcPeeringConnectionOptions", + "ec2:ModifyVpcTenancy", "ec2:MoveAddressToVpc", + "ec2:RejectVpcEndpointConnections", "ec2:RejectVpcPeeringConnection", "ec2:ReleaseAddress", "ec2:ReplaceNetworkAclAssociation", @@ -9802,7 +22542,10 @@ aws_managed_policies_data = """ "ec2:RestoreAddressToClassic", "ec2:RevokeSecurityGroupEgress", "ec2:RevokeSecurityGroupIngress", - "ec2:UnassignPrivateIpAddresses" + "ec2:UnassignIpv6Addresses", + "ec2:UnassignPrivateIpAddresses", + "ec2:UpdateSecurityGroupRuleDescriptionsEgress", + "ec2:UpdateSecurityGroupRuleDescriptionsIngress" ], "Effect": "Allow", "Resource": "*" @@ -9813,39 +22556,50 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJBWPGNOVKZD3JI2P2", "PolicyName": "AmazonVPCFullAccess", - "UpdateDate": "2015-12-17T17:25:44+00:00", - "VersionId": "v5" + "UpdateDate": "2018-03-15T18:30:25+00:00", + "VersionId": "v7" }, "AmazonVPCReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonVPCReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2015-12-17T17:25:56+00:00", - "DefaultVersionId": "v4", + "CreateDate": "2015-02-06T18:41:17+00:00", + "DefaultVersionId": "v6", "Document": { "Statement": [ { "Action": [ + "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", "ec2:DescribeClassicLinkInstances", "ec2:DescribeCustomerGateways", "ec2:DescribeDhcpOptions", + "ec2:DescribeEgressOnlyInternetGateways", "ec2:DescribeFlowLogs", "ec2:DescribeInternetGateways", "ec2:DescribeMovingAddresses", "ec2:DescribeNatGateways", "ec2:DescribeNetworkAcls", "ec2:DescribeNetworkInterfaceAttribute", + "ec2:DescribeNetworkInterfacePermissions", "ec2:DescribeNetworkInterfaces", "ec2:DescribePrefixLists", "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroupReferences", "ec2:DescribeSecurityGroups", + "ec2:DescribeStaleSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeTags", "ec2:DescribeVpcAttribute", "ec2:DescribeVpcClassicLink", + "ec2:DescribeVpcClassicLinkDnsSupport", "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcEndpointConnectionNotifications", + "ec2:DescribeVpcEndpointConnections", + "ec2:DescribeVpcEndpointServiceConfigurations", + "ec2:DescribeVpcEndpointServicePermissions", "ec2:DescribeVpcEndpointServices", "ec2:DescribeVpcPeeringConnections", "ec2:DescribeVpcs", @@ -9861,16 +22615,136 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIICZJNOJN36GTG6CM", "PolicyName": "AmazonVPCReadOnlyAccess", - "UpdateDate": "2015-12-17T17:25:56+00:00", - "VersionId": "v4" + "UpdateDate": "2018-03-07T18:34:42+00:00", + "VersionId": "v6" + }, + "AmazonWorkLinkFullAccess": { + "Arn": "arn:aws:iam::aws:policy/AmazonWorkLinkFullAccess", + "AttachmentCount": 0, + "CreateDate": "2019-01-23T18:52:09+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "worklink:*" + ], + "Effect": "Allow", + "Resource": "arn:aws:worklink:*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJM4ITL7TEVURHCQSY", + "PolicyName": "AmazonWorkLinkFullAccess", + "UpdateDate": "2019-01-23T18:52:09+00:00", + "VersionId": "v1" + }, + "AmazonWorkLinkReadOnly": { + "Arn": "arn:aws:iam::aws:policy/AmazonWorkLinkReadOnly", + "AttachmentCount": 0, + "CreateDate": "2019-01-23T19:07:10+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "worklink:Describe*", + "worklink:List*" + ], + "Effect": "Allow", + "Resource": "arn:aws:worklink:*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIANQMFGU4EUUZKFQ4", + "PolicyName": "AmazonWorkLinkReadOnly", + "UpdateDate": "2019-01-23T19:07:10+00:00", + "VersionId": "v1" + }, + "AmazonWorkLinkServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonWorkLinkServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-03-18T18:00:16+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", + "ec2:CreateNetworkInterfacePermission", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DeleteNetworkInterface" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": "arn:aws:kinesis:*:*:stream/AmazonWorkLink-*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAINJJP6CO7ATFCV4CU", + "PolicyName": "AmazonWorkLinkServiceRolePolicy", + "UpdateDate": "2019-03-18T18:00:16+00:00", + "VersionId": "v1" + }, + "AmazonWorkMailEventsServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonWorkMailEventsServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-04-16T16:52:43+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAZKAPJZG4JG5LNO3U7", + "PolicyName": "AmazonWorkMailEventsServiceRolePolicy", + "UpdateDate": "2019-04-16T16:52:43+00:00", + "VersionId": "v1" }, "AmazonWorkMailFullAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonWorkMailFullAccess", "AttachmentCount": 0, - "CreateDate": "2017-04-20T08:35:49+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2015-02-06T18:40:41+00:00", + "DefaultVersionId": "v6", "Document": { "Statement": [ { @@ -9907,11 +22781,49 @@ aws_managed_policies_data = """ "ec2:RevokeSecurityGroupIngress", "kms:DescribeKey", "kms:ListAliases", + "lambda:ListFunctions", + "route53:ChangeResourceRecordSets", + "route53:ListHostedZones", + "route53:ListResourceRecordSets", + "route53domains:CheckDomainAvailability", + "route53domains:ListDomains", "ses:*", - "workmail:*" + "workmail:*", + "iam:ListRoles", + "logs:DescribeLogGroups", + "logs:CreateLogGroup", + "logs:PutRetentionPolicy" ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "events.workmail.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/events.workmail.amazonaws.com/AWSServiceRoleForAmazonWorkMailEvents*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:PassedToService": "events.workmail.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/*workmail*" } ], "Version": "2012-10-17" @@ -9919,16 +22831,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJQVKNMT7SVATQ4AUY", "PolicyName": "AmazonWorkMailFullAccess", - "UpdateDate": "2017-04-20T08:35:49+00:00", - "VersionId": "v3" + "UpdateDate": "2019-05-13T15:21:29+00:00", + "VersionId": "v6" }, "AmazonWorkMailReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AmazonWorkMailReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:42+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -9938,7 +22851,10 @@ aws_managed_policies_data = """ "workmail:Describe*", "workmail:Get*", "workmail:List*", - "workmail:Search*" + "workmail:Search*", + "lambda:ListFunctions", + "iam:ListRoles", + "logs:DescribeLogGroups" ], "Effect": "Allow", "Resource": "*" @@ -9949,15 +22865,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJHF7J65E2QFKCWAJM", "PolicyName": "AmazonWorkMailReadOnlyAccess", - "UpdateDate": "2015-02-06T18:40:42+00:00", - "VersionId": "v1" + "UpdateDate": "2019-05-13T15:12:46+00:00", + "VersionId": "v3" }, "AmazonWorkSpacesAdmin": { "Arn": "arn:aws:iam::aws:policy/AmazonWorkSpacesAdmin", "AttachmentCount": 0, - "CreateDate": "2016-08-18T23:08:42+00:00", + "CreateDate": "2015-09-22T22:21:15+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -9990,6 +22907,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ26AU6ATUQCT5KVJU", "PolicyName": "AmazonWorkSpacesAdmin", "UpdateDate": "2016-08-18T23:08:42+00:00", @@ -10013,6 +22931,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJPRL4KYETIH7XGTSS", "PolicyName": "AmazonWorkSpacesApplicationManagerAdminAccess", "UpdateDate": "2015-04-09T14:03:18+00:00", @@ -10054,6 +22973,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJLCDXYRINDMUXEVL6", "PolicyName": "AmazonZocaloFullAccess", "UpdateDate": "2015-02-06T18:41:13+00:00", @@ -10082,6 +23002,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAISRCSSJNS3QPKZJPM", "PolicyName": "AmazonZocaloReadOnlyAccess", "UpdateDate": "2015-02-06T18:41:14+00:00", @@ -10119,16 +23040,108 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIEL3HJCCWFVHA6KPG", "PolicyName": "ApplicationAutoScalingForAmazonAppStreamAccess", "UpdateDate": "2017-02-06T21:39:56+00:00", "VersionId": "v1" }, + "ApplicationDiscoveryServiceContinuousExportServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/ApplicationDiscoveryServiceContinuousExportServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-08-09T20:22:01+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "glue:CreateDatabase", + "glue:UpdateDatabase", + "glue:CreateTable", + "glue:UpdateTable", + "firehose:CreateDeliveryStream", + "firehose:DescribeDeliveryStream", + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "firehose:DeleteDeliveryStream", + "firehose:PutRecord", + "firehose:PutRecordBatch", + "firehose:UpdateDestination" + ], + "Effect": "Allow", + "Resource": "arn:aws:firehose:*:*:deliverystream/aws-application-discovery-service*" + }, + { + "Action": [ + "s3:CreateBucket", + "s3:ListBucket", + "s3:PutBucketLogging", + "s3:PutEncryptionConfiguration" + ], + "Effect": "Allow", + "Resource": "arn:aws:s3:::aws-application-discovery-service*" + }, + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": "arn:aws:s3:::aws-application-discovery-service*/*" + }, + { + "Action": [ + "logs:CreateLogStream", + "logs:PutRetentionPolicy" + ], + "Effect": "Allow", + "Resource": "arn:aws:logs:*:*:log-group:/aws/application-discovery-service/firehose*" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": "firehose.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/AWSApplicationDiscoveryServiceFirehose" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": "firehose.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/service-role/AWSApplicationDiscoveryServiceFirehose" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJMGMY3P6OEWOELRFE", + "PolicyName": "ApplicationDiscoveryServiceContinuousExportServiceRolePolicy", + "UpdateDate": "2018-08-13T22:31:21+00:00", + "VersionId": "v2" + }, "AutoScalingConsoleFullAccess": { "Arn": "arn:aws:iam::aws:policy/AutoScalingConsoleFullAccess", "AttachmentCount": 0, "CreateDate": "2017-01-12T19:43:16+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -10136,10 +23149,16 @@ aws_managed_policies_data = """ "ec2:AuthorizeSecurityGroupIngress", "ec2:CreateKeyPair", "ec2:CreateSecurityGroup", + "ec2:DescribeAccountAttributes", "ec2:DescribeAvailabilityZones", "ec2:DescribeImages", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstances", "ec2:DescribeKeyPairs", + "ec2:DescribeLaunchTemplateVersions", + "ec2:DescribePlacementGroups", "ec2:DescribeSecurityGroups", + "ec2:DescribeSpotInstanceRequests", "ec2:DescribeSubnets", "ec2:DescribeVpcs", "ec2:DescribeVpcClassicLink", @@ -10175,6 +23194,21 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": "iam:ListRoles", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "autoscaling.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -10182,10 +23216,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIYEN6FJGYYWJFFCZW", "PolicyName": "AutoScalingConsoleFullAccess", - "UpdateDate": "2017-01-12T19:43:16+00:00", - "VersionId": "v1" + "UpdateDate": "2018-02-06T23:15:36+00:00", + "VersionId": "v2" }, "AutoScalingConsoleReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/AutoScalingConsoleReadOnlyAccess", @@ -10237,6 +23272,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI3A7GDXOYQV3VUQMK", "PolicyName": "AutoScalingConsoleReadOnlyAccess", "UpdateDate": "2017-01-12T19:48:53+00:00", @@ -10246,7 +23282,7 @@ aws_managed_policies_data = """ "Arn": "arn:aws:iam::aws:policy/AutoScalingFullAccess", "AttachmentCount": 0, "CreateDate": "2017-01-12T19:31:58+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -10258,6 +23294,42 @@ aws_managed_policies_data = """ "Action": "cloudwatch:PutMetricAlarm", "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "ec2:DescribeAccountAttributes", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeImages", + "ec2:DescribeInstanceAttribute", + "ec2:DescribeInstances", + "ec2:DescribeKeyPairs", + "ec2:DescribeLaunchTemplateVersions", + "ec2:DescribePlacementGroups", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSpotInstanceRequests", + "ec2:DescribeSubnets", + "ec2:DescribeVpcClassicLink" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeTargetGroups" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "autoscaling.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -10265,10 +23337,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIAWRCSJDDXDXGPCFU", "PolicyName": "AutoScalingFullAccess", - "UpdateDate": "2017-01-12T19:31:58+00:00", - "VersionId": "v1" + "UpdateDate": "2018-02-06T21:59:13+00:00", + "VersionId": "v2" }, "AutoScalingNotificationAccessRole": { "Arn": "arn:aws:iam::aws:policy/service-role/AutoScalingNotificationAccessRole", @@ -10292,6 +23365,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIO2VMUPGDC5PZVXVA", "PolicyName": "AutoScalingNotificationAccessRole", "UpdateDate": "2015-02-06T18:41:22+00:00", @@ -10315,25 +23389,121 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIAFWUVLC2LPLSFTFG", "PolicyName": "AutoScalingReadOnlyAccess", "UpdateDate": "2017-01-12T19:39:35+00:00", "VersionId": "v1" }, + "AutoScalingServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/AutoScalingServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-01-08T23:10:55+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AttachClassicLinkVpc", + "ec2:CancelSpotInstanceRequests", + "ec2:CreateFleet", + "ec2:CreateTags", + "ec2:DeleteTags", + "ec2:Describe*", + "ec2:DetachClassicLinkVpc", + "ec2:ModifyInstanceAttribute", + "ec2:RequestSpotInstances", + "ec2:RunInstances", + "ec2:TerminateInstances" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "EC2InstanceManagement" + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringLike": { + "iam:PassedToService": "ec2.amazonaws.com*" + } + }, + "Effect": "Allow", + "Resource": "*", + "Sid": "EC2InstanceProfileManagement" + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "spot.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*", + "Sid": "EC2SpotManagement" + }, + { + "Action": [ + "elasticloadbalancing:Register*", + "elasticloadbalancing:Deregister*", + "elasticloadbalancing:Describe*" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "ELBManagement" + }, + { + "Action": [ + "cloudwatch:DeleteAlarms", + "cloudwatch:DescribeAlarms", + "cloudwatch:PutMetricAlarm" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "CWManagement" + }, + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "SNSManagement" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIC5D2V7MRWBMHGD7G", + "PolicyName": "AutoScalingServiceRolePolicy", + "UpdateDate": "2018-10-31T18:19:10+00:00", + "VersionId": "v2" + }, "Billing": { "Arn": "arn:aws:iam::aws:policy/job-function/Billing", "AttachmentCount": 0, "CreateDate": "2016-11-10T17:33:18+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ "aws-portal:*Billing", + "awsbillingconsole:*Billing", "aws-portal:*Usage", + "awsbillingconsole:*Usage", "aws-portal:*PaymentMethods", + "awsbillingconsole:*PaymentMethods", "budgets:ViewBudget", - "budgets:ModifyBudget" + "budgets:ModifyBudget", + "cur:*" ], "Effect": "Allow", "Resource": "*" @@ -10344,15 +23514,61 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/job-function/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIFTHXT6FFMIRT7ZEA", "PolicyName": "Billing", - "UpdateDate": "2016-11-10T17:33:18+00:00", - "VersionId": "v1" + "UpdateDate": "2018-02-06T23:46:37+00:00", + "VersionId": "v2" + }, + "ClientVPNServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/ClientVPNServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-12-10T21:20:25+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:DescribeSecurityGroups", + "ec2:DescribeVpcs", + "ec2:DescribeSubnets", + "ec2:DescribeInternetGateways", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DeleteNetworkInterface", + "ec2:DescribeAccountAttributes", + "ds:AuthorizeApplication", + "ds:DescribeDirectories", + "ds:GetDirectoryLimits", + "ds:ListAuthorizedApplications", + "ds:UnauthorizeApplication", + "logs:DescribeLogStreams", + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogGroups", + "acm:GetCertificate", + "acm:DescribeCertificate" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI2SV25KUCYQYS5N74", + "PolicyName": "ClientVPNServiceRolePolicy", + "UpdateDate": "2019-01-16T22:22:28+00:00", + "VersionId": "v2" }, "CloudFrontFullAccess": { "Arn": "arn:aws:iam::aws:policy/CloudFrontFullAccess", "AttachmentCount": 0, - "CreateDate": "2016-01-21T17:03:57+00:00", + "CreateDate": "2015-02-06T18:39:50+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -10380,6 +23596,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIPRV52SH6HDCCFY6U", "PolicyName": "CloudFrontFullAccess", "UpdateDate": "2016-01-21T17:03:57+00:00", @@ -10388,7 +23605,7 @@ aws_managed_policies_data = """ "CloudFrontReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/CloudFrontReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-01-21T17:03:28+00:00", + "CreateDate": "2015-02-06T18:39:55+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -10411,11 +23628,43 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJJZMNYOTZCNQP36LG", "PolicyName": "CloudFrontReadOnlyAccess", "UpdateDate": "2016-01-21T17:03:28+00:00", "VersionId": "v3" }, + "CloudHSMServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/CloudHSMServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-06T19:12:46+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents", + "logs:DescribeLogStreams" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJILYY7JP6JLMQG56I", + "PolicyName": "CloudHSMServiceRolePolicy", + "UpdateDate": "2017-11-06T19:12:46+00:00", + "VersionId": "v1" + }, "CloudSearchFullAccess": { "Arn": "arn:aws:iam::aws:policy/CloudSearchFullAccess", "AttachmentCount": 0, @@ -10436,6 +23685,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIM6OOWKQ7L7VBOZOC", "PolicyName": "CloudSearchFullAccess", "UpdateDate": "2015-02-06T18:39:56+00:00", @@ -10462,11 +23712,52 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJWPLX7N7BCC3RZLHW", "PolicyName": "CloudSearchReadOnlyAccess", "UpdateDate": "2015-02-06T18:39:57+00:00", "VersionId": "v1" }, + "CloudTrailServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/CloudTrailServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-10-24T21:21:44+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudtrail:*" + ], + "Effect": "Allow", + "Resource": "*", + "Sid": "CloudTrailFullAccess" + }, + { + "Action": [ + "organizations:DescribeAccount", + "organizations:DescribeOrganization", + "organizations:ListAccounts", + "organizations:ListAWSServiceAccessForOrganization" + ], + "Effect": "Allow", + "Resource": [ + "*" + ], + "Sid": "AwsOrgsAccess" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJXQJ45EGU6U7NQBW4", + "PolicyName": "CloudTrailServiceRolePolicy", + "UpdateDate": "2018-10-24T21:21:44+00:00", + "VersionId": "v1" + }, "CloudWatchActionsEC2Access": { "Arn": "arn:aws:iam::aws:policy/CloudWatchActionsEC2Access", "AttachmentCount": 0, @@ -10491,11 +23782,91 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIOWD4E3FVSORSZTGU", "PolicyName": "CloudWatchActionsEC2Access", "UpdateDate": "2015-07-07T00:00:33+00:00", "VersionId": "v1" }, + "CloudWatchAgentAdminPolicy": { + "Arn": "arn:aws:iam::aws:policy/CloudWatchAgentAdminPolicy", + "AttachmentCount": 0, + "CreateDate": "2018-03-07T00:52:31+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudwatch:PutMetricData", + "ec2:DescribeTags", + "logs:PutLogEvents", + "logs:DescribeLogStreams", + "logs:DescribeLogGroups", + "logs:CreateLogStream", + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:GetParameter", + "ssm:PutParameter" + ], + "Effect": "Allow", + "Resource": "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAICMXPKT7EBAF6KR3O", + "PolicyName": "CloudWatchAgentAdminPolicy", + "UpdateDate": "2018-03-07T00:52:31+00:00", + "VersionId": "v1" + }, + "CloudWatchAgentServerPolicy": { + "Arn": "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy", + "AttachmentCount": 0, + "CreateDate": "2018-03-07T01:06:44+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "cloudwatch:PutMetricData", + "ec2:DescribeTags", + "logs:PutLogEvents", + "logs:DescribeLogStreams", + "logs:DescribeLogGroups", + "logs:CreateLogStream", + "logs:CreateLogGroup" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ssm:GetParameter" + ], + "Effect": "Allow", + "Resource": "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIGOPKN7KRDAKTLG4I", + "PolicyName": "CloudWatchAgentServerPolicy", + "UpdateDate": "2018-03-07T01:06:44+00:00", + "VersionId": "v1" + }, "CloudWatchEventsBuiltInTargetExecutionAccess": { "Arn": "arn:aws:iam::aws:policy/service-role/CloudWatchEventsBuiltInTargetExecutionAccess", "AttachmentCount": 0, @@ -10521,6 +23892,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIC5AQ5DATYSNF4AUM", "PolicyName": "CloudWatchEventsBuiltInTargetExecutionAccess", "UpdateDate": "2016-01-14T18:35:49+00:00", @@ -10551,6 +23923,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJZLOYLNHESMYOJAFU", "PolicyName": "CloudWatchEventsFullAccess", "UpdateDate": "2016-01-14T18:37:08+00:00", @@ -10577,6 +23950,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJJXD6JKJLK2WDLZNO", "PolicyName": "CloudWatchEventsInvocationAccess", "UpdateDate": "2016-01-14T18:36:33+00:00", @@ -10585,7 +23959,7 @@ aws_managed_policies_data = """ "CloudWatchEventsReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/CloudWatchEventsReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-10T17:25:34+00:00", + "CreateDate": "2016-01-14T18:27:18+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -10608,24 +23982,31 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIILJPXXA6F7GYLYBS", "PolicyName": "CloudWatchEventsReadOnlyAccess", "UpdateDate": "2017-08-10T17:25:34+00:00", "VersionId": "v2" }, - "CloudWatchFullAccess": { - "Arn": "arn:aws:iam::aws:policy/CloudWatchFullAccess", + "CloudWatchEventsServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/CloudWatchEventsServiceRolePolicy", "AttachmentCount": 0, - "CreateDate": "2015-02-06T18:40:00+00:00", + "CreateDate": "2017-11-17T00:42:04+00:00", "DefaultVersionId": "v1", "Document": { "Statement": [ { "Action": [ - "autoscaling:Describe*", - "cloudwatch:*", - "logs:*", - "sns:*" + "cloudwatch:DescribeAlarms", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances", + "ec2:DescribeSnapshots", + "ec2:DescribeVolumeStatus", + "ec2:DescribeVolumes", + "ec2:RebootInstances", + "ec2:StopInstances", + "ec2:TerminateInstances", + "ec2:CreateSnapshot" ], "Effect": "Allow", "Resource": "*" @@ -10635,11 +24016,54 @@ aws_managed_policies_data = """ }, "IsAttachable": true, "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJNVASSNSIDZIP4X7I", + "PolicyName": "CloudWatchEventsServiceRolePolicy", + "UpdateDate": "2017-11-17T00:42:04+00:00", + "VersionId": "v1" + }, + "CloudWatchFullAccess": { + "Arn": "arn:aws:iam::aws:policy/CloudWatchFullAccess", + "AttachmentCount": 0, + "CreateDate": "2015-02-06T18:40:00+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "autoscaling:Describe*", + "cloudwatch:*", + "logs:*", + "sns:*", + "iam:GetPolicy", + "iam:GetPolicyVersion", + "iam:GetRole" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "events.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIKEABORKUXN6DEAZU", "PolicyName": "CloudWatchFullAccess", - "UpdateDate": "2015-02-06T18:40:00+00:00", - "VersionId": "v1" + "UpdateDate": "2018-08-09T19:10:43+00:00", + "VersionId": "v3" }, "CloudWatchLogsFullAccess": { "Arn": "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess", @@ -10661,6 +24085,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ3ZGNWK2R5HW5BQFO", "PolicyName": "CloudWatchLogsFullAccess", "UpdateDate": "2015-02-06T18:40:02+00:00", @@ -10669,8 +24094,8 @@ aws_managed_policies_data = """ "CloudWatchLogsReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/CloudWatchLogsReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-14T22:22:16+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2015-02-06T18:40:03+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -10678,6 +24103,8 @@ aws_managed_policies_data = """ "logs:Describe*", "logs:Get*", "logs:List*", + "logs:StartQuery", + "logs:StopQuery", "logs:TestMetricFilter", "logs:FilterLogEvents" ], @@ -10690,16 +24117,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ2YIYDYSNNEHK3VKW", "PolicyName": "CloudWatchLogsReadOnlyAccess", - "UpdateDate": "2017-08-14T22:22:16+00:00", - "VersionId": "v3" + "UpdateDate": "2019-01-14T19:32:45+00:00", + "VersionId": "v4" }, "CloudWatchReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:01+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -10709,8 +24137,10 @@ aws_managed_policies_data = """ "cloudwatch:Get*", "cloudwatch:List*", "logs:Get*", + "logs:List*", "logs:Describe*", "logs:TestMetricFilter", + "logs:FilterLogEvents", "sns:Get*", "sns:List*" ], @@ -10723,16 +24153,353 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJN23PDQP7SZQAE3QE", "PolicyName": "CloudWatchReadOnlyAccess", - "UpdateDate": "2015-02-06T18:40:01+00:00", + "UpdateDate": "2018-05-10T21:40:42+00:00", + "VersionId": "v3" + }, + "CloudwatchApplicationInsightsServiceLinkedRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/CloudwatchApplicationInsightsServiceLinkedRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-12-01T16:22:12+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "cloudwatch:DescribeAlarmHistory", + "cloudwatch:DescribeAlarms", + "cloudwatch:GetMetricData", + "cloudwatch:ListMetrics", + "cloudwatch:PutMetricAlarm", + "cloudwatch:DeleteAlarms" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "logs:GetLogEvents", + "logs:DescribeLogStreams", + "logs:DescribeLogGroups" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "events:DescribeRule" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "cloudFormation:CreateStack", + "cloudFormation:UpdateStack", + "cloudFormation:DeleteStack" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:cloudformation:*:*:stack/ApplicationInsights-*" + ] + }, + { + "Action": [ + "cloudFormation:DescribeStacks", + "cloudFormation:ListStackResources" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "resource-groups:ListGroupResources", + "resource-groups:GetGroupQuery", + "resource-groups:GetGroup" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "elasticloadbalancing:DescribeLoadBalancers", + "elasticloadbalancing:DescribeTargetGroups", + "elasticloadbalancing:DescribeTargetHealth" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "autoscaling:DescribeAutoScalingGroups" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "ssm:PutParameter", + "ssm:DeleteParameter", + "ssm:AddTagsToResource" + ], + "Effect": "Allow", + "Resource": "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-ApplicationInsights-*" + }, + { + "Action": [ + "ssm:CreateAssociation", + "ssm:UpdateAssociation", + "ssm:DeleteAssociation", + "ssm:DescribeAssociation" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:ec2:*:*:instance/*", + "arn:aws:ssm:*:*:association/*", + "arn:aws:ssm:*:*:managed-instance/*", + "arn:aws:ssm:*:*:document/AWSEC2-ApplicationInsightsCloudwatchAgentInstallAndConfigure", + "arn:aws:ssm:*:*:document/AWS-ConfigureAWSPackage", + "arn:aws:ssm:*:*:document/AmazonCloudWatch-ManageAgent" + ] + }, + { + "Action": [ + "ssm:GetOpsItem", + "ssm:CreateOpsItem", + "ssm:DescribeOpsItems", + "ssm:UpdateOpsItem", + "ssm:DescribeInstanceInformation" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "ec2:DescribeInstances" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJH3SHQERZRQMQOQ44", + "PolicyName": "CloudwatchApplicationInsightsServiceLinkedRolePolicy", + "UpdateDate": "2019-05-24T18:26:41+00:00", + "VersionId": "v3" + }, + "ComprehendDataAccessRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/service-role/ComprehendDataAccessRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-03-06T22:28:15+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": { + "Action": [ + "s3:GetObject", + "s3:ListBucket", + "s3:PutObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*Comprehend*", + "arn:aws:s3:::*comprehend*" + ] + }, + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJHSDRRKS2Z3MYUPQY", + "PolicyName": "ComprehendDataAccessRolePolicy", + "UpdateDate": "2019-03-06T22:28:15+00:00", + "VersionId": "v1" + }, + "ComprehendFullAccess": { + "Arn": "arn:aws:iam::aws:policy/ComprehendFullAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T18:08:43+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "comprehend:*", + "s3:ListAllMyBuckets", + "s3:ListBucket", + "s3:GetBucketLocation", + "iam:ListRoles", + "iam:GetRole" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAITBM2PMWNG2P7RZEQ", + "PolicyName": "ComprehendFullAccess", + "UpdateDate": "2017-12-05T01:36:24+00:00", + "VersionId": "v2" + }, + "ComprehendMedicalFullAccess": { + "Arn": "arn:aws:iam::aws:policy/ComprehendMedicalFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T17:55:52+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "comprehendmedical:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJR5SUEX6PPJ3K4RAO", + "PolicyName": "ComprehendMedicalFullAccess", + "UpdateDate": "2018-11-27T17:55:52+00:00", + "VersionId": "v1" + }, + "ComprehendReadOnly": { + "Arn": "arn:aws:iam::aws:policy/ComprehendReadOnly", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T18:10:19+00:00", + "DefaultVersionId": "v5", + "Document": { + "Statement": [ + { + "Action": [ + "comprehend:DetectDominantLanguage", + "comprehend:BatchDetectDominantLanguage", + "comprehend:DetectEntities", + "comprehend:BatchDetectEntities", + "comprehend:DetectKeyPhrases", + "comprehend:BatchDetectKeyPhrases", + "comprehend:DetectSentiment", + "comprehend:BatchDetectSentiment", + "comprehend:DetectSyntax", + "comprehend:BatchDetectSyntax", + "comprehend:DescribeTopicsDetectionJob", + "comprehend:ListTopicsDetectionJobs", + "comprehend:DescribeDominantLanguageDetectionJob", + "comprehend:ListDominantLanguageDetectionJobs", + "comprehend:DescribeEntitiesDetectionJob", + "comprehend:ListEntitiesDetectionJobs", + "comprehend:DescribeKeyPhrasesDetectionJob", + "comprehend:ListKeyPhrasesDetectionJobs", + "comprehend:DescribeSentimentDetectionJob", + "comprehend:ListSentimentDetectionJobs", + "comprehend:DescribeDocumentClassifier", + "comprehend:ListDocumentClassifiers", + "comprehend:DescribeDocumentClassificationJob", + "comprehend:ListDocumentClassificationJobs", + "comprehend:DescribeEntityRecognizer", + "comprehend:ListEntityRecognizers" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJIUV5K2YCHQBBAH7G", + "PolicyName": "ComprehendReadOnly", + "UpdateDate": "2018-11-20T01:54:51+00:00", + "VersionId": "v5" + }, + "DAXServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/DAXServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-03-05T17:51:25+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateNetworkInterface", + "ec2:CreateSecurityGroup", + "ec2:DeleteNetworkInterface", + "ec2:DeleteSecurityGroup", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:RevokeSecurityGroupIngress" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJQWMGC67G4DWMREGM", + "PolicyName": "DAXServiceRolePolicy", + "UpdateDate": "2018-03-05T17:51:25+00:00", "VersionId": "v1" }, "DataScientist": { "Arn": "arn:aws:iam::aws:policy/job-function/DataScientist", "AttachmentCount": 0, "CreateDate": "2016-11-10T17:28:48+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v3", "Document": { "Statement": [ { @@ -10785,7 +24552,8 @@ aws_managed_policies_data = """ "s3:CreateBucket", "sns:CreateTopic", "sns:Get*", - "sns:List*" + "sns:List*", + "sagemaker:*" ], "Effect": "Allow", "Resource": "*" @@ -10821,7 +24589,6 @@ aws_managed_policies_data = """ }, { "Action": [ - "iam:GetRole", "iam:PassRole" ], "Effect": "Allow", @@ -10832,6 +24599,18 @@ aws_managed_policies_data = """ "arn:aws:iam::*:role/EMR_DefaultRole", "arn:aws:iam::*:role/kinesis-*" ] + }, + { + "Action": [ + "iam:PassRole" + ], + "Condition": { + "StringEquals": { + "iam:PassedToService": "sagemaker.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" } ], "Version": "2012-10-17" @@ -10839,16 +24618,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/job-function/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ5YHI2BQW7EQFYDXS", "PolicyName": "DataScientist", - "UpdateDate": "2016-11-10T17:28:48+00:00", - "VersionId": "v1" + "UpdateDate": "2019-01-18T19:26:23+00:00", + "VersionId": "v3" }, "DatabaseAdministrator": { "Arn": "arn:aws:iam::aws:policy/job-function/DatabaseAdministrator", "AttachmentCount": 0, "CreateDate": "2016-11-10T17:25:43+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { @@ -10932,7 +24712,6 @@ aws_managed_policies_data = """ }, { "Action": [ - "iam:GetRole", "iam:PassRole" ], "Effect": "Allow", @@ -10952,14 +24731,454 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/job-function/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIGBMAW4VUQKOQNVT6", "PolicyName": "DatabaseAdministrator", - "UpdateDate": "2016-11-10T17:25:43+00:00", + "UpdateDate": "2019-01-08T00:48:02+00:00", + "VersionId": "v2" + }, + "DynamoDBReplicationServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/DynamoDBReplicationServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-11-09T23:55:34+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "dynamodb:GetItem", + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem", + "dynamodb:DescribeTable", + "dynamodb:Scan", + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator", + "dynamodb:DescribeTimeToLive", + "application-autoscaling:RegisterScalableTarget", + "application-autoscaling:DescribeScalableTargets", + "application-autoscaling:PutScalingPolicy", + "application-autoscaling:DescribeScalingPolicies" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:CreateServiceLinkedRole" + ], + "Condition": { + "StringEquals": { + "iam:AWSServiceName": [ + "dynamodb.application-autoscaling.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJCUNRXL4BWASNJED2", + "PolicyName": "DynamoDBReplicationServiceRolePolicy", + "UpdateDate": "2018-07-02T21:48:12+00:00", + "VersionId": "v3" + }, + "ElastiCacheServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/ElastiCacheServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2017-12-07T17:50:04+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateNetworkInterface", + "ec2:CreateSecurityGroup", + "ec2:DeleteNetworkInterface", + "ec2:DeleteSecurityGroup", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:RevokeSecurityGroupIngress" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIML5LIBUZBVCSF7PI", + "PolicyName": "ElastiCacheServiceRolePolicy", + "UpdateDate": "2017-12-07T17:50:04+00:00", "VersionId": "v1" }, + "ElasticLoadBalancingFullAccess": { + "Arn": "arn:aws:iam::aws:policy/ElasticLoadBalancingFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-09-20T20:42:07+00:00", + "DefaultVersionId": "v4", + "Document": { + "Statement": [ + { + "Action": "elasticloadbalancing:*", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DescribeAccountAttributes", + "ec2:DescribeAddresses", + "ec2:DescribeInternetGateways", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:DescribeVpcClassicLink", + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeClassicLinkInstances", + "ec2:DescribeRouteTables", + "cognito-idp:DescribeUserPoolClient" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringEquals": { + "iam:AWSServiceName": "elasticloadbalancing.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIDPMLA3IUIOQCISJ4", + "PolicyName": "ElasticLoadBalancingFullAccess", + "UpdateDate": "2019-03-25T21:33:12+00:00", + "VersionId": "v4" + }, + "ElasticLoadBalancingReadOnly": { + "Arn": "arn:aws:iam::aws:policy/ElasticLoadBalancingReadOnly", + "AttachmentCount": 0, + "CreateDate": "2018-09-20T20:17:09+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": "elasticloadbalancing:Describe*", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DescribeInstances", + "ec2:DescribeClassicLinkInstances", + "ec2:DescribeSecurityGroups" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJMO7B7SNFLQ6HH736", + "PolicyName": "ElasticLoadBalancingReadOnly", + "UpdateDate": "2018-09-20T20:17:09+00:00", + "VersionId": "v1" + }, + "FMSServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/FMSServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-03-28T23:01:12+00:00", + "DefaultVersionId": "v7", + "Document": { + "Statement": [ + { + "Action": [ + "waf:UpdateWebACL", + "waf:DeleteWebACL", + "waf:GetWebACL", + "waf:GetRuleGroup", + "waf:ListSubscribedRuleGroups", + "waf-regional:UpdateWebACL", + "waf-regional:DeleteWebACL", + "waf-regional:GetWebACL", + "waf-regional:GetRuleGroup", + "waf-regional:ListSubscribedRuleGroups", + "waf-regional:ListResourcesForWebACL", + "waf-regional:AssociateWebACL", + "waf-regional:DisassociateWebACL", + "elasticloadbalancing:SetWebACL", + "apigateway:SetWebACL" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:waf:*:*:webacl/*", + "arn:aws:waf-regional:*:*:webacl/*", + "arn:aws:waf:*:*:rulegroup/*", + "arn:aws:waf-regional:*:*:rulegroup/*", + "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*", + "arn:aws:apigateway:*::/restapis/*/stages/*" + ] + }, + { + "Action": [ + "waf:CreateWebACL", + "waf-regional:CreateWebACL", + "waf:GetChangeToken", + "waf-regional:GetChangeToken" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:waf:*", + "arn:aws:waf-regional:*" + ] + }, + { + "Action": [ + "waf:PutPermissionPolicy", + "waf:GetPermissionPolicy", + "waf:DeletePermissionPolicy", + "waf-regional:PutPermissionPolicy", + "waf-regional:GetPermissionPolicy", + "waf-regional:DeletePermissionPolicy" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:waf:*:*:webacl/*", + "arn:aws:waf:*:*:rulegroup/*", + "arn:aws:waf-regional:*:*:webacl/*", + "arn:aws:waf-regional:*:*:rulegroup/*" + ] + }, + { + "Action": [ + "cloudfront:GetDistribution", + "cloudfront:UpdateDistribution", + "cloudfront:ListDistributionsByWebACLId" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "config:DeleteConfigRule", + "config:DescribeComplianceByConfigRule", + "config:DescribeConfigRuleEvaluationStatus", + "config:DescribeConfigRules", + "config:GetComplianceDetailsByConfigRule", + "config:PutConfigRule", + "config:StartConfigRulesEvaluation" + ], + "Effect": "Allow", + "Resource": "arn:aws:config:*:*:config-rule/aws-service-rule/fms.amazonaws.com/*" + }, + { + "Action": [ + "config:DescribeConfigurationRecorders", + "config:DescribeConfigurationRecorderStatus", + "config:PutConfigurationRecorder", + "config:StartConfigurationRecorder", + "config:PutDeliveryChannel", + "config:DescribeDeliveryChannels", + "config:DescribeDeliveryChannelStatus", + "config:GetComplianceSummaryByConfigRule", + "config:GetDiscoveredResourceCounts" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:iam::*:role/aws-service-role/fms.amazonaws.com/AWSServiceRoleForFMS" + ] + }, + { + "Action": [ + "organizations:DescribeAccount", + "organizations:DescribeOrganization", + "organizations:ListAccounts" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "shield:CreateProtection", + "shield:DeleteProtection", + "shield:DescribeProtection", + "shield:ListProtections", + "shield:ListAttacks", + "shield:CreateSubscription", + "shield:DescribeSubscription", + "shield:GetSubscriptionState", + "shield:DescribeDRTAccess", + "shield:DescribeEmergencyContactSettings", + "shield:UpdateEmergencyContactSettings", + "elasticloadbalancing:DescribeLoadBalancers", + "ec2:DescribeAddresses" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI62NTGYJB446ACUEA", + "PolicyName": "FMSServiceRolePolicy", + "UpdateDate": "2019-03-08T18:02:51+00:00", + "VersionId": "v7" + }, + "FSxDeleteServiceLinkedRoleAccess": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/FSxDeleteServiceLinkedRoleAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-28T10:40:24+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus", + "iam:GetRole" + ], + "Effect": "Allow", + "Resource": "arn:*:iam::*:role/aws-service-role/s3.data-source.lustre.fsx.amazonaws.com/AWSServiceRoleForFSxS3Access_*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ6IRP2YV2YPKWPPNQ", + "PolicyName": "FSxDeleteServiceLinkedRoleAccess", + "UpdateDate": "2018-11-28T10:40:24+00:00", + "VersionId": "v1" + }, + "GlobalAcceleratorFullAccess": { + "Arn": "arn:aws:iam::aws:policy/GlobalAcceleratorFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T02:44:44+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "globalaccelerator:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ3NSRQKPB42BCNRT6", + "PolicyName": "GlobalAcceleratorFullAccess", + "UpdateDate": "2018-11-27T02:44:44+00:00", + "VersionId": "v1" + }, + "GlobalAcceleratorReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/GlobalAcceleratorReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T02:41:00+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "globalaccelerator:Describe*", + "globalaccelerator:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJYXHGCVENJKQZRNGU", + "PolicyName": "GlobalAcceleratorReadOnlyAccess", + "UpdateDate": "2018-11-27T02:41:00+00:00", + "VersionId": "v1" + }, + "GreengrassOTAUpdateArtifactAccess": { + "Arn": "arn:aws:iam::aws:policy/service-role/GreengrassOTAUpdateArtifactAccess", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T18:11:47+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::*-greengrass-updates/*" + ], + "Sid": "AllowsIotToAccessGreengrassOTAUpdateArtifacts" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIFGE66SKIK3GW5UC2", + "PolicyName": "GreengrassOTAUpdateArtifactAccess", + "UpdateDate": "2018-12-18T00:59:43+00:00", + "VersionId": "v2" + }, "IAMFullAccess": { "Arn": "arn:aws:iam::aws:policy/IAMFullAccess", - "AttachmentCount": 2, + "AttachmentCount": 0, "CreateDate": "2015-02-06T18:40:38+00:00", "DefaultVersionId": "v1", "Document": { @@ -10975,6 +25194,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI7XKCFMBPM3QQRRVQ", "PolicyName": "IAMFullAccess", "UpdateDate": "2015-02-06T18:40:38+00:00", @@ -10983,8 +25203,8 @@ aws_managed_policies_data = """ "IAMReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/IAMReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2016-09-06T17:06:37+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2015-02-06T18:40:39+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -10992,7 +25212,9 @@ aws_managed_policies_data = """ "iam:GenerateCredentialReport", "iam:GenerateServiceLastAccessedDetails", "iam:Get*", - "iam:List*" + "iam:List*", + "iam:SimulateCustomPolicy", + "iam:SimulatePrincipalPolicy" ], "Effect": "Allow", "Resource": "*" @@ -11003,10 +25225,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJKSO7NDY4T57MWDSQ", "PolicyName": "IAMReadOnlyAccess", - "UpdateDate": "2016-09-06T17:06:37+00:00", - "VersionId": "v3" + "UpdateDate": "2018-01-25T19:11:27+00:00", + "VersionId": "v4" }, "IAMSelfManageServiceSpecificCredentials": { "Arn": "arn:aws:iam::aws:policy/IAMSelfManageServiceSpecificCredentials", @@ -11032,6 +25255,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI4VT74EMXK2PMQJM2", "PolicyName": "IAMSelfManageServiceSpecificCredentials", "UpdateDate": "2016-12-22T17:25:18+00:00", @@ -11040,7 +25264,7 @@ aws_managed_policies_data = """ "IAMUserChangePassword": { "Arn": "arn:aws:iam::aws:policy/IAMUserChangePassword", "AttachmentCount": 1, - "CreateDate": "2016-11-15T23:18:55+00:00", + "CreateDate": "2016-11-15T00:25:16+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -11066,6 +25290,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ4L4MM2A7QIEB56MS", "PolicyName": "IAMUserChangePassword", "UpdateDate": "2016-11-15T23:18:55+00:00", @@ -11073,7 +25298,7 @@ aws_managed_policies_data = """ }, "IAMUserSSHKeys": { "Arn": "arn:aws:iam::aws:policy/IAMUserSSHKeys", - "AttachmentCount": 1, + "AttachmentCount": 0, "CreateDate": "2015-07-09T17:08:54+00:00", "DefaultVersionId": "v1", "Document": { @@ -11095,38 +25320,577 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJTSHUA4UXGXU7ANUA", "PolicyName": "IAMUserSSHKeys", "UpdateDate": "2015-07-09T17:08:54+00:00", "VersionId": "v1" }, - "NetworkAdministrator": { - "Arn": "arn:aws:iam::aws:policy/job-function/NetworkAdministrator", + "KafkaServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/KafkaServiceRolePolicy", "AttachmentCount": 0, - "CreateDate": "2017-03-20T18:44:58+00:00", + "CreateDate": "2018-11-15T23:31:48+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ - "autoscaling:Describe*", + "ec2:CreateNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:CreateNetworkInterfacePermission", + "ec2:AttachNetworkInterface", + "ec2:DeleteNetworkInterface", + "ec2:DetachNetworkInterface", + "acm-pca:GetCertificateAuthorityCertificate" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJUXPRZ76MAP2EVQJU", + "PolicyName": "KafkaServiceRolePolicy", + "UpdateDate": "2019-05-23T19:58:58+00:00", + "VersionId": "v2" + }, + "LexBotPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/LexBotPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-02-17T22:18:13+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "polly:SynthesizeSpeech" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJJ3NZRBBQKSESXXJC", + "PolicyName": "LexBotPolicy", + "UpdateDate": "2017-02-17T22:18:13+00:00", + "VersionId": "v1" + }, + "LexChannelPolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/LexChannelPolicy", + "AttachmentCount": 0, + "CreateDate": "2017-02-17T23:23:24+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "lex:PostText" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJKYEISPO63JTBJWPY", + "PolicyName": "LexChannelPolicy", + "UpdateDate": "2017-02-17T23:23:24+00:00", + "VersionId": "v1" + }, + "LightsailExportAccess": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/LightsailExportAccess", + "AttachmentCount": 0, + "CreateDate": "2018-09-28T16:35:54+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "iam:DeleteServiceLinkedRole", + "iam:GetServiceLinkedRoleDeletionStatus" + ], + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/lightsail.amazonaws.com/AWSServiceRoleForLightsail*" + }, + { + "Action": [ + "ec2:CopySnapshot", + "ec2:DescribeSnapshots", + "ec2:CopyImage", + "ec2:DescribeImages" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ4LZGPQLZWMVR4WMQ", + "PolicyName": "LightsailExportAccess", + "UpdateDate": "2018-09-28T16:35:54+00:00", + "VersionId": "v1" + }, + "NeptuneConsoleFullAccess": { + "Arn": "arn:aws:iam::aws:policy/NeptuneConsoleFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-06-19T21:35:19+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "rds:CreateDBCluster", + "rds:CreateDBInstance" + ], + "Condition": { + "StringEquals": { + "rds:DatabaseEngine": "graphdb" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:rds:*" + ] + }, + { + "Action": [ + "rds:AddRoleToDBCluster", + "rds:AddSourceIdentifierToSubscription", + "rds:AddTagsToResource", + "rds:ApplyPendingMaintenanceAction", + "rds:CopyDBClusterParameterGroup", + "rds:CopyDBClusterSnapshot", + "rds:CopyDBParameterGroup", + "rds:CreateDBClusterParameterGroup", + "rds:CreateDBClusterSnapshot", + "rds:CreateDBParameterGroup", + "rds:CreateDBSubnetGroup", + "rds:CreateEventSubscription", + "rds:DeleteDBCluster", + "rds:DeleteDBClusterParameterGroup", + "rds:DeleteDBClusterSnapshot", + "rds:DeleteDBInstance", + "rds:DeleteDBParameterGroup", + "rds:DeleteDBSubnetGroup", + "rds:DeleteEventSubscription", + "rds:DescribeAccountAttributes", + "rds:DescribeCertificates", + "rds:DescribeDBClusterParameterGroups", + "rds:DescribeDBClusterParameters", + "rds:DescribeDBClusterSnapshotAttributes", + "rds:DescribeDBClusterSnapshots", + "rds:DescribeDBClusters", + "rds:DescribeDBEngineVersions", + "rds:DescribeDBInstances", + "rds:DescribeDBLogFiles", + "rds:DescribeDBParameterGroups", + "rds:DescribeDBParameters", + "rds:DescribeDBSecurityGroups", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEngineDefaultClusterParameters", + "rds:DescribeEngineDefaultParameters", + "rds:DescribeEventCategories", + "rds:DescribeEventSubscriptions", + "rds:DescribeEvents", + "rds:DescribeOptionGroups", + "rds:DescribeOrderableDBInstanceOptions", + "rds:DescribePendingMaintenanceActions", + "rds:DescribeValidDBInstanceModifications", + "rds:DownloadDBLogFilePortion", + "rds:FailoverDBCluster", + "rds:ListTagsForResource", + "rds:ModifyDBCluster", + "rds:ModifyDBClusterParameterGroup", + "rds:ModifyDBClusterSnapshotAttribute", + "rds:ModifyDBInstance", + "rds:ModifyDBParameterGroup", + "rds:ModifyDBSubnetGroup", + "rds:ModifyEventSubscription", + "rds:PromoteReadReplicaDBCluster", + "rds:RebootDBInstance", + "rds:RemoveRoleFromDBCluster", + "rds:RemoveSourceIdentifierFromSubscription", + "rds:RemoveTagsFromResource", + "rds:ResetDBClusterParameterGroup", + "rds:ResetDBParameterGroup", + "rds:RestoreDBClusterFromSnapshot", + "rds:RestoreDBClusterToPointInTime" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics", "ec2:AllocateAddress", + "ec2:AssignIpv6Addresses", + "ec2:AssignPrivateIpAddresses", + "ec2:AssociateAddress", + "ec2:AssociateRouteTable", + "ec2:AssociateSubnetCidrBlock", + "ec2:AssociateVpcCidrBlock", + "ec2:AttachInternetGateway", + "ec2:AttachNetworkInterface", + "ec2:CreateCustomerGateway", + "ec2:CreateDefaultSubnet", + "ec2:CreateDefaultVpc", + "ec2:CreateInternetGateway", + "ec2:CreateNatGateway", + "ec2:CreateNetworkInterface", + "ec2:CreateRoute", + "ec2:CreateRouteTable", + "ec2:CreateSecurityGroup", + "ec2:CreateSubnet", + "ec2:CreateVpc", + "ec2:CreateVpcEndpoint", + "ec2:CreateVpcEndpoint", + "ec2:DescribeAccountAttributes", + "ec2:DescribeAccountAttributes", + "ec2:DescribeAddresses", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeCustomerGateways", + "ec2:DescribeInstances", + "ec2:DescribeNatGateways", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribePrefixLists", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroupReferences", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcs", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:ModifySubnetAttribute", + "ec2:ModifyVpcAttribute", + "ec2:ModifyVpcEndpoint", + "iam:ListRoles", + "iam:PassRole", + "kms:ListAliases", + "kms:ListKeyPolicies", + "kms:ListKeys", + "kms:ListRetirableGrants", + "logs:DescribeLogStreams", + "logs:GetLogEvents", + "sns:ListSubscriptions", + "sns:ListTopics", + "sns:Publish" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "rds.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJWTD4ELX2KRNICUVQ", + "PolicyName": "NeptuneConsoleFullAccess", + "UpdateDate": "2018-11-06T21:19:54+00:00", + "VersionId": "v2" + }, + "NeptuneFullAccess": { + "Arn": "arn:aws:iam::aws:policy/NeptuneFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-05-30T19:17:31+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "rds:CreateDBCluster", + "rds:CreateDBInstance" + ], + "Condition": { + "StringEquals": { + "rds:DatabaseEngine": "graphdb" + } + }, + "Effect": "Allow", + "Resource": [ + "arn:aws:rds:*" + ] + }, + { + "Action": [ + "rds:AddRoleToDBCluster", + "rds:AddSourceIdentifierToSubscription", + "rds:AddTagsToResource", + "rds:ApplyPendingMaintenanceAction", + "rds:CopyDBClusterParameterGroup", + "rds:CopyDBClusterSnapshot", + "rds:CopyDBParameterGroup", + "rds:CreateDBClusterParameterGroup", + "rds:CreateDBClusterSnapshot", + "rds:CreateDBParameterGroup", + "rds:CreateDBSubnetGroup", + "rds:CreateEventSubscription", + "rds:DeleteDBCluster", + "rds:DeleteDBClusterParameterGroup", + "rds:DeleteDBClusterSnapshot", + "rds:DeleteDBInstance", + "rds:DeleteDBParameterGroup", + "rds:DeleteDBSubnetGroup", + "rds:DeleteEventSubscription", + "rds:DescribeAccountAttributes", + "rds:DescribeCertificates", + "rds:DescribeDBClusterParameterGroups", + "rds:DescribeDBClusterParameters", + "rds:DescribeDBClusterSnapshotAttributes", + "rds:DescribeDBClusterSnapshots", + "rds:DescribeDBClusters", + "rds:DescribeDBEngineVersions", + "rds:DescribeDBInstances", + "rds:DescribeDBLogFiles", + "rds:DescribeDBParameterGroups", + "rds:DescribeDBParameters", + "rds:DescribeDBSecurityGroups", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEngineDefaultClusterParameters", + "rds:DescribeEngineDefaultParameters", + "rds:DescribeEventCategories", + "rds:DescribeEventSubscriptions", + "rds:DescribeEvents", + "rds:DescribeOptionGroups", + "rds:DescribeOrderableDBInstanceOptions", + "rds:DescribePendingMaintenanceActions", + "rds:DescribeValidDBInstanceModifications", + "rds:DownloadDBLogFilePortion", + "rds:FailoverDBCluster", + "rds:ListTagsForResource", + "rds:ModifyDBCluster", + "rds:ModifyDBClusterParameterGroup", + "rds:ModifyDBClusterSnapshotAttribute", + "rds:ModifyDBInstance", + "rds:ModifyDBParameterGroup", + "rds:ModifyDBSubnetGroup", + "rds:ModifyEventSubscription", + "rds:PromoteReadReplicaDBCluster", + "rds:RebootDBInstance", + "rds:RemoveRoleFromDBCluster", + "rds:RemoveSourceIdentifierFromSubscription", + "rds:RemoveTagsFromResource", + "rds:ResetDBClusterParameterGroup", + "rds:ResetDBParameterGroup", + "rds:RestoreDBClusterFromSnapshot", + "rds:RestoreDBClusterToPointInTime" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics", + "ec2:DescribeAccountAttributes", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "iam:PassRole", + "kms:ListAliases", + "kms:ListKeyPolicies", + "kms:ListKeys", + "kms:ListRetirableGrants", + "logs:DescribeLogStreams", + "logs:GetLogEvents", + "sns:ListSubscriptions", + "sns:ListTopics", + "sns:Publish" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": "iam:CreateServiceLinkedRole", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "rds.amazonaws.com" + } + }, + "Effect": "Allow", + "Resource": "arn:aws:iam::*:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIXSDEYRCNJRC6ITFK", + "PolicyName": "NeptuneFullAccess", + "UpdateDate": "2018-11-06T21:21:19+00:00", + "VersionId": "v3" + }, + "NeptuneReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/NeptuneReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-05-30T19:16:37+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "rds:DescribeAccountAttributes", + "rds:DescribeCertificates", + "rds:DescribeDBClusterParameterGroups", + "rds:DescribeDBClusterParameters", + "rds:DescribeDBClusterSnapshotAttributes", + "rds:DescribeDBClusterSnapshots", + "rds:DescribeDBClusters", + "rds:DescribeDBEngineVersions", + "rds:DescribeDBInstances", + "rds:DescribeDBLogFiles", + "rds:DescribeDBParameterGroups", + "rds:DescribeDBParameters", + "rds:DescribeDBSubnetGroups", + "rds:DescribeEventCategories", + "rds:DescribeEventSubscriptions", + "rds:DescribeEvents", + "rds:DescribeOrderableDBInstanceOptions", + "rds:DescribePendingMaintenanceActions", + "rds:DownloadDBLogFilePortion", + "rds:ListTagsForResource" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DescribeAccountAttributes", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInternetGateways", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "kms:ListKeys", + "kms:ListRetirableGrants", + "kms:ListAliases", + "kms:ListKeyPolicies" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "logs:DescribeLogStreams", + "logs:GetLogEvents" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:logs:*:*:log-group:/aws/rds/*:log-stream:*", + "arn:aws:logs:*:*:log-group:/aws/neptune/*:log-stream:*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJS5OQ5RXULC66WTGQ", + "PolicyName": "NeptuneReadOnlyAccess", + "UpdateDate": "2018-05-30T19:16:37+00:00", + "VersionId": "v1" + }, + "NetworkAdministrator": { + "Arn": "arn:aws:iam::aws:policy/job-function/NetworkAdministrator", + "AttachmentCount": 0, + "CreateDate": "2016-11-10T17:31:35+00:00", + "DefaultVersionId": "v3", + "Document": { + "Statement": [ + { + "Action": [ + "autoscaling:Describe*", + "ec2:AcceptVpcEndpointConnections", + "ec2:AllocateAddress", + "ec2:AssignIpv6Addresses", "ec2:AssignPrivateIpAddresses", "ec2:AssociateAddress", "ec2:AssociateDhcpOptions", "ec2:AssociateRouteTable", + "ec2:AssociateSubnetCidrBlock", + "ec2:AssociateVpcCidrBlock", "ec2:AttachInternetGateway", "ec2:AttachNetworkInterface", "ec2:AttachVpnGateway", "ec2:CreateCustomerGateway", + "ec2:CreateDefaultSubnet", + "ec2:CreateDefaultVpc", "ec2:CreateDhcpOptions", + "ec2:CreateEgressOnlyInternetGateway", "ec2:CreateFlowLogs", "ec2:CreateInternetGateway", "ec2:CreateNatGateway", "ec2:CreateNetworkAcl", - "ec2:CreateNetworkAcl", "ec2:CreateNetworkAclEntry", "ec2:CreateNetworkInterface", + "ec2:CreateNetworkInterfacePermission", + "ec2:CreatePlacementGroup", "ec2:CreateRoute", "ec2:CreateRouteTable", "ec2:CreateSecurityGroup", @@ -11134,28 +25898,33 @@ aws_managed_policies_data = """ "ec2:CreateTags", "ec2:CreateVpc", "ec2:CreateVpcEndpoint", + "ec2:CreateVpcEndpointConnectionNotification", + "ec2:CreateVpcEndpointServiceConfiguration", "ec2:CreateVpnConnection", "ec2:CreateVpnConnectionRoute", "ec2:CreateVpnGateway", - "ec2:CreatePlacementGroup", - "ec2:DeletePlacementGroup", - "ec2:DescribePlacementGroups", + "ec2:DeleteEgressOnlyInternetGateway", "ec2:DeleteFlowLogs", "ec2:DeleteNatGateway", "ec2:DeleteNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", + "ec2:DeletePlacementGroup", "ec2:DeleteSubnet", "ec2:DeleteTags", "ec2:DeleteVpc", + "ec2:DeleteVpcEndpointConnectionNotifications", "ec2:DeleteVpcEndpoints", + "ec2:DeleteVpcEndpointServiceConfigurations", "ec2:DeleteVpnConnection", "ec2:DeleteVpnConnectionRoute", "ec2:DeleteVpnGateway", + "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", "ec2:DescribeAvailabilityZones", "ec2:DescribeClassicLinkInstances", "ec2:DescribeCustomerGateways", - "ec2:DescribeVpcClassicLinkDnsSupport", "ec2:DescribeDhcpOptions", + "ec2:DescribeEgressOnlyInternetGateways", "ec2:DescribeFlowLogs", "ec2:DescribeInstances", "ec2:DescribeInternetGateways", @@ -11164,15 +25933,24 @@ aws_managed_policies_data = """ "ec2:DescribeNatGateways", "ec2:DescribeNetworkAcls", "ec2:DescribeNetworkInterfaceAttribute", + "ec2:DescribeNetworkInterfacePermissions", "ec2:DescribeNetworkInterfaces", + "ec2:DescribePlacementGroups", "ec2:DescribePrefixLists", "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroupReferences", "ec2:DescribeSecurityGroups", + "ec2:DescribeStaleSecurityGroups", "ec2:DescribeSubnets", "ec2:DescribeTags", "ec2:DescribeVpcAttribute", "ec2:DescribeVpcClassicLink", + "ec2:DescribeVpcClassicLinkDnsSupport", + "ec2:DescribeVpcEndpointConnectionNotifications", + "ec2:DescribeVpcEndpointConnections", "ec2:DescribeVpcEndpoints", + "ec2:DescribeVpcEndpointServiceConfigurations", + "ec2:DescribeVpcEndpointServicePermissions", "ec2:DescribeVpcEndpointServices", "ec2:DescribeVpcPeeringConnections", "ec2:DescribeVpcs", @@ -11182,14 +25960,24 @@ aws_managed_policies_data = """ "ec2:DetachNetworkInterface", "ec2:DetachVpnGateway", "ec2:DisableVgwRoutePropagation", + "ec2:DisableVpcClassicLinkDnsSupport", "ec2:DisassociateAddress", "ec2:DisassociateRouteTable", + "ec2:DisassociateSubnetCidrBlock", + "ec2:DisassociateVpcCidrBlock", "ec2:EnableVgwRoutePropagation", + "ec2:EnableVpcClassicLinkDnsSupport", "ec2:ModifyNetworkInterfaceAttribute", "ec2:ModifySubnetAttribute", "ec2:ModifyVpcAttribute", "ec2:ModifyVpcEndpoint", + "ec2:ModifyVpcEndpointConnectionNotification", + "ec2:ModifyVpcEndpointServiceConfiguration", + "ec2:ModifyVpcEndpointServicePermissions", + "ec2:ModifyVpcPeeringConnectionOptions", + "ec2:ModifyVpcTenancy", "ec2:MoveAddressToVpc", + "ec2:RejectVpcEndpointConnections", "ec2:ReleaseAddress", "ec2:ReplaceNetworkAclAssociation", "ec2:ReplaceNetworkAclEntry", @@ -11197,7 +25985,10 @@ aws_managed_policies_data = """ "ec2:ReplaceRouteTableAssociation", "ec2:ResetNetworkInterfaceAttribute", "ec2:RestoreAddressToClassic", + "ec2:UnassignIpv6Addresses", "ec2:UnassignPrivateIpAddresses", + "ec2:UpdateSecurityGroupRuleDescriptionsEgress", + "ec2:UpdateSecurityGroupRuleDescriptionsIngress", "directconnect:*", "route53:*", "route53domains:*", @@ -11277,28 +26068,36 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/job-function/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJPNMADZFJCVPJVZA2", "PolicyName": "NetworkAdministrator", - "UpdateDate": "2017-03-20T18:44:58+00:00", - "VersionId": "v2" + "UpdateDate": "2018-12-13T19:43:41+00:00", + "VersionId": "v3" }, "PowerUserAccess": { "Arn": "arn:aws:iam::aws:policy/PowerUserAccess", "AttachmentCount": 0, - "CreateDate": "2016-12-06T18:11:16+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2015-02-06T18:39:47+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { "Effect": "Allow", "NotAction": [ "iam:*", - "organizations:*" + "organizations:*", + "account:*" ], "Resource": "*" }, { - "Action": "organizations:DescribeOrganization", + "Action": [ + "iam:CreateServiceLinkedRole", + "iam:DeleteServiceLinkedRole", + "iam:ListRoles", + "organizations:DescribeOrganization", + "account:ListRegions" + ], "Effect": "Allow", "Resource": "*" } @@ -11308,15 +26107,16 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJYRXTHIB4FOVS3ZXS", "PolicyName": "PowerUserAccess", - "UpdateDate": "2016-12-06T18:11:16+00:00", - "VersionId": "v2" + "UpdateDate": "2019-03-20T22:19:03+00:00", + "VersionId": "v4" }, "QuickSightAccessForS3StorageManagementAnalyticsReadOnly": { "Arn": "arn:aws:iam::aws:policy/service-role/QuickSightAccessForS3StorageManagementAnalyticsReadOnly", "AttachmentCount": 0, - "CreateDate": "2017-07-21T00:02:14+00:00", + "CreateDate": "2017-06-12T18:18:38+00:00", "DefaultVersionId": "v3", "Document": { "Statement": [ @@ -11345,6 +26145,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIFWG3L3WDMR4I7ZJW", "PolicyName": "QuickSightAccessForS3StorageManagementAnalyticsReadOnly", "UpdateDate": "2017-07-21T00:02:14+00:00", @@ -11377,6 +26178,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIWKFXRLQG2ROKKXLE", "PolicyName": "RDSCloudHsmAuthorizationRole", "UpdateDate": "2015-02-06T18:41:29+00:00", @@ -11385,31 +26187,55 @@ aws_managed_policies_data = """ "ReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/ReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-07-20T17:43:06+00:00", - "DefaultVersionId": "v29", + "CreateDate": "2015-02-06T18:39:48+00:00", + "DefaultVersionId": "v50", "Document": { "Statement": [ { "Action": [ + "a4b:Get*", + "a4b:List*", + "a4b:Describe*", + "a4b:Search*", "acm:Describe*", "acm:Get*", "acm:List*", + "acm-pca:Describe*", + "acm-pca:Get*", + "acm-pca:List*", + "amplify:GetApp", + "amplify:GetBranch", + "amplify:GetJob", + "amplify:GetDomainAssociation", + "amplify:ListApps", + "amplify:ListBranches", + "amplify:ListDomainAssociations", + "amplify:ListJobs", "apigateway:GET", "application-autoscaling:Describe*", + "appmesh:Describe*", + "appmesh:List*", "appstream:Describe*", "appstream:Get*", "appstream:List*", + "appsync:Get*", + "appsync:List*", + "autoscaling:Describe*", + "autoscaling-plans:Describe*", + "autoscaling-plans:GetScalingPlanResourceForecastData", "athena:List*", "athena:Batch*", "athena:Get*", - "autoscaling:Describe*", "batch:List*", "batch:Describe*", + "cloud9:Describe*", + "cloud9:List*", "clouddirectory:List*", "clouddirectory:BatchRead", "clouddirectory:Get*", "clouddirectory:LookupPolicy", "cloudformation:Describe*", + "cloudformation:Detect*", "cloudformation:Get*", "cloudformation:List*", "cloudformation:Estimate*", @@ -11431,6 +26257,7 @@ aws_managed_policies_data = """ "codebuild:BatchGet*", "codebuild:List*", "codecommit:BatchGet*", + "codecommit:Describe*", "codecommit:Get*", "codecommit:GitPull", "codecommit:List*", @@ -11443,13 +26270,15 @@ aws_managed_policies_data = """ "codestar:Describe*", "codestar:Get*", "codestar:Verify*", - "cognito-identity:List*", "cognito-identity:Describe*", + "cognito-identity:Get*", + "cognito-identity:List*", "cognito-identity:Lookup*", "cognito-sync:List*", "cognito-sync:Describe*", "cognito-sync:Get*", "cognito-sync:QueryRecords", + "cognito-idp:AdminGet*", "cognito-idp:AdminList*", "cognito-idp:List*", "cognito-idp:Describe*", @@ -11460,20 +26289,28 @@ aws_managed_policies_data = """ "config:List*", "connect:List*", "connect:Describe*", - "connect:Get*", + "connect:GetFederationToken", + "datasync:Describe*", + "datasync:List*", "datapipeline:Describe*", "datapipeline:EvaluateExpression", "datapipeline:Get*", "datapipeline:List*", "datapipeline:QueryObjects", "datapipeline:Validate*", + "dax:BatchGetItem", + "dax:Describe*", + "dax:GetItem", + "dax:ListTags", + "dax:Query", + "dax:Scan", "directconnect:Describe*", - "directconnect:Confirm*", "devicefarm:List*", "devicefarm:Get*", "discovery:Describe*", "discovery:List*", "discovery:Get*", + "dlm:Get*", "dms:Describe*", "dms:List*", "dms:Test*", @@ -11490,6 +26327,7 @@ aws_managed_policies_data = """ "dynamodb:Scan", "ec2:Describe*", "ec2:Get*", + "ec2:SearchTransitGatewayRoutes", "ec2messages:Get*", "ecr:BatchCheck*", "ecr:BatchGet*", @@ -11498,6 +26336,10 @@ aws_managed_policies_data = """ "ecr:List*", "ecs:Describe*", "ecs:List*", + "eks:DescribeCluster", + "eks:DescribeUpdates", + "eks:ListClusters", + "eks:ListUpdates", "elasticache:Describe*", "elasticache:List*", "elasticbeanstalk:Check*", @@ -11515,6 +26357,7 @@ aws_managed_policies_data = """ "elastictranscoder:Read*", "es:Describe*", "es:List*", + "es:Get*", "es:ESHttpGet", "es:ESHttpHead", "events:Describe*", @@ -11522,6 +26365,8 @@ aws_managed_policies_data = """ "events:Test*", "firehose:Describe*", "firehose:List*", + "fsx:Describe*", + "fsx:List*", "gamelift:List*", "gamelift:Get*", "gamelift:Describe*", @@ -11531,6 +26376,45 @@ aws_managed_policies_data = """ "glacier:List*", "glacier:Describe*", "glacier:Get*", + "globalaccelerator:Describe*", + "globalaccelerator:List*", + "glue:BatchGetPartition", + "glue:GetCatalogImportStatus", + "glue:GetClassifier", + "glue:GetClassifiers", + "glue:GetCrawler", + "glue:GetCrawlers", + "glue:GetCrawlerMetrics", + "glue:GetDatabase", + "glue:GetDatabases", + "glue:GetDataCatalogEncryptionSettings", + "glue:GetDataflowGraph", + "glue:GetDevEndpoint", + "glue:GetDevEndpoints", + "glue:GetJob", + "glue:GetJobs", + "glue:GetJobRun", + "glue:GetJobRuns", + "glue:GetMapping", + "glue:GetPartition", + "glue:GetPartitions", + "glue:GetPlan", + "glue:GetResourcePolicy", + "glue:GetSecurityConfiguration", + "glue:GetSecurityConfigurations", + "glue:GetTable", + "glue:GetTables", + "glue:GetTableVersion", + "glue:GetTableVersions", + "glue:GetTags", + "glue:GetTrigger", + "glue:GetTriggers", + "glue:GetUserDefinedFunction", + "glue:GetUserDefinedFunctions", + "greengrass:Get*", + "greengrass:List*", + "guardduty:Get*", + "guardduty:List*", "health:Describe*", "health:Get*", "health:List*", @@ -11548,10 +26432,20 @@ aws_managed_policies_data = """ "iot:Describe*", "iot:Get*", "iot:List*", + "iotanalytics:Describe*", + "iotanalytics:List*", + "iotanalytics:Get*", + "iotanalytics:SampleChannelData", + "kafka:Describe*", + "kafka:List*", + "kafka:Get*", "kinesisanalytics:Describe*", "kinesisanalytics:Discover*", "kinesisanalytics:Get*", "kinesisanalytics:List*", + "kinesisvideo:Describe*", + "kinesisvideo:Get*", + "kinesisvideo:List*", "kinesis:Describe*", "kinesis:Get*", "kinesis:List*", @@ -11561,27 +26455,80 @@ aws_managed_policies_data = """ "lambda:List*", "lambda:Get*", "lex:Get*", - "lightsail:Get*", + "lightsail:GetActiveNames", + "lightsail:GetBlueprints", + "lightsail:GetBundles", + "lightsail:GetCloudFormationStackRecords", + "lightsail:GetDisk", + "lightsail:GetDisks", + "lightsail:GetDiskSnapshot", + "lightsail:GetDiskSnapshots", + "lightsail:GetDomain", + "lightsail:GetDomains", + "lightsail:GetExportSnapshotRecords", + "lightsail:GetInstance", + "lightsail:GetInstanceMetricData", + "lightsail:GetInstancePortStates", + "lightsail:GetInstances", + "lightsail:GetInstanceSnapshot", + "lightsail:GetInstanceSnapshots", + "lightsail:GetInstanceState", + "lightsail:GetKeyPair", + "lightsail:GetKeyPairs", + "lightsail:GetLoadBalancer", + "lightsail:GetLoadBalancerMetricData", + "lightsail:GetLoadBalancers", + "lightsail:GetLoadBalancerTlsCertificates", + "lightsail:GetOperation", + "lightsail:GetOperations", + "lightsail:GetOperationsForResource", + "lightsail:GetRegions", + "lightsail:GetRelationalDatabase", + "lightsail:GetRelationalDatabaseBlueprints", + "lightsail:GetRelationalDatabaseBundles", + "lightsail:GetRelationalDatabaseEvents", + "lightsail:GetRelationalDatabaseLogEvents", + "lightsail:GetRelationalDatabaseLogStreams", + "lightsail:GetRelationalDatabaseMetricData", + "lightsail:GetRelationalDatabaseParameters", + "lightsail:GetRelationalDatabases", + "lightsail:GetRelationalDatabaseSnapshot", + "lightsail:GetRelationalDatabaseSnapshots", + "lightsail:GetResources", + "lightsail:GetStaticIp", + "lightsail:GetStaticIps", + "lightsail:GetTagKeys", + "lightsail:GetTagValues", "lightsail:Is*", - "lightsail:Download*", + "lightsail:List*", "logs:Describe*", "logs:Get*", "logs:FilterLogEvents", "logs:ListTagsLogGroup", + "logs:StartQuery", "logs:TestMetricFilter", "machinelearning:Describe*", "machinelearning:Get*", + "mgh:Describe*", + "mgh:List*", "mobileanalytics:Get*", + "mobilehub:Describe*", + "mobilehub:Export*", + "mobilehub:Generate*", "mobilehub:Get*", "mobilehub:List*", "mobilehub:Validate*", "mobilehub:Verify*", "mobiletargeting:Get*", + "mq:Describe*", + "mq:List*", "opsworks:Describe*", "opsworks:Get*", "opsworks-cm:Describe*", "organizations:Describe*", "organizations:List*", + "pi:DescribeDimensionKeys", + "pi:GetResourceMetrics", "polly:Describe*", "polly:Get*", "polly:List*", @@ -11594,8 +26541,15 @@ aws_managed_policies_data = """ "rds:List*", "rds:Download*", "redshift:Describe*", + "redshift:GetReservedNodeExchangeOfferings", "redshift:View*", - "redshift:Get*", + "resource-groups:Describe*", + "resource-groups:Get*", + "resource-groups:List*", + "resource-groups:Search*", + "robomaker:BatchDescribe*", + "robomaker:Describe*", + "robomaker:List*", "route53:Get*", "route53:List*", "route53:Test*", @@ -11606,19 +26560,34 @@ aws_managed_policies_data = """ "s3:Get*", "s3:List*", "s3:Head*", + "sagemaker:Describe*", + "sagemaker:List*", "sdb:Get*", "sdb:List*", "sdb:Select*", + "secretsmanager:List*", + "secretsmanager:Describe*", + "secretsmanager:GetResourcePolicy", + "securityhub:Get*", + "securityhub:List*", + "serverlessrepo:List*", + "serverlessrepo:Get*", + "serverlessrepo:SearchApplications", "servicecatalog:List*", "servicecatalog:Scan*", "servicecatalog:Search*", "servicecatalog:Describe*", + "servicediscovery:Get*", + "servicediscovery:List*", "ses:Get*", "ses:List*", "ses:Describe*", - "ses:Verify*", "shield:Describe*", + "shield:Get*", "shield:List*", + "snowball:Get*", + "snowball:Describe*", + "snowball:List*", "sns:Get*", "sns:List*", "sns:Check*", @@ -11639,6 +26608,11 @@ aws_managed_policies_data = """ "swf:Get*", "swf:List*", "tag:Get*", + "transfer:Describe*", + "transfer:List*", + "transfer:TestIdentityProvider", + "transcribe:Get*", + "transcribe:List*", "trustedadvisor:Describe*", "waf:Get*", "waf:List*", @@ -11647,6 +26621,8 @@ aws_managed_policies_data = """ "workdocs:Describe*", "workdocs:Get*", "workdocs:CheckAlias", + "worklink:Describe*", + "worklink:List*", "workmail:Describe*", "workmail:Get*", "workmail:List*", @@ -11664,16 +26640,17 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAILL3HVNFSB6DCOWYQ", "PolicyName": "ReadOnlyAccess", - "UpdateDate": "2017-07-20T17:43:06+00:00", - "VersionId": "v29" + "UpdateDate": "2019-06-03T20:01:28+00:00", + "VersionId": "v50" }, "ResourceGroupsandTagEditorFullAccess": { "Arn": "arn:aws:iam::aws:policy/ResourceGroupsandTagEditorFullAccess", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:39:53+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -11681,8 +26658,13 @@ aws_managed_policies_data = """ "tag:getResources", "tag:getTagKeys", "tag:getTagValues", - "tag:addResourceTags", - "tag:removeResourceTags" + "tag:TagResources", + "tag:UntagResources", + "tag:AddResourceTags", + "tag:RemoveResourceTags", + "resource-groups:*", + "cloudformation:DescribeStacks", + "cloudformation:ListStackResources" ], "Effect": "Allow", "Resource": "*" @@ -11693,23 +26675,29 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJNOS54ZFXN4T2Y34A", "PolicyName": "ResourceGroupsandTagEditorFullAccess", - "UpdateDate": "2015-02-06T18:39:53+00:00", - "VersionId": "v1" + "UpdateDate": "2019-03-07T21:54:03+00:00", + "VersionId": "v4" }, "ResourceGroupsandTagEditorReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/ResourceGroupsandTagEditorReadOnlyAccess", "AttachmentCount": 0, "CreateDate": "2015-02-06T18:39:54+00:00", - "DefaultVersionId": "v1", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ "tag:getResources", "tag:getTagKeys", - "tag:getTagValues" + "tag:getTagValues", + "resource-groups:Get*", + "resource-groups:List*", + "resource-groups:Search*", + "cloudformation:DescribeStacks", + "cloudformation:ListStackResources" ], "Effect": "Allow", "Resource": "*" @@ -11720,35 +26708,119 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJHXQTPI5I5JKAIU74", "PolicyName": "ResourceGroupsandTagEditorReadOnlyAccess", - "UpdateDate": "2015-02-06T18:39:54+00:00", - "VersionId": "v1" + "UpdateDate": "2019-03-07T19:43:17+00:00", + "VersionId": "v2" }, - "SecurityAudit": { - "Arn": "arn:aws:iam::aws:policy/SecurityAudit", + "SecretsManagerReadWrite": { + "Arn": "arn:aws:iam::aws:policy/SecretsManagerReadWrite", "AttachmentCount": 0, - "CreateDate": "2017-07-12T20:16:44+00:00", - "DefaultVersionId": "v12", + "CreateDate": "2018-04-04T18:05:29+00:00", + "DefaultVersionId": "v2", "Document": { "Statement": [ { "Action": [ - "acm:ListCertificates", - "acm:DescribeCertificate", - "cloudformation:getStackPolicy", - "logs:describeLogGroups", - "logs:describeMetricFilters", + "secretsmanager:*", + "cloudformation:CreateChangeSet", + "cloudformation:DescribeChangeSet", + "cloudformation:DescribeStackResource", + "cloudformation:DescribeStacks", + "cloudformation:ExecuteChangeSet", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "kms:DescribeKey", + "kms:ListAliases", + "kms:ListKeys", + "lambda:ListFunctions", + "rds:DescribeDBClusters", + "rds:DescribeDBInstances", + "tag:GetResources" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "lambda:AddPermission", + "lambda:CreateFunction", + "lambda:GetFunction", + "lambda:InvokeFunction", + "lambda:UpdateFunctionConfiguration" + ], + "Effect": "Allow", + "Resource": "arn:aws:lambda:*:*:function:SecretsManager*" + }, + { + "Action": [ + "serverlessrepo:CreateCloudFormationChangeSet" + ], + "Effect": "Allow", + "Resource": "arn:aws:serverlessrepo:*:*:applications/SecretsManager*" + }, + { + "Action": [ + "s3:GetObject" + ], + "Effect": "Allow", + "Resource": "arn:aws:s3:::awsserverlessrepo-changesets*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAI3VG7CI5BIQZQ6G2E", + "PolicyName": "SecretsManagerReadWrite", + "UpdateDate": "2018-05-03T20:02:35+00:00", + "VersionId": "v2" + }, + "SecurityAudit": { + "Arn": "arn:aws:iam::aws:policy/SecurityAudit", + "AttachmentCount": 0, + "CreateDate": "2015-02-06T18:41:01+00:00", + "DefaultVersionId": "v27", + "Document": { + "Statement": [ + { + "Action": [ + "acm:Describe*", + "acm:List*", + "application-autoscaling:Describe*", + "appmesh:Describe*", + "appmesh:List*", + "appsync:List*", + "athena:List*", "autoscaling:Describe*", + "batch:DescribeComputeEnvironments", + "batch:DescribeJobDefinitions", + "chime:List*", + "cloud9:Describe*", + "cloud9:ListEnvironments", + "clouddirectory:ListDirectories", "cloudformation:DescribeStack*", "cloudformation:GetTemplate", "cloudformation:ListStack*", + "cloudformation:GetStackPolicy", "cloudfront:Get*", "cloudfront:List*", + "cloudhsm:ListHapgs", + "cloudhsm:ListHsms", + "cloudhsm:ListLunaClients", + "cloudsearch:DescribeDomains", + "cloudsearch:DescribeServiceAccessPolicies", "cloudtrail:DescribeTrails", + "cloudtrail:GetEventSelectors", "cloudtrail:GetTrailStatus", "cloudtrail:ListTags", + "cloudtrail:LookupEvents", "cloudwatch:Describe*", + "codebuild:ListProjects", "codecommit:BatchGetRepositories", "codecommit:GetBranch", "codecommit:GetObjectIdentifier", @@ -11757,9 +26829,21 @@ aws_managed_policies_data = """ "codedeploy:Batch*", "codedeploy:Get*", "codedeploy:List*", + "codepipeline:ListPipelines", + "codestar:Describe*", + "codestar:List*", + "cognito-identity:ListIdentityPools", + "cognito-idp:ListUserPools", + "cognito-sync:Describe*", + "cognito-sync:List*", + "comprehend:Describe*", + "comprehend:List*", + "config:BatchGetAggregateResourceConfig", + "config:BatchGetResourceConfig", "config:Deliver*", "config:Describe*", "config:Get*", + "config:List*", "datapipeline:DescribeObjects", "datapipeline:DescribePipelines", "datapipeline:EvaluateExpression", @@ -11767,83 +26851,204 @@ aws_managed_policies_data = """ "datapipeline:ListPipelines", "datapipeline:QueryObjects", "datapipeline:ValidatePipelineDefinition", + "datasync:Describe*", + "datasync:List*", + "dax:Describe*", + "dax:ListTags", "directconnect:Describe*", + "dms:Describe*", + "dms:ListTagsForResource", + "ds:DescribeDirectories", + "dynamodb:DescribeContinuousBackups", + "dynamodb:DescribeGlobalTable", + "dynamodb:DescribeTable", + "dynamodb:DescribeTimeToLive", + "dynamodb:ListBackups", + "dynamodb:ListGlobalTables", + "dynamodb:ListStreams", "dynamodb:ListTables", "ec2:Describe*", + "ecr:DescribeRepositories", + "ecr:GetRepositoryPolicy", "ecs:Describe*", "ecs:List*", + "eks:DescribeCluster", + "eks:ListClusters", "elasticache:Describe*", "elasticbeanstalk:Describe*", + "elasticfilesystem:DescribeFileSystems", + "elasticfilesystem:DescribeMountTargetSecurityGroups", + "elasticfilesystem:DescribeMountTargets", "elasticloadbalancing:Describe*", - "elasticmapreduce:DescribeJobFlows", + "elasticmapreduce:Describe*", "elasticmapreduce:ListClusters", "elasticmapreduce:ListInstances", - "es:ListDomainNames", "es:Describe*", + "es:ListDomainNames", + "events:Describe*", + "events:List*", "firehose:Describe*", "firehose:List*", + "fms:ListComplianceStatus", + "fms:ListPolicies", + "fsx:Describe*", + "fsx:List*", + "gamelift:ListBuilds", + "gamelift:ListFleets", "glacier:DescribeVault", "glacier:GetVaultAccessPolicy", "glacier:ListVaults", + "globalaccelerator:Describe*", + "globalaccelerator:List*", + "greengrass:List*", + "guardduty:Get*", + "guardduty:List*", "iam:GenerateCredentialReport", + "iam:GenerateServiceLastAccessedDetails", "iam:Get*", "iam:List*", + "iam:SimulateCustomPolicy", + "iam:SimulatePrincipalPolicy", + "inspector:Describe*", + "inspector:Get*", + "inspector:List*", + "inspector:Preview*", + "iot:Describe*", + "iot:GetPolicy", + "iot:GetPolicyVersion", + "iot:List*", + "kinesis:DescribeStream", + "kinesis:ListStreams", + "kinesis:ListTagsForStream", + "kinesisanalytics:ListApplications", "kms:Describe*", "kms:Get*", "kms:List*", + "lambda:GetAccountSettings", + "lambda:GetFunctionConfiguration", + "lambda:GetLayerVersionPolicy", "lambda:GetPolicy", - "lambda:ListFunctions", + "lambda:List*", + "license-manager:List*", + "lightsail:GetInstances", + "logs:Describe*", + "logs:ListTagsLogGroup", + "machinelearning:DescribeMLModels", + "mediaconnect:Describe*", + "mediaconnect:List*", + "mediastore:GetContainerPolicy", + "mediastore:ListContainers", + "opsworks:DescribeStacks", + "opsworks-cm:DescribeServers", + "organizations:List*", + "organizations:Describe*", + "quicksight:Describe*", + "quicksight:List*", + "ram:List*", "rds:Describe*", "rds:DownloadDBLogFilePortion", "rds:ListTagsForResource", "redshift:Describe*", - "route53:GetChange", - "route53:GetCheckerIpRanges", - "route53:GetGeoLocation", - "route53:GetHealthCheck", - "route53:GetHealthCheckCount", - "route53:GetHealthCheckLastFailureReason", - "route53:GetHostedZone", - "route53:GetHostedZoneCount", - "route53:GetReusableDelegationSet", - "route53:ListGeoLocations", - "route53:ListHealthChecks", - "route53:ListHostedZones", - "route53:ListHostedZonesByName", - "route53:ListResourceRecordSets", - "route53:ListReusableDelegationSets", - "route53:ListTagsForResource", - "route53:ListTagsForResources", + "rekognition:Describe*", + "rekognition:List*", + "robomaker:Describe*", + "robomaker:List*", + "route53:Get*", + "route53:List*", "route53domains:GetDomainDetail", "route53domains:GetOperationDetail", "route53domains:ListDomains", "route53domains:ListOperations", "route53domains:ListTagsForDomain", - "s3:GetBucket*", + "route53resolver:List*", "s3:GetAccelerateConfiguration", + "s3:GetAccountPublicAccessBlock", "s3:GetAnalyticsConfiguration", + "s3:GetBucket*", + "s3:GetEncryptionConfiguration", "s3:GetInventoryConfiguration", - "s3:GetMetricsConfiguration", - "s3:GetReplicationConfiguration", "s3:GetLifecycleConfiguration", + "s3:GetMetricsConfiguration", "s3:GetObjectAcl", "s3:GetObjectVersionAcl", + "s3:GetPublicAccessBlock", + "s3:GetReplicationConfiguration", "s3:ListAllMyBuckets", + "sagemaker:Describe*", + "sagemaker:List*", "sdb:DomainMetadata", "sdb:ListDomains", + "secretsmanager:GetResourcePolicy", + "secretsmanager:ListSecrets", + "secretsmanager:ListSecretVersionIds", + "securityhub:Get*", + "securityhub:List*", + "serverlessrepo:GetApplicationPolicy", + "serverlessrepo:List*", "ses:GetIdentityDkimAttributes", "ses:GetIdentityVerificationAttributes", "ses:ListIdentities", + "ses:ListVerifiedEmailAddresses", + "shield:Describe*", + "shield:List*", + "snowball:ListClusters", + "snowball:ListJobs", "sns:GetTopicAttributes", "sns:ListSubscriptionsByTopic", "sns:ListTopics", "sqs:GetQueueAttributes", + "sqs:ListDeadLetterSourceQueues", "sqs:ListQueues", + "sqs:ListQueueTags", + "ssm:Describe*", + "ssm:ListDocuments", + "sso:DescribePermissionsPolicies", + "sso:List*", + "states:ListStateMachines", + "storagegateway:DescribeBandwidthRateLimit", + "storagegateway:DescribeCache", + "storagegateway:DescribeCachediSCSIVolumes", + "storagegateway:DescribeGatewayInformation", + "storagegateway:DescribeMaintenanceStartTime", + "storagegateway:DescribeNFSFileShares", + "storagegateway:DescribeSnapshotSchedule", + "storagegateway:DescribeStorediSCSIVolumes", + "storagegateway:DescribeTapeArchives", + "storagegateway:DescribeTapeRecoveryPoints", + "storagegateway:DescribeTapes", + "storagegateway:DescribeUploadBuffer", + "storagegateway:DescribeVTLDevices", + "storagegateway:DescribeWorkingStorage", + "storagegateway:List*", "tag:GetResources", - "tag:GetTagKeys" + "tag:GetTagKeys", + "transfer:Describe*", + "transfer:List*", + "translate:List*", + "trustedadvisor:Describe*", + "waf:ListWebACLs", + "waf-regional:ListWebACLs", + "workspaces:Describe*" ], "Effect": "Allow", "Resource": "*" + }, + { + "Action": [ + "apigateway:HEAD", + "apigateway:GET", + "apigateway:OPTIONS" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:apigateway:*::/restapis", + "arn:aws:apigateway:*::/restapis/*/authorizers", + "arn:aws:apigateway:*::/restapis/*/authorizers/*", + "arn:aws:apigateway:*::/restapis/*/resources", + "arn:aws:apigateway:*::/restapis/*/resources/*", + "arn:aws:apigateway:*::/restapis/*/resources/*/methods/*", + "arn:aws:apigateway:*::/vpclinks" + ] } ], "Version": "2012-10-17" @@ -11851,10 +27056,11 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIX2T3QCXHR2OGGCTO", "PolicyName": "SecurityAudit", - "UpdateDate": "2017-07-12T20:16:44+00:00", - "VersionId": "v12" + "UpdateDate": "2019-04-29T18:33:52+00:00", + "VersionId": "v27" }, "ServerMigrationConnector": { "Arn": "arn:aws:iam::aws:policy/ServerMigrationConnector", @@ -11923,18 +27129,135 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJKZRWXIPK5HSG3QDQ", "PolicyName": "ServerMigrationConnector", "UpdateDate": "2016-10-24T21:45:56+00:00", "VersionId": "v1" }, + "ServerMigrationServiceLaunchRole": { + "Arn": "arn:aws:iam::aws:policy/service-role/ServerMigrationServiceLaunchRole", + "AttachmentCount": 0, + "CreateDate": "2018-11-26T19:53:06+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:ModifyInstanceAttribute", + "ec2:StopInstances", + "ec2:StartInstances", + "ec2:TerminateInstances" + ], + "Condition": { + "ForAllValues:StringLike": { + "ec2:ResourceTag/aws:cloudformation:stack-id": "arn:aws:cloudformation:*:*:stack/sms-app-*/*" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "ec2:CreateTags", + "Effect": "Allow", + "Resource": "arn:aws:ec2:*:*:instance/*" + }, + { + "Action": [ + "ec2:RunInstances", + "ec2:Describe*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIIIAAMVUCBR2OLXZO", + "PolicyName": "ServerMigrationServiceLaunchRole", + "UpdateDate": "2018-11-26T19:53:06+00:00", + "VersionId": "v1" + }, "ServerMigrationServiceRole": { "Arn": "arn:aws:iam::aws:policy/service-role/ServerMigrationServiceRole", "AttachmentCount": 0, - "CreateDate": "2017-06-16T18:02:04+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2016-10-24T21:19:00+00:00", + "DefaultVersionId": "v3", "Document": { "Statement": [ + { + "Action": [ + "cloudformation:CreateChangeSet", + "cloudformation:CreateStack", + "cloudformation:DeleteStack", + "cloudformation:ExecuteChangeSet" + ], + "Condition": { + "ForAllValues:StringLikeIfExists": { + "cloudformation:ResourceTypes": [ + "AWS::EC2::*" + ] + } + }, + "Effect": "Allow", + "Resource": "arn:aws:cloudformation:*:*:stack/sms-app-*/*" + }, + { + "Action": [ + "cloudformation:DeleteChangeSet", + "cloudformation:DescribeChangeSet", + "cloudformation:DescribeStackEvents", + "cloudformation:DescribeStackResources", + "cloudformation:GetTemplate" + ], + "Effect": "Allow", + "Resource": "arn:aws:cloudformation:*:*:stack/sms-app-*/*" + }, + { + "Action": [ + "cloudformation:DescribeStacks", + "cloudformation:ValidateTemplate", + "cloudformation:DescribeStackResource", + "s3:ListAllMyBuckets" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "s3:CreateBucket", + "s3:DeleteBucket", + "s3:DeleteObject", + "s3:GetBucketAcl", + "s3:GetBucketLocation", + "s3:GetObject", + "s3:ListBucket", + "s3:PutObject", + "s3:PutObjectAcl", + "s3:PutLifecycleConfiguration", + "s3:ListAllMyBuckets" + ], + "Effect": "Allow", + "Resource": "arn:aws:s3:::sms-app-*" + }, + { + "Action": [ + "sms:CreateReplicationJob", + "sms:DeleteReplicationJob", + "sms:GetReplicationJobs", + "sms:GetReplicationRuns", + "sms:GetServers", + "sms:ImportServerCatalog", + "sms:StartOnDemandReplicationRun", + "sms:UpdateReplicationJob" + ], + "Effect": "Allow", + "Resource": "*" + }, { "Action": [ "ec2:ModifySnapshotAttribute", @@ -11948,50 +27271,19 @@ aws_managed_policies_data = """ ], "Effect": "Allow", "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "IsAttachable": true, - "IsDefaultVersion": true, - "Path": "/service-role/", - "PolicyId": "ANPAJMBH3M6BO63XFW2D4", - "PolicyName": "ServerMigrationServiceRole", - "UpdateDate": "2017-06-16T18:02:04+00:00", - "VersionId": "v2" - }, - "ServiceCatalogAdminFullAccess": { - "Arn": "arn:aws:iam::aws:policy/ServiceCatalogAdminFullAccess", - "AttachmentCount": 0, - "CreateDate": "2016-11-11T18:40:24+00:00", - "DefaultVersionId": "v2", - "Document": { - "Statement": [ + }, { - "Action": [ - "catalog-admin:*", - "catalog-user:*", - "cloudformation:CreateStack", - "cloudformation:CreateUploadBucket", - "cloudformation:DeleteStack", - "cloudformation:DescribeStackEvents", - "cloudformation:DescribeStacks", - "cloudformation:GetTemplateSummary", - "cloudformation:SetStackPolicy", - "cloudformation:ValidateTemplate", - "cloudformation:UpdateStack", - "iam:GetGroup", - "iam:GetRole", - "iam:GetUser", - "iam:ListGroups", - "iam:ListRoles", - "iam:ListUsers", - "iam:PassRole", - "s3:CreateBucket", - "s3:GetObject", - "s3:PutObject", - "servicecatalog:*" - ], + "Action": "iam:GetRole", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": "iam:PassRole", + "Condition": { + "StringLike": { + "iam:AssociatedResourceArn": "arn:aws:cloudformation:*:*:stack/sms-app-*/*" + } + }, "Effect": "Allow", "Resource": "*" } @@ -12000,16 +27292,17 @@ aws_managed_policies_data = """ }, "IsAttachable": true, "IsDefaultVersion": true, - "Path": "/", - "PolicyId": "ANPAIKTX42IAS75B7B7BY", - "PolicyName": "ServiceCatalogAdminFullAccess", - "UpdateDate": "2016-11-11T18:40:24+00:00", - "VersionId": "v2" + "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJMBH3M6BO63XFW2D4", + "PolicyName": "ServerMigrationServiceRole", + "UpdateDate": "2018-11-26T19:33:29+00:00", + "VersionId": "v3" }, "ServiceCatalogAdminReadOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/ServiceCatalogAdminReadOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-08T18:57:36+00:00", + "CreateDate": "2015-09-29T18:40:35+00:00", "DefaultVersionId": "v5", "Document": { "Statement": [ @@ -12080,6 +27373,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ7XOUSS75M4LIPKO4", "PolicyName": "ServiceCatalogAdminReadOnlyAccess", "UpdateDate": "2017-08-08T18:57:36+00:00", @@ -12088,7 +27382,7 @@ aws_managed_policies_data = """ "ServiceCatalogEndUserAccess": { "Arn": "arn:aws:iam::aws:policy/ServiceCatalogEndUserAccess", "AttachmentCount": 0, - "CreateDate": "2017-08-08T18:58:57+00:00", + "CreateDate": "2015-09-29T18:41:33+00:00", "DefaultVersionId": "v4", "Document": { "Statement": [ @@ -12126,68 +27420,12 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJ56OMCO72RI4J5FSA", "PolicyName": "ServiceCatalogEndUserAccess", "UpdateDate": "2017-08-08T18:58:57+00:00", "VersionId": "v4" }, - "ServiceCatalogEndUserFullAccess": { - "Arn": "arn:aws:iam::aws:policy/ServiceCatalogEndUserFullAccess", - "AttachmentCount": 0, - "CreateDate": "2017-08-08T18:58:54+00:00", - "DefaultVersionId": "v4", - "Document": { - "Statement": [ - { - "Action": [ - "catalog-user:*", - "cloudformation:CreateStack", - "cloudformation:DeleteStack", - "cloudformation:DescribeStackEvents", - "cloudformation:DescribeStacks", - "cloudformation:GetTemplateSummary", - "cloudformation:SetStackPolicy", - "cloudformation:ValidateTemplate", - "cloudformation:UpdateStack", - "servicecatalog:DescribeProduct", - "servicecatalog:DescribeProductView", - "servicecatalog:DescribeProvisioningParameters", - "servicecatalog:ListLaunchPaths", - "servicecatalog:ProvisionProduct", - "servicecatalog:SearchProducts", - "s3:GetObject" - ], - "Effect": "Allow", - "Resource": "*" - }, - { - "Action": [ - "servicecatalog:DescribeProvisionedProduct", - "servicecatalog:DescribeRecord", - "servicecatalog:ListRecordHistory", - "servicecatalog:ScanProvisionedProducts", - "servicecatalog:TerminateProvisionedProduct", - "servicecatalog:UpdateProvisionedProduct" - ], - "Condition": { - "StringEquals": { - "servicecatalog:userLevel": "self" - } - }, - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "IsAttachable": true, - "IsDefaultVersion": true, - "Path": "/", - "PolicyId": "ANPAJIW7AFFOONVKW75KU", - "PolicyName": "ServiceCatalogEndUserFullAccess", - "UpdateDate": "2017-08-08T18:58:54+00:00", - "VersionId": "v4" - }, "SimpleWorkflowFullAccess": { "Arn": "arn:aws:iam::aws:policy/SimpleWorkflowFullAccess", "AttachmentCount": 0, @@ -12208,6 +27446,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAIFE3AV6VE7EANYBVM", "PolicyName": "SimpleWorkflowFullAccess", "UpdateDate": "2015-02-06T18:41:04+00:00", @@ -12216,7 +27455,7 @@ aws_managed_policies_data = """ "SupportUser": { "Arn": "arn:aws:iam::aws:policy/job-function/SupportUser", "AttachmentCount": 0, - "CreateDate": "2017-05-17T23:11:51+00:00", + "CreateDate": "2016-11-10T17:21:53+00:00", "DefaultVersionId": "v2", "Document": { "Statement": [ @@ -12434,6 +27673,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/job-function/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAI3V4GSSN5SJY3P2RO", "PolicyName": "SupportUser", "UpdateDate": "2017-05-17T23:11:51+00:00", @@ -12442,8 +27682,8 @@ aws_managed_policies_data = """ "SystemAdministrator": { "Arn": "arn:aws:iam::aws:policy/job-function/SystemAdministrator", "AttachmentCount": 0, - "CreateDate": "2017-03-24T17:45:43+00:00", - "DefaultVersionId": "v2", + "CreateDate": "2016-11-10T17:23:56+00:00", + "DefaultVersionId": "v4", "Document": { "Statement": [ { @@ -12554,6 +27794,8 @@ aws_managed_policies_data = """ "ec2:RunScheduledInstances", "ec2:UnassignPrivateIpAddresses", "ec2:UnmonitorInstances", + "ec2:UpdateSecurityGroupRuleDescriptionsEgress", + "ec2:UpdateSecurityGroupRuleDescriptionsIngress", "elasticloadbalancing:*", "events:*", "iam:GetAccount*", @@ -12688,7 +27930,8 @@ aws_managed_policies_data = """ "arn:aws:iam::*:role/rds-monitoring-role", "arn:aws:iam::*:role/ec2-sysadmin-*", "arn:aws:iam::*:role/ecr-sysadmin-*", - "arn:aws:iam::*:role/lamdba-sysadmin-*" + "arn:aws:iam::*:role/lamdba-sysadmin-*", + "arn:aws:iam::*:role/lambda-sysadmin-*" ] } ], @@ -12697,11 +27940,120 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/job-function/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAITJPEZXCYCBXANDSW", "PolicyName": "SystemAdministrator", - "UpdateDate": "2017-03-24T17:45:43+00:00", + "UpdateDate": "2018-10-08T21:33:45+00:00", + "VersionId": "v4" + }, + "TagPoliciesServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/TagPoliciesServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-10-26T20:02:52+00:00", + "DefaultVersionId": "v2", + "Document": { + "Statement": [ + { + "Action": [ + "organizations:ListAccounts", + "organizations:ListAccountsForParent", + "organizations:ListChildren", + "organizations:DescribeAccount", + "organizations:DescribeOrganization", + "organizations:ListRoots", + "organizations:ListParents" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "organizations:DisableAWSServiceAccess" + ], + "Condition": { + "ForAllValues:StringLike": { + "organizations:ServicePrincipal": [ + "tagpolicies.tag.amazonaws.com" + ] + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJGGCZXCABSYJA7UBI", + "PolicyName": "TagPoliciesServiceRolePolicy", + "UpdateDate": "2019-05-10T21:38:33+00:00", "VersionId": "v2" }, + "TranslateFullAccess": { + "Arn": "arn:aws:iam::aws:policy/TranslateFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-27T23:36:20+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "translate:*", + "comprehend:DetectDominantLanguage", + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIAPOAEI2VFQYUK5RY", + "PolicyName": "TranslateFullAccess", + "UpdateDate": "2018-11-27T23:36:20+00:00", + "VersionId": "v1" + }, + "TranslateReadOnly": { + "Arn": "arn:aws:iam::aws:policy/TranslateReadOnly", + "AttachmentCount": 0, + "CreateDate": "2017-11-29T18:22:00+00:00", + "DefaultVersionId": "v4", + "Document": { + "Statement": [ + { + "Action": [ + "translate:TranslateText", + "translate:GetTerminology", + "translate:ListTerminologies", + "comprehend:DetectDominantLanguage", + "cloudwatch:GetMetricStatistics", + "cloudwatch:ListMetrics" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJYAMZMTQNWUDJKY2E", + "PolicyName": "TranslateReadOnly", + "UpdateDate": "2018-11-27T23:29:08+00:00", + "VersionId": "v4" + }, "VMImportExportRoleForAWSConnector": { "Arn": "arn:aws:iam::aws:policy/service-role/VMImportExportRoleForAWSConnector", "AttachmentCount": 0, @@ -12736,6 +28088,7 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/service-role/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAJFLQOOJ6F5XNX4LAW", "PolicyName": "VMImportExportRoleForAWSConnector", "UpdateDate": "2015-09-03T20:48:59+00:00", @@ -12744,8 +28097,8 @@ aws_managed_policies_data = """ "ViewOnlyAccess": { "Arn": "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess", "AttachmentCount": 0, - "CreateDate": "2017-06-26T22:35:31+00:00", - "DefaultVersionId": "v3", + "CreateDate": "2016-11-10T17:20:15+00:00", + "DefaultVersionId": "v7", "Document": { "Statement": [ { @@ -12771,7 +28124,7 @@ aws_managed_policies_data = """ "cloudtrail:DescribeTrails", "cloudtrail:LookupEvents", "cloudwatch:List*", - "cloudwatch:GetMetricData", + "cloudwatch:Get*", "codebuild:ListBuilds*", "codebuild:ListProjects", "codecommit:List*", @@ -12790,12 +28143,35 @@ aws_managed_policies_data = """ "datapipeline:ListPipelines", "datapipeline:DescribePipelines", "datapipeline:GetAccountLimits", + "dax:DescribeClusters", + "dax:DescribeDefaultParameters", + "dax:DescribeEvents", + "dax:DescribeParameterGroups", + "dax:DescribeParameters", + "dax:DescribeSubnetGroups", + "dax:DescribeTable", + "dax:ListTables", + "dax:ListTags", "devicefarm:List*", "directconnect:Describe*", "discovery:List*", "dms:List*", "ds:DescribeDirectories", + "dynamodb:DescribeBackup", + "dynamodb:DescribeContinuousBackups", + "dynamodb:DescribeGlobalTable", + "dynamodb:DescribeGlobalTableSettings", + "dynamodb:DescribeLimits", + "dynamodb:DescribeReservedCapacity", + "dynamodb:DescribeReservedCapacityOfferings", + "dynamodb:DescribeStream", + "dynamodb:DescribeTable", + "dynamodb:DescribeTimeToLive", + "dynamodb:ListBackups", + "dynamodb:ListGlobalTables", + "dynamodb:ListStreams", "dynamodb:ListTables", + "dynamodb:ListTagsOfResource", "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", "ec2:DescribeAvailabilityZones", @@ -12826,12 +28202,14 @@ aws_managed_policies_data = """ "ec2:DescribeSnapshot*", "ec2:DescribeSpot*", "ec2:DescribeSubnets", + "ec2:DescribeTags", "ec2:DescribeVolume*", "ec2:DescribeVpc*", "ec2:DescribeVpnGateways", "ecr:DescribeRepositories", "ecr:ListImages", "ecs:List*", + "ecs:Describe*", "elasticache:Describe*", "elasticbeanstalk:DescribeApplicationVersions", "elasticbeanstalk:DescribeApplications", @@ -12854,6 +28232,7 @@ aws_managed_policies_data = """ "firehose:DescribeDeliveryStream", "gamelift:List*", "glacier:List*", + "greengrass:List*", "iam:List*", "iam:GetAccountSummary", "iam:GetLoginProfile", @@ -12904,6 +28283,8 @@ aws_managed_policies_data = """ "route53domains:List*", "s3:ListAllMyBuckets", "s3:ListBucket", + "sagemaker:Describe*", + "sagemaker:List*", "sdb:List*", "servicecatalog:List*", "ses:List*", @@ -12936,9 +28317,159 @@ aws_managed_policies_data = """ "IsAttachable": true, "IsDefaultVersion": true, "Path": "/job-function/", + "PermissionsBoundaryUsageCount": 0, "PolicyId": "ANPAID22R6XPJATWOFDK6", "PolicyName": "ViewOnlyAccess", - "UpdateDate": "2017-06-26T22:35:31+00:00", - "VersionId": "v3" + "UpdateDate": "2018-10-15T18:34:54+00:00", + "VersionId": "v7" + }, + "WAFLoggingServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/WAFLoggingServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-08-24T21:05:47+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "firehose:PutRecord", + "firehose:PutRecordBatch" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:firehose:*:*:deliverystream/aws-waf-logs-*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJZ7N545GUNUHNTYOM", + "PolicyName": "WAFLoggingServiceRolePolicy", + "UpdateDate": "2018-08-24T21:05:47+00:00", + "VersionId": "v1" + }, + "WAFRegionalLoggingServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/aws-service-role/WAFRegionalLoggingServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2018-08-24T18:40:55+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "firehose:PutRecord", + "firehose:PutRecordBatch" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:firehose:*:*:deliverystream/aws-waf-logs-*" + ] + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/aws-service-role/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJE43HAZMEH4CI6SU2", + "PolicyName": "WAFRegionalLoggingServiceRolePolicy", + "UpdateDate": "2018-08-24T18:40:55+00:00", + "VersionId": "v1" + }, + "WellArchitectedConsoleFullAccess": { + "Arn": "arn:aws:iam::aws:policy/WellArchitectedConsoleFullAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-29T18:19:23+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "wellarchitected:*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIH6HSBHM3VSYC5SKA", + "PolicyName": "WellArchitectedConsoleFullAccess", + "UpdateDate": "2018-11-29T18:19:23+00:00", + "VersionId": "v1" + }, + "WellArchitectedConsoleReadOnlyAccess": { + "Arn": "arn:aws:iam::aws:policy/WellArchitectedConsoleReadOnlyAccess", + "AttachmentCount": 0, + "CreateDate": "2018-11-29T18:21:08+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "wellarchitected:Get*", + "wellarchitected:List*" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAIUTK35NDTYF6T2GFY", + "PolicyName": "WellArchitectedConsoleReadOnlyAccess", + "UpdateDate": "2018-11-29T18:21:08+00:00", + "VersionId": "v1" + }, + "WorkLinkServiceRolePolicy": { + "Arn": "arn:aws:iam::aws:policy/WorkLinkServiceRolePolicy", + "AttachmentCount": 0, + "CreateDate": "2019-01-23T19:03:45+00:00", + "DefaultVersionId": "v1", + "Document": { + "Statement": [ + { + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:DeleteNetworkInterfacePermission", + "ec2:CreateNetworkInterfacePermission", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:DeleteNetworkInterface" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": "arn:aws:kinesis:*:*:stream/AmazonWorkLink-*" + } + ], + "Version": "2012-10-17" + }, + "IsAttachable": true, + "IsDefaultVersion": true, + "Path": "/", + "PermissionsBoundaryUsageCount": 0, + "PolicyId": "ANPAJ6JTE3DI5JOULLNLS", + "PolicyName": "WorkLinkServiceRolePolicy", + "UpdateDate": "2019-01-23T19:03:45+00:00", + "VersionId": "v1" } }""" diff --git a/moto/iam/exceptions.py b/moto/iam/exceptions.py index 5b13277da..ac08e0d88 100644 --- a/moto/iam/exceptions.py +++ b/moto/iam/exceptions.py @@ -26,6 +26,14 @@ class IAMReportNotPresentException(RESTError): "ReportNotPresent", message) +class IAMLimitExceededException(RESTError): + code = 400 + + def __init__(self, message): + super(IAMLimitExceededException, self).__init__( + "LimitExceeded", message) + + class MalformedCertificate(RESTError): code = 400 @@ -34,6 +42,14 @@ class MalformedCertificate(RESTError): 'MalformedCertificate', 'Certificate {cert} is malformed'.format(cert=cert)) +class MalformedPolicyDocument(RESTError): + code = 400 + + def __init__(self, message=""): + super(MalformedPolicyDocument, self).__init__( + 'MalformedPolicyDocument', message) + + class DuplicateTags(RESTError): code = 400 diff --git a/moto/iam/models.py b/moto/iam/models.py index 095bbab29..d76df8a28 100644 --- a/moto/iam/models.py +++ b/moto/iam/models.py @@ -8,14 +8,14 @@ import re from cryptography import x509 from cryptography.hazmat.backends import default_backend -import pytz from moto.core.exceptions import RESTError from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_without_milliseconds +from moto.core.utils import iso_8601_datetime_without_milliseconds, iso_8601_datetime_with_milliseconds +from moto.iam.policy_validation import IAMPolicyDocumentValidator from .aws_managed_policies import aws_managed_policies_data -from .exceptions import IAMNotFoundException, IAMConflictException, IAMReportNotPresentException, MalformedCertificate, \ - DuplicateTags, TagKeyTooBig, InvalidTagCharacters, TooManyTags, TagValueTooBig +from .exceptions import IAMNotFoundException, IAMConflictException, IAMReportNotPresentException, IAMLimitExceededException, \ + MalformedCertificate, DuplicateTags, TagKeyTooBig, InvalidTagCharacters, TooManyTags, TagValueTooBig from .utils import random_access_key, random_alphanumeric, random_resource_id, random_policy_id ACCOUNT_ID = 123456789012 @@ -28,11 +28,15 @@ class MFADevice(object): serial_number, authentication_code_1, authentication_code_2): - self.enable_date = datetime.now(pytz.utc) + self.enable_date = datetime.utcnow() self.serial_number = serial_number self.authentication_code_1 = authentication_code_1 self.authentication_code_2 = authentication_code_2 + @property + def enabled_iso_8601(self): + return iso_8601_datetime_without_milliseconds(self.enable_date) + class Policy(BaseModel): is_attachable = False @@ -42,7 +46,9 @@ class Policy(BaseModel): default_version_id=None, description=None, document=None, - path=None): + path=None, + create_date=None, + update_date=None): self.name = name self.attachment_count = 0 @@ -56,10 +62,25 @@ class Policy(BaseModel): else: self.default_version_id = 'v1' self.next_version_num = 2 - self.versions = [PolicyVersion(self.arn, document, True)] + self.versions = [PolicyVersion(self.arn, document, True, self.default_version_id, update_date)] - self.create_datetime = datetime.now(pytz.utc) - self.update_datetime = datetime.now(pytz.utc) + self.create_date = create_date if create_date is not None else datetime.utcnow() + self.update_date = update_date if update_date is not None else datetime.utcnow() + + def update_default_version(self, new_default_version_id): + for version in self.versions: + if version.version_id == self.default_version_id: + version.is_default = False + break + self.default_version_id = new_default_version_id + + @property + def created_iso_8601(self): + return iso_8601_datetime_with_milliseconds(self.create_date) + + @property + def updated_iso_8601(self): + return iso_8601_datetime_with_milliseconds(self.update_date) class SAMLProvider(BaseModel): @@ -77,13 +98,19 @@ class PolicyVersion(object): def __init__(self, policy_arn, document, - is_default=False): + is_default=False, + version_id='v1', + create_date=None): self.policy_arn = policy_arn self.document = document or {} self.is_default = is_default - self.version_id = 'v1' + self.version_id = version_id - self.create_datetime = datetime.now(pytz.utc) + self.create_date = create_date if create_date is not None else datetime.utcnow() + + @property + def created_iso_8601(self): + return iso_8601_datetime_with_milliseconds(self.create_date) class ManagedPolicy(Policy): @@ -112,7 +139,9 @@ class AWSManagedPolicy(ManagedPolicy): return cls(name, default_version_id=data.get('DefaultVersionId'), path=data.get('Path'), - document=data.get('Document')) + document=json.dumps(data.get('Document')), + create_date=datetime.strptime(data.get('CreateDate'), "%Y-%m-%dT%H:%M:%S+00:00"), + update_date=datetime.strptime(data.get('UpdateDate'), "%Y-%m-%dT%H:%M:%S+00:00")) @property def arn(self): @@ -132,18 +161,22 @@ class InlinePolicy(Policy): class Role(BaseModel): - def __init__(self, role_id, name, assume_role_policy_document, path, permissions_boundary): + def __init__(self, role_id, name, assume_role_policy_document, path, permissions_boundary, description, tags): self.id = role_id self.name = name self.assume_role_policy_document = assume_role_policy_document self.path = path or '/' self.policies = {} self.managed_policies = {} - self.create_date = datetime.now(pytz.utc) - self.tags = {} - self.description = "" + self.create_date = datetime.utcnow() + self.tags = tags + self.description = description self.permissions_boundary = permissions_boundary + @property + def created_iso_8601(self): + return iso_8601_datetime_with_milliseconds(self.create_date) + @classmethod def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): properties = cloudformation_json['Properties'] @@ -152,7 +185,9 @@ class Role(BaseModel): role_name=resource_name, assume_role_policy_document=properties['AssumeRolePolicyDocument'], path=properties.get('Path', '/'), - permissions_boundary=properties.get('PermissionsBoundary', '') + permissions_boundary=properties.get('PermissionsBoundary', ''), + description=properties.get('Description', ''), + tags=properties.get('Tags', {}) ) policies = properties.get('Policies', []) @@ -198,7 +233,11 @@ class InstanceProfile(BaseModel): self.name = name self.path = path or '/' self.roles = roles if roles else [] - self.create_date = datetime.now(pytz.utc) + self.create_date = datetime.utcnow() + + @property + def created_iso_8601(self): + return iso_8601_datetime_with_milliseconds(self.create_date) @classmethod def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): @@ -250,25 +289,31 @@ class SigningCertificate(BaseModel): self.id = id self.user_name = user_name self.body = body - self.upload_date = datetime.strftime(datetime.utcnow(), "%Y-%m-%d-%H-%M-%S") + self.upload_date = datetime.utcnow() self.status = 'Active' + @property + def uploaded_iso_8601(self): + return iso_8601_datetime_without_milliseconds(self.upload_date) + class AccessKey(BaseModel): def __init__(self, user_name): self.user_name = user_name - self.access_key_id = random_access_key() - self.secret_access_key = random_alphanumeric(32) + self.access_key_id = "AKIA" + random_access_key() + self.secret_access_key = random_alphanumeric(40) self.status = 'Active' - self.create_date = datetime.strftime( - datetime.utcnow(), - "%Y-%m-%dT%H:%M:%SZ" - ) - self.last_used = datetime.strftime( - datetime.utcnow(), - "%Y-%m-%dT%H:%M:%SZ" - ) + self.create_date = datetime.utcnow() + self.last_used = datetime.utcnow() + + @property + def created_iso_8601(self): + return iso_8601_datetime_without_milliseconds(self.create_date) + + @property + def last_used_iso_8601(self): + return iso_8601_datetime_without_milliseconds(self.last_used) def get_cfn_attribute(self, attribute_name): from moto.cloudformation.exceptions import UnformattedGetAttTemplateException @@ -283,15 +328,16 @@ class Group(BaseModel): self.name = name self.id = random_resource_id() self.path = path - self.created = datetime.strftime( - datetime.utcnow(), - "%Y-%m-%d-%H-%M-%S" - ) + self.create_date = datetime.utcnow() self.users = [] self.managed_policies = {} self.policies = {} + @property + def created_iso_8601(self): + return iso_8601_datetime_with_milliseconds(self.create_date) + def get_cfn_attribute(self, attribute_name): from moto.cloudformation.exceptions import UnformattedGetAttTemplateException if attribute_name == 'Arn': @@ -306,10 +352,6 @@ class Group(BaseModel): else: return "arn:aws:iam::{0}:group/{1}/{2}".format(ACCOUNT_ID, self.path, self.name) - @property - def create_date(self): - return self.created - def get_policy(self, policy_name): try: policy_json = self.policies[policy_name] @@ -335,7 +377,7 @@ class User(BaseModel): self.name = name self.id = random_resource_id() self.path = path if path else "/" - self.created = datetime.utcnow() + self.create_date = datetime.utcnow() self.mfa_devices = {} self.policies = {} self.managed_policies = {} @@ -350,7 +392,7 @@ class User(BaseModel): @property def created_iso_8601(self): - return iso_8601_datetime_without_milliseconds(self.created) + return iso_8601_datetime_with_milliseconds(self.create_date) def get_policy(self, policy_name): policy_json = None @@ -421,7 +463,7 @@ class User(BaseModel): def to_csv(self): date_format = '%Y-%m-%dT%H:%M:%S+00:00' - date_created = self.created + date_created = self.create_date # aagrawal,arn:aws:iam::509284790694:user/aagrawal,2014-09-01T22:28:48+00:00,true,2014-11-12T23:36:49+00:00,2014-09-03T18:59:00+00:00,N/A,false,true,2014-09-01T22:28:48+00:00,false,N/A,false,N/A,false,N/A if not self.password: password_enabled = 'false' @@ -478,7 +520,7 @@ class IAMBackend(BaseBackend): super(IAMBackend, self).__init__() def _init_managed_policies(self): - return dict((p.name, p) for p in aws_managed_policies) + return dict((p.arn, p) for p in aws_managed_policies) def attach_role_policy(self, policy_arn, role_name): arns = dict((p.arn, p) for p in self.managed_policies.values()) @@ -536,6 +578,9 @@ class IAMBackend(BaseBackend): policy.detach_from(self.get_user(user_name)) def create_policy(self, description, path, policy_document, policy_name): + iam_policy_document_validator = IAMPolicyDocumentValidator(policy_document) + iam_policy_document_validator.validate() + policy = ManagedPolicy( policy_name, description=description, @@ -592,12 +637,13 @@ class IAMBackend(BaseBackend): return policies, marker - def create_role(self, role_name, assume_role_policy_document, path, permissions_boundary): + def create_role(self, role_name, assume_role_policy_document, path, permissions_boundary, description, tags): role_id = random_resource_id() if permissions_boundary and not self.policy_arn_regex.match(permissions_boundary): raise RESTError('InvalidParameterValue', 'Value ({}) for parameter PermissionsBoundary is invalid.'.format(permissions_boundary)) - role = Role(role_id, role_name, assume_role_policy_document, path, permissions_boundary) + clean_tags = self._tag_verification(tags) + role = Role(role_id, role_name, assume_role_policy_document, path, permissions_boundary, description, clean_tags) self.roles[role_id] = role return role @@ -628,6 +674,9 @@ class IAMBackend(BaseBackend): def put_role_policy(self, role_name, policy_name, policy_json): role = self.get_role(role_name) + + iam_policy_document_validator = IAMPolicyDocumentValidator(policy_json) + iam_policy_document_validator.validate() role.put_policy(policy_name, policy_json) def delete_role_policy(self, role_name, policy_name): @@ -639,15 +688,32 @@ class IAMBackend(BaseBackend): for p, d in role.policies.items(): if p == policy_name: return p, d + raise IAMNotFoundException("Policy Document {0} not attached to role {1}".format(policy_name, role_name)) def list_role_policies(self, role_name): role = self.get_role(role_name) return role.policies.keys() + def _tag_verification(self, tags): + if len(tags) > 50: + raise TooManyTags(tags) + + tag_keys = {} + for tag in tags: + # Need to index by the lowercase tag key since the keys are case insensitive, but their case is retained. + ref_key = tag['Key'].lower() + self._check_tag_duplicate(tag_keys, ref_key) + self._validate_tag_key(tag['Key']) + if len(tag['Value']) > 256: + raise TagValueTooBig(tag['Value']) + + tag_keys[ref_key] = tag + + return tag_keys + def _validate_tag_key(self, tag_key, exception_param='tags.X.member.key'): """Validates the tag key. - :param all_tags: Dict to check if there is a duplicate tag. :param tag_key: The tag key to check against. :param exception_param: The exception parameter to send over to help format the message. This is to reflect the difference between the tag and untag APIs. @@ -694,23 +760,9 @@ class IAMBackend(BaseBackend): return tags, marker def tag_role(self, role_name, tags): - if len(tags) > 50: - raise TooManyTags(tags) - + clean_tags = self._tag_verification(tags) role = self.get_role(role_name) - - tag_keys = {} - for tag in tags: - # Need to index by the lowercase tag key since the keys are case insensitive, but their case is retained. - ref_key = tag['Key'].lower() - self._check_tag_duplicate(tag_keys, ref_key) - self._validate_tag_key(tag['Key']) - if len(tag['Value']) > 256: - raise TagValueTooBig(tag['Value']) - - tag_keys[ref_key] = tag - - role.tags.update(tag_keys) + role.tags.update(clean_tags) def untag_role(self, role_name, tag_keys): if len(tag_keys) > 50: @@ -725,15 +777,21 @@ class IAMBackend(BaseBackend): role.tags.pop(ref_key, None) def create_policy_version(self, policy_arn, policy_document, set_as_default): + iam_policy_document_validator = IAMPolicyDocumentValidator(policy_document) + iam_policy_document_validator.validate() + policy = self.get_policy(policy_arn) if not policy: raise IAMNotFoundException("Policy not found") + if len(policy.versions) >= 5: + raise IAMLimitExceededException("A managed policy can have up to 5 versions. Before you create a new version, you must delete an existing version.") + set_as_default = (set_as_default == "true") # convert it to python bool version = PolicyVersion(policy_arn, policy_document, set_as_default) policy.versions.append(version) version.version_id = 'v{0}'.format(policy.next_version_num) policy.next_version_num += 1 if set_as_default: - policy.default_version_id = version.version_id + policy.update_default_version(version.version_id) return version def get_policy_version(self, policy_arn, version_id): @@ -756,8 +814,8 @@ class IAMBackend(BaseBackend): if not policy: raise IAMNotFoundException("Policy not found") if version_id == policy.default_version_id: - raise IAMConflictException( - "Cannot delete the default version of a policy") + raise IAMConflictException(code="DeleteConflict", + message="Cannot delete the default version of a policy.") for i, v in enumerate(policy.versions): if v.version_id == version_id: del policy.versions[i] @@ -869,6 +927,9 @@ class IAMBackend(BaseBackend): def put_group_policy(self, group_name, policy_name, policy_json): group = self.get_group(group_name) + + iam_policy_document_validator = IAMPolicyDocumentValidator(policy_json) + iam_policy_document_validator.validate() group.put_policy(policy_name, policy_json) def list_group_policies(self, group_name, marker=None, max_items=None): @@ -1029,6 +1090,9 @@ class IAMBackend(BaseBackend): def put_user_policy(self, user_name, policy_name, policy_json): user = self.get_user(user_name) + + iam_policy_document_validator = IAMPolicyDocumentValidator(policy_json) + iam_policy_document_validator.validate() user.put_policy(policy_name, policy_json) def delete_user_policy(self, user_name, policy_name): @@ -1050,7 +1114,7 @@ class IAMBackend(BaseBackend): if key.access_key_id == access_key_id: return { 'user_name': key.user_name, - 'last_used': key.last_used + 'last_used': key.last_used_iso_8601, } else: raise IAMNotFoundException( @@ -1189,5 +1253,13 @@ class IAMBackend(BaseBackend): return saml_provider raise IAMNotFoundException("SamlProvider {0} not found".format(saml_provider_arn)) + def get_user_from_access_key_id(self, access_key_id): + for user_name, user in self.users.items(): + access_keys = self.get_all_access_keys(user_name) + for access_key in access_keys: + if access_key.access_key_id == access_key_id: + return user + return None + iam_backend = IAMBackend() diff --git a/moto/iam/responses.py b/moto/iam/responses.py index 8d2a557cb..806dd37f4 100644 --- a/moto/iam/responses.py +++ b/moto/iam/responses.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals from moto.core.responses import BaseResponse + from .models import iam_backend, User @@ -177,9 +178,11 @@ class IamResponse(BaseResponse): 'AssumeRolePolicyDocument') permissions_boundary = self._get_param( 'PermissionsBoundary') + description = self._get_param('Description') + tags = self._get_multi_param('Tags.member') role = iam_backend.create_role( - role_name, assume_role_policy_document, path, permissions_boundary) + role_name, assume_role_policy_document, path, permissions_boundary, description, tags) template = self.response_template(CREATE_ROLE_TEMPLATE) return template.render(role=role) @@ -425,11 +428,13 @@ class IamResponse(BaseResponse): def get_user(self): user_name = self._get_param('UserName') - if user_name: - user = iam_backend.get_user(user_name) + if not user_name: + access_key_id = self.get_current_user() + user = iam_backend.get_user_from_access_key_id(access_key_id) + if user is None: + user = User("default_user") else: - user = User(name='default_user') - # If no user is specific, IAM returns the current user + user = iam_backend.get_user(user_name) template = self.response_template(USER_TEMPLATE) return template.render(action='Get', user=user) @@ -457,7 +462,6 @@ class IamResponse(BaseResponse): def create_login_profile(self): user_name = self._get_param('UserName') password = self._get_param('Password') - password = self._get_param('Password') user = iam_backend.create_login_profile(user_name, password) template = self.response_template(CREATE_LOGIN_PROFILE_TEMPLATE) @@ -818,12 +822,12 @@ CREATE_POLICY_TEMPLATE = """ {{ policy.arn }} {{ policy.attachment_count }} - {{ policy.create_datetime.isoformat() }} + {{ policy.created_iso_8601 }} {{ policy.default_version_id }} {{ policy.path }} {{ policy.id }} {{ policy.name }} - {{ policy.update_datetime.isoformat() }} + {{ policy.updated_iso_8601 }} @@ -841,8 +845,8 @@ GET_POLICY_TEMPLATE = """ {{ policy.path }} {{ policy.arn }} {{ policy.attachment_count }} - {{ policy.create_datetime.isoformat() }} - {{ policy.update_datetime.isoformat() }} + {{ policy.created_iso_8601 }} + {{ policy.updated_iso_8601 }} @@ -929,12 +933,12 @@ LIST_POLICIES_TEMPLATE = """ {{ policy.arn }} {{ policy.attachment_count }} - {{ policy.create_datetime.isoformat() }} + {{ policy.created_iso_8601 }} {{ policy.default_version_id }} {{ policy.path }} {{ policy.id }} {{ policy.name }} - {{ policy.update_datetime.isoformat() }} + {{ policy.updated_iso_8601 }} {% endfor %} @@ -958,7 +962,7 @@ CREATE_INSTANCE_PROFILE_TEMPLATE = """ {{ group.name }} {{ group.id }} {{ group.arn }} - {{ group.create_date }} + {{ group.created_iso_8601 }} @@ -1302,7 +1319,7 @@ GET_GROUP_TEMPLATE = """ {{ group.name }} {{ group.id }} {{ group.arn }} - {{ group.create_date }} + {{ group.created_iso_8601 }} {% for user in group.users %} @@ -1349,6 +1366,7 @@ LIST_GROUPS_FOR_USER_TEMPLATE = """ {{ group.name }} {{ group.id }} {{ group.arn }} + {{ group.created_iso_8601 }} {% endfor %} @@ -1493,6 +1511,7 @@ CREATE_ACCESS_KEY_TEMPLATE = """ {{ key.access_key_id }} {{ key.status }} {{ key.secret_access_key }} + {{ key.created_iso_8601 }} @@ -1509,7 +1528,7 @@ LIST_ACCESS_KEYS_TEMPLATE = """ {{ user_name }} {{ key.access_key_id }} {{ key.status }} - {{ key.create_date }} + {{ key.created_iso_8601 }} {% endfor %} @@ -1577,7 +1596,7 @@ LIST_INSTANCE_PROFILES_FOR_ROLE_TEMPLATE = """{{ role.arn }} {{ role.name }} {{ role.assume_policy_document }} - {{ role.create_date }} + {{ role.created_iso_8601 }} {{ role.id }} {% endfor %} @@ -1585,7 +1604,7 @@ LIST_INSTANCE_PROFILES_FOR_ROLE_TEMPLATE = """{{ profile.name }} {{ profile.path }} {{ profile.arn }} - {{ profile.create_date }} + {{ profile.created_iso_8601 }} {% endfor %} @@ -1651,6 +1670,7 @@ LIST_GROUPS_FOR_USER_TEMPLATE = """ {{ group.name }} {{ group.id }} {{ group.arn }} + {{ group.created_iso_8601 }} {% endfor %} @@ -1704,7 +1724,7 @@ GET_ACCOUNT_AUTHORIZATION_DETAILS_TEMPLATE = """{{ group.name }} {{ group.path }} {{ group.arn }} - {{ group.create_date }} + {{ group.created_iso_8601 }} {% for policy in group.policies %} @@ -1754,15 +1774,22 @@ GET_ACCOUNT_AUTHORIZATION_DETAILS_TEMPLATE = """{{ role.arn }} {{ role.name }} {{ role.assume_role_policy_document }} - {{ role.create_date }} + {{role.description}} + {{ role.created_iso_8601 }} {{ role.id }} + {% if role.permissions_boundary %} + + PermissionsBoundaryPolicy + {{ role.permissions_boundary }} + + {% endif %} {% endfor %} {{ profile.name }} {{ profile.path }} {{ profile.arn }} - {{ profile.create_date }} + {{ profile.created_iso_8601 }} {% endfor %} @@ -1770,7 +1797,7 @@ GET_ACCOUNT_AUTHORIZATION_DETAILS_TEMPLATE = """{{ role.arn }} {{ role.name }} {{ role.assume_role_policy_document }} - {{ role.create_date }} + {{ role.created_iso_8601 }} {{ role.id }} {% endfor %} @@ -1786,17 +1813,17 @@ GET_ACCOUNT_AUTHORIZATION_DETAILS_TEMPLATE = """ {{ policy_version.document }} - {{ policy_version.is_default }} + {{ policy_version.is_default | lower }} {{ policy_version.version_id }} - {{ policy_version.create_datetime }} + {{ policy_version.created_iso_8601 }} {% endfor %} {{ policy.arn }} 1 - {{ policy.create_datetime }} + {{ policy.created_iso_8601 }} true - {{ policy.update_datetime }} + {{ policy.updated_iso_8601 }} {% endfor %} diff --git a/moto/iam/utils.py b/moto/iam/utils.py index f59bdfffe..2bd6448f9 100644 --- a/moto/iam/utils.py +++ b/moto/iam/utils.py @@ -7,7 +7,7 @@ import six def random_alphanumeric(length): return ''.join(six.text_type( random.choice( - string.ascii_letters + string.digits + string.ascii_letters + string.digits + "+" + "/" )) for _ in range(length) ) diff --git a/moto/kinesis/models.py b/moto/kinesis/models.py index 886a3a61f..e7a389981 100644 --- a/moto/kinesis/models.py +++ b/moto/kinesis/models.py @@ -123,17 +123,12 @@ class Stream(BaseModel): self.tags = {} self.status = "ACTIVE" - if six.PY3: - izip_longest = itertools.zip_longest - else: - izip_longest = itertools.izip_longest + step = 2**128 // shard_count + hash_ranges = itertools.chain(map(lambda i: (i, i * step, (i + 1) * step), + range(shard_count - 1)), + [(shard_count - 1, (shard_count - 1) * step, 2**128)]) + for index, start, end in hash_ranges: - for index, start, end in izip_longest(range(shard_count), - range(0, 2**128, 2 ** - 128 // shard_count), - range(2**128 // shard_count, 2 ** - 128, 2**128 // shard_count), - fillvalue=2**128): shard = Shard(index, start, end) self.shards[shard.shard_id] = shard diff --git a/moto/kms/models.py b/moto/kms/models.py index 2d6245ad2..577840b06 100644 --- a/moto/kms/models.py +++ b/moto/kms/models.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import os import boto.kms from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_without_milliseconds, unix_time +from moto.core.utils import iso_8601_datetime_without_milliseconds from .utils import generate_key_id from collections import defaultdict from datetime import datetime, timedelta @@ -11,7 +11,7 @@ from datetime import datetime, timedelta class Key(BaseModel): - def __init__(self, policy, key_usage, description, region): + def __init__(self, policy, key_usage, description, tags, region): self.id = generate_key_id() self.policy = policy self.key_usage = key_usage @@ -22,7 +22,7 @@ class Key(BaseModel): self.account_id = "0123456789012" self.key_rotation_status = False self.deletion_date = None - self.tags = {} + self.tags = tags or {} @property def physical_resource_id(self): @@ -37,7 +37,7 @@ class Key(BaseModel): "KeyMetadata": { "AWSAccountId": self.account_id, "Arn": self.arn, - "CreationDate": "%d" % unix_time(), + "CreationDate": iso_8601_datetime_without_milliseconds(datetime.now()), "Description": self.description, "Enabled": self.enabled, "KeyId": self.id, @@ -61,6 +61,7 @@ class Key(BaseModel): policy=properties['KeyPolicy'], key_usage='ENCRYPT_DECRYPT', description=properties['Description'], + tags=properties.get('Tags'), region=region_name, ) key.key_rotation_status = properties['EnableKeyRotation'] @@ -80,8 +81,8 @@ class KmsBackend(BaseBackend): self.keys = {} self.key_to_aliases = defaultdict(set) - def create_key(self, policy, key_usage, description, region): - key = Key(policy, key_usage, description, region) + def create_key(self, policy, key_usage, description, tags, region): + key = Key(policy, key_usage, description, tags, region) self.keys[key.id] = key return key diff --git a/moto/kms/responses.py b/moto/kms/responses.py index 92195ed6b..53012b7f8 100644 --- a/moto/kms/responses.py +++ b/moto/kms/responses.py @@ -31,9 +31,10 @@ class KmsResponse(BaseResponse): policy = self.parameters.get('Policy') key_usage = self.parameters.get('KeyUsage') description = self.parameters.get('Description') + tags = self.parameters.get('Tags') key = self.kms_backend.create_key( - policy, key_usage, description, self.region) + policy, key_usage, description, tags, self.region) return json.dumps(key.to_dict()) def update_key_description(self): @@ -237,7 +238,7 @@ class KmsResponse(BaseResponse): value = self.parameters.get("CiphertextBlob") try: - return json.dumps({"Plaintext": base64.b64decode(value).decode("utf-8")}) + return json.dumps({"Plaintext": base64.b64decode(value).decode("utf-8"), 'KeyId': 'key_id'}) except UnicodeDecodeError: # Generate data key will produce random bytes which when decrypted is still returned as base64 return json.dumps({"Plaintext": value}) diff --git a/moto/logs/models.py b/moto/logs/models.py index a44b76812..2b8dcfeb4 100644 --- a/moto/logs/models.py +++ b/moto/logs/models.py @@ -98,17 +98,29 @@ class LogStream: return True + def get_paging_token_from_index(index, back=False): + if index is not None: + return "b/{:056d}".format(index) if back else "f/{:056d}".format(index) + return 0 + + def get_index_from_paging_token(token): + if token is not None: + return int(token[2:]) + return 0 + events = sorted(filter(filter_func, self.events), key=lambda event: event.timestamp, reverse=start_from_head) - back_token = next_token - if next_token is None: - next_token = 0 + next_index = get_index_from_paging_token(next_token) + back_index = next_index - events_page = [event.to_response_dict() for event in events[next_token: next_token + limit]] - next_token += limit - if next_token >= len(self.events): - next_token = None + events_page = [event.to_response_dict() for event in events[next_index: next_index + limit]] + if next_index + limit < len(self.events): + next_index += limit - return events_page, back_token, next_token + back_index -= limit + if back_index <= 0: + back_index = 0 + + return events_page, get_paging_token_from_index(back_index, True), get_paging_token_from_index(next_index) def filter_log_events(self, log_group_name, log_stream_names, start_time, end_time, limit, next_token, filter_pattern, interleaved): def filter_func(event): diff --git a/moto/organizations/models.py b/moto/organizations/models.py index 91004b9ba..561c6c3a8 100644 --- a/moto/organizations/models.py +++ b/moto/organizations/models.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import datetime import re +import json from moto.core import BaseBackend, BaseModel from moto.core.exceptions import RESTError @@ -151,7 +152,6 @@ class FakeRoot(FakeOrganizationalUnit): class FakeServiceControlPolicy(BaseModel): def __init__(self, organization, **kwargs): - self.type = 'POLICY' self.content = kwargs.get('Content') self.description = kwargs.get('Description') self.name = kwargs.get('Name') @@ -197,7 +197,38 @@ class OrganizationsBackend(BaseBackend): def create_organization(self, **kwargs): self.org = FakeOrganization(kwargs['FeatureSet']) - self.ou.append(FakeRoot(self.org)) + root_ou = FakeRoot(self.org) + self.ou.append(root_ou) + master_account = FakeAccount( + self.org, + AccountName='master', + Email=self.org.master_account_email, + ) + master_account.id = self.org.master_account_id + self.accounts.append(master_account) + default_policy = FakeServiceControlPolicy( + self.org, + Name='FullAWSAccess', + Description='Allows access to every operation', + Type='SERVICE_CONTROL_POLICY', + Content=json.dumps( + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "*", + "Resource": "*" + } + ] + } + ) + ) + default_policy.id = utils.DEFAULT_POLICY_ID + default_policy.aws_managed = True + self.policies.append(default_policy) + self.attach_policy(PolicyId=default_policy.id, TargetId=root_ou.id) + self.attach_policy(PolicyId=default_policy.id, TargetId=master_account.id) return self.org.describe() def describe_organization(self): @@ -216,6 +247,7 @@ class OrganizationsBackend(BaseBackend): def create_organizational_unit(self, **kwargs): new_ou = FakeOrganizationalUnit(self.org, **kwargs) self.ou.append(new_ou) + self.attach_policy(PolicyId=utils.DEFAULT_POLICY_ID, TargetId=new_ou.id) return new_ou.describe() def get_organizational_unit_by_id(self, ou_id): @@ -258,6 +290,7 @@ class OrganizationsBackend(BaseBackend): def create_account(self, **kwargs): new_account = FakeAccount(self.org, **kwargs) self.accounts.append(new_account) + self.attach_policy(PolicyId=utils.DEFAULT_POLICY_ID, TargetId=new_account.id) return new_account.create_account_status def get_account_by_id(self, account_id): @@ -358,8 +391,7 @@ class OrganizationsBackend(BaseBackend): def attach_policy(self, **kwargs): policy = next((p for p in self.policies if p.id == kwargs['PolicyId']), None) - if (re.compile(utils.ROOT_ID_REGEX).match(kwargs['TargetId']) or - re.compile(utils.OU_ID_REGEX).match(kwargs['TargetId'])): + if (re.compile(utils.ROOT_ID_REGEX).match(kwargs['TargetId']) or re.compile(utils.OU_ID_REGEX).match(kwargs['TargetId'])): ou = next((ou for ou in self.ou if ou.id == kwargs['TargetId']), None) if ou is not None: if ou not in ou.attached_policies: diff --git a/moto/organizations/utils.py b/moto/organizations/utils.py index bde3660d2..5cbe59ada 100644 --- a/moto/organizations/utils.py +++ b/moto/organizations/utils.py @@ -4,7 +4,8 @@ import random import string MASTER_ACCOUNT_ID = '123456789012' -MASTER_ACCOUNT_EMAIL = 'fakeorg@moto-example.com' +MASTER_ACCOUNT_EMAIL = 'master@example.com' +DEFAULT_POLICY_ID = 'p-FullAWSAccess' ORGANIZATION_ARN_FORMAT = 'arn:aws:organizations::{0}:organization/{1}' MASTER_ACCOUNT_ARN_FORMAT = 'arn:aws:organizations::{0}:account/{1}/{0}' ACCOUNT_ARN_FORMAT = 'arn:aws:organizations::{0}:account/{1}/{2}' @@ -26,7 +27,7 @@ ROOT_ID_REGEX = r'r-[a-z0-9]{%s}' % ROOT_ID_SIZE OU_ID_REGEX = r'ou-[a-z0-9]{%s}-[a-z0-9]{%s}' % (ROOT_ID_SIZE, OU_ID_SUFFIX_SIZE) ACCOUNT_ID_REGEX = r'[0-9]{%s}' % ACCOUNT_ID_SIZE CREATE_ACCOUNT_STATUS_ID_REGEX = r'car-[a-z0-9]{%s}' % CREATE_ACCOUNT_STATUS_ID_SIZE -SCP_ID_REGEX = r'p-[a-z0-9]{%s}' % SCP_ID_SIZE +SCP_ID_REGEX = r'%s|p-[a-z0-9]{%s}' % (DEFAULT_POLICY_ID, SCP_ID_SIZE) def make_random_org_id(): diff --git a/moto/packages/httpretty/core.py b/moto/packages/httpretty/core.py index 4eb92108f..f94723017 100644 --- a/moto/packages/httpretty/core.py +++ b/moto/packages/httpretty/core.py @@ -268,10 +268,26 @@ class fakesock(object): _sent_data = [] def __init__(self, family=socket.AF_INET, type=socket.SOCK_STREAM, - protocol=0): - self.truesock = (old_socket(family, type, protocol) - if httpretty.allow_net_connect - else None) + proto=0, fileno=None, _sock=None): + """ + Matches both the Python 2 API: + def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None): + https://github.com/python/cpython/blob/2.7/Lib/socket.py + + and the Python 3 API: + def __init__(self, family=-1, type=-1, proto=-1, fileno=None): + https://github.com/python/cpython/blob/3.5/Lib/socket.py + """ + if httpretty.allow_net_connect: + if PY3: + self.truesock = old_socket(family, type, proto, fileno) + else: + # If Python 2, if parameters are passed as arguments, instead of kwargs, + # the 4th argument `_sock` will be interpreted as the `fileno`. + # Check if _sock is none, and if so, pass fileno. + self.truesock = old_socket(family, type, proto, fileno or _sock) + else: + self.truesock = None self._closed = True self.fd = FakeSockFile() self.fd.socket = self diff --git a/moto/rds/responses.py b/moto/rds/responses.py index 987a6f21a..0afb03979 100644 --- a/moto/rds/responses.py +++ b/moto/rds/responses.py @@ -95,7 +95,7 @@ class RDSResponse(BaseResponse): start = all_ids.index(marker) + 1 else: start = 0 - page_size = self._get_param('MaxRecords', 50) # the default is 100, but using 50 to make testing easier + page_size = self._get_int_param('MaxRecords', 50) # the default is 100, but using 50 to make testing easier instances_resp = all_instances[start:start + page_size] next_marker = None if len(all_instances) > start + page_size: diff --git a/moto/rds2/exceptions.py b/moto/rds2/exceptions.py index 0e716310e..e82ae7077 100644 --- a/moto/rds2/exceptions.py +++ b/moto/rds2/exceptions.py @@ -60,6 +60,15 @@ class DBParameterGroupNotFoundError(RDSClientError): 'DB Parameter Group {0} not found.'.format(db_parameter_group_name)) +class OptionGroupNotFoundFaultError(RDSClientError): + + def __init__(self, option_group_name): + super(OptionGroupNotFoundFaultError, self).__init__( + 'OptionGroupNotFoundFault', + 'Specified OptionGroupName: {0} not found.'.format(option_group_name) + ) + + class InvalidDBClusterStateFaultError(RDSClientError): def __init__(self, database_identifier): diff --git a/moto/rds2/models.py b/moto/rds2/models.py index fee004f76..4c0daa230 100644 --- a/moto/rds2/models.py +++ b/moto/rds2/models.py @@ -20,6 +20,7 @@ from .exceptions import (RDSClientError, DBSecurityGroupNotFoundError, DBSubnetGroupNotFoundError, DBParameterGroupNotFoundError, + OptionGroupNotFoundFaultError, InvalidDBClusterStateFaultError, InvalidDBInstanceStateError, SnapshotQuotaExceededError, @@ -70,6 +71,7 @@ class Database(BaseModel): self.port = Database.default_port(self.engine) self.db_instance_identifier = kwargs.get('db_instance_identifier') self.db_name = kwargs.get("db_name") + self.instance_create_time = iso_8601_datetime_with_milliseconds(datetime.datetime.now()) self.publicly_accessible = kwargs.get("publicly_accessible") if self.publicly_accessible is None: self.publicly_accessible = True @@ -99,6 +101,8 @@ class Database(BaseModel): 'preferred_backup_window', '13:14-13:44') self.license_model = kwargs.get('license_model', 'general-public-license') self.option_group_name = kwargs.get('option_group_name', None) + if self.option_group_name and self.option_group_name not in rds2_backends[self.region].option_groups: + raise OptionGroupNotFoundFaultError(self.option_group_name) self.default_option_groups = {"MySQL": "default.mysql5.6", "mysql": "default.mysql5.6", "postgres": "default.postgres9.3" @@ -145,9 +149,17 @@ class Database(BaseModel): {{ database.status }} {% if database.db_name %}{{ database.db_name }}{% endif %} {{ database.multi_az }} - + + {% for vpc_security_group_id in database.vpc_security_group_ids %} + + active + {{ vpc_security_group_id }} + + {% endfor %} + {{ database.db_instance_identifier }} {{ database.dbi_resource_id }} + {{ database.instance_create_time }} 03:50-04:20 wed:06:38-wed:07:08 @@ -173,6 +185,10 @@ class Database(BaseModel): {{ database.license_model }} {{ database.engine_version }} + + {{ database.option_group_name }} + in-sync + {% for db_parameter_group in database.db_parameter_groups() %} @@ -314,6 +330,7 @@ class Database(BaseModel): "storage_encrypted": properties.get("StorageEncrypted"), "storage_type": properties.get("StorageType"), "tags": properties.get("Tags"), + "vpc_security_group_ids": properties.get('VpcSecurityGroupIds', []), } rds2_backend = rds2_backends[region_name] @@ -373,7 +390,7 @@ class Database(BaseModel): "Address": "{{ database.address }}", "Port": "{{ database.port }}" }, - "InstanceCreateTime": null, + "InstanceCreateTime": "{{ database.instance_create_time }}", "Iops": null, "ReadReplicaDBInstanceIdentifiers": [{%- for replica in database.replicas -%} {%- if not loop.first -%},{%- endif -%} @@ -388,10 +405,12 @@ class Database(BaseModel): "SecondaryAvailabilityZone": null, "StatusInfos": null, "VpcSecurityGroups": [ + {% for vpc_security_group_id in database.vpc_security_group_ids %} { "Status": "active", - "VpcSecurityGroupId": "sg-123456" + "VpcSecurityGroupId": "{{ vpc_security_group_id }}" } + {% endfor %} ], "DBInstanceArn": "{{ database.db_instance_arn }}" }""") @@ -873,13 +892,16 @@ class RDS2Backend(BaseBackend): def create_option_group(self, option_group_kwargs): option_group_id = option_group_kwargs['name'] - valid_option_group_engines = {'mysql': ['5.6'], - 'oracle-se1': ['11.2'], - 'oracle-se': ['11.2'], - 'oracle-ee': ['11.2'], + valid_option_group_engines = {'mariadb': ['10.0', '10.1', '10.2', '10.3'], + 'mysql': ['5.5', '5.6', '5.7', '8.0'], + 'oracle-se2': ['11.2', '12.1', '12.2'], + 'oracle-se1': ['11.2', '12.1', '12.2'], + 'oracle-se': ['11.2', '12.1', '12.2'], + 'oracle-ee': ['11.2', '12.1', '12.2'], 'sqlserver-se': ['10.50', '11.00'], - 'sqlserver-ee': ['10.50', '11.00'] - } + 'sqlserver-ee': ['10.50', '11.00'], + 'sqlserver-ex': ['10.50', '11.00'], + 'sqlserver-web': ['10.50', '11.00']} if option_group_kwargs['name'] in self.option_groups: raise RDSClientError('OptionGroupAlreadyExistsFault', 'An option group named {0} already exists.'.format(option_group_kwargs['name'])) @@ -905,8 +927,7 @@ class RDS2Backend(BaseBackend): if option_group_name in self.option_groups: return self.option_groups.pop(option_group_name) else: - raise RDSClientError( - 'OptionGroupNotFoundFault', 'Specified OptionGroupName: {0} not found.'.format(option_group_name)) + raise OptionGroupNotFoundFaultError(option_group_name) def describe_option_groups(self, option_group_kwargs): option_group_list = [] @@ -935,8 +956,7 @@ class RDS2Backend(BaseBackend): else: option_group_list.append(option_group) if not len(option_group_list): - raise RDSClientError('OptionGroupNotFoundFault', - 'Specified OptionGroupName: {0} not found.'.format(option_group_kwargs['name'])) + raise OptionGroupNotFoundFaultError(option_group_kwargs['name']) return option_group_list[marker:max_records + marker] @staticmethod @@ -965,8 +985,7 @@ class RDS2Backend(BaseBackend): def modify_option_group(self, option_group_name, options_to_include=None, options_to_remove=None, apply_immediately=None): if option_group_name not in self.option_groups: - raise RDSClientError('OptionGroupNotFoundFault', - 'Specified OptionGroupName: {0} not found.'.format(option_group_name)) + raise OptionGroupNotFoundFaultError(option_group_name) if not options_to_include and not options_to_remove: raise RDSClientError('InvalidParameterValue', 'At least one option must be added, modified, or removed.') diff --git a/moto/rds2/responses.py b/moto/rds2/responses.py index 66d4e0c52..7b8d0b63a 100644 --- a/moto/rds2/responses.py +++ b/moto/rds2/responses.py @@ -34,7 +34,7 @@ class RDS2Response(BaseResponse): "master_user_password": self._get_param('MasterUserPassword'), "master_username": self._get_param('MasterUsername'), "multi_az": self._get_bool_param("MultiAZ"), - # OptionGroupName + "option_group_name": self._get_param("OptionGroupName"), "port": self._get_param('Port'), # PreferredBackupWindow # PreferredMaintenanceWindow @@ -43,7 +43,7 @@ class RDS2Response(BaseResponse): "security_groups": self._get_multi_param('DBSecurityGroups.DBSecurityGroupName'), "storage_encrypted": self._get_param("StorageEncrypted"), "storage_type": self._get_param("StorageType", 'standard'), - # VpcSecurityGroupIds.member.N + "vpc_security_group_ids": self._get_multi_param("VpcSecurityGroupIds.VpcSecurityGroupId"), "tags": list(), } args['tags'] = self.unpack_complex_list_params( @@ -280,7 +280,7 @@ class RDS2Response(BaseResponse): def describe_option_groups(self): kwargs = self._get_option_group_kwargs() - kwargs['max_records'] = self._get_param('MaxRecords') + kwargs['max_records'] = self._get_int_param('MaxRecords') kwargs['marker'] = self._get_param('Marker') option_groups = self.backend.describe_option_groups(kwargs) template = self.response_template(DESCRIBE_OPTION_GROUP_TEMPLATE) @@ -329,7 +329,7 @@ class RDS2Response(BaseResponse): def describe_db_parameter_groups(self): kwargs = self._get_db_parameter_group_kwargs() - kwargs['max_records'] = self._get_param('MaxRecords') + kwargs['max_records'] = self._get_int_param('MaxRecords') kwargs['marker'] = self._get_param('Marker') db_parameter_groups = self.backend.describe_db_parameter_groups(kwargs) template = self.response_template( diff --git a/moto/redshift/models.py b/moto/redshift/models.py index 64e5c5e35..c0b783bde 100644 --- a/moto/redshift/models.py +++ b/moto/redshift/models.py @@ -78,7 +78,7 @@ class Cluster(TaggableResourceMixin, BaseModel): super(Cluster, self).__init__(region_name, tags) self.redshift_backend = redshift_backend self.cluster_identifier = cluster_identifier - self.create_time = iso_8601_datetime_with_milliseconds(datetime.datetime.now()) + self.create_time = iso_8601_datetime_with_milliseconds(datetime.datetime.utcnow()) self.status = 'available' self.node_type = node_type self.master_username = master_username diff --git a/moto/resourcegroupstaggingapi/models.py b/moto/resourcegroupstaggingapi/models.py index 4aec63aa6..3f15017cc 100644 --- a/moto/resourcegroupstaggingapi/models.py +++ b/moto/resourcegroupstaggingapi/models.py @@ -10,6 +10,7 @@ from moto.ec2 import ec2_backends from moto.elb import elb_backends from moto.elbv2 import elbv2_backends from moto.kinesis import kinesis_backends +from moto.kms import kms_backends from moto.rds2 import rds2_backends from moto.glacier import glacier_backends from moto.redshift import redshift_backends @@ -71,6 +72,13 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend): """ return kinesis_backends[self.region_name] + @property + def kms_backend(self): + """ + :rtype: moto.kms.models.KmsBackend + """ + return kms_backends[self.region_name] + @property def rds_backend(self): """ @@ -221,9 +229,6 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend): if not resource_type_filters or 'elasticloadbalancer' in resource_type_filters or 'elasticloadbalancer:loadbalancer' in resource_type_filters: for elb in self.elbv2_backend.load_balancers.values(): tags = get_elbv2_tags(elb.arn) - # if 'elasticloadbalancer:loadbalancer' in resource_type_filters: - # from IPython import embed - # embed() if not tag_filter(tags): # Skip if no tags, or invalid filter continue @@ -235,6 +240,21 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend): # Kinesis + # KMS + def get_kms_tags(kms_key_id): + result = [] + for tag in self.kms_backend.list_resource_tags(kms_key_id): + result.append({'Key': tag['TagKey'], 'Value': tag['TagValue']}) + return result + + if not resource_type_filters or 'kms' in resource_type_filters: + for kms_key in self.kms_backend.list_keys(): + tags = get_kms_tags(kms_key.id) + if not tag_filter(tags): # Skip if no tags, or invalid filter + continue + + yield {'ResourceARN': '{0}'.format(kms_key.arn), 'Tags': tags} + # RDS Instance # RDS Reserved Database Instance # RDS Option Group @@ -370,7 +390,7 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend): def get_resources(self, pagination_token=None, resources_per_page=50, tags_per_page=100, tag_filters=None, resource_type_filters=None): - # Simple range checning + # Simple range checking if 100 >= tags_per_page >= 500: raise RESTError('InvalidParameterException', 'TagsPerPage must be between 100 and 500') if 1 >= resources_per_page >= 50: diff --git a/moto/route53/models.py b/moto/route53/models.py index 3760d3817..61a6609aa 100644 --- a/moto/route53/models.py +++ b/moto/route53/models.py @@ -85,6 +85,7 @@ class RecordSet(BaseModel): self.health_check = kwargs.get('HealthCheckId') self.hosted_zone_name = kwargs.get('HostedZoneName') self.hosted_zone_id = kwargs.get('HostedZoneId') + self.alias_target = kwargs.get('AliasTarget') @classmethod def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): @@ -119,7 +120,7 @@ class RecordSet(BaseModel): properties["HostedZoneId"]) try: - hosted_zone.delete_rrset_by_name(resource_name) + hosted_zone.delete_rrset({'Name': resource_name}) except KeyError: pass @@ -143,6 +144,13 @@ class RecordSet(BaseModel): {% if record_set.ttl %} {{ record_set.ttl }} {% endif %} + {% if record_set.alias_target %} + + {{ record_set.alias_target['HostedZoneId'] }} + {{ record_set.alias_target['DNSName'] }} + {{ record_set.alias_target['EvaluateTargetHealth'] }} + + {% else %} {% for record in record_set.records %} @@ -150,6 +158,7 @@ class RecordSet(BaseModel): {% endfor %} + {% endif %} {% if record_set.health_check %} {{ record_set.health_check }} {% endif %} @@ -162,7 +171,13 @@ class RecordSet(BaseModel): self.hosted_zone_name) if not hosted_zone: hosted_zone = route53_backend.get_hosted_zone(self.hosted_zone_id) - hosted_zone.delete_rrset_by_name(self.name) + hosted_zone.delete_rrset({'Name': self.name, 'Type': self.type_}) + + +def reverse_domain_name(domain_name): + if domain_name.endswith('.'): # normalize without trailing dot + domain_name = domain_name[:-1] + return '.'.join(reversed(domain_name.split('.'))) class FakeZone(BaseModel): @@ -183,16 +198,20 @@ class FakeZone(BaseModel): def upsert_rrset(self, record_set): new_rrset = RecordSet(record_set) for i, rrset in enumerate(self.rrsets): - if rrset.name == new_rrset.name and rrset.type_ == new_rrset.type_: + if rrset.name == new_rrset.name and rrset.type_ == new_rrset.type_ and rrset.set_identifier == new_rrset.set_identifier: self.rrsets[i] = new_rrset break else: self.rrsets.append(new_rrset) return new_rrset - def delete_rrset_by_name(self, name): + def delete_rrset(self, rrset): self.rrsets = [ - record_set for record_set in self.rrsets if record_set.name != name] + record_set + for record_set in self.rrsets + if record_set.name != rrset['Name'] or + (rrset.get('Type') is not None and record_set.type_ != rrset['Type']) + ] def delete_rrset_by_id(self, set_identifier): self.rrsets = [ @@ -200,12 +219,15 @@ class FakeZone(BaseModel): def get_record_sets(self, start_type, start_name): record_sets = list(self.rrsets) # Copy the list + if start_name: + record_sets = [ + record_set + for record_set in record_sets + if reverse_domain_name(record_set.name) >= reverse_domain_name(start_name) + ] if start_type: record_sets = [ record_set for record_set in record_sets if record_set.type_ >= start_type] - if start_name: - record_sets = [ - record_set for record_set in record_sets if record_set.name >= start_name] return record_sets diff --git a/moto/route53/responses.py b/moto/route53/responses.py index 98ffa4c47..f933c575a 100644 --- a/moto/route53/responses.py +++ b/moto/route53/responses.py @@ -134,10 +134,7 @@ class Route53(BaseResponse): # Depending on how many records there are, this may # or may not be a list resource_records = [resource_records] - record_values = [x['Value'] for x in resource_records] - elif 'AliasTarget' in record_set: - record_values = [record_set['AliasTarget']['DNSName']] - record_set['ResourceRecords'] = record_values + record_set['ResourceRecords'] = [x['Value'] for x in resource_records] if action == 'CREATE': the_zone.add_rrset(record_set) else: @@ -147,7 +144,7 @@ class Route53(BaseResponse): the_zone.delete_rrset_by_id( record_set["SetIdentifier"]) else: - the_zone.delete_rrset_by_name(record_set["Name"]) + the_zone.delete_rrset(record_set) return 200, headers, CHANGE_RRSET_RESPONSE diff --git a/moto/s3/exceptions.py b/moto/s3/exceptions.py index 27c842111..8d2326fa1 100644 --- a/moto/s3/exceptions.py +++ b/moto/s3/exceptions.py @@ -60,6 +60,17 @@ class MissingKey(S3ClientError): ) +class ObjectNotInActiveTierError(S3ClientError): + code = 403 + + def __init__(self, key_name): + super(ObjectNotInActiveTierError, self).__init__( + "ObjectNotInActiveTierError", + "The source object of the COPY operation is not in the active tier and is only stored in Amazon Glacier.", + Key=key_name, + ) + + class InvalidPartOrder(S3ClientError): code = 400 @@ -199,3 +210,67 @@ class DuplicateTagKeys(S3ClientError): "InvalidTag", "Cannot provide multiple Tags with the same key", *args, **kwargs) + + +class S3AccessDeniedError(S3ClientError): + code = 403 + + def __init__(self, *args, **kwargs): + super(S3AccessDeniedError, self).__init__('AccessDenied', 'Access Denied', *args, **kwargs) + + +class BucketAccessDeniedError(BucketError): + code = 403 + + def __init__(self, *args, **kwargs): + super(BucketAccessDeniedError, self).__init__('AccessDenied', 'Access Denied', *args, **kwargs) + + +class S3InvalidTokenError(S3ClientError): + code = 400 + + def __init__(self, *args, **kwargs): + super(S3InvalidTokenError, self).__init__('InvalidToken', 'The provided token is malformed or otherwise invalid.', *args, **kwargs) + + +class BucketInvalidTokenError(BucketError): + code = 400 + + def __init__(self, *args, **kwargs): + super(BucketInvalidTokenError, self).__init__('InvalidToken', 'The provided token is malformed or otherwise invalid.', *args, **kwargs) + + +class S3InvalidAccessKeyIdError(S3ClientError): + code = 403 + + def __init__(self, *args, **kwargs): + super(S3InvalidAccessKeyIdError, self).__init__( + 'InvalidAccessKeyId', + "The AWS Access Key Id you provided does not exist in our records.", *args, **kwargs) + + +class BucketInvalidAccessKeyIdError(S3ClientError): + code = 403 + + def __init__(self, *args, **kwargs): + super(BucketInvalidAccessKeyIdError, self).__init__( + 'InvalidAccessKeyId', + "The AWS Access Key Id you provided does not exist in our records.", *args, **kwargs) + + +class S3SignatureDoesNotMatchError(S3ClientError): + code = 403 + + def __init__(self, *args, **kwargs): + super(S3SignatureDoesNotMatchError, self).__init__( + 'SignatureDoesNotMatch', + "The request signature we calculated does not match the signature you provided. Check your key and signing method.", *args, **kwargs) + + +class BucketSignatureDoesNotMatchError(S3ClientError): + code = 403 + + def __init__(self, *args, **kwargs): + super(BucketSignatureDoesNotMatchError, self).__init__( + 'SignatureDoesNotMatch', + "The request signature we calculated does not match the signature you provided. Check your key and signing method.", *args, **kwargs) diff --git a/moto/s3/models.py b/moto/s3/models.py index 7488114e3..b5aef34d3 100644 --- a/moto/s3/models.py +++ b/moto/s3/models.py @@ -28,7 +28,8 @@ MAX_BUCKET_NAME_LENGTH = 63 MIN_BUCKET_NAME_LENGTH = 3 UPLOAD_ID_BYTES = 43 UPLOAD_PART_MIN_SIZE = 5242880 -STORAGE_CLASS = ["STANDARD", "REDUCED_REDUNDANCY", "STANDARD_IA", "ONEZONE_IA"] +STORAGE_CLASS = ["STANDARD", "REDUCED_REDUNDANCY", "STANDARD_IA", "ONEZONE_IA", + "INTELLIGENT_TIERING", "GLACIER", "DEEP_ARCHIVE"] DEFAULT_KEY_BUFFER_SIZE = 16 * 1024 * 1024 DEFAULT_TEXT_ENCODING = sys.getdefaultencoding() @@ -52,8 +53,17 @@ class FakeDeleteMarker(BaseModel): class FakeKey(BaseModel): - def __init__(self, name, value, storage="STANDARD", etag=None, is_versioned=False, version_id=0, - max_buffer_size=DEFAULT_KEY_BUFFER_SIZE): + def __init__( + self, + name, + value, + storage="STANDARD", + etag=None, + is_versioned=False, + version_id=0, + max_buffer_size=DEFAULT_KEY_BUFFER_SIZE, + multipart=None + ): self.name = name self.last_modified = datetime.datetime.utcnow() self.acl = get_canned_acl('private') @@ -65,6 +75,7 @@ class FakeKey(BaseModel): self._version_id = version_id self._is_versioned = is_versioned self._tagging = FakeTagging() + self.multipart = multipart self._value_buffer = tempfile.SpooledTemporaryFile(max_size=max_buffer_size) self._max_buffer_size = max_buffer_size @@ -754,7 +765,7 @@ class S3Backend(BaseBackend): prefix=''): bucket = self.get_bucket(bucket_name) - if any((delimiter, encoding_type, key_marker, version_id_marker)): + if any((delimiter, key_marker, version_id_marker)): raise NotImplementedError( "Called get_bucket_versions with some of delimiter, encoding_type, key_marker, version_id_marker") @@ -782,7 +793,15 @@ class S3Backend(BaseBackend): bucket = self.get_bucket(bucket_name) return bucket.website_configuration - def set_key(self, bucket_name, key_name, value, storage=None, etag=None): + def set_key( + self, + bucket_name, + key_name, + value, + storage=None, + etag=None, + multipart=None, + ): key_name = clean_key_name(key_name) if storage is not None and storage not in STORAGE_CLASS: raise InvalidStorageClass(storage=storage) @@ -795,7 +814,9 @@ class S3Backend(BaseBackend): storage=storage, etag=etag, is_versioned=bucket.is_versioned, - version_id=str(uuid.uuid4()) if bucket.is_versioned else None) + version_id=str(uuid.uuid4()) if bucket.is_versioned else None, + multipart=multipart, + ) keys = [ key for key in bucket.keys.getlist(key_name, []) @@ -812,7 +833,7 @@ class S3Backend(BaseBackend): key.append_to_value(value) return key - def get_key(self, bucket_name, key_name, version_id=None): + def get_key(self, bucket_name, key_name, version_id=None, part_number=None): key_name = clean_key_name(key_name) bucket = self.get_bucket(bucket_name) key = None @@ -827,6 +848,9 @@ class S3Backend(BaseBackend): key = key_version break + if part_number and key.multipart: + key = key.multipart.parts[part_number] + if isinstance(key, FakeKey): return key else: @@ -890,7 +914,12 @@ class S3Backend(BaseBackend): return del bucket.multiparts[multipart_id] - key = self.set_key(bucket_name, multipart.key_name, value, etag=etag) + key = self.set_key( + bucket_name, + multipart.key_name, + value, etag=etag, + multipart=multipart + ) key.set_metadata(multipart.metadata) return key diff --git a/moto/s3/responses.py b/moto/s3/responses.py index e03666666..ee047a14f 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -3,20 +3,21 @@ from __future__ import unicode_literals import re import six + from moto.core.utils import str_to_rfc_1123_datetime from six.moves.urllib.parse import parse_qs, urlparse, unquote import xmltodict from moto.packages.httpretty.core import HTTPrettyRequest -from moto.core.responses import _TemplateEnvironmentMixin +from moto.core.responses import _TemplateEnvironmentMixin, ActionAuthenticatorMixin from moto.core.utils import path_url from moto.s3bucket_path.utils import bucket_name_from_url as bucketpath_bucket_name_from_url, \ parse_key_name as bucketpath_parse_key_name, is_delete_keys as bucketpath_is_delete_keys from .exceptions import BucketAlreadyExists, S3ClientError, MissingBucket, MissingKey, InvalidPartOrder, MalformedXML, \ - MalformedACLError, InvalidNotificationARN, InvalidNotificationEvent + MalformedACLError, InvalidNotificationARN, InvalidNotificationEvent, ObjectNotInActiveTierError from .models import s3_backend, get_canned_acl, FakeGrantee, FakeGrant, FakeAcl, FakeKey, FakeTagging, FakeTagSet, \ FakeTag from .utils import bucket_name_from_url, clean_key_name, metadata_from_headers, parse_region_from_url @@ -25,6 +26,72 @@ from xml.dom import minidom DEFAULT_REGION_NAME = 'us-east-1' +ACTION_MAP = { + "BUCKET": { + "GET": { + "uploads": "ListBucketMultipartUploads", + "location": "GetBucketLocation", + "lifecycle": "GetLifecycleConfiguration", + "versioning": "GetBucketVersioning", + "policy": "GetBucketPolicy", + "website": "GetBucketWebsite", + "acl": "GetBucketAcl", + "tagging": "GetBucketTagging", + "logging": "GetBucketLogging", + "cors": "GetBucketCORS", + "notification": "GetBucketNotification", + "accelerate": "GetAccelerateConfiguration", + "versions": "ListBucketVersions", + "DEFAULT": "ListBucket" + }, + "PUT": { + "lifecycle": "PutLifecycleConfiguration", + "versioning": "PutBucketVersioning", + "policy": "PutBucketPolicy", + "website": "PutBucketWebsite", + "acl": "PutBucketAcl", + "tagging": "PutBucketTagging", + "logging": "PutBucketLogging", + "cors": "PutBucketCORS", + "notification": "PutBucketNotification", + "accelerate": "PutAccelerateConfiguration", + "DEFAULT": "CreateBucket" + }, + "DELETE": { + "lifecycle": "PutLifecycleConfiguration", + "policy": "DeleteBucketPolicy", + "tagging": "PutBucketTagging", + "cors": "PutBucketCORS", + "DEFAULT": "DeleteBucket" + } + }, + "KEY": { + "GET": { + "uploadId": "ListMultipartUploadParts", + "acl": "GetObjectAcl", + "tagging": "GetObjectTagging", + "versionId": "GetObjectVersion", + "DEFAULT": "GetObject" + }, + "PUT": { + "acl": "PutObjectAcl", + "tagging": "PutObjectTagging", + "DEFAULT": "PutObject" + }, + "DELETE": { + "uploadId": "AbortMultipartUpload", + "versionId": "DeleteObjectVersion", + "DEFAULT": " DeleteObject" + }, + "POST": { + "uploads": "PutObject", + "restore": "RestoreObject", + "uploadId": "PutObject" + } + } + +} + def parse_key_name(pth): return pth.lstrip("/") @@ -37,17 +104,24 @@ def is_delete_keys(request, path, bucket_name): ) -class ResponseObject(_TemplateEnvironmentMixin): +class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin): def __init__(self, backend): super(ResponseObject, self).__init__() self.backend = backend + self.method = "" + self.path = "" + self.data = {} + self.headers = {} @property def should_autoescape(self): return True def all_buckets(self): + self.data["Action"] = "ListAllMyBuckets" + self._authenticate_and_authorize_s3_action() + # No bucket specified. Listing all buckets all_buckets = self.backend.get_all_buckets() template = self.response_template(S3_ALL_BUCKETS) @@ -112,11 +186,20 @@ class ResponseObject(_TemplateEnvironmentMixin): return self.bucket_response(request, full_url, headers) def bucket_response(self, request, full_url, headers): + self.method = request.method + self.path = self._get_path(request) + self.headers = request.headers + if 'host' not in self.headers: + self.headers['host'] = urlparse(full_url).netloc try: response = self._bucket_response(request, full_url, headers) except S3ClientError as s3error: response = s3error.code, {}, s3error.description + return self._send_response(response) + + @staticmethod + def _send_response(response): if isinstance(response, six.string_types): return 200, {}, response.encode("utf-8") else: @@ -127,8 +210,7 @@ class ResponseObject(_TemplateEnvironmentMixin): return status_code, headers, response_content def _bucket_response(self, request, full_url, headers): - parsed_url = urlparse(full_url) - querystring = parse_qs(parsed_url.query, keep_blank_values=True) + querystring = self._get_querystring(full_url) method = request.method region_name = parse_region_from_url(full_url) @@ -137,6 +219,8 @@ class ResponseObject(_TemplateEnvironmentMixin): # If no bucket specified, list all buckets return self.all_buckets() + self.data["BucketName"] = bucket_name + if hasattr(request, 'body'): # Boto body = request.body @@ -150,20 +234,26 @@ class ResponseObject(_TemplateEnvironmentMixin): body = u'{0}'.format(body).encode('utf-8') if method == 'HEAD': - return self._bucket_response_head(bucket_name, headers) + return self._bucket_response_head(bucket_name) elif method == 'GET': - return self._bucket_response_get(bucket_name, querystring, headers) + return self._bucket_response_get(bucket_name, querystring) elif method == 'PUT': - return self._bucket_response_put(request, body, region_name, bucket_name, querystring, headers) + return self._bucket_response_put(request, body, region_name, bucket_name, querystring) elif method == 'DELETE': - return self._bucket_response_delete(body, bucket_name, querystring, headers) + return self._bucket_response_delete(body, bucket_name, querystring) elif method == 'POST': - return self._bucket_response_post(request, body, bucket_name, headers) + return self._bucket_response_post(request, body, bucket_name) else: raise NotImplementedError( "Method {0} has not been impelemented in the S3 backend yet".format(method)) - def _bucket_response_head(self, bucket_name, headers): + @staticmethod + def _get_querystring(full_url): + parsed_url = urlparse(full_url) + querystring = parse_qs(parsed_url.query, keep_blank_values=True) + return querystring + + def _bucket_response_head(self, bucket_name): try: self.backend.get_bucket(bucket_name) except MissingBucket: @@ -174,7 +264,10 @@ class ResponseObject(_TemplateEnvironmentMixin): return 404, {}, "" return 200, {}, "" - def _bucket_response_get(self, bucket_name, querystring, headers): + def _bucket_response_get(self, bucket_name, querystring): + self._set_action("BUCKET", "GET", querystring) + self._authenticate_and_authorize_s3_action() + if 'uploads' in querystring: for unsup in ('delimiter', 'max-uploads'): if unsup in querystring: @@ -333,6 +426,15 @@ class ResponseObject(_TemplateEnvironmentMixin): max_keys=max_keys ) + def _set_action(self, action_resource_type, method, querystring): + action_set = False + for action_in_querystring, action in ACTION_MAP[action_resource_type][method].items(): + if action_in_querystring in querystring: + self.data["Action"] = action + action_set = True + if not action_set: + self.data["Action"] = ACTION_MAP[action_resource_type][method]["DEFAULT"] + def _handle_list_objects_v2(self, bucket_name, querystring): template = self.response_template(S3_BUCKET_GET_RESPONSE_V2) bucket = self.backend.get_bucket(bucket_name) @@ -361,10 +463,13 @@ class ResponseObject(_TemplateEnvironmentMixin): else: result_folders, is_truncated, next_continuation_token = self._truncate_result(result_folders, max_keys) + key_count = len(result_keys) + len(result_folders) + return template.render( bucket=bucket, prefix=prefix or '', delimiter=delimiter, + key_count=key_count, result_keys=result_keys, result_folders=result_folders, fetch_owner=fetch_owner, @@ -393,9 +498,13 @@ class ResponseObject(_TemplateEnvironmentMixin): next_continuation_token = None return result_keys, is_truncated, next_continuation_token - def _bucket_response_put(self, request, body, region_name, bucket_name, querystring, headers): + def _bucket_response_put(self, request, body, region_name, bucket_name, querystring): if not request.headers.get('Content-Length'): return 411, {}, "Content-Length required" + + self._set_action("BUCKET", "PUT", querystring) + self._authenticate_and_authorize_s3_action() + if 'versioning' in querystring: ver = re.search('([A-Za-z]+)', body.decode()) if ver: @@ -494,7 +603,10 @@ class ResponseObject(_TemplateEnvironmentMixin): template = self.response_template(S3_BUCKET_CREATE_RESPONSE) return 200, {}, template.render(bucket=new_bucket) - def _bucket_response_delete(self, body, bucket_name, querystring, headers): + def _bucket_response_delete(self, body, bucket_name, querystring): + self._set_action("BUCKET", "DELETE", querystring) + self._authenticate_and_authorize_s3_action() + if 'policy' in querystring: self.backend.delete_bucket_policy(bucket_name, body) return 204, {}, "" @@ -521,17 +633,20 @@ class ResponseObject(_TemplateEnvironmentMixin): S3_DELETE_BUCKET_WITH_ITEMS_ERROR) return 409, {}, template.render(bucket=removed_bucket) - def _bucket_response_post(self, request, body, bucket_name, headers): + def _bucket_response_post(self, request, body, bucket_name): if not request.headers.get('Content-Length'): return 411, {}, "Content-Length required" - if isinstance(request, HTTPrettyRequest): - path = request.path - else: - path = request.full_path if hasattr(request, 'full_path') else path_url(request.url) + path = self._get_path(request) if self.is_delete_keys(request, path, bucket_name): - return self._bucket_response_delete_keys(request, body, bucket_name, headers) + self.data["Action"] = "DeleteObject" + self._authenticate_and_authorize_s3_action() + + return self._bucket_response_delete_keys(request, body, bucket_name) + + self.data["Action"] = "PutObject" + self._authenticate_and_authorize_s3_action() # POST to bucket-url should create file from form if hasattr(request, 'form'): @@ -560,12 +675,22 @@ class ResponseObject(_TemplateEnvironmentMixin): return 200, {}, "" - def _bucket_response_delete_keys(self, request, body, bucket_name, headers): + @staticmethod + def _get_path(request): + if isinstance(request, HTTPrettyRequest): + path = request.path + else: + path = request.full_path if hasattr(request, 'full_path') else path_url(request.url) + return path + + def _bucket_response_delete_keys(self, request, body, bucket_name): template = self.response_template(S3_DELETE_KEYS_RESPONSE) keys = minidom.parseString(body).getElementsByTagName('Key') deleted_names = [] error_names = [] + if len(keys) == 0: + raise MalformedXML() for k in keys: key_name = k.firstChild.nodeValue @@ -604,6 +729,11 @@ class ResponseObject(_TemplateEnvironmentMixin): return 206, response_headers, response_content[begin:end + 1] def key_response(self, request, full_url, headers): + self.method = request.method + self.path = self._get_path(request) + self.headers = request.headers + if 'host' not in self.headers: + self.headers['host'] = urlparse(full_url).netloc response_headers = {} try: response = self._key_response(request, full_url, headers) @@ -657,20 +787,23 @@ class ResponseObject(_TemplateEnvironmentMixin): body = b'' if method == 'GET': - return self._key_response_get(bucket_name, query, key_name, headers) + return self._key_response_get(bucket_name, query, key_name, headers=request.headers) elif method == 'PUT': return self._key_response_put(request, body, bucket_name, query, key_name, headers) elif method == 'HEAD': return self._key_response_head(bucket_name, query, key_name, headers=request.headers) elif method == 'DELETE': - return self._key_response_delete(bucket_name, query, key_name, headers) + return self._key_response_delete(bucket_name, query, key_name) elif method == 'POST': - return self._key_response_post(request, body, bucket_name, query, key_name, headers) + return self._key_response_post(request, body, bucket_name, query, key_name) else: raise NotImplementedError( "Method {0} has not been implemented in the S3 backend yet".format(method)) def _key_response_get(self, bucket_name, query, key_name, headers): + self._set_action("KEY", "GET", query) + self._authenticate_and_authorize_s3_action() + response_headers = {} if query.get('uploadId'): upload_id = query['uploadId'][0] @@ -684,10 +817,15 @@ class ResponseObject(_TemplateEnvironmentMixin): parts=parts ) version_id = query.get('versionId', [None])[0] + if_modified_since = headers.get('If-Modified-Since', None) key = self.backend.get_key( bucket_name, key_name, version_id=version_id) if key is None: raise MissingKey(key_name) + if if_modified_since: + if_modified_since = str_to_rfc_1123_datetime(if_modified_since) + if if_modified_since and key.last_modified < if_modified_since: + return 304, response_headers, 'Not Modified' if 'acl' in query: template = self.response_template(S3_OBJECT_ACL_RESPONSE) return 200, response_headers, template.render(obj=key) @@ -700,6 +838,9 @@ class ResponseObject(_TemplateEnvironmentMixin): return 200, response_headers, key.value def _key_response_put(self, request, body, bucket_name, query, key_name, headers): + self._set_action("KEY", "PUT", query) + self._authenticate_and_authorize_s3_action() + response_headers = {} if query.get('uploadId') and query.get('partNumber'): upload_id = query['uploadId'][0] @@ -764,7 +905,11 @@ class ResponseObject(_TemplateEnvironmentMixin): src_version_id = parse_qs(src_key_parsed.query).get( 'versionId', [None])[0] - if self.backend.get_key(src_bucket, src_key, version_id=src_version_id): + key = self.backend.get_key(src_bucket, src_key, version_id=src_version_id) + + if key is not None: + if key.storage_class in ["GLACIER", "DEEP_ARCHIVE"]: + raise ObjectNotInActiveTierError(key) self.backend.copy_key(src_bucket, src_key, bucket_name, key_name, storage=storage_class, acl=acl, src_version_id=src_version_id) else: @@ -804,13 +949,20 @@ class ResponseObject(_TemplateEnvironmentMixin): def _key_response_head(self, bucket_name, query, key_name, headers): response_headers = {} version_id = query.get('versionId', [None])[0] + part_number = query.get('partNumber', [None])[0] + if part_number: + part_number = int(part_number) if_modified_since = headers.get('If-Modified-Since', None) if if_modified_since: if_modified_since = str_to_rfc_1123_datetime(if_modified_since) key = self.backend.get_key( - bucket_name, key_name, version_id=version_id) + bucket_name, + key_name, + version_id=version_id, + part_number=part_number + ) if key: response_headers.update(key.metadata) response_headers.update(key.response_dict) @@ -1066,7 +1218,10 @@ class ResponseObject(_TemplateEnvironmentMixin): config = parsed_xml['AccelerateConfiguration'] return config['Status'] - def _key_response_delete(self, bucket_name, query, key_name, headers): + def _key_response_delete(self, bucket_name, query, key_name): + self._set_action("KEY", "DELETE", query) + self._authenticate_and_authorize_s3_action() + if query.get('uploadId'): upload_id = query['uploadId'][0] self.backend.cancel_multipart(bucket_name, upload_id) @@ -1086,7 +1241,10 @@ class ResponseObject(_TemplateEnvironmentMixin): raise InvalidPartOrder() yield (pn, p.getElementsByTagName('ETag')[0].firstChild.wholeText) - def _key_response_post(self, request, body, bucket_name, query, key_name, headers): + def _key_response_post(self, request, body, bucket_name, query, key_name): + self._set_action("KEY", "POST", query) + self._authenticate_and_authorize_s3_action() + if body == b'' and 'uploads' in query: metadata = metadata_from_headers(request.headers) multipart = self.backend.initiate_multipart( @@ -1175,7 +1333,7 @@ S3_BUCKET_GET_RESPONSE_V2 = """ {{ bucket.name }} {{ prefix }} {{ max_keys }} - {{ result_keys | length }} + {{ key_count }} {% if delimiter %} {{ delimiter }} {% endif %} diff --git a/moto/s3/urls.py b/moto/s3/urls.py index 1d439a549..fa81568a4 100644 --- a/moto/s3/urls.py +++ b/moto/s3/urls.py @@ -7,15 +7,6 @@ url_bases = [ r"https?://(?P[a-zA-Z0-9\-_.]*)\.?s3(.*).amazonaws.com" ] - -def ambiguous_response1(*args, **kwargs): - return S3ResponseInstance.ambiguous_response(*args, **kwargs) - - -def ambiguous_response2(*args, **kwargs): - return S3ResponseInstance.ambiguous_response(*args, **kwargs) - - url_paths = { # subdomain bucket '{0}/$': S3ResponseInstance.bucket_response, diff --git a/moto/secretsmanager/models.py b/moto/secretsmanager/models.py index ec90c3e19..3e0424b6b 100644 --- a/moto/secretsmanager/models.py +++ b/moto/secretsmanager/models.py @@ -70,24 +70,31 @@ class SecretsManagerBackend(BaseBackend): secret_version = secret['versions'][version_id] - response = json.dumps({ + response_data = { "ARN": secret_arn(self.region, secret['secret_id']), "Name": secret['name'], "VersionId": secret_version['version_id'], - "SecretString": secret_version['secret_string'], "VersionStages": secret_version['version_stages'], "CreatedDate": secret_version['createdate'], - }) + } + + if 'secret_string' in secret_version: + response_data["SecretString"] = secret_version['secret_string'] + + if 'secret_binary' in secret_version: + response_data["SecretBinary"] = secret_version['secret_binary'] + + response = json.dumps(response_data) return response - def create_secret(self, name, secret_string, tags, **kwargs): + def create_secret(self, name, secret_string=None, secret_binary=None, tags=[], **kwargs): # error if secret exists if name in self.secrets.keys(): raise ResourceExistsException('A resource with the ID you requested already exists.') - version_id = self._add_secret(name, secret_string, tags=tags) + version_id = self._add_secret(name, secret_string=secret_string, secret_binary=secret_binary, tags=tags) response = json.dumps({ "ARN": secret_arn(self.region, name), @@ -97,7 +104,7 @@ class SecretsManagerBackend(BaseBackend): return response - def _add_secret(self, secret_id, secret_string, tags=[], version_id=None, version_stages=None): + def _add_secret(self, secret_id, secret_string=None, secret_binary=None, tags=[], version_id=None, version_stages=None): if version_stages is None: version_stages = ['AWSCURRENT'] @@ -106,12 +113,17 @@ class SecretsManagerBackend(BaseBackend): version_id = str(uuid.uuid4()) secret_version = { - 'secret_string': secret_string, 'createdate': int(time.time()), 'version_id': version_id, 'version_stages': version_stages, } + if secret_string is not None: + secret_version['secret_string'] = secret_string + + if secret_binary is not None: + secret_version['secret_binary'] = secret_binary + if secret_id in self.secrets: # remove all old AWSPREVIOUS stages for secret_verion_to_look_at in self.secrets[secret_id]['versions'].values(): diff --git a/moto/secretsmanager/responses.py b/moto/secretsmanager/responses.py index fe51d8c1b..090688351 100644 --- a/moto/secretsmanager/responses.py +++ b/moto/secretsmanager/responses.py @@ -21,10 +21,12 @@ class SecretsManagerResponse(BaseResponse): def create_secret(self): name = self._get_param('Name') secret_string = self._get_param('SecretString') + secret_binary = self._get_param('SecretBinary') tags = self._get_param('Tags', if_none=[]) return secretsmanager_backends[self.region].create_secret( name=name, secret_string=secret_string, + secret_binary=secret_binary, tags=tags ) diff --git a/moto/server.py b/moto/server.py index 5ad02d383..89be47093 100644 --- a/moto/server.py +++ b/moto/server.py @@ -21,6 +21,16 @@ from moto.core.utils import convert_flask_to_httpretty_response HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "HEAD", "PATCH"] +DEFAULT_SERVICE_REGION = ('s3', 'us-east-1') + +# Map of unsigned calls to service-region as per AWS API docs +# https://docs.aws.amazon.com/cognito/latest/developerguide/resource-permissions.html#amazon-cognito-signed-versus-unsigned-apis +UNSIGNED_REQUESTS = { + 'AWSCognitoIdentityService': ('cognito-identity', 'us-east-1'), + 'AWSCognitoIdentityProviderService': ('cognito-idp', 'us-east-1'), +} + + class DomainDispatcherApplication(object): """ Dispatch requests to different applications based on the "Host:" header @@ -48,7 +58,45 @@ class DomainDispatcherApplication(object): if re.match(url_base, 'http://%s' % host): return backend_name - raise RuntimeError('Invalid host: "%s"' % host) + def infer_service_region_host(self, environ): + auth = environ.get('HTTP_AUTHORIZATION') + if auth: + # Signed request + # Parse auth header to find service assuming a SigV4 request + # https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html + # ['Credential=sdffdsa', '20170220', 'us-east-1', 'sns', 'aws4_request'] + try: + credential_scope = auth.split(",")[0].split()[1] + _, _, region, service, _ = credential_scope.split("/") + except ValueError: + # Signature format does not match, this is exceptional and we can't + # infer a service-region. A reduced set of services still use + # the deprecated SigV2, ergo prefer S3 as most likely default. + # https://docs.aws.amazon.com/general/latest/gr/signature-version-2.html + service, region = DEFAULT_SERVICE_REGION + else: + # Unsigned request + target = environ.get('HTTP_X_AMZ_TARGET') + if target: + service, _ = target.split('.', 1) + service, region = UNSIGNED_REQUESTS.get(service, DEFAULT_SERVICE_REGION) + else: + # S3 is the last resort when the target is also unknown + service, region = DEFAULT_SERVICE_REGION + + if service == 'dynamodb': + if environ['HTTP_X_AMZ_TARGET'].startswith('DynamoDBStreams'): + host = 'dynamodbstreams' + else: + dynamo_api_version = environ['HTTP_X_AMZ_TARGET'].split("_")[1].split(".")[0] + # If Newer API version, use dynamodb2 + if dynamo_api_version > "20111205": + host = "dynamodb2" + else: + host = "{service}.{region}.amazonaws.com".format( + service=service, region=region) + + return host def get_application(self, environ): path_info = environ.get('PATH_INFO', '') @@ -65,34 +113,14 @@ class DomainDispatcherApplication(object): host = "instance_metadata" else: host = environ['HTTP_HOST'].split(':')[0] - if host in {'localhost', 'motoserver'} or host.startswith("192.168."): - # Fall back to parsing auth header to find service - # ['Credential=sdffdsa', '20170220', 'us-east-1', 'sns', 'aws4_request'] - try: - _, _, region, service, _ = environ['HTTP_AUTHORIZATION'].split(",")[0].split()[ - 1].split("/") - except (KeyError, ValueError): - # Some cognito-idp endpoints (e.g. change password) do not receive an auth header. - if environ.get('HTTP_X_AMZ_TARGET', '').startswith('AWSCognitoIdentityProviderService'): - service = 'cognito-idp' - else: - service = 's3' - - region = 'us-east-1' - if service == 'dynamodb': - if environ['HTTP_X_AMZ_TARGET'].startswith('DynamoDBStreams'): - host = 'dynamodbstreams' - else: - dynamo_api_version = environ['HTTP_X_AMZ_TARGET'].split("_")[1].split(".")[0] - # If Newer API version, use dynamodb2 - if dynamo_api_version > "20111205": - host = "dynamodb2" - else: - host = "{service}.{region}.amazonaws.com".format( - service=service, region=region) with self.lock: backend = self.get_backend_for_host(host) + if not backend: + # No regular backend found; try parsing other headers + host = self.infer_service_region_host(environ) + backend = self.get_backend_for_host(host) + app = self.app_instances.get(backend, None) if app is None: app = self.create_app(backend) diff --git a/moto/ses/models.py b/moto/ses/models.py index 71fe9d9a1..0544ac278 100644 --- a/moto/ses/models.py +++ b/moto/ses/models.py @@ -4,13 +4,41 @@ import email from email.utils import parseaddr from moto.core import BaseBackend, BaseModel +from moto.sns.models import sns_backends from .exceptions import MessageRejectedError from .utils import get_random_message_id - +from .feedback import COMMON_MAIL, BOUNCE, COMPLAINT, DELIVERY RECIPIENT_LIMIT = 50 +class SESFeedback(BaseModel): + + BOUNCE = "Bounce" + COMPLAINT = "Complaint" + DELIVERY = "Delivery" + + SUCCESS_ADDR = "success" + BOUNCE_ADDR = "bounce" + COMPLAINT_ADDR = "complaint" + + FEEDBACK_SUCCESS_MSG = {"test": "success"} + FEEDBACK_BOUNCE_MSG = {"test": "bounce"} + FEEDBACK_COMPLAINT_MSG = {"test": "complaint"} + + @staticmethod + def generate_message(msg_type): + msg = dict(COMMON_MAIL) + if msg_type == SESFeedback.BOUNCE: + msg["bounce"] = BOUNCE + elif msg_type == SESFeedback.COMPLAINT: + msg["complaint"] = COMPLAINT + elif msg_type == SESFeedback.DELIVERY: + msg["delivery"] = DELIVERY + + return msg + + class Message(BaseModel): def __init__(self, message_id, source, subject, body, destinations): @@ -48,6 +76,7 @@ class SESBackend(BaseBackend): self.domains = [] self.sent_messages = [] self.sent_message_count = 0 + self.sns_topics = {} def _is_verified_address(self, source): _, address = parseaddr(source) @@ -77,7 +106,7 @@ class SESBackend(BaseBackend): else: self.domains.remove(identity) - def send_email(self, source, subject, body, destinations): + def send_email(self, source, subject, body, destinations, region): recipient_count = sum(map(len, destinations.values())) if recipient_count > RECIPIENT_LIMIT: raise MessageRejectedError('Too many recipients.') @@ -86,13 +115,46 @@ class SESBackend(BaseBackend): "Email address not verified %s" % source ) + self.__process_sns_feedback__(source, destinations, region) + message_id = get_random_message_id() message = Message(message_id, source, subject, body, destinations) self.sent_messages.append(message) self.sent_message_count += recipient_count return message - def send_raw_email(self, source, destinations, raw_data): + def __type_of_message__(self, destinations): + """Checks the destination for any special address that could indicate delivery, complaint or bounce + like in SES simualtor""" + alladdress = destinations.get("ToAddresses", []) + destinations.get("CcAddresses", []) + destinations.get("BccAddresses", []) + for addr in alladdress: + if SESFeedback.SUCCESS_ADDR in addr: + return SESFeedback.DELIVERY + elif SESFeedback.COMPLAINT_ADDR in addr: + return SESFeedback.COMPLAINT + elif SESFeedback.BOUNCE_ADDR in addr: + return SESFeedback.BOUNCE + + return None + + def __generate_feedback__(self, msg_type): + """Generates the SNS message for the feedback""" + return SESFeedback.generate_message(msg_type) + + def __process_sns_feedback__(self, source, destinations, region): + domain = str(source) + if "@" in domain: + domain = domain.split("@")[1] + if domain in self.sns_topics: + msg_type = self.__type_of_message__(destinations) + if msg_type is not None: + sns_topic = self.sns_topics[domain].get(msg_type, None) + if sns_topic is not None: + message = self.__generate_feedback__(msg_type) + if message: + sns_backends[region].publish(sns_topic, message) + + def send_raw_email(self, source, destinations, raw_data, region): if source is not None: _, source_email_address = parseaddr(source) if source_email_address not in self.addresses: @@ -122,6 +184,8 @@ class SESBackend(BaseBackend): if recipient_count > RECIPIENT_LIMIT: raise MessageRejectedError('Too many recipients.') + self.__process_sns_feedback__(source, destinations, region) + self.sent_message_count += recipient_count message_id = get_random_message_id() message = RawMessage(message_id, source, destinations, raw_data) @@ -131,5 +195,16 @@ class SESBackend(BaseBackend): def get_send_quota(self): return SESQuota(self.sent_message_count) + def set_identity_notification_topic(self, identity, notification_type, sns_topic): + identity_sns_topics = self.sns_topics.get(identity, {}) + if sns_topic is None: + del identity_sns_topics[notification_type] + else: + identity_sns_topics[notification_type] = sns_topic + + self.sns_topics[identity] = identity_sns_topics + + return {} + ses_backend = SESBackend() diff --git a/moto/ses/responses.py b/moto/ses/responses.py index bdf873836..d2dda55f1 100644 --- a/moto/ses/responses.py +++ b/moto/ses/responses.py @@ -70,7 +70,7 @@ class EmailResponse(BaseResponse): break destinations[dest_type].append(address[0]) - message = ses_backend.send_email(source, subject, body, destinations) + message = ses_backend.send_email(source, subject, body, destinations, self.region) template = self.response_template(SEND_EMAIL_RESPONSE) return template.render(message=message) @@ -92,7 +92,7 @@ class EmailResponse(BaseResponse): break destinations.append(address[0]) - message = ses_backend.send_raw_email(source, destinations, raw_data) + message = ses_backend.send_raw_email(source, destinations, raw_data, self.region) template = self.response_template(SEND_RAW_EMAIL_RESPONSE) return template.render(message=message) @@ -101,6 +101,18 @@ class EmailResponse(BaseResponse): template = self.response_template(GET_SEND_QUOTA_RESPONSE) return template.render(quota=quota) + def set_identity_notification_topic(self): + + identity = self.querystring.get("Identity")[0] + not_type = self.querystring.get("NotificationType")[0] + sns_topic = self.querystring.get("SnsTopic") + if sns_topic: + sns_topic = sns_topic[0] + + ses_backend.set_identity_notification_topic(identity, not_type, sns_topic) + template = self.response_template(SET_IDENTITY_NOTIFICATION_TOPIC_RESPONSE) + return template.render() + VERIFY_EMAIL_IDENTITY = """ @@ -200,3 +212,10 @@ GET_SEND_QUOTA_RESPONSE = """ + + + 47e0ef1a-9bf2-11e1-9279-0100e8cf109a + +""" diff --git a/moto/settings.py b/moto/settings.py index a5240f130..12402dc80 100644 --- a/moto/settings.py +++ b/moto/settings.py @@ -1,3 +1,4 @@ import os TEST_SERVER_MODE = os.environ.get('TEST_SERVER_MODE', '0').lower() == 'true' +INITIAL_NO_AUTH_ACTION_COUNT = float(os.environ.get('INITIAL_NO_AUTH_ACTION_COUNT', float('inf'))) diff --git a/moto/sns/models.py b/moto/sns/models.py index c764cb25f..f1293eb0f 100644 --- a/moto/sns/models.py +++ b/moto/sns/models.py @@ -12,7 +12,7 @@ from boto3 import Session from moto.compat import OrderedDict from moto.core import BaseBackend, BaseModel -from moto.core.utils import iso_8601_datetime_with_milliseconds +from moto.core.utils import iso_8601_datetime_with_milliseconds, camelcase_to_underscores from moto.sqs import sqs_backends from moto.awslambda import lambda_backends @@ -119,7 +119,7 @@ class Subscription(BaseModel): else: assert False - lambda_backends[region].send_message(function_name, message, subject=subject, qualifier=qualifier) + lambda_backends[region].send_sns_message(function_name, message, subject=subject, qualifier=qualifier) def _matches_filter_policy(self, message_attributes): # TODO: support Anything-but matching, prefix matching and @@ -243,11 +243,14 @@ class SNSBackend(BaseBackend): def update_sms_attributes(self, attrs): self.sms_attributes.update(attrs) - def create_topic(self, name): + def create_topic(self, name, attributes=None): fails_constraints = not re.match(r'^[a-zA-Z0-9_-]{1,256}$', name) if fails_constraints: raise InvalidParameterValue("Topic names must be made up of only uppercase and lowercase ASCII letters, numbers, underscores, and hyphens, and must be between 1 and 256 characters long.") candidate_topic = Topic(name, self) + if attributes: + for attribute in attributes: + setattr(candidate_topic, camelcase_to_underscores(attribute), attributes[attribute]) if candidate_topic.arn in self.topics: return self.topics[candidate_topic.arn] else: diff --git a/moto/sns/responses.py b/moto/sns/responses.py index 8c1bb885e..440115429 100644 --- a/moto/sns/responses.py +++ b/moto/sns/responses.py @@ -75,7 +75,8 @@ class SNSResponse(BaseResponse): def create_topic(self): name = self._get_param('Name') - topic = self.backend.create_topic(name) + attributes = self._get_attributes() + topic = self.backend.create_topic(name, attributes) if self.request_json: return json.dumps({ diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 1404ded75..e774e261c 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -189,6 +189,8 @@ class Queue(BaseModel): self.name) self.dead_letter_queue = None + self.lambda_event_source_mappings = {} + # default settings for a non fifo queue defaults = { 'ContentBasedDeduplication': 'false', @@ -360,6 +362,33 @@ class Queue(BaseModel): def add_message(self, message): self._messages.append(message) + from moto.awslambda import lambda_backends + for arn, esm in self.lambda_event_source_mappings.items(): + backend = sqs_backends[self.region] + + """ + Lambda polls the queue and invokes your function synchronously with an event + that contains queue messages. Lambda reads messages in batches and invokes + your function once for each batch. When your function successfully processes + a batch, Lambda deletes its messages from the queue. + """ + messages = backend.receive_messages( + self.name, + esm.batch_size, + self.receive_message_wait_time_seconds, + self.visibility_timeout, + ) + + result = lambda_backends[self.region].send_sqs_batch( + arn, + messages, + self.queue_arn, + ) + + if result: + [backend.delete_message(self.name, m.receipt_handle) for m in messages] + else: + [backend.change_message_visibility(self.name, m.receipt_handle, 0) for m in messages] def get_cfn_attribute(self, attribute_name): from moto.cloudformation.exceptions import UnformattedGetAttTemplateException @@ -379,6 +408,7 @@ class SQSBackend(BaseBackend): def reset(self): region_name = self.region_name + self._reset_model_refs() self.__dict__ = {} self.__init__(region_name) diff --git a/moto/sts/models.py b/moto/sts/models.py index c7163a335..c2ff7a8d3 100644 --- a/moto/sts/models.py +++ b/moto/sts/models.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals import datetime from moto.core import BaseBackend, BaseModel from moto.core.utils import iso_8601_datetime_with_milliseconds +from moto.iam.models import ACCOUNT_ID +from moto.sts.utils import random_access_key_id, random_secret_access_key, random_session_token, random_assumed_role_id class Token(BaseModel): @@ -21,19 +23,38 @@ class AssumedRole(BaseModel): def __init__(self, role_session_name, role_arn, policy, duration, external_id): self.session_name = role_session_name - self.arn = role_arn + self.role_arn = role_arn self.policy = policy now = datetime.datetime.utcnow() self.expiration = now + datetime.timedelta(seconds=duration) self.external_id = external_id + self.access_key_id = "ASIA" + random_access_key_id() + self.secret_access_key = random_secret_access_key() + self.session_token = random_session_token() + self.assumed_role_id = "AROA" + random_assumed_role_id() @property def expiration_ISO8601(self): return iso_8601_datetime_with_milliseconds(self.expiration) + @property + def user_id(self): + return self.assumed_role_id + ":" + self.session_name + + @property + def arn(self): + return "arn:aws:sts::{account_id}:assumed-role/{role_name}/{session_name}".format( + account_id=ACCOUNT_ID, + role_name=self.role_arn.split("/")[-1], + session_name=self.session_name + ) + class STSBackend(BaseBackend): + def __init__(self): + self.assumed_roles = [] + def get_session_token(self, duration): token = Token(duration=duration) return token @@ -44,7 +65,17 @@ class STSBackend(BaseBackend): def assume_role(self, **kwargs): role = AssumedRole(**kwargs) + self.assumed_roles.append(role) return role + def get_assumed_role_from_access_key(self, access_key_id): + for assumed_role in self.assumed_roles: + if assumed_role.access_key_id == access_key_id: + return assumed_role + return None + + def assume_role_with_web_identity(self, **kwargs): + return self.assume_role(**kwargs) + sts_backend = STSBackend() diff --git a/moto/sts/responses.py b/moto/sts/responses.py index a5abb6b81..ebdc4321c 100644 --- a/moto/sts/responses.py +++ b/moto/sts/responses.py @@ -1,8 +1,13 @@ from __future__ import unicode_literals from moto.core.responses import BaseResponse +from moto.iam.models import ACCOUNT_ID +from moto.iam import iam_backend +from .exceptions import STSValidationError from .models import sts_backend +MAX_FEDERATION_TOKEN_POLICY_LENGTH = 2048 + class TokenResponse(BaseResponse): @@ -15,11 +20,20 @@ class TokenResponse(BaseResponse): def get_federation_token(self): duration = int(self.querystring.get('DurationSeconds', [43200])[0]) policy = self.querystring.get('Policy', [None])[0] + + if policy is not None and len(policy) > MAX_FEDERATION_TOKEN_POLICY_LENGTH: + raise STSValidationError( + "1 validation error detected: Value " + "'{\"Version\": \"2012-10-17\", \"Statement\": [...]}' " + "at 'policy' failed to satisfy constraint: Member must have length less than or " + " equal to %s" % MAX_FEDERATION_TOKEN_POLICY_LENGTH + ) + name = self.querystring.get('Name')[0] token = sts_backend.get_federation_token( duration=duration, name=name, policy=policy) template = self.response_template(GET_FEDERATION_TOKEN_RESPONSE) - return template.render(token=token) + return template.render(token=token, account_id=ACCOUNT_ID) def assume_role(self): role_session_name = self.querystring.get('RoleSessionName')[0] @@ -39,9 +53,43 @@ class TokenResponse(BaseResponse): template = self.response_template(ASSUME_ROLE_RESPONSE) return template.render(role=role) + def assume_role_with_web_identity(self): + role_session_name = self.querystring.get('RoleSessionName')[0] + role_arn = self.querystring.get('RoleArn')[0] + + policy = self.querystring.get('Policy', [None])[0] + duration = int(self.querystring.get('DurationSeconds', [3600])[0]) + external_id = self.querystring.get('ExternalId', [None])[0] + + role = sts_backend.assume_role_with_web_identity( + role_session_name=role_session_name, + role_arn=role_arn, + policy=policy, + duration=duration, + external_id=external_id, + ) + template = self.response_template(ASSUME_ROLE_WITH_WEB_IDENTITY_RESPONSE) + return template.render(role=role) + def get_caller_identity(self): template = self.response_template(GET_CALLER_IDENTITY_RESPONSE) - return template.render() + + # Default values in case the request does not use valid credentials generated by moto + user_id = "AKIAIOSFODNN7EXAMPLE" + arn = "arn:aws:sts::{account_id}:user/moto".format(account_id=ACCOUNT_ID) + + access_key_id = self.get_current_user() + assumed_role = sts_backend.get_assumed_role_from_access_key(access_key_id) + if assumed_role: + user_id = assumed_role.user_id + arn = assumed_role.arn + + user = iam_backend.get_user_from_access_key_id(access_key_id) + if user: + user_id = user.id + arn = user.arn + + return template.render(account_id=ACCOUNT_ID, user_id=user_id, arn=arn) GET_SESSION_TOKEN_RESPONSE = """ @@ -69,8 +117,8 @@ GET_FEDERATION_TOKEN_RESPONSE = """ - BQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT+FvwqnKwRcOIfrRh3c/LTo6UDdyJwOOvEVPvLXCrrrUtdnniCEXAMPLE/IvU1dYUg2RVAJBanLiHb4IgRmpRV3zrkuWJOgQs8IZZaIv2BXIa2R4OlgkBN9bkUDNCJiBeb/AXlzBBko7b15fjrBs2+cTQtpZ3CYWFXG8C5zqx37wnOE49mRl/+OtkIKGO7fAE - aJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY + {{ role.session_token }} + {{ role.secret_access_key }} {{ role.expiration_ISO8601 }} - AKIAIOSFODNN7EXAMPLE + {{ role.access_key_id }} {{ role.arn }} - ARO123EXAMPLE123:{{ role.session_name }} + {{ role.user_id }} 6 @@ -100,11 +148,32 @@ ASSUME_ROLE_RESPONSE = """ + + + {{ role.session_token }} + {{ role.secret_access_key }} + {{ role.expiration_ISO8601 }} + {{ role.access_key_id }} + + + {{ role.arn }} + ARO123EXAMPLE123:{{ role.session_name }} + + 6 + + + c6104cbe-af31-11e0-8154-cbc7ccf896c7 + +""" + + GET_CALLER_IDENTITY_RESPONSE = """ - arn:aws:sts::123456789012:user/moto - AKIAIOSFODNN7EXAMPLE - 123456789012 + {{ arn }} + {{ user_id }} + {{ account_id }} c6104cbe-af31-11e0-8154-cbc7ccf896c7 diff --git a/scripts/implementation_coverage.py b/scripts/implementation_coverage.py index 4e385e1d6..0e1816088 100755 --- a/scripts/implementation_coverage.py +++ b/scripts/implementation_coverage.py @@ -61,7 +61,8 @@ def print_implementation_coverage(coverage): percentage_implemented = 0 print("") - print("## {} - {}% implemented".format(service_name, percentage_implemented)) + print("## {}\n".format(service_name)) + print("{}% implemented\n".format(percentage_implemented)) for op in operations: if op in implemented: print("- [X] {}".format(op)) @@ -93,7 +94,8 @@ def write_implementation_coverage_to_file(coverage): percentage_implemented = 0 file.write("\n") - file.write("## {} - {}% implemented\n".format(service_name, percentage_implemented)) + file.write("## {}\n".format(service_name)) + file.write("{}% implemented\n".format(percentage_implemented)) for op in operations: if op in implemented: file.write("- [X] {}\n".format(op)) diff --git a/scripts/update_managed_policies.py b/scripts/update_managed_policies.py index 5b60660f6..de7058fd7 100755 --- a/scripts/update_managed_policies.py +++ b/scripts/update_managed_policies.py @@ -48,7 +48,8 @@ for policy_name in policies: PolicyArn=policies[policy_name]['Arn'], VersionId=policies[policy_name]['DefaultVersionId']) for key in response['PolicyVersion']: - policies[policy_name][key] = response['PolicyVersion'][key] + if key != "CreateDate": # the policy's CreateDate should not be overwritten by its version's CreateDate + policies[policy_name][key] = response['PolicyVersion'][key] with open(output_file, 'w') as f: triple_quote = '\"\"\"' diff --git a/setup.py b/setup.py index e3fea2828..77ebdfcf7 100755 --- a/setup.py +++ b/setup.py @@ -18,17 +18,26 @@ def read(*parts): return fp.read() +def get_version(): + version_file = read('moto', '__init__.py') + version_match = re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', + version_file, re.MULTILINE) + if version_match: + return version_match.group(1) + raise RuntimeError('Unable to find version string.') + + install_requires = [ "Jinja2>=2.10.1", "boto>=2.36.0", - "boto3>=1.9.86", - "botocore>=1.12.86", + "boto3>=1.9.201", + "botocore>=1.12.201", "cryptography>=2.3.0", "requests>=2.5", "xmltodict", "six>1.9", "werkzeug", - "PyYAML==3.13", + "PyYAML>=5.1", "pytz", "python-dateutil<3.0.0,>=2.1", "python-jose<4.0.0", @@ -38,7 +47,7 @@ install_requires = [ "aws-xray-sdk!=0.96,>=0.93", "responses>=0.9.0", "idna<2.9,>=2.5", - "cfn-lint", + "cfn-lint>=0.4.0", "sshpubkeys>=3.1.0,<4.0" ] @@ -56,7 +65,7 @@ else: setup( name='moto', - version='1.3.8', + version=get_version(), description='A library that allows your python tests to easily' ' mock out the boto library', long_description=read('README.md'), @@ -79,10 +88,9 @@ setup( "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.3", - "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", "License :: OSI Approved :: Apache Software License", "Topic :: Software Development :: Testing", ], diff --git a/tests/test_acm/test_acm.py b/tests/test_acm/test_acm.py index ccac48181..cdd8682e1 100644 --- a/tests/test_acm/test_acm.py +++ b/tests/test_acm/test_acm.py @@ -74,6 +74,31 @@ def test_list_certificates(): resp['CertificateSummaryList'][0]['DomainName'].should.equal(SERVER_COMMON_NAME) +@mock_acm +def test_list_certificates_by_status(): + client = boto3.client('acm', region_name='eu-central-1') + issued_arn = _import_cert(client) + pending_arn = client.request_certificate(DomainName='google.com')['CertificateArn'] + + resp = client.list_certificates() + len(resp['CertificateSummaryList']).should.equal(2) + resp = client.list_certificates(CertificateStatuses=['EXPIRED', 'INACTIVE']) + len(resp['CertificateSummaryList']).should.equal(0) + resp = client.list_certificates(CertificateStatuses=['PENDING_VALIDATION']) + len(resp['CertificateSummaryList']).should.equal(1) + resp['CertificateSummaryList'][0]['CertificateArn'].should.equal(pending_arn) + + resp = client.list_certificates(CertificateStatuses=['ISSUED']) + len(resp['CertificateSummaryList']).should.equal(1) + resp['CertificateSummaryList'][0]['CertificateArn'].should.equal(issued_arn) + resp = client.list_certificates(CertificateStatuses=['ISSUED', 'PENDING_VALIDATION']) + len(resp['CertificateSummaryList']).should.equal(2) + arns = {cert['CertificateArn'] for cert in resp['CertificateSummaryList']} + arns.should.contain(issued_arn) + arns.should.contain(pending_arn) + + + @mock_acm def test_get_invalid_certificate(): client = boto3.client('acm', region_name='eu-central-1') @@ -291,6 +316,7 @@ def test_request_certificate(): ) resp.should.contain('CertificateArn') arn = resp['CertificateArn'] + arn.should.match(r"arn:aws:acm:eu-central-1:\d{12}:certificate/") resp = client.request_certificate( DomainName='google.com', diff --git a/tests/test_apigateway/test_apigateway.py b/tests/test_apigateway/test_apigateway.py index 5954de8ca..0a33f2f9f 100644 --- a/tests/test_apigateway/test_apigateway.py +++ b/tests/test_apigateway/test_apigateway.py @@ -988,13 +988,30 @@ def test_api_keys(): apikey['name'].should.equal(apikey_name) len(apikey['value']).should.equal(40) + apikey_name = 'TESTKEY3' + payload = {'name': apikey_name } + response = client.create_api_key(**payload) + apikey_id = response['id'] + + patch_operations = [ + {'op': 'replace', 'path': '/name', 'value': 'TESTKEY3_CHANGE'}, + {'op': 'replace', 'path': '/customerId', 'value': '12345'}, + {'op': 'replace', 'path': '/description', 'value': 'APIKEY UPDATE TEST'}, + {'op': 'replace', 'path': '/enabled', 'value': 'false'}, + ] + response = client.update_api_key(apiKey=apikey_id, patchOperations=patch_operations) + response['name'].should.equal('TESTKEY3_CHANGE') + response['customerId'].should.equal('12345') + response['description'].should.equal('APIKEY UPDATE TEST') + response['enabled'].should.equal(False) + response = client.get_api_keys() - len(response['items']).should.equal(2) + len(response['items']).should.equal(3) client.delete_api_key(apiKey=apikey_id) response = client.get_api_keys() - len(response['items']).should.equal(1) + len(response['items']).should.equal(2) @mock_apigateway def test_usage_plans(): diff --git a/tests/test_autoscaling/test_autoscaling.py b/tests/test_autoscaling/test_autoscaling.py index 750605c07..2df7bf30f 100644 --- a/tests/test_autoscaling/test_autoscaling.py +++ b/tests/test_autoscaling/test_autoscaling.py @@ -7,11 +7,13 @@ from boto.ec2.autoscale.group import AutoScalingGroup from boto.ec2.autoscale import Tag import boto.ec2.elb import sure # noqa +from botocore.exceptions import ClientError +from nose.tools import assert_raises from moto import mock_autoscaling, mock_ec2_deprecated, mock_elb_deprecated, mock_elb, mock_autoscaling_deprecated, mock_ec2 from tests.helpers import requires_boto_gte -from utils import setup_networking, setup_networking_deprecated +from utils import setup_networking, setup_networking_deprecated, setup_instance_with_networking @mock_autoscaling_deprecated @@ -724,6 +726,67 @@ def test_create_autoscaling_group_boto3(): response['ResponseMetadata']['HTTPStatusCode'].should.equal(200) +@mock_autoscaling +def test_create_autoscaling_group_from_instance(): + autoscaling_group_name = 'test_asg' + image_id = 'ami-0cc293023f983ed53' + instance_type = 't2.micro' + + mocked_instance_with_networking = setup_instance_with_networking(image_id, instance_type) + client = boto3.client('autoscaling', region_name='us-east-1') + response = client.create_auto_scaling_group( + AutoScalingGroupName=autoscaling_group_name, + InstanceId=mocked_instance_with_networking['instance'], + MinSize=1, + MaxSize=3, + DesiredCapacity=2, + Tags=[ + {'ResourceId': 'test_asg', + 'ResourceType': 'auto-scaling-group', + 'Key': 'propogated-tag-key', + 'Value': 'propogate-tag-value', + 'PropagateAtLaunch': True + }, + {'ResourceId': 'test_asg', + 'ResourceType': 'auto-scaling-group', + 'Key': 'not-propogated-tag-key', + 'Value': 'not-propogate-tag-value', + 'PropagateAtLaunch': False + }], + VPCZoneIdentifier=mocked_instance_with_networking['subnet1'], + NewInstancesProtectedFromScaleIn=False, + ) + response['ResponseMetadata']['HTTPStatusCode'].should.equal(200) + + describe_launch_configurations_response = client.describe_launch_configurations() + describe_launch_configurations_response['LaunchConfigurations'].should.have.length_of(1) + launch_configuration_from_instance = describe_launch_configurations_response['LaunchConfigurations'][0] + launch_configuration_from_instance['LaunchConfigurationName'].should.equal('test_asg') + launch_configuration_from_instance['ImageId'].should.equal(image_id) + launch_configuration_from_instance['InstanceType'].should.equal(instance_type) + + +@mock_autoscaling +def test_create_autoscaling_group_from_invalid_instance_id(): + invalid_instance_id = 'invalid_instance' + + mocked_networking = setup_networking() + client = boto3.client('autoscaling', region_name='us-east-1') + with assert_raises(ClientError) as ex: + client.create_auto_scaling_group( + AutoScalingGroupName='test_asg', + InstanceId=invalid_instance_id, + MinSize=9, + MaxSize=15, + DesiredCapacity=12, + VPCZoneIdentifier=mocked_networking['subnet1'], + NewInstancesProtectedFromScaleIn=False, + ) + ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400) + ex.exception.response['Error']['Code'].should.equal('ValidationError') + ex.exception.response['Error']['Message'].should.equal('Instance [{0}] is invalid.'.format(invalid_instance_id)) + + @mock_autoscaling def test_describe_autoscaling_groups_boto3(): mocked_networking = setup_networking() @@ -823,6 +886,62 @@ def test_update_autoscaling_group_boto3(): group['NewInstancesProtectedFromScaleIn'].should.equal(False) +@mock_autoscaling +def test_update_autoscaling_group_min_size_desired_capacity_change(): + mocked_networking = setup_networking() + client = boto3.client('autoscaling', region_name='us-east-1') + + client.create_launch_configuration( + LaunchConfigurationName='test_launch_configuration' + ) + client.create_auto_scaling_group( + AutoScalingGroupName='test_asg', + LaunchConfigurationName='test_launch_configuration', + MinSize=2, + MaxSize=20, + DesiredCapacity=3, + VPCZoneIdentifier=mocked_networking['subnet1'], + ) + client.update_auto_scaling_group( + AutoScalingGroupName='test_asg', + MinSize=5, + ) + response = client.describe_auto_scaling_groups( + AutoScalingGroupNames=['test_asg']) + group = response['AutoScalingGroups'][0] + group['DesiredCapacity'].should.equal(5) + group['MinSize'].should.equal(5) + group['Instances'].should.have.length_of(5) + + +@mock_autoscaling +def test_update_autoscaling_group_max_size_desired_capacity_change(): + mocked_networking = setup_networking() + client = boto3.client('autoscaling', region_name='us-east-1') + + client.create_launch_configuration( + LaunchConfigurationName='test_launch_configuration' + ) + client.create_auto_scaling_group( + AutoScalingGroupName='test_asg', + LaunchConfigurationName='test_launch_configuration', + MinSize=2, + MaxSize=20, + DesiredCapacity=10, + VPCZoneIdentifier=mocked_networking['subnet1'], + ) + client.update_auto_scaling_group( + AutoScalingGroupName='test_asg', + MaxSize=5, + ) + response = client.describe_auto_scaling_groups( + AutoScalingGroupNames=['test_asg']) + group = response['AutoScalingGroups'][0] + group['DesiredCapacity'].should.equal(5) + group['MaxSize'].should.equal(5) + group['Instances'].should.have.length_of(5) + + @mock_autoscaling def test_autoscaling_taqs_update_boto3(): mocked_networking = setup_networking() @@ -1269,3 +1388,36 @@ def test_set_desired_capacity_down_boto3(): instance_ids = {instance['InstanceId'] for instance in group['Instances']} set(protected).should.equal(instance_ids) set(unprotected).should_not.be.within(instance_ids) # only unprotected killed + + +@mock_autoscaling +@mock_ec2 +def test_terminate_instance_in_autoscaling_group(): + mocked_networking = setup_networking() + client = boto3.client('autoscaling', region_name='us-east-1') + _ = client.create_launch_configuration( + LaunchConfigurationName='test_launch_configuration' + ) + _ = client.create_auto_scaling_group( + AutoScalingGroupName='test_asg', + LaunchConfigurationName='test_launch_configuration', + MinSize=1, + MaxSize=20, + VPCZoneIdentifier=mocked_networking['subnet1'], + NewInstancesProtectedFromScaleIn=False + ) + + response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg']) + original_instance_id = next( + instance['InstanceId'] + for instance in response['AutoScalingGroups'][0]['Instances'] + ) + ec2_client = boto3.client('ec2', region_name='us-east-1') + ec2_client.terminate_instances(InstanceIds=[original_instance_id]) + + response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg']) + replaced_instance_id = next( + instance['InstanceId'] + for instance in response['AutoScalingGroups'][0]['Instances'] + ) + replaced_instance_id.should_not.equal(original_instance_id) diff --git a/tests/test_autoscaling/utils.py b/tests/test_autoscaling/utils.py index ebbffbed3..dc38aba3d 100644 --- a/tests/test_autoscaling/utils.py +++ b/tests/test_autoscaling/utils.py @@ -31,3 +31,18 @@ def setup_networking_deprecated(): "10.11.2.0/24", availability_zone='us-east-1b') return {'vpc': vpc.id, 'subnet1': subnet1.id, 'subnet2': subnet2.id} + + +@mock_ec2 +def setup_instance_with_networking(image_id, instance_type): + mock_data = setup_networking() + ec2 = boto3.resource('ec2', region_name='us-east-1') + instances = ec2.create_instances( + ImageId=image_id, + InstanceType=instance_type, + MaxCount=1, + MinCount=1, + SubnetId=mock_data['subnet1'] + ) + mock_data['instance'] = instances[0].id + return mock_data diff --git a/tests/test_awslambda/test_lambda.py b/tests/test_awslambda/test_lambda.py index 9ef6fdb0d..9467b0803 100644 --- a/tests/test_awslambda/test_lambda.py +++ b/tests/test_awslambda/test_lambda.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import base64 +import uuid import botocore.client import boto3 import hashlib @@ -11,11 +12,12 @@ import zipfile import sure # noqa from freezegun import freeze_time -from moto import mock_lambda, mock_s3, mock_ec2, mock_sns, mock_logs, settings +from moto import mock_lambda, mock_s3, mock_ec2, mock_sns, mock_logs, settings, mock_sqs from nose.tools import assert_raises from botocore.exceptions import ClientError _lambda_region = 'us-west-2' +boto3.setup_default_session(region_name=_lambda_region) def _process_lambda(func_str): @@ -59,6 +61,13 @@ def lambda_handler(event, context): """ return _process_lambda(pfunc) +def get_test_zip_file4(): + pfunc = """ +def lambda_handler(event, context): + raise Exception('I failed!') +""" + return _process_lambda(pfunc) + @mock_lambda def test_list_functions(): @@ -933,3 +942,306 @@ def test_list_versions_by_function_for_nonexistent_function(): versions = conn.list_versions_by_function(FunctionName='testFunction') assert len(versions['Versions']) == 0 + + +@mock_logs +@mock_lambda +@mock_sqs +def test_create_event_source_mapping(): + sqs = boto3.resource('sqs') + queue = sqs.create_queue(QueueName="test-sqs-queue1") + + conn = boto3.client('lambda') + func = conn.create_function( + FunctionName='testFunction', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.lambda_handler', + Code={ + 'ZipFile': get_test_zip_file3(), + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + ) + + response = conn.create_event_source_mapping( + EventSourceArn=queue.attributes['QueueArn'], + FunctionName=func['FunctionArn'], + ) + + assert response['EventSourceArn'] == queue.attributes['QueueArn'] + assert response['FunctionArn'] == func['FunctionArn'] + assert response['State'] == 'Enabled' + + +@mock_logs +@mock_lambda +@mock_sqs +def test_invoke_function_from_sqs(): + logs_conn = boto3.client("logs") + sqs = boto3.resource('sqs') + queue = sqs.create_queue(QueueName="test-sqs-queue1") + + conn = boto3.client('lambda') + func = conn.create_function( + FunctionName='testFunction', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.lambda_handler', + Code={ + 'ZipFile': get_test_zip_file3(), + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + ) + + response = conn.create_event_source_mapping( + EventSourceArn=queue.attributes['QueueArn'], + FunctionName=func['FunctionArn'], + ) + + assert response['EventSourceArn'] == queue.attributes['QueueArn'] + assert response['State'] == 'Enabled' + + sqs_client = boto3.client('sqs') + sqs_client.send_message(QueueUrl=queue.url, MessageBody='test') + start = time.time() + while (time.time() - start) < 30: + result = logs_conn.describe_log_streams(logGroupName='/aws/lambda/testFunction') + log_streams = result.get('logStreams') + if not log_streams: + time.sleep(1) + continue + + assert len(log_streams) == 1 + result = logs_conn.get_log_events(logGroupName='/aws/lambda/testFunction', logStreamName=log_streams[0]['logStreamName']) + for event in result.get('events'): + if event['message'] == 'get_test_zip_file3 success': + return + time.sleep(1) + + assert False, "Test Failed" + + +@mock_logs +@mock_lambda +@mock_sqs +def test_invoke_function_from_sqs_exception(): + logs_conn = boto3.client("logs") + sqs = boto3.resource('sqs') + queue = sqs.create_queue(QueueName="test-sqs-queue1") + + conn = boto3.client('lambda') + func = conn.create_function( + FunctionName='testFunction', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.lambda_handler', + Code={ + 'ZipFile': get_test_zip_file4(), + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + ) + + response = conn.create_event_source_mapping( + EventSourceArn=queue.attributes['QueueArn'], + FunctionName=func['FunctionArn'], + ) + + assert response['EventSourceArn'] == queue.attributes['QueueArn'] + assert response['State'] == 'Enabled' + + entries = [] + for i in range(3): + body = { + "uuid": str(uuid.uuid4()), + "test": "test_{}".format(i), + } + entry = { + 'Id': str(i), + 'MessageBody': json.dumps(body) + } + entries.append(entry) + + queue.send_messages(Entries=entries) + + start = time.time() + while (time.time() - start) < 30: + result = logs_conn.describe_log_streams(logGroupName='/aws/lambda/testFunction') + log_streams = result.get('logStreams') + if not log_streams: + time.sleep(1) + continue + assert len(log_streams) >= 1 + + result = logs_conn.get_log_events(logGroupName='/aws/lambda/testFunction', logStreamName=log_streams[0]['logStreamName']) + for event in result.get('events'): + if 'I failed!' in event['message']: + messages = queue.receive_messages(MaxNumberOfMessages=10) + # Verify messages are still visible and unprocessed + assert len(messages) is 3 + return + time.sleep(1) + + assert False, "Test Failed" + + +@mock_logs +@mock_lambda +@mock_sqs +def test_list_event_source_mappings(): + sqs = boto3.resource('sqs') + queue = sqs.create_queue(QueueName="test-sqs-queue1") + + conn = boto3.client('lambda') + func = conn.create_function( + FunctionName='testFunction', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.lambda_handler', + Code={ + 'ZipFile': get_test_zip_file3(), + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + ) + response = conn.create_event_source_mapping( + EventSourceArn=queue.attributes['QueueArn'], + FunctionName=func['FunctionArn'], + ) + mappings = conn.list_event_source_mappings(EventSourceArn='123') + assert len(mappings['EventSourceMappings']) == 0 + + mappings = conn.list_event_source_mappings(EventSourceArn=queue.attributes['QueueArn']) + assert len(mappings['EventSourceMappings']) == 1 + assert mappings['EventSourceMappings'][0]['UUID'] == response['UUID'] + assert mappings['EventSourceMappings'][0]['FunctionArn'] == func['FunctionArn'] + + +@mock_lambda +@mock_sqs +def test_get_event_source_mapping(): + sqs = boto3.resource('sqs') + queue = sqs.create_queue(QueueName="test-sqs-queue1") + + conn = boto3.client('lambda') + func = conn.create_function( + FunctionName='testFunction', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.lambda_handler', + Code={ + 'ZipFile': get_test_zip_file3(), + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + ) + response = conn.create_event_source_mapping( + EventSourceArn=queue.attributes['QueueArn'], + FunctionName=func['FunctionArn'], + ) + mapping = conn.get_event_source_mapping(UUID=response['UUID']) + assert mapping['UUID'] == response['UUID'] + assert mapping['FunctionArn'] == func['FunctionArn'] + + conn.get_event_source_mapping.when.called_with(UUID='1')\ + .should.throw(botocore.client.ClientError) + + +@mock_lambda +@mock_sqs +def test_update_event_source_mapping(): + sqs = boto3.resource('sqs') + queue = sqs.create_queue(QueueName="test-sqs-queue1") + + conn = boto3.client('lambda') + func1 = conn.create_function( + FunctionName='testFunction', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.lambda_handler', + Code={ + 'ZipFile': get_test_zip_file3(), + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + ) + func2 = conn.create_function( + FunctionName='testFunction2', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.lambda_handler', + Code={ + 'ZipFile': get_test_zip_file3(), + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + ) + response = conn.create_event_source_mapping( + EventSourceArn=queue.attributes['QueueArn'], + FunctionName=func1['FunctionArn'], + ) + assert response['FunctionArn'] == func1['FunctionArn'] + assert response['BatchSize'] == 10 + assert response['State'] == 'Enabled' + + mapping = conn.update_event_source_mapping( + UUID=response['UUID'], + Enabled=False, + BatchSize=15, + FunctionName='testFunction2' + + ) + assert mapping['UUID'] == response['UUID'] + assert mapping['FunctionArn'] == func2['FunctionArn'] + assert mapping['State'] == 'Disabled' + + +@mock_lambda +@mock_sqs +def test_delete_event_source_mapping(): + sqs = boto3.resource('sqs') + queue = sqs.create_queue(QueueName="test-sqs-queue1") + + conn = boto3.client('lambda') + func1 = conn.create_function( + FunctionName='testFunction', + Runtime='python2.7', + Role='test-iam-role', + Handler='lambda_function.lambda_handler', + Code={ + 'ZipFile': get_test_zip_file3(), + }, + Description='test lambda function', + Timeout=3, + MemorySize=128, + Publish=True, + ) + response = conn.create_event_source_mapping( + EventSourceArn=queue.attributes['QueueArn'], + FunctionName=func1['FunctionArn'], + ) + assert response['FunctionArn'] == func1['FunctionArn'] + assert response['BatchSize'] == 10 + assert response['State'] == 'Enabled' + + response = conn.delete_event_source_mapping(UUID=response['UUID']) + + assert response['State'] == 'Deleting' + conn.get_event_source_mapping.when.called_with(UUID=response['UUID'])\ + .should.throw(botocore.client.ClientError) diff --git a/tests/test_batch/test_batch.py b/tests/test_batch/test_batch.py index 310ac0b48..89a8d4d0e 100644 --- a/tests/test_batch/test_batch.py +++ b/tests/test_batch/test_batch.py @@ -642,6 +642,87 @@ def test_describe_task_definition(): len(resp['jobDefinitions']).should.equal(3) +@mock_logs +@mock_ec2 +@mock_ecs +@mock_iam +@mock_batch +def test_submit_job_by_name(): + ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() + vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) + + compute_name = 'test_compute_env' + resp = batch_client.create_compute_environment( + computeEnvironmentName=compute_name, + type='UNMANAGED', + state='ENABLED', + serviceRole=iam_arn + ) + arn = resp['computeEnvironmentArn'] + + resp = batch_client.create_job_queue( + jobQueueName='test_job_queue', + state='ENABLED', + priority=123, + computeEnvironmentOrder=[ + { + 'order': 123, + 'computeEnvironment': arn + }, + ] + ) + queue_arn = resp['jobQueueArn'] + + job_definition_name = 'sleep10' + + batch_client.register_job_definition( + jobDefinitionName=job_definition_name, + type='container', + containerProperties={ + 'image': 'busybox', + 'vcpus': 1, + 'memory': 128, + 'command': ['sleep', '10'] + } + ) + batch_client.register_job_definition( + jobDefinitionName=job_definition_name, + type='container', + containerProperties={ + 'image': 'busybox', + 'vcpus': 1, + 'memory': 256, + 'command': ['sleep', '10'] + } + ) + resp = batch_client.register_job_definition( + jobDefinitionName=job_definition_name, + type='container', + containerProperties={ + 'image': 'busybox', + 'vcpus': 1, + 'memory': 512, + 'command': ['sleep', '10'] + } + ) + job_definition_arn = resp['jobDefinitionArn'] + + resp = batch_client.submit_job( + jobName='test1', + jobQueue=queue_arn, + jobDefinition=job_definition_name + ) + job_id = resp['jobId'] + + resp_jobs = batch_client.describe_jobs(jobs=[job_id]) + + # batch_client.terminate_job(jobId=job_id) + + len(resp_jobs['jobs']).should.equal(1) + resp_jobs['jobs'][0]['jobId'].should.equal(job_id) + resp_jobs['jobs'][0]['jobQueue'].should.equal(queue_arn) + resp_jobs['jobs'][0]['jobDefinition'].should.equal(job_definition_arn) + # SLOW TESTS @expected_failure @mock_logs diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud.py b/tests/test_cloudformation/test_cloudformation_stack_crud.py index b7906632b..27424bf8c 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_crud.py +++ b/tests/test_cloudformation/test_cloudformation_stack_crud.py @@ -593,9 +593,11 @@ def test_create_stack_lambda_and_dynamodb(): } }, "func1version": { - "Type": "AWS::Lambda::LambdaVersion", - "Properties" : { - "Version": "v1.2.3" + "Type": "AWS::Lambda::Version", + "Properties": { + "FunctionName": { + "Ref": "func1" + } } }, "tab1": { @@ -618,8 +620,10 @@ def test_create_stack_lambda_and_dynamodb(): }, "func1mapping": { "Type": "AWS::Lambda::EventSourceMapping", - "Properties" : { - "FunctionName": "v1.2.3", + "Properties": { + "FunctionName": { + "Ref": "func1" + }, "EventSourceArn": "arn:aws:dynamodb:region:XXXXXX:table/tab1/stream/2000T00:00:00.000", "StartingPosition": "0", "BatchSize": 100, diff --git a/tests/test_cognitoidentity/test_cognitoidentity.py b/tests/test_cognitoidentity/test_cognitoidentity.py index 278c20660..ea9ccbc78 100644 --- a/tests/test_cognitoidentity/test_cognitoidentity.py +++ b/tests/test_cognitoidentity/test_cognitoidentity.py @@ -1,85 +1,97 @@ -from __future__ import unicode_literals - -import boto3 - -from moto import mock_cognitoidentity -import sure # noqa - -from moto.cognitoidentity.utils import get_random_identity_id - - -@mock_cognitoidentity -def test_create_identity_pool(): - conn = boto3.client('cognito-identity', 'us-west-2') - - result = conn.create_identity_pool(IdentityPoolName='TestPool', - AllowUnauthenticatedIdentities=False, - SupportedLoginProviders={'graph.facebook.com': '123456789012345'}, - DeveloperProviderName='devname', - OpenIdConnectProviderARNs=['arn:aws:rds:eu-west-2:123456789012:db:mysql-db'], - CognitoIdentityProviders=[ - { - 'ProviderName': 'testprovider', - 'ClientId': 'CLIENT12345', - 'ServerSideTokenCheck': True - }, - ], - SamlProviderARNs=['arn:aws:rds:eu-west-2:123456789012:db:mysql-db']) - assert result['IdentityPoolId'] != '' - - -# testing a helper function -def test_get_random_identity_id(): - assert len(get_random_identity_id('us-west-2')) > 0 - assert len(get_random_identity_id('us-west-2').split(':')[1]) == 19 - - -@mock_cognitoidentity -def test_get_id(): - # These two do NOT work in server mode. They just don't return the data from the model. - conn = boto3.client('cognito-identity', 'us-west-2') - result = conn.get_id(AccountId='someaccount', - IdentityPoolId='us-west-2:12345', - Logins={ - 'someurl': '12345' - }) - print(result) - assert result.get('IdentityId', "").startswith('us-west-2') or result.get('ResponseMetadata').get('HTTPStatusCode') == 200 - - -@mock_cognitoidentity -def test_get_credentials_for_identity(): - # These two do NOT work in server mode. They just don't return the data from the model. - conn = boto3.client('cognito-identity', 'us-west-2') - result = conn.get_credentials_for_identity(IdentityId='12345') - - assert result.get('Expiration', 0) > 0 or result.get('ResponseMetadata').get('HTTPStatusCode') == 200 - assert result.get('IdentityId') == '12345' or result.get('ResponseMetadata').get('HTTPStatusCode') == 200 - - -@mock_cognitoidentity -def test_get_open_id_token_for_developer_identity(): - conn = boto3.client('cognito-identity', 'us-west-2') - result = conn.get_open_id_token_for_developer_identity( - IdentityPoolId='us-west-2:12345', - IdentityId='12345', - Logins={ - 'someurl': '12345' - }, - TokenDuration=123 - ) - assert len(result['Token']) - assert result['IdentityId'] == '12345' - -@mock_cognitoidentity -def test_get_open_id_token_for_developer_identity_when_no_explicit_identity_id(): - conn = boto3.client('cognito-identity', 'us-west-2') - result = conn.get_open_id_token_for_developer_identity( - IdentityPoolId='us-west-2:12345', - Logins={ - 'someurl': '12345' - }, - TokenDuration=123 - ) - assert len(result['Token']) > 0 - assert len(result['IdentityId']) > 0 +from __future__ import unicode_literals + +import boto3 + +from moto import mock_cognitoidentity +import sure # noqa + +from moto.cognitoidentity.utils import get_random_identity_id + + +@mock_cognitoidentity +def test_create_identity_pool(): + conn = boto3.client('cognito-identity', 'us-west-2') + + result = conn.create_identity_pool(IdentityPoolName='TestPool', + AllowUnauthenticatedIdentities=False, + SupportedLoginProviders={'graph.facebook.com': '123456789012345'}, + DeveloperProviderName='devname', + OpenIdConnectProviderARNs=['arn:aws:rds:eu-west-2:123456789012:db:mysql-db'], + CognitoIdentityProviders=[ + { + 'ProviderName': 'testprovider', + 'ClientId': 'CLIENT12345', + 'ServerSideTokenCheck': True + }, + ], + SamlProviderARNs=['arn:aws:rds:eu-west-2:123456789012:db:mysql-db']) + assert result['IdentityPoolId'] != '' + + +# testing a helper function +def test_get_random_identity_id(): + assert len(get_random_identity_id('us-west-2')) > 0 + assert len(get_random_identity_id('us-west-2').split(':')[1]) == 19 + + +@mock_cognitoidentity +def test_get_id(): + # These two do NOT work in server mode. They just don't return the data from the model. + conn = boto3.client('cognito-identity', 'us-west-2') + result = conn.get_id(AccountId='someaccount', + IdentityPoolId='us-west-2:12345', + Logins={ + 'someurl': '12345' + }) + print(result) + assert result.get('IdentityId', "").startswith('us-west-2') or result.get('ResponseMetadata').get('HTTPStatusCode') == 200 + + +@mock_cognitoidentity +def test_get_credentials_for_identity(): + # These two do NOT work in server mode. They just don't return the data from the model. + conn = boto3.client('cognito-identity', 'us-west-2') + result = conn.get_credentials_for_identity(IdentityId='12345') + + assert result.get('Expiration', 0) > 0 or result.get('ResponseMetadata').get('HTTPStatusCode') == 200 + assert result.get('IdentityId') == '12345' or result.get('ResponseMetadata').get('HTTPStatusCode') == 200 + + +@mock_cognitoidentity +def test_get_open_id_token_for_developer_identity(): + conn = boto3.client('cognito-identity', 'us-west-2') + result = conn.get_open_id_token_for_developer_identity( + IdentityPoolId='us-west-2:12345', + IdentityId='12345', + Logins={ + 'someurl': '12345' + }, + TokenDuration=123 + ) + assert len(result['Token']) > 0 + assert result['IdentityId'] == '12345' + +@mock_cognitoidentity +def test_get_open_id_token_for_developer_identity_when_no_explicit_identity_id(): + conn = boto3.client('cognito-identity', 'us-west-2') + result = conn.get_open_id_token_for_developer_identity( + IdentityPoolId='us-west-2:12345', + Logins={ + 'someurl': '12345' + }, + TokenDuration=123 + ) + assert len(result['Token']) > 0 + assert len(result['IdentityId']) > 0 + +@mock_cognitoidentity +def test_get_open_id_token(): + conn = boto3.client('cognito-identity', 'us-west-2') + result = conn.get_open_id_token( + IdentityId='12345', + Logins={ + 'someurl': '12345' + } + ) + assert len(result['Token']) > 0 + assert result['IdentityId'] == '12345' diff --git a/tests/test_cognitoidp/test_cognitoidp.py b/tests/test_cognitoidp/test_cognitoidp.py index 1483fcd0e..774ff7621 100644 --- a/tests/test_cognitoidp/test_cognitoidp.py +++ b/tests/test_cognitoidp/test_cognitoidp.py @@ -133,6 +133,22 @@ def test_create_user_pool_domain(): result["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) +@mock_cognitoidp +def test_create_user_pool_domain_custom_domain_config(): + conn = boto3.client("cognito-idp", "us-west-2") + + domain = str(uuid.uuid4()) + custom_domain_config = { + "CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/123456789012", + } + user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"] + result = conn.create_user_pool_domain( + UserPoolId=user_pool_id, Domain=domain, CustomDomainConfig=custom_domain_config + ) + result["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) + result["CloudFrontDomain"].should.equal("e2c343b3293ee505.cloudfront.net") + + @mock_cognitoidp def test_describe_user_pool_domain(): conn = boto3.client("cognito-idp", "us-west-2") @@ -162,6 +178,23 @@ def test_delete_user_pool_domain(): result["DomainDescription"].keys().should.have.length_of(0) +@mock_cognitoidp +def test_update_user_pool_domain(): + conn = boto3.client("cognito-idp", "us-west-2") + + domain = str(uuid.uuid4()) + custom_domain_config = { + "CertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/123456789012", + } + user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"] + conn.create_user_pool_domain(UserPoolId=user_pool_id, Domain=domain) + result = conn.update_user_pool_domain( + UserPoolId=user_pool_id, Domain=domain, CustomDomainConfig=custom_domain_config + ) + result["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) + result["CloudFrontDomain"].should.equal("e2c343b3293ee505.cloudfront.net") + + @mock_cognitoidp def test_create_user_pool_client(): conn = boto3.client("cognito-idp", "us-west-2") diff --git a/tests/test_config/test_config.py b/tests/test_config/test_config.py index 96c62455c..95e88cab1 100644 --- a/tests/test_config/test_config.py +++ b/tests/test_config/test_config.py @@ -123,6 +123,526 @@ def test_put_configuration_recorder(): assert "maximum number of configuration recorders: 1 is reached." in ce.exception.response['Error']['Message'] +@mock_config +def test_put_configuration_aggregator(): + client = boto3.client('config', region_name='us-west-2') + + # With too many aggregation sources: + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + '111111111111', + '222222222222' + ], + 'AwsRegions': [ + 'us-east-1', + 'us-west-2' + ] + }, + { + 'AccountIds': [ + '012345678910', + '111111111111', + '222222222222' + ], + 'AwsRegions': [ + 'us-east-1', + 'us-west-2' + ] + } + ] + ) + assert 'Member must have length less than or equal to 1' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # With an invalid region config (no regions defined): + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + '111111111111', + '222222222222' + ], + 'AllAwsRegions': False + } + ] + ) + assert 'Your request does not specify any regions' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidParameterValueException' + + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + OrganizationAggregationSource={ + 'RoleArn': 'arn:aws:iam::012345678910:role/SomeRole' + } + ) + assert 'Your request does not specify any regions' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidParameterValueException' + + # With both region flags defined: + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + '111111111111', + '222222222222' + ], + 'AwsRegions': [ + 'us-east-1', + 'us-west-2' + ], + 'AllAwsRegions': True + } + ] + ) + assert 'You must choose one of these options' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidParameterValueException' + + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + OrganizationAggregationSource={ + 'RoleArn': 'arn:aws:iam::012345678910:role/SomeRole', + 'AwsRegions': [ + 'us-east-1', + 'us-west-2' + ], + 'AllAwsRegions': True + } + ) + assert 'You must choose one of these options' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidParameterValueException' + + # Name too long: + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='a' * 257, + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': True + } + ] + ) + assert 'configurationAggregatorName' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # Too many tags (>50): + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': True + } + ], + Tags=[{'Key': '{}'.format(x), 'Value': '{}'.format(x)} for x in range(0, 51)] + ) + assert 'Member must have length less than or equal to 50' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # Tag key is too big (>128 chars): + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': True + } + ], + Tags=[{'Key': 'a' * 129, 'Value': 'a'}] + ) + assert 'Member must have length less than or equal to 128' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # Tag value is too big (>256 chars): + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': True + } + ], + Tags=[{'Key': 'tag', 'Value': 'a' * 257}] + ) + assert 'Member must have length less than or equal to 256' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # Duplicate Tags: + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': True + } + ], + Tags=[{'Key': 'a', 'Value': 'a'}, {'Key': 'a', 'Value': 'a'}] + ) + assert 'Duplicate tag keys found.' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidInput' + + # Invalid characters in the tag key: + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': True + } + ], + Tags=[{'Key': '!', 'Value': 'a'}] + ) + assert 'Member must satisfy regular expression pattern:' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # If it contains both the AccountAggregationSources and the OrganizationAggregationSource + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': False + } + ], + OrganizationAggregationSource={ + 'RoleArn': 'arn:aws:iam::012345678910:role/SomeRole', + 'AllAwsRegions': False + } + ) + assert 'AccountAggregationSource and the OrganizationAggregationSource' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidParameterValueException' + + # If it contains neither: + with assert_raises(ClientError) as ce: + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + ) + assert 'AccountAggregationSource or the OrganizationAggregationSource' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidParameterValueException' + + # Just make one: + account_aggregation_source = { + 'AccountIds': [ + '012345678910', + '111111111111', + '222222222222' + ], + 'AwsRegions': [ + 'us-east-1', + 'us-west-2' + ], + 'AllAwsRegions': False + } + + result = client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[account_aggregation_source], + ) + assert result['ConfigurationAggregator']['ConfigurationAggregatorName'] == 'testing' + assert result['ConfigurationAggregator']['AccountAggregationSources'] == [account_aggregation_source] + assert 'arn:aws:config:us-west-2:123456789012:config-aggregator/config-aggregator-' in \ + result['ConfigurationAggregator']['ConfigurationAggregatorArn'] + assert result['ConfigurationAggregator']['CreationTime'] == result['ConfigurationAggregator']['LastUpdatedTime'] + + # Update the existing one: + original_arn = result['ConfigurationAggregator']['ConfigurationAggregatorArn'] + account_aggregation_source.pop('AwsRegions') + account_aggregation_source['AllAwsRegions'] = True + result = client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[account_aggregation_source] + ) + + assert result['ConfigurationAggregator']['ConfigurationAggregatorName'] == 'testing' + assert result['ConfigurationAggregator']['AccountAggregationSources'] == [account_aggregation_source] + assert result['ConfigurationAggregator']['ConfigurationAggregatorArn'] == original_arn + + # Make an org one: + result = client.put_configuration_aggregator( + ConfigurationAggregatorName='testingOrg', + OrganizationAggregationSource={ + 'RoleArn': 'arn:aws:iam::012345678910:role/SomeRole', + 'AwsRegions': ['us-east-1', 'us-west-2'] + } + ) + + assert result['ConfigurationAggregator']['ConfigurationAggregatorName'] == 'testingOrg' + assert result['ConfigurationAggregator']['OrganizationAggregationSource'] == { + 'RoleArn': 'arn:aws:iam::012345678910:role/SomeRole', + 'AwsRegions': [ + 'us-east-1', + 'us-west-2' + ], + 'AllAwsRegions': False + } + + +@mock_config +def test_describe_configuration_aggregators(): + client = boto3.client('config', region_name='us-west-2') + + # Without any config aggregators: + assert not client.describe_configuration_aggregators()['ConfigurationAggregators'] + + # Make 10 config aggregators: + for x in range(0, 10): + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing{}'.format(x), + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': True + } + ] + ) + + # Describe with an incorrect name: + with assert_raises(ClientError) as ce: + client.describe_configuration_aggregators(ConfigurationAggregatorNames=['DoesNotExist']) + assert 'The configuration aggregator does not exist.' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationAggregatorException' + + # Error describe with more than 1 item in the list: + with assert_raises(ClientError) as ce: + client.describe_configuration_aggregators(ConfigurationAggregatorNames=['testing0', 'DoesNotExist']) + assert 'At least one of the configuration aggregators does not exist.' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationAggregatorException' + + # Get the normal list: + result = client.describe_configuration_aggregators() + assert not result.get('NextToken') + assert len(result['ConfigurationAggregators']) == 10 + + # Test filtered list: + agg_names = ['testing0', 'testing1', 'testing2'] + result = client.describe_configuration_aggregators(ConfigurationAggregatorNames=agg_names) + assert not result.get('NextToken') + assert len(result['ConfigurationAggregators']) == 3 + assert [agg['ConfigurationAggregatorName'] for agg in result['ConfigurationAggregators']] == agg_names + + # Test Pagination: + result = client.describe_configuration_aggregators(Limit=4) + assert len(result['ConfigurationAggregators']) == 4 + assert result['NextToken'] == 'testing4' + assert [agg['ConfigurationAggregatorName'] for agg in result['ConfigurationAggregators']] == \ + ['testing{}'.format(x) for x in range(0, 4)] + result = client.describe_configuration_aggregators(Limit=4, NextToken='testing4') + assert len(result['ConfigurationAggregators']) == 4 + assert result['NextToken'] == 'testing8' + assert [agg['ConfigurationAggregatorName'] for agg in result['ConfigurationAggregators']] == \ + ['testing{}'.format(x) for x in range(4, 8)] + result = client.describe_configuration_aggregators(Limit=4, NextToken='testing8') + assert len(result['ConfigurationAggregators']) == 2 + assert not result.get('NextToken') + assert [agg['ConfigurationAggregatorName'] for agg in result['ConfigurationAggregators']] == \ + ['testing{}'.format(x) for x in range(8, 10)] + + # Test Pagination with Filtering: + result = client.describe_configuration_aggregators(ConfigurationAggregatorNames=['testing2', 'testing4'], Limit=1) + assert len(result['ConfigurationAggregators']) == 1 + assert result['NextToken'] == 'testing4' + assert result['ConfigurationAggregators'][0]['ConfigurationAggregatorName'] == 'testing2' + result = client.describe_configuration_aggregators(ConfigurationAggregatorNames=['testing2', 'testing4'], Limit=1, NextToken='testing4') + assert not result.get('NextToken') + assert result['ConfigurationAggregators'][0]['ConfigurationAggregatorName'] == 'testing4' + + # Test with an invalid filter: + with assert_raises(ClientError) as ce: + client.describe_configuration_aggregators(NextToken='WRONG') + assert 'The nextToken provided is invalid' == ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidNextTokenException' + + +@mock_config +def test_put_aggregation_authorization(): + client = boto3.client('config', region_name='us-west-2') + + # Too many tags (>50): + with assert_raises(ClientError) as ce: + client.put_aggregation_authorization( + AuthorizedAccountId='012345678910', + AuthorizedAwsRegion='us-west-2', + Tags=[{'Key': '{}'.format(x), 'Value': '{}'.format(x)} for x in range(0, 51)] + ) + assert 'Member must have length less than or equal to 50' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # Tag key is too big (>128 chars): + with assert_raises(ClientError) as ce: + client.put_aggregation_authorization( + AuthorizedAccountId='012345678910', + AuthorizedAwsRegion='us-west-2', + Tags=[{'Key': 'a' * 129, 'Value': 'a'}] + ) + assert 'Member must have length less than or equal to 128' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # Tag value is too big (>256 chars): + with assert_raises(ClientError) as ce: + client.put_aggregation_authorization( + AuthorizedAccountId='012345678910', + AuthorizedAwsRegion='us-west-2', + Tags=[{'Key': 'tag', 'Value': 'a' * 257}] + ) + assert 'Member must have length less than or equal to 256' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # Duplicate Tags: + with assert_raises(ClientError) as ce: + client.put_aggregation_authorization( + AuthorizedAccountId='012345678910', + AuthorizedAwsRegion='us-west-2', + Tags=[{'Key': 'a', 'Value': 'a'}, {'Key': 'a', 'Value': 'a'}] + ) + assert 'Duplicate tag keys found.' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidInput' + + # Invalid characters in the tag key: + with assert_raises(ClientError) as ce: + client.put_aggregation_authorization( + AuthorizedAccountId='012345678910', + AuthorizedAwsRegion='us-west-2', + Tags=[{'Key': '!', 'Value': 'a'}] + ) + assert 'Member must satisfy regular expression pattern:' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'ValidationException' + + # Put a normal one there: + result = client.put_aggregation_authorization(AuthorizedAccountId='012345678910', AuthorizedAwsRegion='us-east-1', + Tags=[{'Key': 'tag', 'Value': 'a'}]) + + assert result['AggregationAuthorization']['AggregationAuthorizationArn'] == 'arn:aws:config:us-west-2:123456789012:' \ + 'aggregation-authorization/012345678910/us-east-1' + assert result['AggregationAuthorization']['AuthorizedAccountId'] == '012345678910' + assert result['AggregationAuthorization']['AuthorizedAwsRegion'] == 'us-east-1' + assert isinstance(result['AggregationAuthorization']['CreationTime'], datetime) + + creation_date = result['AggregationAuthorization']['CreationTime'] + + # And again: + result = client.put_aggregation_authorization(AuthorizedAccountId='012345678910', AuthorizedAwsRegion='us-east-1') + assert result['AggregationAuthorization']['AggregationAuthorizationArn'] == 'arn:aws:config:us-west-2:123456789012:' \ + 'aggregation-authorization/012345678910/us-east-1' + assert result['AggregationAuthorization']['AuthorizedAccountId'] == '012345678910' + assert result['AggregationAuthorization']['AuthorizedAwsRegion'] == 'us-east-1' + assert result['AggregationAuthorization']['CreationTime'] == creation_date + + +@mock_config +def test_describe_aggregation_authorizations(): + client = boto3.client('config', region_name='us-west-2') + + # With no aggregation authorizations: + assert not client.describe_aggregation_authorizations()['AggregationAuthorizations'] + + # Make 10 account authorizations: + for i in range(0, 10): + client.put_aggregation_authorization(AuthorizedAccountId='{}'.format(str(i) * 12), AuthorizedAwsRegion='us-west-2') + + result = client.describe_aggregation_authorizations() + assert len(result['AggregationAuthorizations']) == 10 + assert not result.get('NextToken') + for i in range(0, 10): + assert result['AggregationAuthorizations'][i]['AuthorizedAccountId'] == str(i) * 12 + + # Test Pagination: + result = client.describe_aggregation_authorizations(Limit=4) + assert len(result['AggregationAuthorizations']) == 4 + assert result['NextToken'] == ('4' * 12) + '/us-west-2' + assert [auth['AuthorizedAccountId'] for auth in result['AggregationAuthorizations']] == ['{}'.format(str(x) * 12) for x in range(0, 4)] + + result = client.describe_aggregation_authorizations(Limit=4, NextToken=('4' * 12) + '/us-west-2') + assert len(result['AggregationAuthorizations']) == 4 + assert result['NextToken'] == ('8' * 12) + '/us-west-2' + assert [auth['AuthorizedAccountId'] for auth in result['AggregationAuthorizations']] == ['{}'.format(str(x) * 12) for x in range(4, 8)] + + result = client.describe_aggregation_authorizations(Limit=4, NextToken=('8' * 12) + '/us-west-2') + assert len(result['AggregationAuthorizations']) == 2 + assert not result.get('NextToken') + assert [auth['AuthorizedAccountId'] for auth in result['AggregationAuthorizations']] == ['{}'.format(str(x) * 12) for x in range(8, 10)] + + # Test with an invalid filter: + with assert_raises(ClientError) as ce: + client.describe_aggregation_authorizations(NextToken='WRONG') + assert 'The nextToken provided is invalid' == ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'InvalidNextTokenException' + + +@mock_config +def test_delete_aggregation_authorization(): + client = boto3.client('config', region_name='us-west-2') + + client.put_aggregation_authorization(AuthorizedAccountId='012345678910', AuthorizedAwsRegion='us-west-2') + + # Delete it: + client.delete_aggregation_authorization(AuthorizedAccountId='012345678910', AuthorizedAwsRegion='us-west-2') + + # Verify that none are there: + assert not client.describe_aggregation_authorizations()['AggregationAuthorizations'] + + # Try it again -- nothing should happen: + client.delete_aggregation_authorization(AuthorizedAccountId='012345678910', AuthorizedAwsRegion='us-west-2') + + +@mock_config +def test_delete_configuration_aggregator(): + client = boto3.client('config', region_name='us-west-2') + client.put_configuration_aggregator( + ConfigurationAggregatorName='testing', + AccountAggregationSources=[ + { + 'AccountIds': [ + '012345678910', + ], + 'AllAwsRegions': True + } + ] + ) + + client.delete_configuration_aggregator(ConfigurationAggregatorName='testing') + + # And again to confirm that it's deleted: + with assert_raises(ClientError) as ce: + client.delete_configuration_aggregator(ConfigurationAggregatorName='testing') + assert 'The configuration aggregator does not exist.' in ce.exception.response['Error']['Message'] + assert ce.exception.response['Error']['Code'] == 'NoSuchConfigurationAggregatorException' + + @mock_config def test_describe_configurations(): client = boto3.client('config', region_name='us-west-2') diff --git a/tests/test_core/test_server.py b/tests/test_core/test_server.py index d1261a49a..ef04ae049 100644 --- a/tests/test_core/test_server.py +++ b/tests/test_core/test_server.py @@ -38,12 +38,6 @@ def test_domain_dispatched(): keys[0].should.equal('EmailResponse.dispatch') -def test_domain_without_matches(): - dispatcher = DomainDispatcherApplication(create_backend_app) - dispatcher.get_application.when.called_with( - {"HTTP_HOST": "not-matching-anything.com"}).should.throw(RuntimeError) - - def test_domain_dispatched_with_service(): # If we pass a particular service, always return that. dispatcher = DomainDispatcherApplication(create_backend_app, service="s3") diff --git a/tests/test_dynamodb2/test_dynamodb.py b/tests/test_dynamodb2/test_dynamodb.py index 77846de04..fb6c0e17d 100644 --- a/tests/test_dynamodb2/test_dynamodb.py +++ b/tests/test_dynamodb2/test_dynamodb.py @@ -452,6 +452,90 @@ def test_basic_projection_expressions(): assert 'body' in results['Items'][1] assert 'forum_name' in results['Items'][1] +@mock_dynamodb2 +def test_basic_projection_expressions_using_scan(): + dynamodb = boto3.resource('dynamodb', region_name='us-east-1') + + # Create the DynamoDB table. + table = dynamodb.create_table( + TableName='users', + KeySchema=[ + { + 'AttributeName': 'forum_name', + 'KeyType': 'HASH' + }, + { + 'AttributeName': 'subject', + 'KeyType': 'RANGE' + }, + ], + AttributeDefinitions=[ + { + 'AttributeName': 'forum_name', + 'AttributeType': 'S' + }, + { + 'AttributeName': 'subject', + 'AttributeType': 'S' + }, + ], + ProvisionedThroughput={ + 'ReadCapacityUnits': 5, + 'WriteCapacityUnits': 5 + } + ) + table = dynamodb.Table('users') + + table.put_item(Item={ + 'forum_name': 'the-key', + 'subject': '123', + 'body': 'some test message' + }) + + table.put_item(Item={ + 'forum_name': 'not-the-key', + 'subject': '123', + 'body': 'some other test message' + }) + # Test a scan returning all items + results = table.scan( + FilterExpression=Key('forum_name').eq( + 'the-key'), + ProjectionExpression='body, subject' + ) + + assert 'body' in results['Items'][0] + assert results['Items'][0]['body'] == 'some test message' + assert 'subject' in results['Items'][0] + + table.put_item(Item={ + 'forum_name': 'the-key', + 'subject': '1234', + 'body': 'yet another test message' + }) + + results = table.scan( + FilterExpression=Key('forum_name').eq( + 'the-key'), + ProjectionExpression='body' + ) + + assert 'body' in results['Items'][0] + assert 'subject' not in results['Items'][0] + assert 'forum_name' not in results['Items'][0] + assert 'body' in results['Items'][1] + assert 'subject' not in results['Items'][1] + assert 'forum_name' not in results['Items'][1] + + # The projection expression should not remove data from storage + results = table.query( + KeyConditionExpression=Key('forum_name').eq( + 'the-key'), + ) + assert 'subject' in results['Items'][0] + assert 'body' in results['Items'][1] + assert 'forum_name' in results['Items'][1] + @mock_dynamodb2 def test_basic_projection_expressions_with_attr_expression_names(): @@ -519,6 +603,84 @@ def test_basic_projection_expressions_with_attr_expression_names(): assert 'attachment' in results['Items'][0] assert results['Items'][0]['attachment'] == 'something' +@mock_dynamodb2 +def test_basic_projection_expressions_using_scan_with_attr_expression_names(): + dynamodb = boto3.resource('dynamodb', region_name='us-east-1') + + # Create the DynamoDB table. + table = dynamodb.create_table( + TableName='users', + KeySchema=[ + { + 'AttributeName': 'forum_name', + 'KeyType': 'HASH' + }, + { + 'AttributeName': 'subject', + 'KeyType': 'RANGE' + }, + ], + AttributeDefinitions=[ + { + 'AttributeName': 'forum_name', + 'AttributeType': 'S' + }, + { + 'AttributeName': 'subject', + 'AttributeType': 'S' + }, + ], + ProvisionedThroughput={ + 'ReadCapacityUnits': 5, + 'WriteCapacityUnits': 5 + } + ) + table = dynamodb.Table('users') + + table.put_item(Item={ + 'forum_name': 'the-key', + 'subject': '123', + 'body': 'some test message', + 'attachment': 'something' + }) + + table.put_item(Item={ + 'forum_name': 'not-the-key', + 'subject': '123', + 'body': 'some other test message', + 'attachment': 'something' + }) + # Test a scan returning all items + + results = table.scan( + FilterExpression=Key('forum_name').eq( + 'the-key'), + ProjectionExpression='#rl, #rt, subject', + ExpressionAttributeNames={ + '#rl': 'body', + '#rt': 'attachment' + }, + ) + + assert 'body' in results['Items'][0] + assert 'attachment' in results['Items'][0] + assert 'subject' in results['Items'][0] + assert 'form_name' not in results['Items'][0] + + # Test without a FilterExpression + results = table.scan( + ProjectionExpression='#rl, #rt, subject', + ExpressionAttributeNames={ + '#rl': 'body', + '#rt': 'attachment' + }, + ) + + assert 'body' in results['Items'][0] + assert 'attachment' in results['Items'][0] + assert 'subject' in results['Items'][0] + assert 'form_name' not in results['Items'][0] + @mock_dynamodb2 def test_put_item_returns_consumed_capacity(): @@ -676,44 +838,47 @@ def test_filter_expression(): filter_expr.expr(row1).should.be(True) # NOT test 2 - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('NOT (Id = :v0)', {}, {':v0': {'N': 8}}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('NOT (Id = :v0)', {}, {':v0': {'N': '8'}}) filter_expr.expr(row1).should.be(False) # Id = 8 so should be false # AND test - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id > :v0 AND Subs < :v1', {}, {':v0': {'N': 5}, ':v1': {'N': 7}}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id > :v0 AND Subs < :v1', {}, {':v0': {'N': '5'}, ':v1': {'N': '7'}}) filter_expr.expr(row1).should.be(True) filter_expr.expr(row2).should.be(False) # OR test - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id = :v0 OR Id=:v1', {}, {':v0': {'N': 5}, ':v1': {'N': 8}}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id = :v0 OR Id=:v1', {}, {':v0': {'N': '5'}, ':v1': {'N': '8'}}) filter_expr.expr(row1).should.be(True) # BETWEEN test - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id BETWEEN :v0 AND :v1', {}, {':v0': {'N': 5}, ':v1': {'N': 10}}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id BETWEEN :v0 AND :v1', {}, {':v0': {'N': '5'}, ':v1': {'N': '10'}}) filter_expr.expr(row1).should.be(True) # PAREN test - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id = :v0 AND (Subs = :v0 OR Subs = :v1)', {}, {':v0': {'N': 8}, ':v1': {'N': 5}}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id = :v0 AND (Subs = :v0 OR Subs = :v1)', {}, {':v0': {'N': '8'}, ':v1': {'N': '5'}}) filter_expr.expr(row1).should.be(True) # IN test - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id IN :v0', {}, {':v0': {'NS': [7, 8, 9]}}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('Id IN (:v0, :v1, :v2)', {}, { + ':v0': {'N': '7'}, + ':v1': {'N': '8'}, + ':v2': {'N': '9'}}) filter_expr.expr(row1).should.be(True) # attribute function tests (with extra spaces) filter_expr = moto.dynamodb2.comparisons.get_filter_expression('attribute_exists(Id) AND attribute_not_exists (User)', {}, {}) filter_expr.expr(row1).should.be(True) - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('attribute_type(Id, N)', {}, {}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('attribute_type(Id, :v0)', {}, {':v0': {'S': 'N'}}) filter_expr.expr(row1).should.be(True) # beginswith function test - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('begins_with(Desc, Some)', {}, {}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('begins_with(Desc, :v0)', {}, {':v0': {'S': 'Some'}}) filter_expr.expr(row1).should.be(True) filter_expr.expr(row2).should.be(False) # contains function test - filter_expr = moto.dynamodb2.comparisons.get_filter_expression('contains(KV, test1)', {}, {}) + filter_expr = moto.dynamodb2.comparisons.get_filter_expression('contains(KV, :v0)', {}, {':v0': {'S': 'test1'}}) filter_expr.expr(row1).should.be(True) filter_expr.expr(row2).should.be(False) @@ -754,14 +919,26 @@ def test_query_filter(): TableName='test1', Item={ 'client': {'S': 'client1'}, - 'app': {'S': 'app1'} + 'app': {'S': 'app1'}, + 'nested': {'M': { + 'version': {'S': 'version1'}, + 'contents': {'L': [ + {'S': 'value1'}, {'S': 'value2'}, + ]}, + }}, } ) client.put_item( TableName='test1', Item={ 'client': {'S': 'client1'}, - 'app': {'S': 'app2'} + 'app': {'S': 'app2'}, + 'nested': {'M': { + 'version': {'S': 'version2'}, + 'contents': {'L': [ + {'S': 'value1'}, {'S': 'value2'}, + ]}, + }}, } ) @@ -783,6 +960,18 @@ def test_query_filter(): ) assert response['Count'] == 2 + response = table.query( + KeyConditionExpression=Key('client').eq('client1'), + FilterExpression=Attr('nested.version').contains('version') + ) + assert response['Count'] == 2 + + response = table.query( + KeyConditionExpression=Key('client').eq('client1'), + FilterExpression=Attr('nested.contents[0]').eq('value1') + ) + assert response['Count'] == 2 + @mock_dynamodb2 def test_scan_filter(): @@ -1061,7 +1250,7 @@ def test_delete_item(): with assert_raises(ClientError) as ex: table.delete_item(Key={'client': 'client1', 'app': 'app1'}, ReturnValues='ALL_NEW') - + # Test deletion and returning old value response = table.delete_item(Key={'client': 'client1', 'app': 'app1'}, ReturnValues='ALL_OLD') response['Attributes'].should.contain('client') @@ -1153,6 +1342,46 @@ def test_query_missing_expr_names(): resp['Items'][0]['client']['S'].should.equal('test2') +# https://github.com/spulec/moto/issues/2328 +@mock_dynamodb2 +def test_update_item_with_list(): + dynamodb = boto3.resource('dynamodb', region_name='us-east-1') + + # Create the DynamoDB table. + dynamodb.create_table( + TableName='Table', + KeySchema=[ + { + 'AttributeName': 'key', + 'KeyType': 'HASH' + } + ], + AttributeDefinitions=[ + { + 'AttributeName': 'key', + 'AttributeType': 'S' + }, + ], + ProvisionedThroughput={ + 'ReadCapacityUnits': 1, + 'WriteCapacityUnits': 1 + } + ) + table = dynamodb.Table('Table') + table.update_item( + Key={'key': 'the-key'}, + AttributeUpdates={ + 'list': {'Value': [1, 2], 'Action': 'PUT'} + } + ) + + resp = table.get_item(Key={'key': 'the-key'}) + resp['Item'].should.equal({ + 'key': 'the-key', + 'list': [1, 2] + }) + + # https://github.com/spulec/moto/issues/1342 @mock_dynamodb2 def test_update_item_on_map(): @@ -1364,7 +1593,7 @@ def test_put_return_attributes(): ReturnValues='NONE' ) assert 'Attributes' not in r - + r = dynamodb.put_item( TableName='moto-test', Item={'id': {'S': 'foo'}, 'col1': {'S': 'val2'}}, @@ -1381,7 +1610,7 @@ def test_put_return_attributes(): ex.exception.response['Error']['Code'].should.equal('ValidationException') ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400) ex.exception.response['Error']['Message'].should.equal('Return values set to invalid value') - + @mock_dynamodb2 def test_query_global_secondary_index_when_created_via_update_table_resource(): @@ -1489,7 +1718,7 @@ def test_dynamodb_streams_1(): 'StreamViewType': 'NEW_AND_OLD_IMAGES' } ) - + assert 'StreamSpecification' in resp['TableDescription'] assert resp['TableDescription']['StreamSpecification'] == { 'StreamEnabled': True, @@ -1497,11 +1726,11 @@ def test_dynamodb_streams_1(): } assert 'LatestStreamLabel' in resp['TableDescription'] assert 'LatestStreamArn' in resp['TableDescription'] - + resp = conn.delete_table(TableName='test-streams') assert 'StreamSpecification' in resp['TableDescription'] - + @mock_dynamodb2 def test_dynamodb_streams_2(): @@ -1532,11 +1761,10 @@ def test_dynamodb_streams_2(): assert 'LatestStreamLabel' in resp['TableDescription'] assert 'LatestStreamArn' in resp['TableDescription'] - + @mock_dynamodb2 def test_condition_expressions(): client = boto3.client('dynamodb', region_name='us-east-1') - dynamodb = boto3.resource('dynamodb', region_name='us-east-1') # Create the DynamoDB table. client.create_table( @@ -1589,6 +1817,57 @@ def test_condition_expressions(): } ) + client.put_item( + TableName='test1', + Item={ + 'client': {'S': 'client1'}, + 'app': {'S': 'app1'}, + 'match': {'S': 'match'}, + 'existing': {'S': 'existing'}, + }, + ConditionExpression='attribute_exists(#nonexistent) OR attribute_exists(#existing)', + ExpressionAttributeNames={ + '#nonexistent': 'nope', + '#existing': 'existing' + } + ) + + client.put_item( + TableName='test1', + Item={ + 'client': {'S': 'client1'}, + 'app': {'S': 'app1'}, + 'match': {'S': 'match'}, + 'existing': {'S': 'existing'}, + }, + ConditionExpression='#client BETWEEN :a AND :z', + ExpressionAttributeNames={ + '#client': 'client', + }, + ExpressionAttributeValues={ + ':a': {'S': 'a'}, + ':z': {'S': 'z'}, + } + ) + + client.put_item( + TableName='test1', + Item={ + 'client': {'S': 'client1'}, + 'app': {'S': 'app1'}, + 'match': {'S': 'match'}, + 'existing': {'S': 'existing'}, + }, + ConditionExpression='#client IN (:client1, :client2)', + ExpressionAttributeNames={ + '#client': 'client', + }, + ExpressionAttributeValues={ + ':client1': {'S': 'client1'}, + ':client2': {'S': 'client2'}, + } + ) + with assert_raises(client.exceptions.ConditionalCheckFailedException): client.put_item( TableName='test1', @@ -1641,6 +1920,119 @@ def test_condition_expressions(): } ) + # Make sure update_item honors ConditionExpression as well + client.update_item( + TableName='test1', + Key={ + 'client': {'S': 'client1'}, + 'app': {'S': 'app1'}, + }, + UpdateExpression='set #match=:match', + ConditionExpression='attribute_exists(#existing)', + ExpressionAttributeNames={ + '#existing': 'existing', + '#match': 'match', + }, + ExpressionAttributeValues={ + ':match': {'S': 'match'} + } + ) + + with assert_raises(client.exceptions.ConditionalCheckFailedException): + client.update_item( + TableName='test1', + Key={ + 'client': { 'S': 'client1'}, + 'app': { 'S': 'app1'}, + }, + UpdateExpression='set #match=:match', + ConditionExpression='attribute_not_exists(#existing)', + ExpressionAttributeValues={ + ':match': {'S': 'match'} + }, + ExpressionAttributeNames={ + '#existing': 'existing', + '#match': 'match', + }, + ) + + +@mock_dynamodb2 +def test_condition_expression__attr_doesnt_exist(): + client = boto3.client('dynamodb', region_name='us-east-1') + + client.create_table( + TableName='test', + KeySchema=[{'AttributeName': 'forum_name', 'KeyType': 'HASH'}], + AttributeDefinitions=[ + {'AttributeName': 'forum_name', 'AttributeType': 'S'}, + ], + ProvisionedThroughput={'ReadCapacityUnits': 1, 'WriteCapacityUnits': 1}, + ) + + client.put_item( + TableName='test', + Item={ + 'forum_name': {'S': 'foo'}, + 'ttl': {'N': 'bar'}, + } + ) + + + def update_if_attr_doesnt_exist(): + # Test nonexistent top-level attribute. + client.update_item( + TableName='test', + Key={ + 'forum_name': {'S': 'the-key'}, + 'subject': {'S': 'the-subject'}, + }, + UpdateExpression='set #new_state=:new_state, #ttl=:ttl', + ConditionExpression='attribute_not_exists(#new_state)', + ExpressionAttributeNames={'#new_state': 'foobar', '#ttl': 'ttl'}, + ExpressionAttributeValues={ + ':new_state': {'S': 'some-value'}, + ':ttl': {'N': '12345.67'}, + }, + ReturnValues='ALL_NEW', + ) + + update_if_attr_doesnt_exist() + + # Second time should fail + with assert_raises(client.exceptions.ConditionalCheckFailedException): + update_if_attr_doesnt_exist() + + +@mock_dynamodb2 +def test_condition_expression__or_order(): + client = boto3.client('dynamodb', region_name='us-east-1') + + client.create_table( + TableName='test', + KeySchema=[{'AttributeName': 'forum_name', 'KeyType': 'HASH'}], + AttributeDefinitions=[ + {'AttributeName': 'forum_name', 'AttributeType': 'S'}, + ], + ProvisionedThroughput={'ReadCapacityUnits': 1, 'WriteCapacityUnits': 1}, + ) + + # ensure that the RHS of the OR expression is not evaluated if the LHS + # returns true (as it would result an error) + client.update_item( + TableName='test', + Key={ + 'forum_name': {'S': 'the-key'}, + }, + UpdateExpression='set #ttl=:ttl', + ConditionExpression='attribute_not_exists(#ttl) OR #ttl <= :old_ttl', + ExpressionAttributeNames={'#ttl': 'ttl'}, + ExpressionAttributeValues={ + ':ttl': {'N': '6'}, + ':old_ttl': {'N': '5'}, + } + ) + @mock_dynamodb2 def test_query_gsi_with_range_key(): @@ -1749,3 +2141,55 @@ def test_scan_by_non_exists_index(): ex.exception.response['Error']['Message'].should.equal( 'The table does not have the specified index: non_exists_index' ) + + +@mock_dynamodb2 +def test_batch_items_returns_all(): + dynamodb = _create_user_table() + returned_items = dynamodb.batch_get_item(RequestItems={ + 'users': { + 'Keys': [{ + 'username': {'S': 'user0'} + }, { + 'username': {'S': 'user1'} + }, { + 'username': {'S': 'user2'} + }, { + 'username': {'S': 'user3'} + }], + 'ConsistentRead': True + } + })['Responses']['users'] + assert len(returned_items) == 3 + assert [item['username']['S'] for item in returned_items] == ['user1', 'user2', 'user3'] + + +@mock_dynamodb2 +def test_batch_items_should_throw_exception_for_duplicate_request(): + client = _create_user_table() + with assert_raises(ClientError) as ex: + client.batch_get_item(RequestItems={ + 'users': { + 'Keys': [{ + 'username': {'S': 'user0'} + }, { + 'username': {'S': 'user0'} + }], + 'ConsistentRead': True + }}) + ex.exception.response['Error']['Code'].should.equal('ValidationException') + ex.exception.response['Error']['Message'].should.equal('Provided list of item keys contains duplicates') + + +def _create_user_table(): + client = boto3.client('dynamodb', region_name='us-east-1') + client.create_table( + TableName='users', + KeySchema=[{'AttributeName': 'username', 'KeyType': 'HASH'}], + AttributeDefinitions=[{'AttributeName': 'username', 'AttributeType': 'S'}], + ProvisionedThroughput={'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5} + ) + client.put_item(TableName='users', Item={'username': {'S': 'user1'}, 'foo': {'S': 'bar'}}) + client.put_item(TableName='users', Item={'username': {'S': 'user2'}, 'foo': {'S': 'bar'}}) + client.put_item(TableName='users', Item={'username': {'S': 'user3'}, 'foo': {'S': 'bar'}}) + return client diff --git a/tests/test_ec2/test_amis.py b/tests/test_ec2/test_amis.py index fd7234511..feff4a16c 100644 --- a/tests/test_ec2/test_amis.py +++ b/tests/test_ec2/test_amis.py @@ -10,7 +10,7 @@ from nose.tools import assert_raises import sure # noqa from moto import mock_ec2_deprecated, mock_ec2 -from moto.ec2.models import AMIS +from moto.ec2.models import AMIS, OWNER_ID from tests.helpers import requires_boto_gte @@ -152,6 +152,29 @@ def test_ami_copy(): cm.exception.request_id.should_not.be.none +@mock_ec2 +def test_copy_image_changes_owner_id(): + conn = boto3.client('ec2', region_name='us-east-1') + + # this source AMI ID is from moto/ec2/resources/amis.json + source_ami_id = "ami-03cf127a" + + # confirm the source ami owner id is different from the default owner id. + # if they're ever the same it means this test is invalid. + check_resp = conn.describe_images(ImageIds=[source_ami_id]) + check_resp["Images"][0]["OwnerId"].should_not.equal(OWNER_ID) + + copy_resp = conn.copy_image( + SourceImageId=source_ami_id, + Name="new-image", + Description="a copy of an image", + SourceRegion="us-east-1") + + describe_resp = conn.describe_images(Owners=["self"]) + describe_resp["Images"][0]["OwnerId"].should.equal(OWNER_ID) + describe_resp["Images"][0]["ImageId"].should.equal(copy_resp["ImageId"]) + + @mock_ec2_deprecated def test_ami_tagging(): conn = boto.connect_vpc('the_key', 'the_secret') diff --git a/tests/test_ec2/test_elastic_block_store.py b/tests/test_ec2/test_elastic_block_store.py index ab5b31ba0..9dbaa5ea6 100644 --- a/tests/test_ec2/test_elastic_block_store.py +++ b/tests/test_ec2/test_elastic_block_store.py @@ -12,6 +12,7 @@ from freezegun import freeze_time import sure # noqa from moto import mock_ec2_deprecated, mock_ec2 +from moto.ec2.models import OWNER_ID @mock_ec2_deprecated @@ -395,7 +396,7 @@ def test_snapshot_filters(): ).should.equal({snapshot3.id}) snapshots_by_owner_id = conn.get_all_snapshots( - filters={'owner-id': '123456789012'}) + filters={'owner-id': OWNER_ID}) set([snap.id for snap in snapshots_by_owner_id] ).should.equal({snapshot1.id, snapshot2.id, snapshot3.id}) diff --git a/tests/test_ec2/test_elastic_network_interfaces.py b/tests/test_ec2/test_elastic_network_interfaces.py index 70e78ae12..05b45fda9 100644 --- a/tests/test_ec2/test_elastic_network_interfaces.py +++ b/tests/test_ec2/test_elastic_network_interfaces.py @@ -161,7 +161,7 @@ def test_elastic_network_interfaces_filtering(): subnet.id, groups=[security_group1.id, security_group2.id]) eni2 = conn.create_network_interface( subnet.id, groups=[security_group1.id]) - eni3 = conn.create_network_interface(subnet.id) + eni3 = conn.create_network_interface(subnet.id, description='test description') all_enis = conn.get_all_network_interfaces() all_enis.should.have.length_of(3) @@ -189,6 +189,12 @@ def test_elastic_network_interfaces_filtering(): enis_by_group.should.have.length_of(1) set([eni.id for eni in enis_by_group]).should.equal(set([eni1.id])) + # Filter by Description + enis_by_description = conn.get_all_network_interfaces( + filters={'description': eni3.description }) + enis_by_description.should.have.length_of(1) + enis_by_description[0].description.should.equal(eni3.description) + # Unsupported filter conn.get_all_network_interfaces.when.called_with( filters={'not-implemented-filter': 'foobar'}).should.throw(NotImplementedError) @@ -343,6 +349,106 @@ def test_elastic_network_interfaces_get_by_subnet_id(): enis.should.have.length_of(0) +@mock_ec2 +def test_elastic_network_interfaces_get_by_description(): + ec2 = boto3.resource('ec2', region_name='us-west-2') + ec2_client = boto3.client('ec2', region_name='us-west-2') + + vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16') + subnet = ec2.create_subnet( + VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a') + + eni1 = ec2.create_network_interface( + SubnetId=subnet.id, PrivateIpAddress='10.0.10.5', Description='test interface') + + # The status of the new interface should be 'available' + waiter = ec2_client.get_waiter('network_interface_available') + waiter.wait(NetworkInterfaceIds=[eni1.id]) + + filters = [{'Name': 'description', 'Values': [eni1.description]}] + enis = list(ec2.network_interfaces.filter(Filters=filters)) + enis.should.have.length_of(1) + + filters = [{'Name': 'description', 'Values': ['bad description']}] + enis = list(ec2.network_interfaces.filter(Filters=filters)) + enis.should.have.length_of(0) + + +@mock_ec2 +def test_elastic_network_interfaces_describe_network_interfaces_with_filter(): + ec2 = boto3.resource('ec2', region_name='us-west-2') + ec2_client = boto3.client('ec2', region_name='us-west-2') + + vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16') + subnet = ec2.create_subnet( + VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-2a') + + eni1 = ec2.create_network_interface( + SubnetId=subnet.id, PrivateIpAddress='10.0.10.5', Description='test interface') + + # The status of the new interface should be 'available' + waiter = ec2_client.get_waiter('network_interface_available') + waiter.wait(NetworkInterfaceIds=[eni1.id]) + + # Filter by network-interface-id + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'network-interface-id', 'Values': [eni1.id]}]) + response['NetworkInterfaces'].should.have.length_of(1) + response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id) + response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address) + response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description) + + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'network-interface-id', 'Values': ['bad-id']}]) + response['NetworkInterfaces'].should.have.length_of(0) + + # Filter by private-ip-address + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'private-ip-address', 'Values': [eni1.private_ip_address]}]) + response['NetworkInterfaces'].should.have.length_of(1) + response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id) + response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address) + response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description) + + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'private-ip-address', 'Values': ['11.11.11.11']}]) + response['NetworkInterfaces'].should.have.length_of(0) + + # Filter by sunet-id + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'subnet-id', 'Values': [eni1.subnet.id]}]) + response['NetworkInterfaces'].should.have.length_of(1) + response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id) + response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address) + response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description) + + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'subnet-id', 'Values': ['sn-bad-id']}]) + response['NetworkInterfaces'].should.have.length_of(0) + + # Filter by description + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'description', 'Values': [eni1.description]}]) + response['NetworkInterfaces'].should.have.length_of(1) + response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id) + response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address) + response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description) + + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'description', 'Values': ['bad description']}]) + response['NetworkInterfaces'].should.have.length_of(0) + + # Filter by multiple filters + response = ec2_client.describe_network_interfaces( + Filters=[{'Name': 'private-ip-address', 'Values': [eni1.private_ip_address]}, + {'Name': 'network-interface-id', 'Values': [eni1.id]}, + {'Name': 'subnet-id', 'Values': [eni1.subnet.id]}]) + response['NetworkInterfaces'].should.have.length_of(1) + response['NetworkInterfaces'][0]['NetworkInterfaceId'].should.equal(eni1.id) + response['NetworkInterfaces'][0]['PrivateIpAddress'].should.equal(eni1.private_ip_address) + response['NetworkInterfaces'][0]['Description'].should.equal(eni1.description) + + @mock_ec2_deprecated @mock_cloudformation_deprecated def test_elastic_network_interfaces_cloudformation(): diff --git a/tests/test_ec2/test_instances.py b/tests/test_ec2/test_instances.py index f14f85721..a83384709 100644 --- a/tests/test_ec2/test_instances.py +++ b/tests/test_ec2/test_instances.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals # Ensure 'assert_raises' context manager support for Python 2.6 +from botocore.exceptions import ClientError + import tests.backport_assert_raises from nose.tools import assert_raises @@ -679,8 +681,8 @@ def test_modify_instance_attribute_security_groups(): reservation = conn.run_instances('ami-1234abcd') instance = reservation.instances[0] - sg_id = 'sg-1234abcd' - sg_id2 = 'sg-abcd4321' + sg_id = conn.create_security_group('test security group', 'this is a test security group').id + sg_id2 = conn.create_security_group('test security group 2', 'this is a test security group 2').id with assert_raises(EC2ResponseError) as ex: instance.modify_attribute("groupSet", [sg_id, sg_id2], dry_run=True) @@ -1255,6 +1257,7 @@ def test_create_instance_ebs_optimized(): instance.load() instance.ebs_optimized.should.be(False) + @mock_ec2 def test_run_multiple_instances_in_same_command(): instance_count = 4 @@ -1269,3 +1272,37 @@ def test_run_multiple_instances_in_same_command(): instances = reservations[0]['Instances'] for i in range(0, instance_count): instances[i]['AmiLaunchIndex'].should.be(i) + + +@mock_ec2 +def test_describe_instance_attribute(): + client = boto3.client('ec2', region_name='us-east-1') + security_group_id = client.create_security_group( + GroupName='test security group', Description='this is a test security group')['GroupId'] + client.run_instances(ImageId='ami-1234abcd', + MinCount=1, + MaxCount=1, + SecurityGroupIds=[security_group_id]) + instance_id = client.describe_instances()['Reservations'][0]['Instances'][0]['InstanceId'] + + valid_instance_attributes = ['instanceType', 'kernel', 'ramdisk', 'userData', 'disableApiTermination', 'instanceInitiatedShutdownBehavior', 'rootDeviceName', 'blockDeviceMapping', 'productCodes', 'sourceDestCheck', 'groupSet', 'ebsOptimized', 'sriovNetSupport'] + + for valid_instance_attribute in valid_instance_attributes: + response = client.describe_instance_attribute(InstanceId=instance_id, Attribute=valid_instance_attribute) + if valid_instance_attribute == "groupSet": + response.should.have.key("Groups") + response["Groups"].should.have.length_of(1) + response["Groups"][0]["GroupId"].should.equal(security_group_id) + elif valid_instance_attribute == "userData": + response.should.have.key("UserData") + response["UserData"].should.be.empty + + invalid_instance_attributes = ['abc', 'Kernel', 'RamDisk', 'userdata', 'iNsTaNcEtYpE'] + + for invalid_instance_attribute in invalid_instance_attributes: + with assert_raises(ClientError) as ex: + client.describe_instance_attribute(InstanceId=instance_id, Attribute=invalid_instance_attribute) + ex.exception.response['Error']['Code'].should.equal('InvalidParameterValue') + ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400) + message = 'Value ({invalid_instance_attribute}) for parameter attribute is invalid. Unknown attribute.'.format(invalid_instance_attribute=invalid_instance_attribute) + ex.exception.response['Error']['Message'].should.equal(message) diff --git a/tests/test_ec2/test_network_acls.py b/tests/test_ec2/test_network_acls.py index d4c330f00..1c69624bf 100644 --- a/tests/test_ec2/test_network_acls.py +++ b/tests/test_ec2/test_network_acls.py @@ -30,12 +30,12 @@ def test_new_subnet_associates_with_default_network_acl(): conn = boto.connect_vpc('the_key', 'the secret') vpc = conn.get_all_vpcs()[0] - subnet = conn.create_subnet(vpc.id, "172.31.48.0/20") + subnet = conn.create_subnet(vpc.id, "172.31.112.0/20") all_network_acls = conn.get_all_network_acls() all_network_acls.should.have.length_of(1) acl = all_network_acls[0] - acl.associations.should.have.length_of(4) + acl.associations.should.have.length_of(7) [a.subnet_id for a in acl.associations].should.contain(subnet.id) diff --git a/tests/test_ec2/test_subnets.py b/tests/test_ec2/test_subnets.py index 38571b285..38c36f682 100644 --- a/tests/test_ec2/test_subnets.py +++ b/tests/test_ec2/test_subnets.py @@ -118,7 +118,7 @@ def test_boto3_non_default_subnet(): @mock_ec2 -def test_modify_subnet_attribute(): +def test_modify_subnet_attribute_public_ip_on_launch(): ec2 = boto3.resource('ec2', region_name='us-west-1') client = boto3.client('ec2', region_name='us-west-1') @@ -145,6 +145,34 @@ def test_modify_subnet_attribute(): subnet.map_public_ip_on_launch.should.be.ok +@mock_ec2 +def test_modify_subnet_attribute_assign_ipv6_address_on_creation(): + ec2 = boto3.resource('ec2', region_name='us-west-1') + client = boto3.client('ec2', region_name='us-west-1') + + # Get the default VPC + vpc = list(ec2.vpcs.all())[0] + + subnet = ec2.create_subnet( + VpcId=vpc.id, CidrBlock='172.31.112.0/20', AvailabilityZone='us-west-1a') + + # 'map_public_ip_on_launch' is set when calling 'DescribeSubnets' action + subnet.reload() + + # For non default subnet, attribute value should be 'False' + subnet.assign_ipv6_address_on_creation.shouldnt.be.ok + + client.modify_subnet_attribute( + SubnetId=subnet.id, AssignIpv6AddressOnCreation={'Value': False}) + subnet.reload() + subnet.assign_ipv6_address_on_creation.shouldnt.be.ok + + client.modify_subnet_attribute( + SubnetId=subnet.id, AssignIpv6AddressOnCreation={'Value': True}) + subnet.reload() + subnet.assign_ipv6_address_on_creation.should.be.ok + + @mock_ec2 def test_modify_subnet_attribute_validation(): ec2 = boto3.resource('ec2', region_name='us-west-1') @@ -291,6 +319,84 @@ def test_subnet_tags_through_cloudformation(): subnet.tags["blah"].should.equal("baz") +@mock_ec2 +def test_create_subnet_response_fields(): + ec2 = boto3.resource('ec2', region_name='us-west-1') + client = boto3.client('ec2', region_name='us-west-1') + + vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16') + subnet = client.create_subnet( + VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-1a')['Subnet'] + + subnet.should.have.key('AvailabilityZone') + subnet.should.have.key('AvailabilityZoneId') + subnet.should.have.key('AvailableIpAddressCount') + subnet.should.have.key('CidrBlock') + subnet.should.have.key('State') + subnet.should.have.key('SubnetId') + subnet.should.have.key('VpcId') + subnet.shouldnt.have.key('Tags') + subnet.should.have.key('DefaultForAz').which.should.equal(False) + subnet.should.have.key('MapPublicIpOnLaunch').which.should.equal(False) + subnet.should.have.key('OwnerId') + subnet.should.have.key('AssignIpv6AddressOnCreation').which.should.equal(False) + + subnet_arn = "arn:aws:ec2:{region}:{owner_id}:subnet/{subnet_id}".format(region=subnet['AvailabilityZone'][0:-1], + owner_id=subnet['OwnerId'], + subnet_id=subnet['SubnetId']) + subnet.should.have.key('SubnetArn').which.should.equal(subnet_arn) + subnet.should.have.key('Ipv6CidrBlockAssociationSet').which.should.equal([]) + + +@mock_ec2 +def test_describe_subnet_response_fields(): + ec2 = boto3.resource('ec2', region_name='us-west-1') + client = boto3.client('ec2', region_name='us-west-1') + + vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16') + subnet_object = ec2.create_subnet( + VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-1a') + + subnets = client.describe_subnets(SubnetIds=[subnet_object.id])['Subnets'] + subnets.should.have.length_of(1) + subnet = subnets[0] + + subnet.should.have.key('AvailabilityZone') + subnet.should.have.key('AvailabilityZoneId') + subnet.should.have.key('AvailableIpAddressCount') + subnet.should.have.key('CidrBlock') + subnet.should.have.key('State') + subnet.should.have.key('SubnetId') + subnet.should.have.key('VpcId') + subnet.shouldnt.have.key('Tags') + subnet.should.have.key('DefaultForAz').which.should.equal(False) + subnet.should.have.key('MapPublicIpOnLaunch').which.should.equal(False) + subnet.should.have.key('OwnerId') + subnet.should.have.key('AssignIpv6AddressOnCreation').which.should.equal(False) + + subnet_arn = "arn:aws:ec2:{region}:{owner_id}:subnet/{subnet_id}".format(region=subnet['AvailabilityZone'][0:-1], + owner_id=subnet['OwnerId'], + subnet_id=subnet['SubnetId']) + subnet.should.have.key('SubnetArn').which.should.equal(subnet_arn) + subnet.should.have.key('Ipv6CidrBlockAssociationSet').which.should.equal([]) + + +@mock_ec2 +def test_create_subnet_with_invalid_availability_zone(): + ec2 = boto3.resource('ec2', region_name='us-west-1') + client = boto3.client('ec2', region_name='us-west-1') + + vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16') + + subnet_availability_zone = 'asfasfas' + with assert_raises(ClientError) as ex: + subnet = client.create_subnet( + VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone=subnet_availability_zone) + assert str(ex.exception).startswith( + "An error occurred (InvalidParameterValue) when calling the CreateSubnet " + "operation: Value ({}) for parameter availabilityZone is invalid. Subnets can currently only be created in the following availability zones: ".format(subnet_availability_zone)) + + @mock_ec2 def test_create_subnet_with_invalid_cidr_range(): ec2 = boto3.resource('ec2', region_name='us-west-1') diff --git a/tests/test_ecr/test_ecr_boto3.py b/tests/test_ecr/test_ecr_boto3.py index 3ce48d87d..ec0e4e732 100644 --- a/tests/test_ecr/test_ecr_boto3.py +++ b/tests/test_ecr/test_ecr_boto3.py @@ -1,697 +1,1081 @@ -from __future__ import unicode_literals - -import hashlib -import json -from datetime import datetime -from random import random - -import re -import sure # noqa - -import boto3 -from botocore.exceptions import ClientError, ParamValidationError -from dateutil.tz import tzlocal - -from moto import mock_ecr - - -def _create_image_digest(contents=None): - if not contents: - contents = 'docker_image{0}'.format(int(random() * 10 ** 6)) - return "sha256:%s" % hashlib.sha256(contents.encode('utf-8')).hexdigest() - - -def _create_image_manifest(): - return { - "schemaVersion": 2, - "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "config": - { - "mediaType": "application/vnd.docker.container.image.v1+json", - "size": 7023, - "digest": _create_image_digest("config") - }, - "layers": [ - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 32654, - "digest": _create_image_digest("layer1") - }, - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 16724, - "digest": _create_image_digest("layer2") - }, - { - "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "size": 73109, - # randomize image digest - "digest": _create_image_digest() - } - ] - } - - -@mock_ecr -def test_create_repository(): - client = boto3.client('ecr', region_name='us-east-1') - response = client.create_repository( - repositoryName='test_ecr_repository' - ) - response['repository']['repositoryName'].should.equal('test_ecr_repository') - response['repository']['repositoryArn'].should.equal( - 'arn:aws:ecr:us-east-1:012345678910:repository/test_ecr_repository') - response['repository']['registryId'].should.equal('012345678910') - response['repository']['repositoryUri'].should.equal( - '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository') - # response['repository']['createdAt'].should.equal(0) - - -@mock_ecr -def test_describe_repositories(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository1' - ) - _ = client.create_repository( - repositoryName='test_repository0' - ) - response = client.describe_repositories() - len(response['repositories']).should.equal(2) - - respository_arns = ['arn:aws:ecr:us-east-1:012345678910:repository/test_repository1', - 'arn:aws:ecr:us-east-1:012345678910:repository/test_repository0'] - set([response['repositories'][0]['repositoryArn'], - response['repositories'][1]['repositoryArn']]).should.equal(set(respository_arns)) - - respository_uris = ['012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1', - '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository0'] - set([response['repositories'][0]['repositoryUri'], - response['repositories'][1]['repositoryUri']]).should.equal(set(respository_uris)) - - -@mock_ecr -def test_describe_repositories_1(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository1' - ) - _ = client.create_repository( - repositoryName='test_repository0' - ) - response = client.describe_repositories(registryId='012345678910') - len(response['repositories']).should.equal(2) - - respository_arns = ['arn:aws:ecr:us-east-1:012345678910:repository/test_repository1', - 'arn:aws:ecr:us-east-1:012345678910:repository/test_repository0'] - set([response['repositories'][0]['repositoryArn'], - response['repositories'][1]['repositoryArn']]).should.equal(set(respository_arns)) - - respository_uris = ['012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1', - '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository0'] - set([response['repositories'][0]['repositoryUri'], - response['repositories'][1]['repositoryUri']]).should.equal(set(respository_uris)) - - -@mock_ecr -def test_describe_repositories_2(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository1' - ) - _ = client.create_repository( - repositoryName='test_repository0' - ) - response = client.describe_repositories(registryId='109876543210') - len(response['repositories']).should.equal(0) - - -@mock_ecr -def test_describe_repositories_3(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository1' - ) - _ = client.create_repository( - repositoryName='test_repository0' - ) - response = client.describe_repositories(repositoryNames=['test_repository1']) - len(response['repositories']).should.equal(1) - respository_arn = 'arn:aws:ecr:us-east-1:012345678910:repository/test_repository1' - response['repositories'][0]['repositoryArn'].should.equal(respository_arn) - - respository_uri = '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1' - response['repositories'][0]['repositoryUri'].should.equal(respository_uri) - - -@mock_ecr -def test_describe_repositories_with_image(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='latest' - ) - - response = client.describe_repositories(repositoryNames=['test_repository']) - len(response['repositories']).should.equal(1) - - -@mock_ecr -def test_delete_repository(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - response = client.delete_repository(repositoryName='test_repository') - response['repository']['repositoryName'].should.equal('test_repository') - response['repository']['repositoryArn'].should.equal( - 'arn:aws:ecr:us-east-1:012345678910:repository/test_repository') - response['repository']['registryId'].should.equal('012345678910') - response['repository']['repositoryUri'].should.equal( - '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository') - # response['repository']['createdAt'].should.equal(0) - - response = client.describe_repositories() - len(response['repositories']).should.equal(0) - - -@mock_ecr -def test_put_image(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - response = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='latest' - ) - - response['image']['imageId']['imageTag'].should.equal('latest') - response['image']['imageId']['imageDigest'].should.contain("sha") - response['image']['repositoryName'].should.equal('test_repository') - response['image']['registryId'].should.equal('012345678910') - -@mock_ecr -def test_put_image_with_multiple_tags(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - manifest = _create_image_manifest() - response = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(manifest), - imageTag='v1' - ) - - response['image']['imageId']['imageTag'].should.equal('v1') - response['image']['imageId']['imageDigest'].should.contain("sha") - response['image']['repositoryName'].should.equal('test_repository') - response['image']['registryId'].should.equal('012345678910') - - response1 = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(manifest), - imageTag='latest' - ) - - response1['image']['imageId']['imageTag'].should.equal('latest') - response1['image']['imageId']['imageDigest'].should.contain("sha") - response1['image']['repositoryName'].should.equal('test_repository') - response1['image']['registryId'].should.equal('012345678910') - - response2 = client.describe_images(repositoryName='test_repository') - type(response2['imageDetails']).should.be(list) - len(response2['imageDetails']).should.be(1) - - response2['imageDetails'][0]['imageDigest'].should.contain("sha") - - response2['imageDetails'][0]['registryId'].should.equal("012345678910") - - response2['imageDetails'][0]['repositoryName'].should.equal("test_repository") - - len(response2['imageDetails'][0]['imageTags']).should.be(2) - response2['imageDetails'][0]['imageTags'].should.be.equal(['v1', 'latest']) - -@mock_ecr -def test_list_images(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository_1' - ) - - _ = client.create_repository( - repositoryName='test_repository_2' - ) - - _ = client.put_image( - repositoryName='test_repository_1', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='latest' - ) - - _ = client.put_image( - repositoryName='test_repository_1', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='v1' - ) - - _ = client.put_image( - repositoryName='test_repository_1', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='v2' - ) - - _ = client.put_image( - repositoryName='test_repository_2', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='oldest' - ) - - response = client.list_images(repositoryName='test_repository_1') - type(response['imageIds']).should.be(list) - len(response['imageIds']).should.be(3) - - image_tags = ['latest', 'v1', 'v2'] - set([response['imageIds'][0]['imageTag'], - response['imageIds'][1]['imageTag'], - response['imageIds'][2]['imageTag']]).should.equal(set(image_tags)) - - response = client.list_images(repositoryName='test_repository_2') - type(response['imageIds']).should.be(list) - len(response['imageIds']).should.be(1) - response['imageIds'][0]['imageTag'].should.equal('oldest') - - -@mock_ecr -def test_list_images_from_repository_that_doesnt_exist(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository_1' - ) - - # non existing repo - error_msg = re.compile( - r".*The repository with name 'repo-that-doesnt-exist' does not exist in the registry with id '123'.*", - re.MULTILINE) - client.list_images.when.called_with( - repositoryName='repo-that-doesnt-exist', - registryId='123', - ).should.throw(Exception, error_msg) - - # repo does not exist in specified registry - error_msg = re.compile( - r".*The repository with name 'test_repository_1' does not exist in the registry with id '222'.*", - re.MULTILINE) - client.list_images.when.called_with( - repositoryName='test_repository_1', - registryId='222', - ).should.throw(Exception, error_msg) - - -@mock_ecr -def test_describe_images(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()) - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='latest' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='v1' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='v2' - ) - - response = client.describe_images(repositoryName='test_repository') - type(response['imageDetails']).should.be(list) - len(response['imageDetails']).should.be(4) - - response['imageDetails'][0]['imageDigest'].should.contain("sha") - response['imageDetails'][1]['imageDigest'].should.contain("sha") - response['imageDetails'][2]['imageDigest'].should.contain("sha") - response['imageDetails'][3]['imageDigest'].should.contain("sha") - - response['imageDetails'][0]['registryId'].should.equal("012345678910") - response['imageDetails'][1]['registryId'].should.equal("012345678910") - response['imageDetails'][2]['registryId'].should.equal("012345678910") - response['imageDetails'][3]['registryId'].should.equal("012345678910") - - response['imageDetails'][0]['repositoryName'].should.equal("test_repository") - response['imageDetails'][1]['repositoryName'].should.equal("test_repository") - response['imageDetails'][2]['repositoryName'].should.equal("test_repository") - response['imageDetails'][3]['repositoryName'].should.equal("test_repository") - - response['imageDetails'][0].should_not.have.key('imageTags') - len(response['imageDetails'][1]['imageTags']).should.be(1) - len(response['imageDetails'][2]['imageTags']).should.be(1) - len(response['imageDetails'][3]['imageTags']).should.be(1) - - image_tags = ['latest', 'v1', 'v2'] - set([response['imageDetails'][1]['imageTags'][0], - response['imageDetails'][2]['imageTags'][0], - response['imageDetails'][3]['imageTags'][0]]).should.equal(set(image_tags)) - - response['imageDetails'][0]['imageSizeInBytes'].should.equal(52428800) - response['imageDetails'][1]['imageSizeInBytes'].should.equal(52428800) - response['imageDetails'][2]['imageSizeInBytes'].should.equal(52428800) - response['imageDetails'][3]['imageSizeInBytes'].should.equal(52428800) - - -@mock_ecr -def test_describe_images_by_tag(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - tag_map = {} - for tag in ['latest', 'v1', 'v2']: - put_response = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag=tag - ) - tag_map[tag] = put_response['image'] - - for tag, put_response in tag_map.items(): - response = client.describe_images(repositoryName='test_repository', imageIds=[{'imageTag': tag}]) - len(response['imageDetails']).should.be(1) - image_detail = response['imageDetails'][0] - image_detail['registryId'].should.equal("012345678910") - image_detail['repositoryName'].should.equal("test_repository") - image_detail['imageTags'].should.equal([put_response['imageId']['imageTag']]) - image_detail['imageDigest'].should.equal(put_response['imageId']['imageDigest']) - - -@mock_ecr -def test_describe_images_tags_should_not_contain_empty_tag1(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - manifest = _create_image_manifest() - client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(manifest) - ) - - tags = ['v1', 'v2', 'latest'] - for tag in tags: - client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(manifest), - imageTag=tag - ) - - response = client.describe_images(repositoryName='test_repository', imageIds=[{'imageTag': tag}]) - len(response['imageDetails']).should.be(1) - image_detail = response['imageDetails'][0] - len(image_detail['imageTags']).should.equal(3) - image_detail['imageTags'].should.be.equal(tags) - - -@mock_ecr -def test_describe_images_tags_should_not_contain_empty_tag2(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - manifest = _create_image_manifest() - tags = ['v1', 'v2'] - for tag in tags: - client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(manifest), - imageTag=tag - ) - - client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(manifest) - ) - - client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(manifest), - imageTag='latest' - ) - - response = client.describe_images(repositoryName='test_repository', imageIds=[{'imageTag': tag}]) - len(response['imageDetails']).should.be(1) - image_detail = response['imageDetails'][0] - len(image_detail['imageTags']).should.equal(3) - image_detail['imageTags'].should.be.equal(['v1', 'v2', 'latest']) - - -@mock_ecr -def test_describe_repository_that_doesnt_exist(): - client = boto3.client('ecr', region_name='us-east-1') - - error_msg = re.compile( - r".*The repository with name 'repo-that-doesnt-exist' does not exist in the registry with id '123'.*", - re.MULTILINE) - client.describe_repositories.when.called_with( - repositoryNames=['repo-that-doesnt-exist'], - registryId='123', - ).should.throw(ClientError, error_msg) - -@mock_ecr -def test_describe_image_that_doesnt_exist(): - client = boto3.client('ecr', region_name='us-east-1') - client.create_repository(repositoryName='test_repository') - - error_msg1 = re.compile( - r".*The image with imageId {imageDigest:'null', imageTag:'testtag'} does not exist within " - r"the repository with name 'test_repository' in the registry with id '123'.*", - re.MULTILINE) - - client.describe_images.when.called_with( - repositoryName='test_repository', imageIds=[{'imageTag': 'testtag'}], registryId='123', - ).should.throw(ClientError, error_msg1) - - error_msg2 = re.compile( - r".*The repository with name 'repo-that-doesnt-exist' does not exist in the registry with id '123'.*", - re.MULTILINE) - client.describe_images.when.called_with( - repositoryName='repo-that-doesnt-exist', imageIds=[{'imageTag': 'testtag'}], registryId='123', - ).should.throw(ClientError, error_msg2) - - -@mock_ecr -def test_delete_repository_that_doesnt_exist(): - client = boto3.client('ecr', region_name='us-east-1') - - error_msg = re.compile( - r".*The repository with name 'repo-that-doesnt-exist' does not exist in the registry with id '123'.*", - re.MULTILINE) - - client.delete_repository.when.called_with( - repositoryName='repo-that-doesnt-exist', - registryId='123').should.throw( - ClientError, error_msg) - - -@mock_ecr -def test_describe_images_by_digest(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - tags = ['latest', 'v1', 'v2'] - digest_map = {} - for tag in tags: - put_response = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag=tag - ) - digest_map[put_response['image']['imageId']['imageDigest']] = put_response['image'] - - for digest, put_response in digest_map.items(): - response = client.describe_images(repositoryName='test_repository', - imageIds=[{'imageDigest': digest}]) - len(response['imageDetails']).should.be(1) - image_detail = response['imageDetails'][0] - image_detail['registryId'].should.equal("012345678910") - image_detail['repositoryName'].should.equal("test_repository") - image_detail['imageTags'].should.equal([put_response['imageId']['imageTag']]) - image_detail['imageDigest'].should.equal(digest) - - -@mock_ecr -def test_get_authorization_token_assume_region(): - client = boto3.client('ecr', region_name='us-east-1') - auth_token_response = client.get_authorization_token() - - auth_token_response.should.contain('authorizationData') - auth_token_response.should.contain('ResponseMetadata') - auth_token_response['authorizationData'].should.equal([ - { - 'authorizationToken': 'QVdTOjAxMjM0NTY3ODkxMC1hdXRoLXRva2Vu', - 'proxyEndpoint': 'https://012345678910.dkr.ecr.us-east-1.amazonaws.com', - 'expiresAt': datetime(2015, 1, 1, tzinfo=tzlocal()) - }, - ]) - - -@mock_ecr -def test_get_authorization_token_explicit_regions(): - client = boto3.client('ecr', region_name='us-east-1') - auth_token_response = client.get_authorization_token(registryIds=['10987654321', '878787878787']) - - auth_token_response.should.contain('authorizationData') - auth_token_response.should.contain('ResponseMetadata') - auth_token_response['authorizationData'].should.equal([ - { - 'authorizationToken': 'QVdTOjEwOTg3NjU0MzIxLWF1dGgtdG9rZW4=', - 'proxyEndpoint': 'https://10987654321.dkr.ecr.us-east-1.amazonaws.com', - 'expiresAt': datetime(2015, 1, 1, tzinfo=tzlocal()), - }, - { - 'authorizationToken': 'QVdTOjg3ODc4Nzg3ODc4Ny1hdXRoLXRva2Vu', - 'proxyEndpoint': 'https://878787878787.dkr.ecr.us-east-1.amazonaws.com', - 'expiresAt': datetime(2015, 1, 1, tzinfo=tzlocal()) - - } - ]) - - -@mock_ecr -def test_batch_get_image(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='latest' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='v1' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='v2' - ) - - response = client.batch_get_image( - repositoryName='test_repository', - imageIds=[ - { - 'imageTag': 'v2' - }, - ], - ) - - type(response['images']).should.be(list) - len(response['images']).should.be(1) - - response['images'][0]['imageManifest'].should.contain("vnd.docker.distribution.manifest.v2+json") - response['images'][0]['registryId'].should.equal("012345678910") - response['images'][0]['repositoryName'].should.equal("test_repository") - - response['images'][0]['imageId']['imageTag'].should.equal("v2") - response['images'][0]['imageId']['imageDigest'].should.contain("sha") - - type(response['failures']).should.be(list) - len(response['failures']).should.be(0) - - -@mock_ecr -def test_batch_get_image_that_doesnt_exist(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='latest' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='v1' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='v2' - ) - - response = client.batch_get_image( - repositoryName='test_repository', - imageIds=[ - { - 'imageTag': 'v5' - }, - ], - ) - - type(response['images']).should.be(list) - len(response['images']).should.be(0) - - type(response['failures']).should.be(list) - len(response['failures']).should.be(1) - response['failures'][0]['failureReason'].should.equal("Requested image not found") - response['failures'][0]['failureCode'].should.equal("ImageNotFound") - response['failures'][0]['imageId']['imageTag'].should.equal("v5") - - -@mock_ecr -def test_batch_get_image_no_tags(): - client = boto3.client('ecr', region_name='us-east-1') - _ = client.create_repository( - repositoryName='test_repository' - ) - - _ = client.put_image( - repositoryName='test_repository', - imageManifest=json.dumps(_create_image_manifest()), - imageTag='latest' - ) - - error_msg = re.compile( - r".*Missing required parameter in input: \"imageIds\".*", - re.MULTILINE) - - client.batch_get_image.when.called_with( - repositoryName='test_repository').should.throw( - ParamValidationError, error_msg) +from __future__ import unicode_literals + +import hashlib +import json +from datetime import datetime +from freezegun import freeze_time +import os +from random import random + +import re +import sure # noqa + +import boto3 +from botocore.exceptions import ClientError, ParamValidationError +from dateutil.tz import tzlocal + +from moto import mock_ecr +from nose import SkipTest + + +def _create_image_digest(contents=None): + if not contents: + contents = 'docker_image{0}'.format(int(random() * 10 ** 6)) + return "sha256:%s" % hashlib.sha256(contents.encode('utf-8')).hexdigest() + + +def _create_image_manifest(): + return { + "schemaVersion": 2, + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "config": + { + "mediaType": "application/vnd.docker.container.image.v1+json", + "size": 7023, + "digest": _create_image_digest("config") + }, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 32654, + "digest": _create_image_digest("layer1") + }, + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 16724, + "digest": _create_image_digest("layer2") + }, + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 73109, + # randomize image digest + "digest": _create_image_digest() + } + ] + } + + +@mock_ecr +def test_create_repository(): + client = boto3.client('ecr', region_name='us-east-1') + response = client.create_repository( + repositoryName='test_ecr_repository' + ) + response['repository']['repositoryName'].should.equal('test_ecr_repository') + response['repository']['repositoryArn'].should.equal( + 'arn:aws:ecr:us-east-1:012345678910:repository/test_ecr_repository') + response['repository']['registryId'].should.equal('012345678910') + response['repository']['repositoryUri'].should.equal( + '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_ecr_repository') + # response['repository']['createdAt'].should.equal(0) + + +@mock_ecr +def test_describe_repositories(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository1' + ) + _ = client.create_repository( + repositoryName='test_repository0' + ) + response = client.describe_repositories() + len(response['repositories']).should.equal(2) + + respository_arns = ['arn:aws:ecr:us-east-1:012345678910:repository/test_repository1', + 'arn:aws:ecr:us-east-1:012345678910:repository/test_repository0'] + set([response['repositories'][0]['repositoryArn'], + response['repositories'][1]['repositoryArn']]).should.equal(set(respository_arns)) + + respository_uris = ['012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1', + '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository0'] + set([response['repositories'][0]['repositoryUri'], + response['repositories'][1]['repositoryUri']]).should.equal(set(respository_uris)) + + +@mock_ecr +def test_describe_repositories_1(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository1' + ) + _ = client.create_repository( + repositoryName='test_repository0' + ) + response = client.describe_repositories(registryId='012345678910') + len(response['repositories']).should.equal(2) + + respository_arns = ['arn:aws:ecr:us-east-1:012345678910:repository/test_repository1', + 'arn:aws:ecr:us-east-1:012345678910:repository/test_repository0'] + set([response['repositories'][0]['repositoryArn'], + response['repositories'][1]['repositoryArn']]).should.equal(set(respository_arns)) + + respository_uris = ['012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1', + '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository0'] + set([response['repositories'][0]['repositoryUri'], + response['repositories'][1]['repositoryUri']]).should.equal(set(respository_uris)) + + +@mock_ecr +def test_describe_repositories_2(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository1' + ) + _ = client.create_repository( + repositoryName='test_repository0' + ) + response = client.describe_repositories(registryId='109876543210') + len(response['repositories']).should.equal(0) + + +@mock_ecr +def test_describe_repositories_3(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository1' + ) + _ = client.create_repository( + repositoryName='test_repository0' + ) + response = client.describe_repositories(repositoryNames=['test_repository1']) + len(response['repositories']).should.equal(1) + respository_arn = 'arn:aws:ecr:us-east-1:012345678910:repository/test_repository1' + response['repositories'][0]['repositoryArn'].should.equal(respository_arn) + + respository_uri = '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1' + response['repositories'][0]['repositoryUri'].should.equal(respository_uri) + + +@mock_ecr +def test_describe_repositories_with_image(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + response = client.describe_repositories(repositoryNames=['test_repository']) + len(response['repositories']).should.equal(1) + + +@mock_ecr +def test_delete_repository(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + response = client.delete_repository(repositoryName='test_repository') + response['repository']['repositoryName'].should.equal('test_repository') + response['repository']['repositoryArn'].should.equal( + 'arn:aws:ecr:us-east-1:012345678910:repository/test_repository') + response['repository']['registryId'].should.equal('012345678910') + response['repository']['repositoryUri'].should.equal( + '012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository') + # response['repository']['createdAt'].should.equal(0) + + response = client.describe_repositories() + len(response['repositories']).should.equal(0) + + +@mock_ecr +def test_put_image(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + response = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + response['image']['imageId']['imageTag'].should.equal('latest') + response['image']['imageId']['imageDigest'].should.contain("sha") + response['image']['repositoryName'].should.equal('test_repository') + response['image']['registryId'].should.equal('012345678910') + + +@mock_ecr +def test_put_image_with_push_date(): + if os.environ.get('TEST_SERVER_MODE', 'false').lower() == 'true': + raise SkipTest('Cant manipulate time in server mode') + + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + with freeze_time('2018-08-28 00:00:00'): + image1_date = datetime.now() + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + with freeze_time('2019-05-31 00:00:00'): + image2_date = datetime.now() + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + describe_response = client.describe_images(repositoryName='test_repository') + + type(describe_response['imageDetails']).should.be(list) + len(describe_response['imageDetails']).should.be(2) + + set([describe_response['imageDetails'][0]['imagePushedAt'], + describe_response['imageDetails'][1]['imagePushedAt']]).should.equal(set([image1_date, image2_date])) + + +@mock_ecr +def test_put_image_with_multiple_tags(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + manifest = _create_image_manifest() + response = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag='v1' + ) + + response['image']['imageId']['imageTag'].should.equal('v1') + response['image']['imageId']['imageDigest'].should.contain("sha") + response['image']['repositoryName'].should.equal('test_repository') + response['image']['registryId'].should.equal('012345678910') + + response1 = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag='latest' + ) + + response1['image']['imageId']['imageTag'].should.equal('latest') + response1['image']['imageId']['imageDigest'].should.contain("sha") + response1['image']['repositoryName'].should.equal('test_repository') + response1['image']['registryId'].should.equal('012345678910') + + response2 = client.describe_images(repositoryName='test_repository') + type(response2['imageDetails']).should.be(list) + len(response2['imageDetails']).should.be(1) + + response2['imageDetails'][0]['imageDigest'].should.contain("sha") + + response2['imageDetails'][0]['registryId'].should.equal("012345678910") + + response2['imageDetails'][0]['repositoryName'].should.equal("test_repository") + + len(response2['imageDetails'][0]['imageTags']).should.be(2) + response2['imageDetails'][0]['imageTags'].should.be.equal(['v1', 'latest']) + + +@mock_ecr +def test_list_images(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository_1' + ) + + _ = client.create_repository( + repositoryName='test_repository_2' + ) + + _ = client.put_image( + repositoryName='test_repository_1', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + _ = client.put_image( + repositoryName='test_repository_1', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v1' + ) + + _ = client.put_image( + repositoryName='test_repository_1', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v2' + ) + + _ = client.put_image( + repositoryName='test_repository_2', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='oldest' + ) + + response = client.list_images(repositoryName='test_repository_1') + type(response['imageIds']).should.be(list) + len(response['imageIds']).should.be(3) + + image_tags = ['latest', 'v1', 'v2'] + set([response['imageIds'][0]['imageTag'], + response['imageIds'][1]['imageTag'], + response['imageIds'][2]['imageTag']]).should.equal(set(image_tags)) + + response = client.list_images(repositoryName='test_repository_2') + type(response['imageIds']).should.be(list) + len(response['imageIds']).should.be(1) + response['imageIds'][0]['imageTag'].should.equal('oldest') + + +@mock_ecr +def test_list_images_from_repository_that_doesnt_exist(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository_1' + ) + + # non existing repo + error_msg = re.compile( + r".*The repository with name 'repo-that-doesnt-exist' does not exist in the registry with id '123'.*", + re.MULTILINE) + client.list_images.when.called_with( + repositoryName='repo-that-doesnt-exist', + registryId='123', + ).should.throw(Exception, error_msg) + + # repo does not exist in specified registry + error_msg = re.compile( + r".*The repository with name 'test_repository_1' does not exist in the registry with id '222'.*", + re.MULTILINE) + client.list_images.when.called_with( + repositoryName='test_repository_1', + registryId='222', + ).should.throw(Exception, error_msg) + + +@mock_ecr +def test_describe_images(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()) + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v1' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v2' + ) + + response = client.describe_images(repositoryName='test_repository') + type(response['imageDetails']).should.be(list) + len(response['imageDetails']).should.be(4) + + response['imageDetails'][0]['imageDigest'].should.contain("sha") + response['imageDetails'][1]['imageDigest'].should.contain("sha") + response['imageDetails'][2]['imageDigest'].should.contain("sha") + response['imageDetails'][3]['imageDigest'].should.contain("sha") + + response['imageDetails'][0]['registryId'].should.equal("012345678910") + response['imageDetails'][1]['registryId'].should.equal("012345678910") + response['imageDetails'][2]['registryId'].should.equal("012345678910") + response['imageDetails'][3]['registryId'].should.equal("012345678910") + + response['imageDetails'][0]['repositoryName'].should.equal("test_repository") + response['imageDetails'][1]['repositoryName'].should.equal("test_repository") + response['imageDetails'][2]['repositoryName'].should.equal("test_repository") + response['imageDetails'][3]['repositoryName'].should.equal("test_repository") + + response['imageDetails'][0].should_not.have.key('imageTags') + len(response['imageDetails'][1]['imageTags']).should.be(1) + len(response['imageDetails'][2]['imageTags']).should.be(1) + len(response['imageDetails'][3]['imageTags']).should.be(1) + + image_tags = ['latest', 'v1', 'v2'] + set([response['imageDetails'][1]['imageTags'][0], + response['imageDetails'][2]['imageTags'][0], + response['imageDetails'][3]['imageTags'][0]]).should.equal(set(image_tags)) + + response['imageDetails'][0]['imageSizeInBytes'].should.equal(52428800) + response['imageDetails'][1]['imageSizeInBytes'].should.equal(52428800) + response['imageDetails'][2]['imageSizeInBytes'].should.equal(52428800) + response['imageDetails'][3]['imageSizeInBytes'].should.equal(52428800) + + +@mock_ecr +def test_describe_images_by_tag(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + tag_map = {} + for tag in ['latest', 'v1', 'v2']: + put_response = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag=tag + ) + tag_map[tag] = put_response['image'] + + for tag, put_response in tag_map.items(): + response = client.describe_images(repositoryName='test_repository', imageIds=[{'imageTag': tag}]) + len(response['imageDetails']).should.be(1) + image_detail = response['imageDetails'][0] + image_detail['registryId'].should.equal("012345678910") + image_detail['repositoryName'].should.equal("test_repository") + image_detail['imageTags'].should.equal([put_response['imageId']['imageTag']]) + image_detail['imageDigest'].should.equal(put_response['imageId']['imageDigest']) + + +@mock_ecr +def test_describe_images_tags_should_not_contain_empty_tag1(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + manifest = _create_image_manifest() + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest) + ) + + tags = ['v1', 'v2', 'latest'] + for tag in tags: + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag=tag + ) + + response = client.describe_images(repositoryName='test_repository', imageIds=[{'imageTag': tag}]) + len(response['imageDetails']).should.be(1) + image_detail = response['imageDetails'][0] + len(image_detail['imageTags']).should.equal(3) + image_detail['imageTags'].should.be.equal(tags) + + +@mock_ecr +def test_describe_images_tags_should_not_contain_empty_tag2(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + manifest = _create_image_manifest() + tags = ['v1', 'v2'] + for tag in tags: + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag=tag + ) + + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest) + ) + + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag='latest' + ) + + response = client.describe_images(repositoryName='test_repository', imageIds=[{'imageTag': tag}]) + len(response['imageDetails']).should.be(1) + image_detail = response['imageDetails'][0] + len(image_detail['imageTags']).should.equal(3) + image_detail['imageTags'].should.be.equal(['v1', 'v2', 'latest']) + + +@mock_ecr +def test_describe_repository_that_doesnt_exist(): + client = boto3.client('ecr', region_name='us-east-1') + + error_msg = re.compile( + r".*The repository with name 'repo-that-doesnt-exist' does not exist in the registry with id '123'.*", + re.MULTILINE) + client.describe_repositories.when.called_with( + repositoryNames=['repo-that-doesnt-exist'], + registryId='123', + ).should.throw(ClientError, error_msg) + +@mock_ecr +def test_describe_image_that_doesnt_exist(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository(repositoryName='test_repository') + + error_msg1 = re.compile( + r".*The image with imageId {imageDigest:'null', imageTag:'testtag'} does not exist within " + r"the repository with name 'test_repository' in the registry with id '123'.*", + re.MULTILINE) + + client.describe_images.when.called_with( + repositoryName='test_repository', imageIds=[{'imageTag': 'testtag'}], registryId='123', + ).should.throw(ClientError, error_msg1) + + error_msg2 = re.compile( + r".*The repository with name 'repo-that-doesnt-exist' does not exist in the registry with id '123'.*", + re.MULTILINE) + client.describe_images.when.called_with( + repositoryName='repo-that-doesnt-exist', imageIds=[{'imageTag': 'testtag'}], registryId='123', + ).should.throw(ClientError, error_msg2) + + +@mock_ecr +def test_delete_repository_that_doesnt_exist(): + client = boto3.client('ecr', region_name='us-east-1') + + error_msg = re.compile( + r".*The repository with name 'repo-that-doesnt-exist' does not exist in the registry with id '123'.*", + re.MULTILINE) + + client.delete_repository.when.called_with( + repositoryName='repo-that-doesnt-exist', + registryId='123').should.throw( + ClientError, error_msg) + + +@mock_ecr +def test_describe_images_by_digest(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + tags = ['latest', 'v1', 'v2'] + digest_map = {} + for tag in tags: + put_response = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag=tag + ) + digest_map[put_response['image']['imageId']['imageDigest']] = put_response['image'] + + for digest, put_response in digest_map.items(): + response = client.describe_images(repositoryName='test_repository', + imageIds=[{'imageDigest': digest}]) + len(response['imageDetails']).should.be(1) + image_detail = response['imageDetails'][0] + image_detail['registryId'].should.equal("012345678910") + image_detail['repositoryName'].should.equal("test_repository") + image_detail['imageTags'].should.equal([put_response['imageId']['imageTag']]) + image_detail['imageDigest'].should.equal(digest) + + +@mock_ecr +def test_get_authorization_token_assume_region(): + client = boto3.client('ecr', region_name='us-east-1') + auth_token_response = client.get_authorization_token() + + auth_token_response.should.contain('authorizationData') + auth_token_response.should.contain('ResponseMetadata') + auth_token_response['authorizationData'].should.equal([ + { + 'authorizationToken': 'QVdTOjAxMjM0NTY3ODkxMC1hdXRoLXRva2Vu', + 'proxyEndpoint': 'https://012345678910.dkr.ecr.us-east-1.amazonaws.com', + 'expiresAt': datetime(2015, 1, 1, tzinfo=tzlocal()) + }, + ]) + + +@mock_ecr +def test_get_authorization_token_explicit_regions(): + client = boto3.client('ecr', region_name='us-east-1') + auth_token_response = client.get_authorization_token(registryIds=['10987654321', '878787878787']) + + auth_token_response.should.contain('authorizationData') + auth_token_response.should.contain('ResponseMetadata') + auth_token_response['authorizationData'].should.equal([ + { + 'authorizationToken': 'QVdTOjEwOTg3NjU0MzIxLWF1dGgtdG9rZW4=', + 'proxyEndpoint': 'https://10987654321.dkr.ecr.us-east-1.amazonaws.com', + 'expiresAt': datetime(2015, 1, 1, tzinfo=tzlocal()), + }, + { + 'authorizationToken': 'QVdTOjg3ODc4Nzg3ODc4Ny1hdXRoLXRva2Vu', + 'proxyEndpoint': 'https://878787878787.dkr.ecr.us-east-1.amazonaws.com', + 'expiresAt': datetime(2015, 1, 1, tzinfo=tzlocal()) + + } + ]) + + +@mock_ecr +def test_batch_get_image(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v1' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v2' + ) + + response = client.batch_get_image( + repositoryName='test_repository', + imageIds=[ + { + 'imageTag': 'v2' + }, + ], + ) + + type(response['images']).should.be(list) + len(response['images']).should.be(1) + + response['images'][0]['imageManifest'].should.contain("vnd.docker.distribution.manifest.v2+json") + response['images'][0]['registryId'].should.equal("012345678910") + response['images'][0]['repositoryName'].should.equal("test_repository") + + response['images'][0]['imageId']['imageTag'].should.equal("v2") + response['images'][0]['imageId']['imageDigest'].should.contain("sha") + + type(response['failures']).should.be(list) + len(response['failures']).should.be(0) + + +@mock_ecr +def test_batch_get_image_that_doesnt_exist(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v1' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v2' + ) + + response = client.batch_get_image( + repositoryName='test_repository', + imageIds=[ + { + 'imageTag': 'v5' + }, + ], + ) + + type(response['images']).should.be(list) + len(response['images']).should.be(0) + + type(response['failures']).should.be(list) + len(response['failures']).should.be(1) + response['failures'][0]['failureReason'].should.equal("Requested image not found") + response['failures'][0]['failureCode'].should.equal("ImageNotFound") + response['failures'][0]['imageId']['imageTag'].should.equal("v5") + + +@mock_ecr +def test_batch_get_image_no_tags(): + client = boto3.client('ecr', region_name='us-east-1') + _ = client.create_repository( + repositoryName='test_repository' + ) + + _ = client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='latest' + ) + + error_msg = re.compile( + r".*Missing required parameter in input: \"imageIds\".*", + re.MULTILINE) + + client.batch_get_image.when.called_with( + repositoryName='test_repository').should.throw( + ParamValidationError, error_msg) + + +@mock_ecr +def test_batch_delete_image_by_tag(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository( + repositoryName='test_repository' + ) + + manifest = _create_image_manifest() + + tags = ['v1', 'v1.0', 'latest'] + for tag in tags: + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag=tag, + ) + + describe_response1 = client.describe_images(repositoryName='test_repository') + + batch_delete_response = client.batch_delete_image( + registryId='012345678910', + repositoryName='test_repository', + imageIds=[ + { + 'imageTag': 'latest' + }, + ], + ) + + describe_response2 = client.describe_images(repositoryName='test_repository') + + type(describe_response1['imageDetails'][0]['imageTags']).should.be(list) + len(describe_response1['imageDetails'][0]['imageTags']).should.be(3) + + type(describe_response2['imageDetails'][0]['imageTags']).should.be(list) + len(describe_response2['imageDetails'][0]['imageTags']).should.be(2) + + type(batch_delete_response['imageIds']).should.be(list) + len(batch_delete_response['imageIds']).should.be(1) + + batch_delete_response['imageIds'][0]['imageTag'].should.equal("latest") + + type(batch_delete_response['failures']).should.be(list) + len(batch_delete_response['failures']).should.be(0) + + +@mock_ecr +def test_batch_delete_image_delete_last_tag(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository( + repositoryName='test_repository' + ) + + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(_create_image_manifest()), + imageTag='v1', + ) + + describe_response1 = client.describe_images(repositoryName='test_repository') + + batch_delete_response = client.batch_delete_image( + registryId='012345678910', + repositoryName='test_repository', + imageIds=[ + { + 'imageTag': 'v1' + }, + ], + ) + + describe_response2 = client.describe_images(repositoryName='test_repository') + + type(describe_response1['imageDetails'][0]['imageTags']).should.be(list) + len(describe_response1['imageDetails'][0]['imageTags']).should.be(1) + + type(describe_response2['imageDetails']).should.be(list) + len(describe_response2['imageDetails']).should.be(0) + + type(batch_delete_response['imageIds']).should.be(list) + len(batch_delete_response['imageIds']).should.be(1) + + batch_delete_response['imageIds'][0]['imageTag'].should.equal("v1") + + type(batch_delete_response['failures']).should.be(list) + len(batch_delete_response['failures']).should.be(0) + + +@mock_ecr +def test_batch_delete_image_with_nonexistent_tag(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository( + repositoryName='test_repository' + ) + + manifest = _create_image_manifest() + + tags = ['v1', 'v1.0', 'latest'] + for tag in tags: + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag=tag, + ) + + describe_response = client.describe_images(repositoryName='test_repository') + + missing_tag = "missing-tag" + batch_delete_response = client.batch_delete_image( + registryId='012345678910', + repositoryName='test_repository', + imageIds=[ + { + 'imageTag': missing_tag + }, + ], + ) + + type(describe_response['imageDetails'][0]['imageTags']).should.be(list) + len(describe_response['imageDetails'][0]['imageTags']).should.be(3) + + type(batch_delete_response['imageIds']).should.be(list) + len(batch_delete_response['imageIds']).should.be(0) + + batch_delete_response['failures'][0]['imageId']['imageTag'].should.equal(missing_tag) + batch_delete_response['failures'][0]['failureCode'].should.equal("ImageNotFound") + batch_delete_response['failures'][0]['failureReason'].should.equal("Requested image not found") + + type(batch_delete_response['failures']).should.be(list) + len(batch_delete_response['failures']).should.be(1) + + +@mock_ecr +def test_batch_delete_image_by_digest(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository( + repositoryName='test_repository' + ) + + manifest = _create_image_manifest() + + tags = ['v1', 'v2', 'latest'] + for tag in tags: + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag=tag + ) + + describe_response = client.describe_images(repositoryName='test_repository') + image_digest = describe_response['imageDetails'][0]['imageDigest'] + + batch_delete_response = client.batch_delete_image( + registryId='012345678910', + repositoryName='test_repository', + imageIds=[ + { + 'imageDigest': image_digest + }, + ], + ) + + describe_response = client.describe_images(repositoryName='test_repository') + + type(describe_response['imageDetails']).should.be(list) + len(describe_response['imageDetails']).should.be(0) + + type(batch_delete_response['imageIds']).should.be(list) + len(batch_delete_response['imageIds']).should.be(3) + + batch_delete_response['imageIds'][0]['imageDigest'].should.equal(image_digest) + batch_delete_response['imageIds'][1]['imageDigest'].should.equal(image_digest) + batch_delete_response['imageIds'][2]['imageDigest'].should.equal(image_digest) + + set([ + batch_delete_response['imageIds'][0]['imageTag'], + batch_delete_response['imageIds'][1]['imageTag'], + batch_delete_response['imageIds'][2]['imageTag']]).should.equal(set(tags)) + + type(batch_delete_response['failures']).should.be(list) + len(batch_delete_response['failures']).should.be(0) + + +@mock_ecr +def test_batch_delete_image_with_invalid_digest(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository( + repositoryName='test_repository' + ) + + manifest = _create_image_manifest() + + tags = ['v1', 'v2', 'latest'] + for tag in tags: + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag=tag + ) + + invalid_image_digest = 'sha256:invalid-digest' + + batch_delete_response = client.batch_delete_image( + registryId='012345678910', + repositoryName='test_repository', + imageIds=[ + { + 'imageDigest': invalid_image_digest + }, + ], + ) + + type(batch_delete_response['imageIds']).should.be(list) + len(batch_delete_response['imageIds']).should.be(0) + + type(batch_delete_response['failures']).should.be(list) + len(batch_delete_response['failures']).should.be(1) + + batch_delete_response['failures'][0]['imageId']['imageDigest'].should.equal(invalid_image_digest) + batch_delete_response['failures'][0]['failureCode'].should.equal("InvalidImageDigest") + batch_delete_response['failures'][0]['failureReason'].should.equal("Invalid request parameters: image digest should satisfy the regex '[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+'") + + +@mock_ecr +def test_batch_delete_image_with_missing_parameters(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository( + repositoryName='test_repository' + ) + + batch_delete_response = client.batch_delete_image( + registryId='012345678910', + repositoryName='test_repository', + imageIds=[ + { + }, + ], + ) + + type(batch_delete_response['imageIds']).should.be(list) + len(batch_delete_response['imageIds']).should.be(0) + + type(batch_delete_response['failures']).should.be(list) + len(batch_delete_response['failures']).should.be(1) + + batch_delete_response['failures'][0]['failureCode'].should.equal("MissingDigestAndTag") + batch_delete_response['failures'][0]['failureReason'].should.equal("Invalid request parameters: both tag and digest cannot be null") + + +@mock_ecr +def test_batch_delete_image_with_matching_digest_and_tag(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository( + repositoryName='test_repository' + ) + + manifest = _create_image_manifest() + + tags = ['v1', 'v1.0', 'latest'] + for tag in tags: + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag=tag + ) + + describe_response = client.describe_images(repositoryName='test_repository') + image_digest = describe_response['imageDetails'][0]['imageDigest'] + + batch_delete_response = client.batch_delete_image( + registryId='012345678910', + repositoryName='test_repository', + imageIds=[ + { + 'imageDigest': image_digest, + 'imageTag': 'v1' + }, + ], + ) + + describe_response = client.describe_images(repositoryName='test_repository') + + type(describe_response['imageDetails']).should.be(list) + len(describe_response['imageDetails']).should.be(0) + + type(batch_delete_response['imageIds']).should.be(list) + len(batch_delete_response['imageIds']).should.be(3) + + batch_delete_response['imageIds'][0]['imageDigest'].should.equal(image_digest) + batch_delete_response['imageIds'][1]['imageDigest'].should.equal(image_digest) + batch_delete_response['imageIds'][2]['imageDigest'].should.equal(image_digest) + + set([ + batch_delete_response['imageIds'][0]['imageTag'], + batch_delete_response['imageIds'][1]['imageTag'], + batch_delete_response['imageIds'][2]['imageTag']]).should.equal(set(tags)) + + type(batch_delete_response['failures']).should.be(list) + len(batch_delete_response['failures']).should.be(0) + + +@mock_ecr +def test_batch_delete_image_with_mismatched_digest_and_tag(): + client = boto3.client('ecr', region_name='us-east-1') + client.create_repository( + repositoryName='test_repository' + ) + + manifest = _create_image_manifest() + + tags = ['v1', 'latest'] + for tag in tags: + client.put_image( + repositoryName='test_repository', + imageManifest=json.dumps(manifest), + imageTag=tag + ) + + describe_response = client.describe_images(repositoryName='test_repository') + image_digest = describe_response['imageDetails'][0]['imageDigest'] + + batch_delete_response = client.batch_delete_image( + registryId='012345678910', + repositoryName='test_repository', + imageIds=[ + { + 'imageDigest': image_digest, + 'imageTag': 'v2' + }, + ], + ) + + type(batch_delete_response['imageIds']).should.be(list) + len(batch_delete_response['imageIds']).should.be(0) + + type(batch_delete_response['failures']).should.be(list) + len(batch_delete_response['failures']).should.be(1) + + batch_delete_response['failures'][0]['imageId']['imageDigest'].should.equal(image_digest) + batch_delete_response['failures'][0]['imageId']['imageTag'].should.equal("v2") + batch_delete_response['failures'][0]['failureCode'].should.equal("ImageNotFound") + batch_delete_response['failures'][0]['failureReason'].should.equal("Requested image not found") diff --git a/tests/test_ecs/test_ecs_boto3.py b/tests/test_ecs/test_ecs_boto3.py index b147c4159..9937af26b 100644 --- a/tests/test_ecs/test_ecs_boto3.py +++ b/tests/test_ecs/test_ecs_boto3.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals +from datetime import datetime from copy import deepcopy @@ -94,6 +95,10 @@ def test_register_task_definition(): }], 'logConfiguration': {'logDriver': 'json-file'} } + ], + tags=[ + {'key': 'createdBy', 'value': 'moto-unittest'}, + {'key': 'foo', 'value': 'bar'}, ] ) type(response['taskDefinition']).should.be(dict) @@ -473,6 +478,8 @@ def test_describe_services(): response['services'][0]['deployments'][0]['pendingCount'].should.equal(2) response['services'][0]['deployments'][0]['runningCount'].should.equal(0) response['services'][0]['deployments'][0]['status'].should.equal('PRIMARY') + (datetime.now() - response['services'][0]['deployments'][0]["createdAt"].replace(tzinfo=None)).seconds.should.be.within(0, 10) + (datetime.now() - response['services'][0]['deployments'][0]["updatedAt"].replace(tzinfo=None)).seconds.should.be.within(0, 10) @mock_ecs @@ -2304,3 +2311,52 @@ def test_create_service_load_balancing(): response['service']['status'].should.equal('ACTIVE') response['service']['taskDefinition'].should.equal( 'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1') + + +@mock_ecs +def test_list_tags_for_resource(): + client = boto3.client('ecs', region_name='us-east-1') + response = client.register_task_definition( + family='test_ecs_task', + containerDefinitions=[ + { + 'name': 'hello_world', + 'image': 'docker/hello-world:latest', + 'cpu': 1024, + 'memory': 400, + 'essential': True, + 'environment': [{ + 'name': 'AWS_ACCESS_KEY_ID', + 'value': 'SOME_ACCESS_KEY' + }], + 'logConfiguration': {'logDriver': 'json-file'} + } + ], + tags=[ + {'key': 'createdBy', 'value': 'moto-unittest'}, + {'key': 'foo', 'value': 'bar'}, + ] + ) + type(response['taskDefinition']).should.be(dict) + response['taskDefinition']['revision'].should.equal(1) + response['taskDefinition']['taskDefinitionArn'].should.equal( + 'arn:aws:ecs:us-east-1:012345678910:task-definition/test_ecs_task:1') + + task_definition_arn = response['taskDefinition']['taskDefinitionArn'] + response = client.list_tags_for_resource(resourceArn=task_definition_arn) + + type(response['tags']).should.be(list) + response['tags'].should.equal([ + {'key': 'createdBy', 'value': 'moto-unittest'}, + {'key': 'foo', 'value': 'bar'}, + ]) + + +@mock_ecs +def test_list_tags_for_resource_unknown(): + client = boto3.client('ecs', region_name='us-east-1') + task_definition_arn = 'arn:aws:ecs:us-east-1:012345678910:task-definition/unknown:1' + try: + client.list_tags_for_resource(resourceArn=task_definition_arn) + except ClientError as err: + err.response['Error']['Code'].should.equal('ClientException') diff --git a/tests/test_elbv2/test_elbv2.py b/tests/test_elbv2/test_elbv2.py index 03273ad3a..36772c02e 100644 --- a/tests/test_elbv2/test_elbv2.py +++ b/tests/test_elbv2/test_elbv2.py @@ -667,6 +667,91 @@ def test_register_targets(): response.get('TargetHealthDescriptions').should.have.length_of(1) +@mock_ec2 +@mock_elbv2 +def test_stopped_instance_target(): + target_group_port = 8080 + + conn = boto3.client('elbv2', region_name='us-east-1') + ec2 = boto3.resource('ec2', region_name='us-east-1') + + security_group = ec2.create_security_group( + GroupName='a-security-group', Description='First One') + vpc = ec2.create_vpc(CidrBlock='172.28.7.0/24', InstanceTenancy='default') + subnet1 = ec2.create_subnet( + VpcId=vpc.id, + CidrBlock='172.28.7.192/26', + AvailabilityZone='us-east-1a') + subnet2 = ec2.create_subnet( + VpcId=vpc.id, + CidrBlock='172.28.7.0/26', + AvailabilityZone='us-east-1b') + + conn.create_load_balancer( + Name='my-lb', + Subnets=[subnet1.id, subnet2.id], + SecurityGroups=[security_group.id], + Scheme='internal', + Tags=[{'Key': 'key_name', 'Value': 'a_value'}]) + + response = conn.create_target_group( + Name='a-target', + Protocol='HTTP', + Port=target_group_port, + VpcId=vpc.id, + HealthCheckProtocol='HTTP', + HealthCheckPath='/', + HealthCheckIntervalSeconds=5, + HealthCheckTimeoutSeconds=5, + HealthyThresholdCount=5, + UnhealthyThresholdCount=2, + Matcher={'HttpCode': '200'}) + target_group = response.get('TargetGroups')[0] + + # No targets registered yet + response = conn.describe_target_health( + TargetGroupArn=target_group.get('TargetGroupArn')) + response.get('TargetHealthDescriptions').should.have.length_of(0) + + response = ec2.create_instances( + ImageId='ami-1234abcd', MinCount=1, MaxCount=1) + instance = response[0] + + target_dict = { + 'Id': instance.id, + 'Port': 500 + } + + response = conn.register_targets( + TargetGroupArn=target_group.get('TargetGroupArn'), + Targets=[target_dict]) + + response = conn.describe_target_health( + TargetGroupArn=target_group.get('TargetGroupArn')) + response.get('TargetHealthDescriptions').should.have.length_of(1) + target_health_description = response.get('TargetHealthDescriptions')[0] + + target_health_description['Target'].should.equal(target_dict) + target_health_description['HealthCheckPort'].should.equal(str(target_group_port)) + target_health_description['TargetHealth'].should.equal({ + 'State': 'healthy' + }) + + instance.stop() + + response = conn.describe_target_health( + TargetGroupArn=target_group.get('TargetGroupArn')) + response.get('TargetHealthDescriptions').should.have.length_of(1) + target_health_description = response.get('TargetHealthDescriptions')[0] + target_health_description['Target'].should.equal(target_dict) + target_health_description['HealthCheckPort'].should.equal(str(target_group_port)) + target_health_description['TargetHealth'].should.equal({ + 'State': 'unused', + 'Reason': 'Target.InvalidState', + 'Description': 'Target is in the stopped state' + }) + + @mock_ec2 @mock_elbv2 def test_target_group_attributes(): @@ -1726,3 +1811,132 @@ def test_redirect_action_listener_rule_cloudformation(): 'Port': '443', 'Protocol': 'HTTPS', 'StatusCode': 'HTTP_301', } },]) + + +@mock_elbv2 +@mock_ec2 +def test_cognito_action_listener_rule(): + conn = boto3.client('elbv2', region_name='us-east-1') + ec2 = boto3.resource('ec2', region_name='us-east-1') + + security_group = ec2.create_security_group( + GroupName='a-security-group', Description='First One') + vpc = ec2.create_vpc(CidrBlock='172.28.7.0/24', InstanceTenancy='default') + subnet1 = ec2.create_subnet( + VpcId=vpc.id, + CidrBlock='172.28.7.192/26', + AvailabilityZone='us-east-1a') + subnet2 = ec2.create_subnet( + VpcId=vpc.id, + CidrBlock='172.28.7.128/26', + AvailabilityZone='us-east-1b') + + response = conn.create_load_balancer( + Name='my-lb', + Subnets=[subnet1.id, subnet2.id], + SecurityGroups=[security_group.id], + Scheme='internal', + Tags=[{'Key': 'key_name', 'Value': 'a_value'}]) + load_balancer_arn = response.get('LoadBalancers')[0].get('LoadBalancerArn') + + action = { + 'Type': 'authenticate-cognito', + 'AuthenticateCognitoConfig': { + 'UserPoolArn': 'arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_ABCD1234', + 'UserPoolClientId': 'abcd1234abcd', + 'UserPoolDomain': 'testpool', + } + } + response = conn.create_listener(LoadBalancerArn=load_balancer_arn, + Protocol='HTTP', + Port=80, + DefaultActions=[action]) + + listener = response.get('Listeners')[0] + listener.get('DefaultActions')[0].should.equal(action) + listener_arn = listener.get('ListenerArn') + + describe_rules_response = conn.describe_rules(ListenerArn=listener_arn) + describe_rules_response['Rules'][0]['Actions'][0].should.equal(action) + + describe_listener_response = conn.describe_listeners(ListenerArns=[listener_arn, ]) + describe_listener_actions = describe_listener_response['Listeners'][0]['DefaultActions'][0] + describe_listener_actions.should.equal(action) + + +@mock_elbv2 +@mock_cloudformation +def test_cognito_action_listener_rule_cloudformation(): + cnf_conn = boto3.client('cloudformation', region_name='us-east-1') + elbv2_client = boto3.client('elbv2', region_name='us-east-1') + + template = { + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "ECS Cluster Test CloudFormation", + "Resources": { + "testVPC": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + }, + }, + "subnet1": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.0.0/24", + "VpcId": {"Ref": "testVPC"}, + "AvalabilityZone": "us-east-1b", + }, + }, + "subnet2": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "CidrBlock": "10.0.1.0/24", + "VpcId": {"Ref": "testVPC"}, + "AvalabilityZone": "us-east-1b", + }, + }, + "testLb": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "Name": "my-lb", + "Subnets": [{"Ref": "subnet1"}, {"Ref": "subnet2"}], + "Type": "application", + "SecurityGroups": [], + } + }, + "testListener": { + "Type": "AWS::ElasticLoadBalancingV2::Listener", + "Properties": { + "LoadBalancerArn": {"Ref": "testLb"}, + "Port": 80, + "Protocol": "HTTP", + "DefaultActions": [{ + "Type": "authenticate-cognito", + "AuthenticateCognitoConfig": { + 'UserPoolArn': 'arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_ABCD1234', + 'UserPoolClientId': 'abcd1234abcd', + 'UserPoolDomain': 'testpool', + } + }] + } + + } + } + } + template_json = json.dumps(template) + cnf_conn.create_stack(StackName="test-stack", TemplateBody=template_json) + + describe_load_balancers_response = elbv2_client.describe_load_balancers(Names=['my-lb',]) + load_balancer_arn = describe_load_balancers_response['LoadBalancers'][0]['LoadBalancerArn'] + describe_listeners_response = elbv2_client.describe_listeners(LoadBalancerArn=load_balancer_arn) + + describe_listeners_response['Listeners'].should.have.length_of(1) + describe_listeners_response['Listeners'][0]['DefaultActions'].should.equal([{ + 'Type': 'authenticate-cognito', + "AuthenticateCognitoConfig": { + 'UserPoolArn': 'arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_ABCD1234', + 'UserPoolClientId': 'abcd1234abcd', + 'UserPoolDomain': 'testpool', + } + },]) diff --git a/tests/test_glue/test_datacatalog.py b/tests/test_glue/test_datacatalog.py index e4891f307..9034feb55 100644 --- a/tests/test_glue/test_datacatalog.py +++ b/tests/test_glue/test_datacatalog.py @@ -229,6 +229,26 @@ def test_delete_table(): exc.exception.response['Error']['Code'].should.equal('EntityNotFoundException') exc.exception.response['Error']['Message'].should.match('Table myspecialtable not found') +@mock_glue +def test_batch_delete_table(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + helpers.create_database(client, database_name) + + table_name = 'myspecialtable' + table_input = helpers.create_table_input(database_name, table_name) + helpers.create_table(client, database_name, table_name, table_input) + + result = client.batch_delete_table(DatabaseName=database_name, TablesToDelete=[table_name]) + result['ResponseMetadata']['HTTPStatusCode'].should.equal(200) + + # confirm table is deleted + with assert_raises(ClientError) as exc: + helpers.get_table(client, database_name, table_name) + + exc.exception.response['Error']['Code'].should.equal('EntityNotFoundException') + exc.exception.response['Error']['Message'].should.match('Table myspecialtable not found') + @mock_glue def test_get_partitions_empty(): @@ -310,6 +330,72 @@ def test_get_partition_not_found(): exc.exception.response['Error']['Code'].should.equal('EntityNotFoundException') exc.exception.response['Error']['Message'].should.match('partition') +@mock_glue +def test_batch_create_partition(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + table_name = 'myfirsttable' + helpers.create_database(client, database_name) + + helpers.create_table(client, database_name, table_name) + + before = datetime.now(pytz.utc) + + partition_inputs = [] + for i in range(0, 20): + values = ["2018-10-{:2}".format(i)] + part_input = helpers.create_partition_input(database_name, table_name, values=values) + partition_inputs.append(part_input) + + client.batch_create_partition( + DatabaseName=database_name, + TableName=table_name, + PartitionInputList=partition_inputs + ) + + after = datetime.now(pytz.utc) + + response = client.get_partitions(DatabaseName=database_name, TableName=table_name) + + partitions = response['Partitions'] + + partitions.should.have.length_of(20) + + for idx, partition in enumerate(partitions): + partition_input = partition_inputs[idx] + + partition['TableName'].should.equal(table_name) + partition['StorageDescriptor'].should.equal(partition_input['StorageDescriptor']) + partition['Values'].should.equal(partition_input['Values']) + partition['CreationTime'].should.be.greater_than(before) + partition['CreationTime'].should.be.lower_than(after) + + +@mock_glue +def test_batch_create_partition_already_exist(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + table_name = 'myfirsttable' + values = ['2018-10-01'] + helpers.create_database(client, database_name) + + helpers.create_table(client, database_name, table_name) + + helpers.create_partition(client, database_name, table_name, values=values) + + partition_input = helpers.create_partition_input(database_name, table_name, values=values) + + response = client.batch_create_partition( + DatabaseName=database_name, + TableName=table_name, + PartitionInputList=[partition_input] + ) + + response.should.have.key('Errors') + response['Errors'].should.have.length_of(1) + response['Errors'][0]['PartitionValues'].should.equal(values) + response['Errors'][0]['ErrorDetail']['ErrorCode'].should.equal('AlreadyExistsException') + @mock_glue def test_get_partition(): @@ -333,6 +419,63 @@ def test_get_partition(): partition['Values'].should.equal(values[1]) +@mock_glue +def test_batch_get_partition(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + table_name = 'myfirsttable' + helpers.create_database(client, database_name) + + helpers.create_table(client, database_name, table_name) + + values = [['2018-10-01'], ['2018-09-01']] + + helpers.create_partition(client, database_name, table_name, values=values[0]) + helpers.create_partition(client, database_name, table_name, values=values[1]) + + partitions_to_get = [ + {'Values': values[0]}, + {'Values': values[1]}, + ] + response = client.batch_get_partition(DatabaseName=database_name, TableName=table_name, PartitionsToGet=partitions_to_get) + + partitions = response['Partitions'] + partitions.should.have.length_of(2) + + partition = partitions[1] + partition['TableName'].should.equal(table_name) + partition['Values'].should.equal(values[1]) + + +@mock_glue +def test_batch_get_partition_missing_partition(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + table_name = 'myfirsttable' + helpers.create_database(client, database_name) + + helpers.create_table(client, database_name, table_name) + + values = [['2018-10-01'], ['2018-09-01'], ['2018-08-01']] + + helpers.create_partition(client, database_name, table_name, values=values[0]) + helpers.create_partition(client, database_name, table_name, values=values[2]) + + partitions_to_get = [ + {'Values': values[0]}, + {'Values': values[1]}, + {'Values': values[2]}, + ] + response = client.batch_get_partition(DatabaseName=database_name, TableName=table_name, PartitionsToGet=partitions_to_get) + + partitions = response['Partitions'] + partitions.should.have.length_of(2) + + partitions[0]['Values'].should.equal(values[0]) + partitions[1]['Values'].should.equal(values[2]) + + + @mock_glue def test_update_partition_not_found_moving(): client = boto3.client('glue', region_name='us-east-1') @@ -445,3 +588,112 @@ def test_update_partition_move(): partition['TableName'].should.equal(table_name) partition['StorageDescriptor']['Columns'].should.equal([{'Name': 'country', 'Type': 'string'}]) + +@mock_glue +def test_delete_partition(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + table_name = 'myfirsttable' + values = ['2018-10-01'] + helpers.create_database(client, database_name) + helpers.create_table(client, database_name, table_name) + + part_input = helpers.create_partition_input(database_name, table_name, values=values) + helpers.create_partition(client, database_name, table_name, part_input) + + client.delete_partition( + DatabaseName=database_name, + TableName=table_name, + PartitionValues=values, + ) + + response = client.get_partitions(DatabaseName=database_name, TableName=table_name) + partitions = response['Partitions'] + partitions.should.be.empty + +@mock_glue +def test_delete_partition_bad_partition(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + table_name = 'myfirsttable' + values = ['2018-10-01'] + helpers.create_database(client, database_name) + helpers.create_table(client, database_name, table_name) + + with assert_raises(ClientError) as exc: + client.delete_partition( + DatabaseName=database_name, + TableName=table_name, + PartitionValues=values, + ) + + exc.exception.response['Error']['Code'].should.equal('EntityNotFoundException') + +@mock_glue +def test_batch_delete_partition(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + table_name = 'myfirsttable' + helpers.create_database(client, database_name) + helpers.create_table(client, database_name, table_name) + + partition_inputs = [] + for i in range(0, 20): + values = ["2018-10-{:2}".format(i)] + part_input = helpers.create_partition_input(database_name, table_name, values=values) + partition_inputs.append(part_input) + + client.batch_create_partition( + DatabaseName=database_name, + TableName=table_name, + PartitionInputList=partition_inputs + ) + + partition_values = [{"Values": p["Values"]} for p in partition_inputs] + + response = client.batch_delete_partition( + DatabaseName=database_name, + TableName=table_name, + PartitionsToDelete=partition_values, + ) + + response.should_not.have.key('Errors') + +@mock_glue +def test_batch_delete_partition_with_bad_partitions(): + client = boto3.client('glue', region_name='us-east-1') + database_name = 'myspecialdatabase' + table_name = 'myfirsttable' + helpers.create_database(client, database_name) + helpers.create_table(client, database_name, table_name) + + partition_inputs = [] + for i in range(0, 20): + values = ["2018-10-{:2}".format(i)] + part_input = helpers.create_partition_input(database_name, table_name, values=values) + partition_inputs.append(part_input) + + client.batch_create_partition( + DatabaseName=database_name, + TableName=table_name, + PartitionInputList=partition_inputs + ) + + partition_values = [{"Values": p["Values"]} for p in partition_inputs] + + partition_values.insert(5, {"Values": ["2018-11-01"]}) + partition_values.insert(10, {"Values": ["2018-11-02"]}) + partition_values.insert(15, {"Values": ["2018-11-03"]}) + + response = client.batch_delete_partition( + DatabaseName=database_name, + TableName=table_name, + PartitionsToDelete=partition_values, + ) + + response.should.have.key('Errors') + response['Errors'].should.have.length_of(3) + error_partitions = map(lambda x: x['PartitionValues'], response['Errors']) + ['2018-11-01'].should.be.within(error_partitions) + ['2018-11-02'].should.be.within(error_partitions) + ['2018-11-03'].should.be.within(error_partitions) diff --git a/tests/test_iam/test_iam.py b/tests/test_iam/test_iam.py index 01f52af12..fe2117a3a 100644 --- a/tests/test_iam/test_iam.py +++ b/tests/test_iam/test_iam.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals import base64 +import json import boto import boto3 @@ -29,6 +30,44 @@ FyDHrtlrS80dPUQWNYHw++oACDpWO01LGLPPrGmuO/7cOdojPEd852q5gd+7W9xt 8vUH+pBa6IBLbvBp+szli51V3TLSWcoyy4ceJNQU2vCkTLoFdS0RLd/7tQ== -----END CERTIFICATE-----""" +MOCK_POLICY = """ +{ + "Version": "2012-10-17", + "Statement": + { + "Effect": "Allow", + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::example_bucket" + } +} +""" + +MOCK_POLICY_2 = """ +{ + "Version": "2012-10-17", + "Id": "2", + "Statement": + { + "Effect": "Allow", + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::example_bucket" + } +} +""" + +MOCK_POLICY_3 = """ +{ + "Version": "2012-10-17", + "Id": "3", + "Statement": + { + "Effect": "Allow", + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::example_bucket" + } +} +""" + @mock_iam_deprecated() def test_get_all_server_certs(): @@ -243,12 +282,12 @@ def test_list_instance_profiles_for_role(): def test_list_role_policies(): conn = boto.connect_iam() conn.create_role("my-role") - conn.put_role_policy("my-role", "test policy", "my policy") + conn.put_role_policy("my-role", "test policy", MOCK_POLICY) role = conn.list_role_policies("my-role") role.policy_names.should.have.length_of(1) role.policy_names[0].should.equal("test policy") - conn.put_role_policy("my-role", "test policy 2", "another policy") + conn.put_role_policy("my-role", "test policy 2", MOCK_POLICY) role = conn.list_role_policies("my-role") role.policy_names.should.have.length_of(2) @@ -266,12 +305,21 @@ def test_put_role_policy(): conn = boto.connect_iam() conn.create_role( "my-role", assume_role_policy_document="some policy", path="my-path") - conn.put_role_policy("my-role", "test policy", "my policy") + conn.put_role_policy("my-role", "test policy", MOCK_POLICY) policy = conn.get_role_policy( "my-role", "test policy")['get_role_policy_response']['get_role_policy_result']['policy_name'] policy.should.equal("test policy") +@mock_iam +def test_get_role_policy(): + conn = boto3.client('iam', region_name='us-east-1') + conn.create_role( + RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="my-path") + with assert_raises(conn.exceptions.NoSuchEntityException): + conn.get_role_policy(RoleName="my-role", PolicyName="does-not-exist") + + @mock_iam_deprecated() def test_update_assume_role_policy(): conn = boto.connect_iam() @@ -286,7 +334,7 @@ def test_create_policy(): conn = boto3.client('iam', region_name='us-east-1') response = conn.create_policy( PolicyName="TestCreatePolicy", - PolicyDocument='{"some":"policy"}') + PolicyDocument=MOCK_POLICY) response['Policy']['Arn'].should.equal("arn:aws:iam::123456789012:policy/TestCreatePolicy") @@ -299,20 +347,62 @@ def test_create_policy_versions(): PolicyDocument='{"some":"policy"}') conn.create_policy( PolicyName="TestCreatePolicyVersion", - PolicyDocument='{"some":"policy"}') + PolicyDocument=MOCK_POLICY) version = conn.create_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestCreatePolicyVersion", - PolicyDocument='{"some":"policy"}', + PolicyDocument=MOCK_POLICY, SetAsDefault=True) - version.get('PolicyVersion').get('Document').should.equal({'some': 'policy'}) + version.get('PolicyVersion').get('Document').should.equal(json.loads(MOCK_POLICY)) version.get('PolicyVersion').get('VersionId').should.equal("v2") + version.get('PolicyVersion').get('IsDefaultVersion').should.be.ok conn.delete_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestCreatePolicyVersion", VersionId="v1") version = conn.create_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestCreatePolicyVersion", - PolicyDocument='{"some":"policy"}') + PolicyDocument=MOCK_POLICY) version.get('PolicyVersion').get('VersionId').should.equal("v3") + version.get('PolicyVersion').get('IsDefaultVersion').shouldnt.be.ok + + +@mock_iam +def test_create_many_policy_versions(): + conn = boto3.client('iam', region_name='us-east-1') + conn.create_policy( + PolicyName="TestCreateManyPolicyVersions", + PolicyDocument=MOCK_POLICY) + for _ in range(0, 4): + conn.create_policy_version( + PolicyArn="arn:aws:iam::123456789012:policy/TestCreateManyPolicyVersions", + PolicyDocument=MOCK_POLICY) + with assert_raises(ClientError): + conn.create_policy_version( + PolicyArn="arn:aws:iam::123456789012:policy/TestCreateManyPolicyVersions", + PolicyDocument=MOCK_POLICY) + + +@mock_iam +def test_set_default_policy_version(): + conn = boto3.client('iam', region_name='us-east-1') + conn.create_policy( + PolicyName="TestSetDefaultPolicyVersion", + PolicyDocument=MOCK_POLICY) + conn.create_policy_version( + PolicyArn="arn:aws:iam::123456789012:policy/TestSetDefaultPolicyVersion", + PolicyDocument=MOCK_POLICY_2, + SetAsDefault=True) + conn.create_policy_version( + PolicyArn="arn:aws:iam::123456789012:policy/TestSetDefaultPolicyVersion", + PolicyDocument=MOCK_POLICY_3, + SetAsDefault=True) + versions = conn.list_policy_versions( + PolicyArn="arn:aws:iam::123456789012:policy/TestSetDefaultPolicyVersion") + versions.get('Versions')[0].get('Document').should.equal(json.loads(MOCK_POLICY)) + versions.get('Versions')[0].get('IsDefaultVersion').shouldnt.be.ok + versions.get('Versions')[1].get('Document').should.equal(json.loads(MOCK_POLICY_2)) + versions.get('Versions')[1].get('IsDefaultVersion').shouldnt.be.ok + versions.get('Versions')[2].get('Document').should.equal(json.loads(MOCK_POLICY_3)) + versions.get('Versions')[2].get('IsDefaultVersion').should.be.ok @mock_iam @@ -320,10 +410,21 @@ def test_get_policy(): conn = boto3.client('iam', region_name='us-east-1') response = conn.create_policy( PolicyName="TestGetPolicy", - PolicyDocument='{"some":"policy"}') + PolicyDocument=MOCK_POLICY) policy = conn.get_policy( PolicyArn="arn:aws:iam::123456789012:policy/TestGetPolicy") - response['Policy']['Arn'].should.equal("arn:aws:iam::123456789012:policy/TestGetPolicy") + policy['Policy']['Arn'].should.equal("arn:aws:iam::123456789012:policy/TestGetPolicy") + + +@mock_iam +def test_get_aws_managed_policy(): + conn = boto3.client('iam', region_name='us-east-1') + managed_policy_arn = 'arn:aws:iam::aws:policy/IAMUserChangePassword' + managed_policy_create_date = datetime.strptime("2016-11-15T00:25:16+00:00", "%Y-%m-%dT%H:%M:%S+00:00") + policy = conn.get_policy( + PolicyArn=managed_policy_arn) + policy['Policy']['Arn'].should.equal(managed_policy_arn) + policy['Policy']['CreateDate'].replace(tzinfo=None).should.equal(managed_policy_create_date) @mock_iam @@ -331,10 +432,10 @@ def test_get_policy_version(): conn = boto3.client('iam', region_name='us-east-1') conn.create_policy( PolicyName="TestGetPolicyVersion", - PolicyDocument='{"some":"policy"}') + PolicyDocument=MOCK_POLICY) version = conn.create_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestGetPolicyVersion", - PolicyDocument='{"some":"policy"}') + PolicyDocument=MOCK_POLICY) with assert_raises(ClientError): conn.get_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestGetPolicyVersion", @@ -342,7 +443,40 @@ def test_get_policy_version(): retrieved = conn.get_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestGetPolicyVersion", VersionId=version.get('PolicyVersion').get('VersionId')) - retrieved.get('PolicyVersion').get('Document').should.equal({'some': 'policy'}) + retrieved.get('PolicyVersion').get('Document').should.equal(json.loads(MOCK_POLICY)) + retrieved.get('PolicyVersion').get('IsDefaultVersion').shouldnt.be.ok + + +@mock_iam +def test_get_aws_managed_policy_version(): + conn = boto3.client('iam', region_name='us-east-1') + managed_policy_arn = 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' + managed_policy_version_create_date = datetime.strptime("2015-04-09T15:03:43+00:00", "%Y-%m-%dT%H:%M:%S+00:00") + with assert_raises(ClientError): + conn.get_policy_version( + PolicyArn=managed_policy_arn, + VersionId='v2-does-not-exist') + retrieved = conn.get_policy_version( + PolicyArn=managed_policy_arn, + VersionId="v1") + retrieved['PolicyVersion']['CreateDate'].replace(tzinfo=None).should.equal(managed_policy_version_create_date) + retrieved['PolicyVersion']['Document'].should.be.an(dict) + + +@mock_iam +def test_get_aws_managed_policy_v4_version(): + conn = boto3.client('iam', region_name='us-east-1') + managed_policy_arn = 'arn:aws:iam::aws:policy/job-function/SystemAdministrator' + managed_policy_version_create_date = datetime.strptime("2018-10-08T21:33:45+00:00", "%Y-%m-%dT%H:%M:%S+00:00") + with assert_raises(ClientError): + conn.get_policy_version( + PolicyArn=managed_policy_arn, + VersionId='v2-does-not-exist') + retrieved = conn.get_policy_version( + PolicyArn=managed_policy_arn, + VersionId="v4") + retrieved['PolicyVersion']['CreateDate'].replace(tzinfo=None).should.equal(managed_policy_version_create_date) + retrieved['PolicyVersion']['Document'].should.be.an(dict) @mock_iam @@ -353,22 +487,24 @@ def test_list_policy_versions(): PolicyArn="arn:aws:iam::123456789012:policy/TestListPolicyVersions") conn.create_policy( PolicyName="TestListPolicyVersions", - PolicyDocument='{"first":"policy"}') + PolicyDocument=MOCK_POLICY) versions = conn.list_policy_versions( PolicyArn="arn:aws:iam::123456789012:policy/TestListPolicyVersions") versions.get('Versions')[0].get('VersionId').should.equal('v1') + versions.get('Versions')[0].get('IsDefaultVersion').should.be.ok conn.create_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestListPolicyVersions", - PolicyDocument='{"second":"policy"}') + PolicyDocument=MOCK_POLICY_2) conn.create_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestListPolicyVersions", - PolicyDocument='{"third":"policy"}') + PolicyDocument=MOCK_POLICY_3) versions = conn.list_policy_versions( PolicyArn="arn:aws:iam::123456789012:policy/TestListPolicyVersions") - print(versions.get('Versions')) - versions.get('Versions')[1].get('Document').should.equal({'second': 'policy'}) - versions.get('Versions')[2].get('Document').should.equal({'third': 'policy'}) + versions.get('Versions')[1].get('Document').should.equal(json.loads(MOCK_POLICY_2)) + versions.get('Versions')[1].get('IsDefaultVersion').shouldnt.be.ok + versions.get('Versions')[2].get('Document').should.equal(json.loads(MOCK_POLICY_3)) + versions.get('Versions')[2].get('IsDefaultVersion').shouldnt.be.ok @mock_iam @@ -376,10 +512,10 @@ def test_delete_policy_version(): conn = boto3.client('iam', region_name='us-east-1') conn.create_policy( PolicyName="TestDeletePolicyVersion", - PolicyDocument='{"first":"policy"}') + PolicyDocument=MOCK_POLICY) conn.create_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestDeletePolicyVersion", - PolicyDocument='{"second":"policy"}') + PolicyDocument=MOCK_POLICY) with assert_raises(ClientError): conn.delete_policy_version( PolicyArn="arn:aws:iam::123456789012:policy/TestDeletePolicyVersion", @@ -392,6 +528,21 @@ def test_delete_policy_version(): len(versions.get('Versions')).should.equal(1) +@mock_iam +def test_delete_default_policy_version(): + conn = boto3.client('iam', region_name='us-east-1') + conn.create_policy( + PolicyName="TestDeletePolicyVersion", + PolicyDocument=MOCK_POLICY) + conn.create_policy_version( + PolicyArn="arn:aws:iam::123456789012:policy/TestDeletePolicyVersion", + PolicyDocument=MOCK_POLICY_2) + with assert_raises(ClientError): + conn.delete_policy_version( + PolicyArn="arn:aws:iam::123456789012:policy/TestDeletePolicyVersion", + VersionId='v1') + + @mock_iam_deprecated() def test_create_user(): conn = boto.connect_iam() @@ -446,22 +597,20 @@ def test_list_users(): @mock_iam() def test_user_policies(): policy_name = 'UserManagedPolicy' - policy_document = "{'mypolicy': 'test'}" user_name = 'my-user' conn = boto3.client('iam', region_name='us-east-1') conn.create_user(UserName=user_name) conn.put_user_policy( UserName=user_name, PolicyName=policy_name, - PolicyDocument=policy_document + PolicyDocument=MOCK_POLICY ) policy_doc = conn.get_user_policy( UserName=user_name, PolicyName=policy_name ) - test = policy_document in policy_doc['PolicyDocument'] - test.should.equal(True) + policy_doc['PolicyDocument'].should.equal(json.loads(MOCK_POLICY)) policies = conn.list_user_policies(UserName=user_name) len(policies['PolicyNames']).should.equal(1) @@ -497,13 +646,17 @@ def test_delete_login_profile(): conn.delete_login_profile('my-user') -@mock_iam_deprecated() +@mock_iam() def test_create_access_key(): - conn = boto.connect_iam() - with assert_raises(BotoServerError): - conn.create_access_key('my-user') - conn.create_user('my-user') - conn.create_access_key('my-user') + conn = boto3.client('iam', region_name='us-east-1') + with assert_raises(ClientError): + conn.create_access_key(UserName='my-user') + conn.create_user(UserName='my-user') + access_key = conn.create_access_key(UserName='my-user')["AccessKey"] + (datetime.utcnow() - access_key["CreateDate"].replace(tzinfo=None)).seconds.should.be.within(0, 10) + access_key["AccessKeyId"].should.have.length_of(20) + access_key["SecretAccessKey"].should.have.length_of(40) + assert access_key["AccessKeyId"].startswith("AKIA") @mock_iam_deprecated() @@ -622,7 +775,7 @@ def test_managed_policy(): conn = boto.connect_iam() conn.create_policy(policy_name='UserManagedPolicy', - policy_document={'mypolicy': 'test'}, + policy_document=MOCK_POLICY, path='/mypolicy/', description='my user managed policy') @@ -723,7 +876,7 @@ def test_attach_detach_user_policy(): policy_name = 'UserAttachedPolicy' policy = iam.create_policy(PolicyName=policy_name, - PolicyDocument='{"mypolicy": "test"}', + PolicyDocument=MOCK_POLICY, Path='/mypolicy/', Description='my user attached policy') @@ -779,7 +932,6 @@ def test_get_access_key_last_used(): @mock_iam def test_get_account_authorization_details(): - import json test_policy = json.dumps({ "Version": "2012-10-17", "Statement": [ @@ -792,7 +944,8 @@ def test_get_account_authorization_details(): }) conn = boto3.client('iam', region_name='us-east-1') - conn.create_role(RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/") + boundary = 'arn:aws:iam::123456789012:policy/boundary' + conn.create_role(RoleName="my-role", AssumeRolePolicyDocument="some policy", Path="/my-path/", Description='testing', PermissionsBoundary=boundary) conn.create_user(Path='/', UserName='testUser') conn.create_group(Path='/', GroupName='testGroup') conn.create_policy( @@ -833,6 +986,11 @@ def test_get_account_authorization_details(): assert len(result['GroupDetailList']) == 0 assert len(result['Policies']) == 0 assert len(result['RoleDetailList'][0]['InstanceProfileList']) == 1 + assert result['RoleDetailList'][0]['InstanceProfileList'][0]['Roles'][0]['Description'] == 'testing' + assert result['RoleDetailList'][0]['InstanceProfileList'][0]['Roles'][0]['PermissionsBoundary'] == { + 'PermissionsBoundaryType': 'PermissionsBoundaryPolicy', + 'PermissionsBoundaryArn': 'arn:aws:iam::123456789012:policy/boundary' + } assert len(result['RoleDetailList'][0]['Tags']) == 2 assert len(result['RoleDetailList'][0]['RolePolicyList']) == 1 assert len(result['RoleDetailList'][0]['AttachedManagedPolicies']) == 1 @@ -999,6 +1157,79 @@ def test_delete_saml_provider(): assert not resp['Certificates'] +@mock_iam() +def test_create_role_with_tags(): + """Tests both the tag_role and get_role_tags capability""" + conn = boto3.client('iam', region_name='us-east-1') + conn.create_role(RoleName="my-role", AssumeRolePolicyDocument="{}", Tags=[ + { + 'Key': 'somekey', + 'Value': 'somevalue' + }, + { + 'Key': 'someotherkey', + 'Value': 'someothervalue' + } + ], Description='testing') + + # Get role: + role = conn.get_role(RoleName='my-role')['Role'] + assert len(role['Tags']) == 2 + assert role['Tags'][0]['Key'] == 'somekey' + assert role['Tags'][0]['Value'] == 'somevalue' + assert role['Tags'][1]['Key'] == 'someotherkey' + assert role['Tags'][1]['Value'] == 'someothervalue' + assert role['Description'] == 'testing' + + # Empty is good: + conn.create_role(RoleName="my-role2", AssumeRolePolicyDocument="{}", Tags=[ + { + 'Key': 'somekey', + 'Value': '' + } + ]) + tags = conn.list_role_tags(RoleName='my-role2') + assert len(tags['Tags']) == 1 + assert tags['Tags'][0]['Key'] == 'somekey' + assert tags['Tags'][0]['Value'] == '' + + # Test creating tags with invalid values: + # With more than 50 tags: + with assert_raises(ClientError) as ce: + too_many_tags = list(map(lambda x: {'Key': str(x), 'Value': str(x)}, range(0, 51))) + conn.create_role(RoleName="my-role3", AssumeRolePolicyDocument="{}", Tags=too_many_tags) + assert 'failed to satisfy constraint: Member must have length less than or equal to 50.' \ + in ce.exception.response['Error']['Message'] + + # With a duplicate tag: + with assert_raises(ClientError) as ce: + conn.create_role(RoleName="my-role3", AssumeRolePolicyDocument="{}", Tags=[{'Key': '0', 'Value': ''}, {'Key': '0', 'Value': ''}]) + assert 'Duplicate tag keys found. Please note that Tag keys are case insensitive.' \ + in ce.exception.response['Error']['Message'] + + # Duplicate tag with different casing: + with assert_raises(ClientError) as ce: + conn.create_role(RoleName="my-role3", AssumeRolePolicyDocument="{}", Tags=[{'Key': 'a', 'Value': ''}, {'Key': 'A', 'Value': ''}]) + assert 'Duplicate tag keys found. Please note that Tag keys are case insensitive.' \ + in ce.exception.response['Error']['Message'] + + # With a really big key: + with assert_raises(ClientError) as ce: + conn.create_role(RoleName="my-role3", AssumeRolePolicyDocument="{}", Tags=[{'Key': '0' * 129, 'Value': ''}]) + assert 'Member must have length less than or equal to 128.' in ce.exception.response['Error']['Message'] + + # With a really big value: + with assert_raises(ClientError) as ce: + conn.create_role(RoleName="my-role3", AssumeRolePolicyDocument="{}", Tags=[{'Key': '0', 'Value': '0' * 257}]) + assert 'Member must have length less than or equal to 256.' in ce.exception.response['Error']['Message'] + + # With an invalid character: + with assert_raises(ClientError) as ce: + conn.create_role(RoleName="my-role3", AssumeRolePolicyDocument="{}", Tags=[{'Key': 'NOWAY!', 'Value': ''}]) + assert 'Member must satisfy regular expression pattern: [\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+' \ + in ce.exception.response['Error']['Message'] + + @mock_iam() def test_tag_role(): """Tests both the tag_role and get_role_tags capability""" @@ -1186,6 +1417,7 @@ def test_update_role_description(): assert response['Role']['RoleName'] == 'my-role' + @mock_iam() def test_update_role(): conn = boto3.client('iam', region_name='us-east-1') @@ -1197,6 +1429,7 @@ def test_update_role(): response = conn.update_role_description(RoleName="my-role", Description="test") assert response['Role']['RoleName'] == 'my-role' + @mock_iam() def test_update_role(): conn = boto3.client('iam', region_name='us-east-1') @@ -1211,7 +1444,6 @@ def test_update_role(): @mock_iam() def test_list_entities_for_policy(): - import json test_policy = json.dumps({ "Version": "2012-10-17", "Statement": [ @@ -1292,6 +1524,8 @@ def test_create_role_no_path(): resp = conn.create_role(RoleName='my-role', AssumeRolePolicyDocument='some policy', Description='test') resp.get('Role').get('Arn').should.equal('arn:aws:iam::123456789012:role/my-role') resp.get('Role').should_not.have.key('PermissionsBoundary') + resp.get('Role').get('Description').should.equal('test') + @mock_iam() def test_create_role_with_permissions_boundary(): @@ -1303,6 +1537,7 @@ def test_create_role_with_permissions_boundary(): 'PermissionsBoundaryArn': boundary } resp.get('Role').get('PermissionsBoundary').should.equal(expected) + resp.get('Role').get('Description').should.equal('test') invalid_boundary_arn = 'arn:aws:iam::123456789:not_a_boundary' with assert_raises(ClientError): diff --git a/tests/test_iam/test_iam_groups.py b/tests/test_iam/test_iam_groups.py index 87d4123e2..1ca9f2512 100644 --- a/tests/test_iam/test_iam_groups.py +++ b/tests/test_iam/test_iam_groups.py @@ -1,155 +1,167 @@ -from __future__ import unicode_literals - -from datetime import datetime - -import boto -import boto3 -import sure # noqa - -from nose.tools import assert_raises -from boto.exception import BotoServerError -from moto import mock_iam, mock_iam_deprecated - - -@mock_iam_deprecated() -def test_create_group(): - conn = boto.connect_iam() - conn.create_group('my-group') - with assert_raises(BotoServerError): - conn.create_group('my-group') - - -@mock_iam_deprecated() -def test_get_group(): - conn = boto.connect_iam() - conn.create_group('my-group') - conn.get_group('my-group') - with assert_raises(BotoServerError): - conn.get_group('not-group') - - -@mock_iam() -def test_get_group_current(): - conn = boto3.client('iam', region_name='us-east-1') - conn.create_group(GroupName='my-group') - result = conn.get_group(GroupName='my-group') - - assert result['Group']['Path'] == '/' - assert result['Group']['GroupName'] == 'my-group' - assert isinstance(result['Group']['CreateDate'], datetime) - assert result['Group']['GroupId'] - assert result['Group']['Arn'] == 'arn:aws:iam::123456789012:group/my-group' - assert not result['Users'] - - # Make a group with a different path: - other_group = conn.create_group(GroupName='my-other-group', Path='some/location') - assert other_group['Group']['Path'] == 'some/location' - assert other_group['Group']['Arn'] == 'arn:aws:iam::123456789012:group/some/location/my-other-group' - - -@mock_iam_deprecated() -def test_get_all_groups(): - conn = boto.connect_iam() - conn.create_group('my-group1') - conn.create_group('my-group2') - groups = conn.get_all_groups()['list_groups_response'][ - 'list_groups_result']['groups'] - groups.should.have.length_of(2) - - -@mock_iam_deprecated() -def test_add_user_to_group(): - conn = boto.connect_iam() - with assert_raises(BotoServerError): - conn.add_user_to_group('my-group', 'my-user') - conn.create_group('my-group') - with assert_raises(BotoServerError): - conn.add_user_to_group('my-group', 'my-user') - conn.create_user('my-user') - conn.add_user_to_group('my-group', 'my-user') - - -@mock_iam_deprecated() -def test_remove_user_from_group(): - conn = boto.connect_iam() - with assert_raises(BotoServerError): - conn.remove_user_from_group('my-group', 'my-user') - conn.create_group('my-group') - conn.create_user('my-user') - with assert_raises(BotoServerError): - conn.remove_user_from_group('my-group', 'my-user') - conn.add_user_to_group('my-group', 'my-user') - conn.remove_user_from_group('my-group', 'my-user') - - -@mock_iam_deprecated() -def test_get_groups_for_user(): - conn = boto.connect_iam() - conn.create_group('my-group1') - conn.create_group('my-group2') - conn.create_group('other-group') - conn.create_user('my-user') - conn.add_user_to_group('my-group1', 'my-user') - conn.add_user_to_group('my-group2', 'my-user') - - groups = conn.get_groups_for_user( - 'my-user')['list_groups_for_user_response']['list_groups_for_user_result']['groups'] - groups.should.have.length_of(2) - - -@mock_iam_deprecated() -def test_put_group_policy(): - conn = boto.connect_iam() - conn.create_group('my-group') - conn.put_group_policy('my-group', 'my-policy', '{"some": "json"}') - - -@mock_iam -def test_attach_group_policies(): - conn = boto3.client('iam', region_name='us-east-1') - conn.create_group(GroupName='my-group') - conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty - policy_arn = 'arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role' - conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty - conn.attach_group_policy(GroupName='my-group', PolicyArn=policy_arn) - conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.equal( - [ - { - 'PolicyName': 'AmazonElasticMapReduceforEC2Role', - 'PolicyArn': policy_arn, - } - ]) - - conn.detach_group_policy(GroupName='my-group', PolicyArn=policy_arn) - conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty - - -@mock_iam_deprecated() -def test_get_group_policy(): - conn = boto.connect_iam() - conn.create_group('my-group') - with assert_raises(BotoServerError): - conn.get_group_policy('my-group', 'my-policy') - - conn.put_group_policy('my-group', 'my-policy', '{"some": "json"}') - conn.get_group_policy('my-group', 'my-policy') - - -@mock_iam_deprecated() -def test_get_all_group_policies(): - conn = boto.connect_iam() - conn.create_group('my-group') - policies = conn.get_all_group_policies('my-group')['list_group_policies_response']['list_group_policies_result']['policy_names'] - assert policies == [] - conn.put_group_policy('my-group', 'my-policy', '{"some": "json"}') - policies = conn.get_all_group_policies('my-group')['list_group_policies_response']['list_group_policies_result']['policy_names'] - assert policies == ['my-policy'] - - -@mock_iam() -def test_list_group_policies(): - conn = boto3.client('iam', region_name='us-east-1') - conn.create_group(GroupName='my-group') - conn.list_group_policies(GroupName='my-group')['PolicyNames'].should.be.empty - conn.put_group_policy(GroupName='my-group', PolicyName='my-policy', PolicyDocument='{"some": "json"}') - conn.list_group_policies(GroupName='my-group')['PolicyNames'].should.equal(['my-policy']) +from __future__ import unicode_literals + +from datetime import datetime + +import boto +import boto3 +import sure # noqa + +from nose.tools import assert_raises +from boto.exception import BotoServerError +from moto import mock_iam, mock_iam_deprecated + +MOCK_POLICY = """ +{ + "Version": "2012-10-17", + "Statement": + { + "Effect": "Allow", + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::example_bucket" + } +} +""" + + +@mock_iam_deprecated() +def test_create_group(): + conn = boto.connect_iam() + conn.create_group('my-group') + with assert_raises(BotoServerError): + conn.create_group('my-group') + + +@mock_iam_deprecated() +def test_get_group(): + conn = boto.connect_iam() + conn.create_group('my-group') + conn.get_group('my-group') + with assert_raises(BotoServerError): + conn.get_group('not-group') + + +@mock_iam() +def test_get_group_current(): + conn = boto3.client('iam', region_name='us-east-1') + conn.create_group(GroupName='my-group') + result = conn.get_group(GroupName='my-group') + + assert result['Group']['Path'] == '/' + assert result['Group']['GroupName'] == 'my-group' + assert isinstance(result['Group']['CreateDate'], datetime) + assert result['Group']['GroupId'] + assert result['Group']['Arn'] == 'arn:aws:iam::123456789012:group/my-group' + assert not result['Users'] + + # Make a group with a different path: + other_group = conn.create_group(GroupName='my-other-group', Path='some/location') + assert other_group['Group']['Path'] == 'some/location' + assert other_group['Group']['Arn'] == 'arn:aws:iam::123456789012:group/some/location/my-other-group' + + +@mock_iam_deprecated() +def test_get_all_groups(): + conn = boto.connect_iam() + conn.create_group('my-group1') + conn.create_group('my-group2') + groups = conn.get_all_groups()['list_groups_response'][ + 'list_groups_result']['groups'] + groups.should.have.length_of(2) + + +@mock_iam_deprecated() +def test_add_user_to_group(): + conn = boto.connect_iam() + with assert_raises(BotoServerError): + conn.add_user_to_group('my-group', 'my-user') + conn.create_group('my-group') + with assert_raises(BotoServerError): + conn.add_user_to_group('my-group', 'my-user') + conn.create_user('my-user') + conn.add_user_to_group('my-group', 'my-user') + + +@mock_iam_deprecated() +def test_remove_user_from_group(): + conn = boto.connect_iam() + with assert_raises(BotoServerError): + conn.remove_user_from_group('my-group', 'my-user') + conn.create_group('my-group') + conn.create_user('my-user') + with assert_raises(BotoServerError): + conn.remove_user_from_group('my-group', 'my-user') + conn.add_user_to_group('my-group', 'my-user') + conn.remove_user_from_group('my-group', 'my-user') + + +@mock_iam_deprecated() +def test_get_groups_for_user(): + conn = boto.connect_iam() + conn.create_group('my-group1') + conn.create_group('my-group2') + conn.create_group('other-group') + conn.create_user('my-user') + conn.add_user_to_group('my-group1', 'my-user') + conn.add_user_to_group('my-group2', 'my-user') + + groups = conn.get_groups_for_user( + 'my-user')['list_groups_for_user_response']['list_groups_for_user_result']['groups'] + groups.should.have.length_of(2) + + +@mock_iam_deprecated() +def test_put_group_policy(): + conn = boto.connect_iam() + conn.create_group('my-group') + conn.put_group_policy('my-group', 'my-policy', MOCK_POLICY) + + +@mock_iam +def test_attach_group_policies(): + conn = boto3.client('iam', region_name='us-east-1') + conn.create_group(GroupName='my-group') + conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty + policy_arn = 'arn:aws:iam::aws:policy/service-role/AmazonElasticMapReduceforEC2Role' + conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty + conn.attach_group_policy(GroupName='my-group', PolicyArn=policy_arn) + conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.equal( + [ + { + 'PolicyName': 'AmazonElasticMapReduceforEC2Role', + 'PolicyArn': policy_arn, + } + ]) + + conn.detach_group_policy(GroupName='my-group', PolicyArn=policy_arn) + conn.list_attached_group_policies(GroupName='my-group')['AttachedPolicies'].should.be.empty + + +@mock_iam_deprecated() +def test_get_group_policy(): + conn = boto.connect_iam() + conn.create_group('my-group') + with assert_raises(BotoServerError): + conn.get_group_policy('my-group', 'my-policy') + + conn.put_group_policy('my-group', 'my-policy', MOCK_POLICY) + conn.get_group_policy('my-group', 'my-policy') + + +@mock_iam_deprecated() +def test_get_all_group_policies(): + conn = boto.connect_iam() + conn.create_group('my-group') + policies = conn.get_all_group_policies('my-group')['list_group_policies_response']['list_group_policies_result']['policy_names'] + assert policies == [] + conn.put_group_policy('my-group', 'my-policy', MOCK_POLICY) + policies = conn.get_all_group_policies('my-group')['list_group_policies_response']['list_group_policies_result']['policy_names'] + assert policies == ['my-policy'] + + +@mock_iam() +def test_list_group_policies(): + conn = boto3.client('iam', region_name='us-east-1') + conn.create_group(GroupName='my-group') + conn.list_group_policies(GroupName='my-group')['PolicyNames'].should.be.empty + conn.put_group_policy(GroupName='my-group', PolicyName='my-policy', PolicyDocument=MOCK_POLICY) + conn.list_group_policies(GroupName='my-group')['PolicyNames'].should.equal(['my-policy']) diff --git a/tests/test_kinesis/test_kinesis.py b/tests/test_kinesis/test_kinesis.py index 6986f79fc..e2de866fc 100644 --- a/tests/test_kinesis/test_kinesis.py +++ b/tests/test_kinesis/test_kinesis.py @@ -15,7 +15,7 @@ from moto import mock_kinesis, mock_kinesis_deprecated def test_create_cluster(): conn = boto.kinesis.connect_to_region("us-west-2") - conn.create_stream("my_stream", 2) + conn.create_stream("my_stream", 3) stream_response = conn.describe_stream("my_stream") @@ -27,7 +27,7 @@ def test_create_cluster(): stream["StreamStatus"].should.equal("ACTIVE") shards = stream['Shards'] - shards.should.have.length_of(2) + shards.should.have.length_of(3) @mock_kinesis_deprecated diff --git a/tests/test_kms/test_kms.py b/tests/test_kms/test_kms.py index f0d77d3e9..f189fbe41 100644 --- a/tests/test_kms/test_kms.py +++ b/tests/test_kms/test_kms.py @@ -11,21 +11,29 @@ import sure # noqa from moto import mock_kms, mock_kms_deprecated from nose.tools import assert_raises from freezegun import freeze_time +from datetime import date from datetime import datetime from dateutil.tz import tzutc -@mock_kms_deprecated +@mock_kms def test_create_key(): - conn = boto.kms.connect_to_region("us-west-2") + conn = boto3.client('kms', region_name='us-east-1') with freeze_time("2015-01-01 00:00:00"): - key = conn.create_key(policy="my policy", - description="my key", key_usage='ENCRYPT_DECRYPT') + key = conn.create_key(Policy="my policy", + Description="my key", + KeyUsage='ENCRYPT_DECRYPT', + Tags=[ + { + 'TagKey': 'project', + 'TagValue': 'moto', + }, + ]) key['KeyMetadata']['Description'].should.equal("my key") key['KeyMetadata']['KeyUsage'].should.equal("ENCRYPT_DECRYPT") key['KeyMetadata']['Enabled'].should.equal(True) - key['KeyMetadata']['CreationDate'].should.equal("1420070400") + key['KeyMetadata']['CreationDate'].should.be.a(date) @mock_kms_deprecated @@ -183,6 +191,7 @@ def test_decrypt(): conn = boto.kms.connect_to_region('us-west-2') response = conn.decrypt('ZW5jcnlwdG1l'.encode('utf-8')) response['Plaintext'].should.equal(b'encryptme') + response['KeyId'].should.equal('key_id') @mock_kms_deprecated diff --git a/tests/test_logs/test_logs.py b/tests/test_logs/test_logs.py index 7048061f0..49e593fdc 100644 --- a/tests/test_logs/test_logs.py +++ b/tests/test_logs/test_logs.py @@ -162,3 +162,63 @@ def test_delete_retention_policy(): response = conn.delete_log_group(logGroupName=log_group_name) + +@mock_logs +def test_get_log_events(): + conn = boto3.client('logs', 'us-west-2') + log_group_name = 'test' + log_stream_name = 'stream' + conn.create_log_group(logGroupName=log_group_name) + conn.create_log_stream( + logGroupName=log_group_name, + logStreamName=log_stream_name + ) + + events = [{'timestamp': x, 'message': str(x)} for x in range(20)] + + conn.put_log_events( + logGroupName=log_group_name, + logStreamName=log_stream_name, + logEvents=events + ) + + resp = conn.get_log_events( + logGroupName=log_group_name, + logStreamName=log_stream_name, + limit=10) + + resp['events'].should.have.length_of(10) + resp.should.have.key('nextForwardToken') + resp.should.have.key('nextBackwardToken') + for i in range(10): + resp['events'][i]['timestamp'].should.equal(i) + resp['events'][i]['message'].should.equal(str(i)) + + next_token = resp['nextForwardToken'] + + resp = conn.get_log_events( + logGroupName=log_group_name, + logStreamName=log_stream_name, + nextToken=next_token, + limit=10) + + resp['events'].should.have.length_of(10) + resp.should.have.key('nextForwardToken') + resp.should.have.key('nextBackwardToken') + resp['nextForwardToken'].should.equal(next_token) + for i in range(10): + resp['events'][i]['timestamp'].should.equal(i+10) + resp['events'][i]['message'].should.equal(str(i+10)) + + resp = conn.get_log_events( + logGroupName=log_group_name, + logStreamName=log_stream_name, + nextToken=resp['nextBackwardToken'], + limit=10) + + resp['events'].should.have.length_of(10) + resp.should.have.key('nextForwardToken') + resp.should.have.key('nextBackwardToken') + for i in range(10): + resp['events'][i]['timestamp'].should.equal(i) + resp['events'][i]['message'].should.equal(str(i)) diff --git a/tests/test_organizations/organizations_test_utils.py b/tests/test_organizations/organizations_test_utils.py index 36933d41a..83b60b877 100644 --- a/tests/test_organizations/organizations_test_utils.py +++ b/tests/test_organizations/organizations_test_utils.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals import six -import sure # noqa import datetime from moto.organizations import utils diff --git a/tests/test_organizations/test_organizations_boto3.py b/tests/test_organizations/test_organizations_boto3.py index 05f831e62..28f8cca91 100644 --- a/tests/test_organizations/test_organizations_boto3.py +++ b/tests/test_organizations/test_organizations_boto3.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import boto3 import json import six -import sure # noqa from botocore.exceptions import ClientError from nose.tools import assert_raises @@ -27,6 +26,25 @@ def test_create_organization(): validate_organization(response) response['Organization']['FeatureSet'].should.equal('ALL') + response = client.list_accounts() + len(response['Accounts']).should.equal(1) + response['Accounts'][0]['Name'].should.equal('master') + response['Accounts'][0]['Id'].should.equal(utils.MASTER_ACCOUNT_ID) + response['Accounts'][0]['Email'].should.equal(utils.MASTER_ACCOUNT_EMAIL) + + response = client.list_policies(Filter='SERVICE_CONTROL_POLICY') + len(response['Policies']).should.equal(1) + response['Policies'][0]['Name'].should.equal('FullAWSAccess') + response['Policies'][0]['Id'].should.equal(utils.DEFAULT_POLICY_ID) + response['Policies'][0]['AwsManaged'].should.equal(True) + + response = client.list_targets_for_policy(PolicyId=utils.DEFAULT_POLICY_ID) + len(response['Targets']).should.equal(2) + root_ou = [t for t in response['Targets'] if t['Type'] == 'ROOT'][0] + root_ou['Name'].should.equal('Root') + master_account = [t for t in response['Targets'] if t['Type'] == 'ACCOUNT'][0] + master_account['Name'].should.equal('master') + @mock_organizations def test_describe_organization(): @@ -177,11 +195,11 @@ def test_list_accounts(): response = client.list_accounts() response.should.have.key('Accounts') accounts = response['Accounts'] - len(accounts).should.equal(5) + len(accounts).should.equal(6) for account in accounts: validate_account(org, account) - accounts[3]['Name'].should.equal(mockname + '3') - accounts[2]['Email'].should.equal(mockname + '2' + '@' + mockdomain) + accounts[4]['Name'].should.equal(mockname + '3') + accounts[3]['Email'].should.equal(mockname + '2' + '@' + mockdomain) @mock_organizations @@ -291,8 +309,10 @@ def test_list_children(): response02 = client.list_children(ParentId=root_id, ChildType='ORGANIZATIONAL_UNIT') response03 = client.list_children(ParentId=ou01_id, ChildType='ACCOUNT') response04 = client.list_children(ParentId=ou01_id, ChildType='ORGANIZATIONAL_UNIT') - response01['Children'][0]['Id'].should.equal(account01_id) + response01['Children'][0]['Id'].should.equal(utils.MASTER_ACCOUNT_ID) response01['Children'][0]['Type'].should.equal('ACCOUNT') + response01['Children'][1]['Id'].should.equal(account01_id) + response01['Children'][1]['Type'].should.equal('ACCOUNT') response02['Children'][0]['Id'].should.equal(ou01_id) response02['Children'][0]['Type'].should.equal('ORGANIZATIONAL_UNIT') response03['Children'][0]['Id'].should.equal(account02_id) @@ -591,4 +611,3 @@ def test_list_targets_for_policy_exception(): ex.operation_name.should.equal('ListTargetsForPolicy') ex.response['Error']['Code'].should.equal('400') ex.response['Error']['Message'].should.contain('InvalidInputException') - diff --git a/tests/test_rds2/test_rds2.py b/tests/test_rds2/test_rds2.py index a25b53196..aacaf04f1 100644 --- a/tests/test_rds2/test_rds2.py +++ b/tests/test_rds2/test_rds2.py @@ -18,7 +18,8 @@ def test_create_database(): MasterUsername='root', MasterUserPassword='hunter2', Port=1234, - DBSecurityGroups=["my_sg"]) + DBSecurityGroups=["my_sg"], + VpcSecurityGroupIds=['sg-123456']) db_instance = database['DBInstance'] db_instance['AllocatedStorage'].should.equal(10) db_instance['DBInstanceClass'].should.equal("db.m1.small") @@ -34,6 +35,40 @@ def test_create_database(): db_instance['IAMDatabaseAuthenticationEnabled'].should.equal(False) db_instance['DbiResourceId'].should.contain("db-") db_instance['CopyTagsToSnapshot'].should.equal(False) + db_instance['InstanceCreateTime'].should.be.a("datetime.datetime") + db_instance['VpcSecurityGroups'][0]['VpcSecurityGroupId'].should.equal('sg-123456') + + +@mock_rds2 +def test_create_database_non_existing_option_group(): + conn = boto3.client('rds', region_name='us-west-2') + database = conn.create_db_instance.when.called_with( + DBInstanceIdentifier='db-master-1', + AllocatedStorage=10, + Engine='postgres', + DBName='staging-postgres', + DBInstanceClass='db.m1.small', + OptionGroupName='non-existing').should.throw(ClientError) + + +@mock_rds2 +def test_create_database_with_option_group(): + conn = boto3.client('rds', region_name='us-west-2') + conn.create_option_group(OptionGroupName='my-og', + EngineName='mysql', + MajorEngineVersion='5.6', + OptionGroupDescription='test option group') + database = conn.create_db_instance(DBInstanceIdentifier='db-master-1', + AllocatedStorage=10, + Engine='postgres', + DBName='staging-postgres', + DBInstanceClass='db.m1.small', + OptionGroupName='my-og') + db_instance = database['DBInstance'] + db_instance['AllocatedStorage'].should.equal(10) + db_instance['DBInstanceClass'].should.equal('db.m1.small') + db_instance['DBName'].should.equal('staging-postgres') + db_instance['OptionGroupMemberships'][0]['OptionGroupName'].should.equal('my-og') @mock_rds2 @@ -204,6 +239,7 @@ def test_get_databases_paginated(): resp3 = conn.describe_db_instances(MaxRecords=100) resp3["DBInstances"].should.have.length_of(51) + @mock_rds2 def test_describe_non_existant_database(): conn = boto3.client('rds', region_name='us-west-2') @@ -226,9 +262,11 @@ def test_modify_db_instance(): instances['DBInstances'][0]['AllocatedStorage'].should.equal(10) conn.modify_db_instance(DBInstanceIdentifier='db-master-1', AllocatedStorage=20, - ApplyImmediately=True) + ApplyImmediately=True, + VpcSecurityGroupIds=['sg-123456']) instances = conn.describe_db_instances(DBInstanceIdentifier='db-master-1') instances['DBInstances'][0]['AllocatedStorage'].should.equal(20) + instances['DBInstances'][0]['VpcSecurityGroups'][0]['VpcSecurityGroupId'].should.equal('sg-123456') @mock_rds2 diff --git a/tests/test_redshift/test_redshift.py b/tests/test_redshift/test_redshift.py index 541614788..2c9b42a1d 100644 --- a/tests/test_redshift/test_redshift.py +++ b/tests/test_redshift/test_redshift.py @@ -36,6 +36,7 @@ def test_create_cluster_boto3(): response['Cluster']['NodeType'].should.equal('ds2.xlarge') create_time = response['Cluster']['ClusterCreateTime'] create_time.should.be.lower_than(datetime.datetime.now(create_time.tzinfo)) + create_time.should.be.greater_than(datetime.datetime.now(create_time.tzinfo) - datetime.timedelta(minutes=1)) @mock_redshift diff --git a/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py b/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py index 8015472bf..1e42dfe55 100644 --- a/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py +++ b/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py @@ -2,7 +2,11 @@ from __future__ import unicode_literals import boto3 import sure # noqa -from moto import mock_resourcegroupstaggingapi, mock_s3, mock_ec2, mock_elbv2 +from moto import mock_ec2 +from moto import mock_elbv2 +from moto import mock_kms +from moto import mock_resourcegroupstaggingapi +from moto import mock_s3 @mock_s3 @@ -225,10 +229,12 @@ def test_get_tag_values_ec2(): @mock_ec2 @mock_elbv2 +@mock_kms @mock_resourcegroupstaggingapi -def test_get_resources_elbv2(): - conn = boto3.client('elbv2', region_name='us-east-1') +def test_get_many_resources(): + elbv2 = boto3.client('elbv2', region_name='us-east-1') ec2 = boto3.resource('ec2', region_name='us-east-1') + kms = boto3.client('kms', region_name='us-east-1') security_group = ec2.create_security_group( GroupName='a-security-group', Description='First One') @@ -242,7 +248,7 @@ def test_get_resources_elbv2(): CidrBlock='172.28.7.0/26', AvailabilityZone='us-east-1b') - conn.create_load_balancer( + elbv2.create_load_balancer( Name='my-lb', Subnets=[subnet1.id, subnet2.id], SecurityGroups=[security_group.id], @@ -259,13 +265,27 @@ def test_get_resources_elbv2(): ] ) - conn.create_load_balancer( + elbv2.create_load_balancer( Name='my-other-lb', Subnets=[subnet1.id, subnet2.id], SecurityGroups=[security_group.id], Scheme='internal', ) + kms.create_key( + KeyUsage='ENCRYPT_DECRYPT', + Tags=[ + { + 'TagKey': 'key_name', + 'TagValue': 'a_value' + }, + { + 'TagKey': 'key_2', + 'TagValue': 'val2' + } + ] + ) + rtapi = boto3.client('resourcegroupstaggingapi', region_name='us-east-1') resp = rtapi.get_resources(ResourceTypeFilters=['elasticloadbalancer:loadbalancer']) diff --git a/tests/test_route53/test_route53.py b/tests/test_route53/test_route53.py index d730f8dcf..de9465d6d 100644 --- a/tests/test_route53/test_route53.py +++ b/tests/test_route53/test_route53.py @@ -110,6 +110,7 @@ def test_rrset(): changes = ResourceRecordSets(conn, zoneid) changes.add_change("DELETE", "foo.bar.testdns.aws.com", "A") + changes.add_change("DELETE", "foo.bar.testdns.aws.com", "TXT") changes.commit() changes = ResourceRecordSets(conn, zoneid) @@ -123,12 +124,12 @@ def test_rrset(): rrsets.should.have.length_of(2) rrsets = conn.get_all_rrsets( - zoneid, name="foo.bar.testdns.aws.com", type="A") + zoneid, name="bar.foo.testdns.aws.com", type="A") rrsets.should.have.length_of(1) - rrsets[0].resource_records[0].should.equal('1.2.3.4') + rrsets[0].resource_records[0].should.equal('5.6.7.8') rrsets = conn.get_all_rrsets( - zoneid, name="bar.foo.testdns.aws.com", type="A") + zoneid, name="foo.bar.testdns.aws.com", type="A") rrsets.should.have.length_of(2) resource_records = [rr for rr_set in rrsets for rr in rr_set.resource_records] resource_records.should.contain('1.2.3.4') @@ -172,14 +173,16 @@ def test_alias_rrset(): changes.commit() rrsets = conn.get_all_rrsets(zoneid, type="A") - rrset_records = [(rr_set.name, rr) for rr_set in rrsets for rr in rr_set.resource_records] - rrset_records.should.have.length_of(2) - rrset_records.should.contain(('foo.alias.testdns.aws.com.', 'foo.testdns.aws.com')) - rrset_records.should.contain(('bar.alias.testdns.aws.com.', 'bar.testdns.aws.com')) - rrsets[0].resource_records[0].should.equal('foo.testdns.aws.com') + alias_targets = [rr_set.alias_dns_name for rr_set in rrsets] + alias_targets.should.have.length_of(2) + alias_targets.should.contain('foo.testdns.aws.com') + alias_targets.should.contain('bar.testdns.aws.com') + rrsets[0].alias_dns_name.should.equal('foo.testdns.aws.com') + rrsets[0].resource_records.should.have.length_of(0) rrsets = conn.get_all_rrsets(zoneid, type="CNAME") rrsets.should.have.length_of(1) - rrsets[0].resource_records[0].should.equal('bar.testdns.aws.com') + rrsets[0].alias_dns_name.should.equal('bar.testdns.aws.com') + rrsets[0].resource_records.should.have.length_of(0) @mock_route53_deprecated @@ -582,7 +585,40 @@ def test_change_resource_record_sets_crud_valid(): cname_record_detail['TTL'].should.equal(60) cname_record_detail['ResourceRecords'].should.equal([{'Value': '192.168.1.1'}]) - # Delete record. + # Update to add Alias. + cname_alias_record_endpoint_payload = { + 'Comment': 'Update to Alias prod.redis.db', + 'Changes': [ + { + 'Action': 'UPSERT', + 'ResourceRecordSet': { + 'Name': 'prod.redis.db.', + 'Type': 'A', + 'TTL': 60, + 'AliasTarget': { + 'HostedZoneId': hosted_zone_id, + 'DNSName': 'prod.redis.alias.', + 'EvaluateTargetHealth': False, + } + } + } + ] + } + conn.change_resource_record_sets(HostedZoneId=hosted_zone_id, ChangeBatch=cname_alias_record_endpoint_payload) + + response = conn.list_resource_record_sets(HostedZoneId=hosted_zone_id) + cname_alias_record_detail = response['ResourceRecordSets'][0] + cname_alias_record_detail['Name'].should.equal('prod.redis.db.') + cname_alias_record_detail['Type'].should.equal('A') + cname_alias_record_detail['TTL'].should.equal(60) + cname_alias_record_detail['AliasTarget'].should.equal({ + 'HostedZoneId': hosted_zone_id, + 'DNSName': 'prod.redis.alias.', + 'EvaluateTargetHealth': False, + }) + cname_alias_record_detail.should_not.contain('ResourceRecords') + + # Delete record with wrong type. delete_payload = { 'Comment': 'delete prod.redis.db', 'Changes': [ @@ -597,8 +633,133 @@ def test_change_resource_record_sets_crud_valid(): } conn.change_resource_record_sets(HostedZoneId=hosted_zone_id, ChangeBatch=delete_payload) response = conn.list_resource_record_sets(HostedZoneId=hosted_zone_id) + len(response['ResourceRecordSets']).should.equal(1) + + # Delete record. + delete_payload = { + 'Comment': 'delete prod.redis.db', + 'Changes': [ + { + 'Action': 'DELETE', + 'ResourceRecordSet': { + 'Name': 'prod.redis.db', + 'Type': 'A', + } + } + ] + } + conn.change_resource_record_sets(HostedZoneId=hosted_zone_id, ChangeBatch=delete_payload) + response = conn.list_resource_record_sets(HostedZoneId=hosted_zone_id) len(response['ResourceRecordSets']).should.equal(0) +@mock_route53 +def test_change_weighted_resource_record_sets(): + conn = boto3.client('route53', region_name='us-east-2') + conn.create_hosted_zone( + Name='test.vpc.internal.', + CallerReference=str(hash('test')) + ) + + zones = conn.list_hosted_zones_by_name( + DNSName='test.vpc.internal.' + ) + + hosted_zone_id = zones['HostedZones'][0]['Id'] + + #Create 2 weighted records + conn.change_resource_record_sets( + HostedZoneId=hosted_zone_id, + ChangeBatch={ + 'Changes': [ + { + 'Action': 'CREATE', + 'ResourceRecordSet': { + 'Name': 'test.vpc.internal', + 'Type': 'A', + 'SetIdentifier': 'test1', + 'Weight': 50, + 'AliasTarget': { + 'HostedZoneId': 'Z3AADJGX6KTTL2', + 'DNSName': 'internal-test1lb-447688172.us-east-2.elb.amazonaws.com.', + 'EvaluateTargetHealth': True + } + } + }, + + { + 'Action': 'CREATE', + 'ResourceRecordSet': { + 'Name': 'test.vpc.internal', + 'Type': 'A', + 'SetIdentifier': 'test2', + 'Weight': 50, + 'AliasTarget': { + 'HostedZoneId': 'Z3AADJGX6KTTL2', + 'DNSName': 'internal-testlb2-1116641781.us-east-2.elb.amazonaws.com.', + 'EvaluateTargetHealth': True + } + } + } + ] + } + ) + + response = conn.list_resource_record_sets(HostedZoneId=hosted_zone_id) + record = response['ResourceRecordSets'][0] + #Update the first record to have a weight of 90 + conn.change_resource_record_sets( + HostedZoneId=hosted_zone_id, + ChangeBatch={ + 'Changes' : [ + { + 'Action' : 'UPSERT', + 'ResourceRecordSet' : { + 'Name' : record['Name'], + 'Type' : record['Type'], + 'SetIdentifier' : record['SetIdentifier'], + 'Weight' : 90, + 'AliasTarget' : { + 'HostedZoneId' : record['AliasTarget']['HostedZoneId'], + 'DNSName' : record['AliasTarget']['DNSName'], + 'EvaluateTargetHealth' : record['AliasTarget']['EvaluateTargetHealth'] + } + } + }, + ] + } + ) + + record = response['ResourceRecordSets'][1] + #Update the second record to have a weight of 10 + conn.change_resource_record_sets( + HostedZoneId=hosted_zone_id, + ChangeBatch={ + 'Changes' : [ + { + 'Action' : 'UPSERT', + 'ResourceRecordSet' : { + 'Name' : record['Name'], + 'Type' : record['Type'], + 'SetIdentifier' : record['SetIdentifier'], + 'Weight' : 10, + 'AliasTarget' : { + 'HostedZoneId' : record['AliasTarget']['HostedZoneId'], + 'DNSName' : record['AliasTarget']['DNSName'], + 'EvaluateTargetHealth' : record['AliasTarget']['EvaluateTargetHealth'] + } + } + }, + ] + } + ) + + response = conn.list_resource_record_sets(HostedZoneId=hosted_zone_id) + for record in response['ResourceRecordSets']: + if record['SetIdentifier'] == 'test1': + record['Weight'].should.equal(90) + if record['SetIdentifier'] == 'test2': + record['Weight'].should.equal(10) + @mock_route53 def test_change_resource_record_invalid(): diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index f26964ab7..cd57fc92b 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -639,7 +639,7 @@ def test_delete_keys(): @mock_s3_deprecated -def test_delete_keys_with_invalid(): +def test_delete_keys_invalid(): conn = boto.connect_s3('the_key', 'the_secret') bucket = conn.create_bucket('foobar') @@ -648,6 +648,7 @@ def test_delete_keys_with_invalid(): Key(bucket=bucket, name='file3').set_contents_from_string('abc') Key(bucket=bucket, name='file4').set_contents_from_string('abc') + # non-existing key case result = bucket.delete_keys(['abc', 'file3']) result.deleted.should.have.length_of(1) @@ -656,6 +657,18 @@ def test_delete_keys_with_invalid(): keys.should.have.length_of(3) keys[0].name.should.equal('file1') + # empty keys + result = bucket.delete_keys([]) + + result.deleted.should.have.length_of(0) + result.errors.should.have.length_of(0) + +@mock_s3 +def test_boto3_delete_empty_keys_list(): + with assert_raises(ClientError) as err: + boto3.client('s3').delete_objects(Bucket='foobar', Delete={'Objects': []}) + assert err.exception.response["Error"]["Code"] == "MalformedXML" + @mock_s3_deprecated def test_bucket_name_with_dot(): @@ -1596,6 +1609,28 @@ def test_boto3_delete_versioned_bucket(): client.delete_bucket(Bucket='blah') +@mock_s3 +def test_boto3_get_object_if_modified_since(): + s3 = boto3.client('s3', region_name='us-east-1') + bucket_name = "blah" + s3.create_bucket(Bucket=bucket_name) + + key = 'hello.txt' + + s3.put_object( + Bucket=bucket_name, + Key=key, + Body='test' + ) + + with assert_raises(botocore.exceptions.ClientError) as err: + s3.get_object( + Bucket=bucket_name, + Key=key, + IfModifiedSince=datetime.datetime.utcnow() + datetime.timedelta(hours=1) + ) + e = err.exception + e.response['Error'].should.equal({'Code': '304', 'Message': 'Not Modified'}) @mock_s3 def test_boto3_head_object_if_modified_since(): @@ -1649,6 +1684,42 @@ def test_boto3_multipart_etag(): resp['ETag'].should.equal(EXPECTED_ETAG) +@mock_s3 +@reduced_min_part_size +def test_boto3_multipart_part_size(): + s3 = boto3.client('s3', region_name='us-east-1') + s3.create_bucket(Bucket='mybucket') + + mpu = s3.create_multipart_upload(Bucket='mybucket', Key='the-key') + mpu_id = mpu["UploadId"] + + parts = [] + n_parts = 10 + for i in range(1, n_parts + 1): + part_size = REDUCED_PART_SIZE + i + body = b'1' * part_size + part = s3.upload_part( + Bucket='mybucket', + Key='the-key', + PartNumber=i, + UploadId=mpu_id, + Body=body, + ContentLength=len(body), + ) + parts.append({"PartNumber": i, "ETag": part["ETag"]}) + + s3.complete_multipart_upload( + Bucket='mybucket', + Key='the-key', + UploadId=mpu_id, + MultipartUpload={"Parts": parts}, + ) + + for i in range(1, n_parts + 1): + obj = s3.head_object(Bucket='mybucket', Key='the-key', PartNumber=i) + assert obj["ContentLength"] == REDUCED_PART_SIZE + i + + @mock_s3 def test_boto3_put_object_with_tagging(): s3 = boto3.client('s3', region_name='us-east-1') diff --git a/tests/test_s3/test_s3_storageclass.py b/tests/test_s3/test_s3_storageclass.py index 982376e23..c72b773a9 100644 --- a/tests/test_s3/test_s3_storageclass.py +++ b/tests/test_s3/test_s3_storageclass.py @@ -1,106 +1,138 @@ -from __future__ import unicode_literals - -import boto -import boto3 -from boto.exception import S3CreateError, S3ResponseError -from boto.s3.lifecycle import Lifecycle, Transition, Expiration, Rule - -import sure # noqa -from botocore.exceptions import ClientError -from datetime import datetime -from nose.tools import assert_raises - -from moto import mock_s3_deprecated, mock_s3 - - -@mock_s3 -def test_s3_storage_class_standard(): - s3 = boto3.client("s3") - s3.create_bucket(Bucket="Bucket") - - # add an object to the bucket with standard storage - - s3.put_object(Bucket="Bucket", Key="my_key", Body="my_value") - - list_of_objects = s3.list_objects(Bucket="Bucket") - - list_of_objects['Contents'][0]["StorageClass"].should.equal("STANDARD") - - -@mock_s3 -def test_s3_storage_class_infrequent_access(): - s3 = boto3.client("s3") - s3.create_bucket(Bucket="Bucket") - - # add an object to the bucket with standard storage - - s3.put_object(Bucket="Bucket", Key="my_key_infrequent", Body="my_value_infrequent", StorageClass="STANDARD_IA") - - D = s3.list_objects(Bucket="Bucket") - - D['Contents'][0]["StorageClass"].should.equal("STANDARD_IA") - - -@mock_s3 -def test_s3_storage_class_copy(): - s3 = boto3.client("s3") - s3.create_bucket(Bucket="Bucket") - s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARD") - - s3.create_bucket(Bucket="Bucket2") - # second object is originally of storage class REDUCED_REDUNDANCY - s3.put_object(Bucket="Bucket2", Key="Second_Object", Body="Body2") - - s3.copy_object(CopySource = {"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket2", Key="Second_Object", StorageClass="ONEZONE_IA") - - list_of_copied_objects = s3.list_objects(Bucket="Bucket2") - - # checks that a copied object can be properly copied - list_of_copied_objects["Contents"][0]["StorageClass"].should.equal("ONEZONE_IA") - - -@mock_s3 -def test_s3_invalid_copied_storage_class(): - s3 = boto3.client("s3") - s3.create_bucket(Bucket="Bucket") - s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARD") - - s3.create_bucket(Bucket="Bucket2") - s3.put_object(Bucket="Bucket2", Key="Second_Object", Body="Body2", StorageClass="REDUCED_REDUNDANCY") - - # Try to copy an object with an invalid storage class - with assert_raises(ClientError) as err: - s3.copy_object(CopySource = {"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket2", Key="Second_Object", StorageClass="STANDARD2") - - e = err.exception - e.response["Error"]["Code"].should.equal("InvalidStorageClass") - e.response["Error"]["Message"].should.equal("The storage class you specified is not valid") - - -@mock_s3 -def test_s3_invalid_storage_class(): - s3 = boto3.client("s3") - s3.create_bucket(Bucket="Bucket") - - # Try to add an object with an invalid storage class - with assert_raises(ClientError) as err: - s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARDD") - - e = err.exception - e.response["Error"]["Code"].should.equal("InvalidStorageClass") - e.response["Error"]["Message"].should.equal("The storage class you specified is not valid") - -@mock_s3 -def test_s3_default_storage_class(): - s3 = boto3.client("s3") - s3.create_bucket(Bucket="Bucket") - - s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body") - - list_of_objects = s3.list_objects(Bucket="Bucket") - - # tests that the default storage class is still STANDARD - list_of_objects["Contents"][0]["StorageClass"].should.equal("STANDARD") - - - +from __future__ import unicode_literals + +import boto3 + +import sure # noqa +from botocore.exceptions import ClientError +from nose.tools import assert_raises + +from moto import mock_s3 + + +@mock_s3 +def test_s3_storage_class_standard(): + s3 = boto3.client("s3") + s3.create_bucket(Bucket="Bucket") + + # add an object to the bucket with standard storage + + s3.put_object(Bucket="Bucket", Key="my_key", Body="my_value") + + list_of_objects = s3.list_objects(Bucket="Bucket") + + list_of_objects['Contents'][0]["StorageClass"].should.equal("STANDARD") + + +@mock_s3 +def test_s3_storage_class_infrequent_access(): + s3 = boto3.client("s3") + s3.create_bucket(Bucket="Bucket") + + # add an object to the bucket with standard storage + + s3.put_object(Bucket="Bucket", Key="my_key_infrequent", Body="my_value_infrequent", StorageClass="STANDARD_IA") + + D = s3.list_objects(Bucket="Bucket") + + D['Contents'][0]["StorageClass"].should.equal("STANDARD_IA") + + +@mock_s3 +def test_s3_storage_class_intelligent_tiering(): + s3 = boto3.client("s3") + + s3.create_bucket(Bucket="Bucket") + s3.put_object(Bucket="Bucket", Key="my_key_infrequent", Body="my_value_infrequent", StorageClass="INTELLIGENT_TIERING") + + objects = s3.list_objects(Bucket="Bucket") + + objects['Contents'][0]["StorageClass"].should.equal("INTELLIGENT_TIERING") + + +@mock_s3 +def test_s3_storage_class_copy(): + s3 = boto3.client("s3") + s3.create_bucket(Bucket="Bucket") + s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARD") + + s3.create_bucket(Bucket="Bucket2") + # second object is originally of storage class REDUCED_REDUNDANCY + s3.put_object(Bucket="Bucket2", Key="Second_Object", Body="Body2") + + s3.copy_object(CopySource = {"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket2", Key="Second_Object", StorageClass="ONEZONE_IA") + + list_of_copied_objects = s3.list_objects(Bucket="Bucket2") + + # checks that a copied object can be properly copied + list_of_copied_objects["Contents"][0]["StorageClass"].should.equal("ONEZONE_IA") + + +@mock_s3 +def test_s3_invalid_copied_storage_class(): + s3 = boto3.client("s3") + s3.create_bucket(Bucket="Bucket") + s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARD") + + s3.create_bucket(Bucket="Bucket2") + s3.put_object(Bucket="Bucket2", Key="Second_Object", Body="Body2", StorageClass="REDUCED_REDUNDANCY") + + # Try to copy an object with an invalid storage class + with assert_raises(ClientError) as err: + s3.copy_object(CopySource = {"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket2", Key="Second_Object", StorageClass="STANDARD2") + + e = err.exception + e.response["Error"]["Code"].should.equal("InvalidStorageClass") + e.response["Error"]["Message"].should.equal("The storage class you specified is not valid") + + +@mock_s3 +def test_s3_invalid_storage_class(): + s3 = boto3.client("s3") + s3.create_bucket(Bucket="Bucket") + + # Try to add an object with an invalid storage class + with assert_raises(ClientError) as err: + s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARDD") + + e = err.exception + e.response["Error"]["Code"].should.equal("InvalidStorageClass") + e.response["Error"]["Message"].should.equal("The storage class you specified is not valid") + + +@mock_s3 +def test_s3_default_storage_class(): + s3 = boto3.client("s3") + s3.create_bucket(Bucket="Bucket") + + s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body") + + list_of_objects = s3.list_objects(Bucket="Bucket") + + # tests that the default storage class is still STANDARD + list_of_objects["Contents"][0]["StorageClass"].should.equal("STANDARD") + + +@mock_s3 +def test_s3_copy_object_error_for_glacier_storage_class(): + s3 = boto3.client("s3") + s3.create_bucket(Bucket="Bucket") + + s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="GLACIER") + + with assert_raises(ClientError) as exc: + s3.copy_object(CopySource={"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket", Key="Second_Object") + + exc.exception.response["Error"]["Code"].should.equal("ObjectNotInActiveTierError") + + +@mock_s3 +def test_s3_copy_object_error_for_deep_archive_storage_class(): + s3 = boto3.client("s3") + s3.create_bucket(Bucket="Bucket") + + s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="DEEP_ARCHIVE") + + with assert_raises(ClientError) as exc: + s3.copy_object(CopySource={"Bucket": "Bucket", "Key": "First_Object"}, Bucket="Bucket", Key="Second_Object") + + exc.exception.response["Error"]["Code"].should.equal("ObjectNotInActiveTierError") diff --git a/tests/test_secretsmanager/test_secretsmanager.py b/tests/test_secretsmanager/test_secretsmanager.py index 6735924eb..78b95ee6a 100644 --- a/tests/test_secretsmanager/test_secretsmanager.py +++ b/tests/test_secretsmanager/test_secretsmanager.py @@ -9,6 +9,7 @@ import unittest import pytz from datetime import datetime from nose.tools import assert_raises +from six import b DEFAULT_SECRET_NAME = 'test-secret' @@ -22,6 +23,15 @@ def test_get_secret_value(): result = conn.get_secret_value(SecretId='java-util-test-password') assert result['SecretString'] == 'foosecret' +@mock_secretsmanager +def test_get_secret_value_binary(): + conn = boto3.client('secretsmanager', region_name='us-west-2') + + create_secret = conn.create_secret(Name='java-util-test-password', + SecretBinary=b("foosecret")) + result = conn.get_secret_value(SecretId='java-util-test-password') + assert result['SecretBinary'] == b('foosecret') + @mock_secretsmanager def test_get_secret_that_does_not_exist(): conn = boto3.client('secretsmanager', region_name='us-west-2') diff --git a/tests/test_sns/test_topics_boto3.py b/tests/test_sns/test_topics_boto3.py index f836535ef..870fa6f6e 100644 --- a/tests/test_sns/test_topics_boto3.py +++ b/tests/test_sns/test_topics_boto3.py @@ -1,190 +1,202 @@ -from __future__ import unicode_literals -import boto3 -import six -import json - -import sure # noqa - -from botocore.exceptions import ClientError -from moto import mock_sns -from moto.sns.models import DEFAULT_TOPIC_POLICY, DEFAULT_EFFECTIVE_DELIVERY_POLICY, DEFAULT_PAGE_SIZE - - -@mock_sns -def test_create_and_delete_topic(): - conn = boto3.client("sns", region_name="us-east-1") - for topic_name in ('some-topic', '-some-topic-', '_some-topic_', 'a' * 256): - conn.create_topic(Name=topic_name) - - topics_json = conn.list_topics() - topics = topics_json["Topics"] - topics.should.have.length_of(1) - topics[0]['TopicArn'].should.equal( - "arn:aws:sns:{0}:123456789012:{1}" - .format(conn._client_config.region_name, topic_name) - ) - - # Delete the topic - conn.delete_topic(TopicArn=topics[0]['TopicArn']) - - # And there should now be 0 topics - topics_json = conn.list_topics() - topics = topics_json["Topics"] - topics.should.have.length_of(0) - -@mock_sns -def test_create_topic_should_be_indempodent(): - conn = boto3.client("sns", region_name="us-east-1") - topic_arn = conn.create_topic(Name="some-topic")['TopicArn'] - conn.set_topic_attributes( - TopicArn=topic_arn, - AttributeName="DisplayName", - AttributeValue="should_be_set" - ) - topic_display_name = conn.get_topic_attributes( - TopicArn=topic_arn - )['Attributes']['DisplayName'] - topic_display_name.should.be.equal("should_be_set") - - #recreate topic to prove indempodentcy - topic_arn = conn.create_topic(Name="some-topic")['TopicArn'] - topic_display_name = conn.get_topic_attributes( - TopicArn=topic_arn - )['Attributes']['DisplayName'] - topic_display_name.should.be.equal("should_be_set") - -@mock_sns -def test_get_missing_topic(): - conn = boto3.client("sns", region_name="us-east-1") - conn.get_topic_attributes.when.called_with( - TopicArn="a-fake-arn").should.throw(ClientError) - -@mock_sns -def test_create_topic_must_meet_constraints(): - conn = boto3.client("sns", region_name="us-east-1") - common_random_chars = [':', ";", "!", "@", "|", "^", "%"] - for char in common_random_chars: - conn.create_topic.when.called_with( - Name="no%s_invalidchar" % char).should.throw(ClientError) - conn.create_topic.when.called_with( - Name="no spaces allowed").should.throw(ClientError) - - -@mock_sns -def test_create_topic_should_be_of_certain_length(): - conn = boto3.client("sns", region_name="us-east-1") - too_short = "" - conn.create_topic.when.called_with( - Name=too_short).should.throw(ClientError) - too_long = "x" * 257 - conn.create_topic.when.called_with( - Name=too_long).should.throw(ClientError) - - -@mock_sns -def test_create_topic_in_multiple_regions(): - for region in ['us-west-1', 'us-west-2']: - conn = boto3.client("sns", region_name=region) - conn.create_topic(Name="some-topic") - list(conn.list_topics()["Topics"]).should.have.length_of(1) - - -@mock_sns -def test_topic_corresponds_to_region(): - for region in ['us-east-1', 'us-west-2']: - conn = boto3.client("sns", region_name=region) - conn.create_topic(Name="some-topic") - topics_json = conn.list_topics() - topic_arn = topics_json["Topics"][0]['TopicArn'] - topic_arn.should.equal( - "arn:aws:sns:{0}:123456789012:some-topic".format(region)) - - -@mock_sns -def test_topic_attributes(): - conn = boto3.client("sns", region_name="us-east-1") - conn.create_topic(Name="some-topic") - - topics_json = conn.list_topics() - topic_arn = topics_json["Topics"][0]['TopicArn'] - - attributes = conn.get_topic_attributes(TopicArn=topic_arn)['Attributes'] - attributes["TopicArn"].should.equal( - "arn:aws:sns:{0}:123456789012:some-topic" - .format(conn._client_config.region_name) - ) - attributes["Owner"].should.equal('123456789012') - json.loads(attributes["Policy"]).should.equal(DEFAULT_TOPIC_POLICY) - attributes["DisplayName"].should.equal("") - attributes["SubscriptionsPending"].should.equal('0') - attributes["SubscriptionsConfirmed"].should.equal('0') - attributes["SubscriptionsDeleted"].should.equal('0') - attributes["DeliveryPolicy"].should.equal("") - json.loads(attributes["EffectiveDeliveryPolicy"]).should.equal( - DEFAULT_EFFECTIVE_DELIVERY_POLICY) - - # boto can't handle prefix-mandatory strings: - # i.e. unicode on Python 2 -- u"foobar" - # and bytes on Python 3 -- b"foobar" - if six.PY2: - policy = json.dumps({b"foo": b"bar"}) - displayname = b"My display name" - delivery = json.dumps( - {b"http": {b"defaultHealthyRetryPolicy": {b"numRetries": 5}}}) - else: - policy = json.dumps({u"foo": u"bar"}) - displayname = u"My display name" - delivery = json.dumps( - {u"http": {u"defaultHealthyRetryPolicy": {u"numRetries": 5}}}) - conn.set_topic_attributes(TopicArn=topic_arn, - AttributeName="Policy", - AttributeValue=policy) - conn.set_topic_attributes(TopicArn=topic_arn, - AttributeName="DisplayName", - AttributeValue=displayname) - conn.set_topic_attributes(TopicArn=topic_arn, - AttributeName="DeliveryPolicy", - AttributeValue=delivery) - - attributes = conn.get_topic_attributes(TopicArn=topic_arn)['Attributes'] - attributes["Policy"].should.equal('{"foo": "bar"}') - attributes["DisplayName"].should.equal("My display name") - attributes["DeliveryPolicy"].should.equal( - '{"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}}') - - -@mock_sns -def test_topic_paging(): - conn = boto3.client("sns", region_name="us-east-1") - for index in range(DEFAULT_PAGE_SIZE + int(DEFAULT_PAGE_SIZE / 2)): - conn.create_topic(Name="some-topic_" + str(index)) - - response = conn.list_topics() - topics_list = response["Topics"] - next_token = response["NextToken"] - - len(topics_list).should.equal(DEFAULT_PAGE_SIZE) - int(next_token).should.equal(DEFAULT_PAGE_SIZE) - - response = conn.list_topics(NextToken=next_token) - topics_list = response["Topics"] - response.shouldnt.have("NextToken") - - topics_list.should.have.length_of(int(DEFAULT_PAGE_SIZE / 2)) - - -@mock_sns -def test_add_remove_permissions(): - conn = boto3.client('sns', region_name='us-east-1') - response = conn.create_topic(Name='testpermissions') - - conn.add_permission( - TopicArn=response['TopicArn'], - Label='Test1234', - AWSAccountId=['999999999999'], - ActionName=['AddPermission'] - ) - conn.remove_permission( - TopicArn=response['TopicArn'], - Label='Test1234' - ) +from __future__ import unicode_literals +import boto3 +import six +import json + +import sure # noqa + +from botocore.exceptions import ClientError +from moto import mock_sns +from moto.sns.models import DEFAULT_TOPIC_POLICY, DEFAULT_EFFECTIVE_DELIVERY_POLICY, DEFAULT_PAGE_SIZE + + +@mock_sns +def test_create_and_delete_topic(): + conn = boto3.client("sns", region_name="us-east-1") + for topic_name in ('some-topic', '-some-topic-', '_some-topic_', 'a' * 256): + conn.create_topic(Name=topic_name) + + topics_json = conn.list_topics() + topics = topics_json["Topics"] + topics.should.have.length_of(1) + topics[0]['TopicArn'].should.equal( + "arn:aws:sns:{0}:123456789012:{1}" + .format(conn._client_config.region_name, topic_name) + ) + + # Delete the topic + conn.delete_topic(TopicArn=topics[0]['TopicArn']) + + # And there should now be 0 topics + topics_json = conn.list_topics() + topics = topics_json["Topics"] + topics.should.have.length_of(0) + + +@mock_sns +def test_create_topic_with_attributes(): + conn = boto3.client("sns", region_name="us-east-1") + conn.create_topic(Name='some-topic-with-attribute', Attributes={'DisplayName': 'test-topic'}) + topics_json = conn.list_topics() + topic_arn = topics_json["Topics"][0]['TopicArn'] + + attributes = conn.get_topic_attributes(TopicArn=topic_arn)['Attributes'] + attributes['DisplayName'].should.equal('test-topic') + + +@mock_sns +def test_create_topic_should_be_indempodent(): + conn = boto3.client("sns", region_name="us-east-1") + topic_arn = conn.create_topic(Name="some-topic")['TopicArn'] + conn.set_topic_attributes( + TopicArn=topic_arn, + AttributeName="DisplayName", + AttributeValue="should_be_set" + ) + topic_display_name = conn.get_topic_attributes( + TopicArn=topic_arn + )['Attributes']['DisplayName'] + topic_display_name.should.be.equal("should_be_set") + + #recreate topic to prove indempodentcy + topic_arn = conn.create_topic(Name="some-topic")['TopicArn'] + topic_display_name = conn.get_topic_attributes( + TopicArn=topic_arn + )['Attributes']['DisplayName'] + topic_display_name.should.be.equal("should_be_set") + +@mock_sns +def test_get_missing_topic(): + conn = boto3.client("sns", region_name="us-east-1") + conn.get_topic_attributes.when.called_with( + TopicArn="a-fake-arn").should.throw(ClientError) + +@mock_sns +def test_create_topic_must_meet_constraints(): + conn = boto3.client("sns", region_name="us-east-1") + common_random_chars = [':', ";", "!", "@", "|", "^", "%"] + for char in common_random_chars: + conn.create_topic.when.called_with( + Name="no%s_invalidchar" % char).should.throw(ClientError) + conn.create_topic.when.called_with( + Name="no spaces allowed").should.throw(ClientError) + + +@mock_sns +def test_create_topic_should_be_of_certain_length(): + conn = boto3.client("sns", region_name="us-east-1") + too_short = "" + conn.create_topic.when.called_with( + Name=too_short).should.throw(ClientError) + too_long = "x" * 257 + conn.create_topic.when.called_with( + Name=too_long).should.throw(ClientError) + + +@mock_sns +def test_create_topic_in_multiple_regions(): + for region in ['us-west-1', 'us-west-2']: + conn = boto3.client("sns", region_name=region) + conn.create_topic(Name="some-topic") + list(conn.list_topics()["Topics"]).should.have.length_of(1) + + +@mock_sns +def test_topic_corresponds_to_region(): + for region in ['us-east-1', 'us-west-2']: + conn = boto3.client("sns", region_name=region) + conn.create_topic(Name="some-topic") + topics_json = conn.list_topics() + topic_arn = topics_json["Topics"][0]['TopicArn'] + topic_arn.should.equal( + "arn:aws:sns:{0}:123456789012:some-topic".format(region)) + + +@mock_sns +def test_topic_attributes(): + conn = boto3.client("sns", region_name="us-east-1") + conn.create_topic(Name="some-topic") + + topics_json = conn.list_topics() + topic_arn = topics_json["Topics"][0]['TopicArn'] + + attributes = conn.get_topic_attributes(TopicArn=topic_arn)['Attributes'] + attributes["TopicArn"].should.equal( + "arn:aws:sns:{0}:123456789012:some-topic" + .format(conn._client_config.region_name) + ) + attributes["Owner"].should.equal('123456789012') + json.loads(attributes["Policy"]).should.equal(DEFAULT_TOPIC_POLICY) + attributes["DisplayName"].should.equal("") + attributes["SubscriptionsPending"].should.equal('0') + attributes["SubscriptionsConfirmed"].should.equal('0') + attributes["SubscriptionsDeleted"].should.equal('0') + attributes["DeliveryPolicy"].should.equal("") + json.loads(attributes["EffectiveDeliveryPolicy"]).should.equal( + DEFAULT_EFFECTIVE_DELIVERY_POLICY) + + # boto can't handle prefix-mandatory strings: + # i.e. unicode on Python 2 -- u"foobar" + # and bytes on Python 3 -- b"foobar" + if six.PY2: + policy = json.dumps({b"foo": b"bar"}) + displayname = b"My display name" + delivery = json.dumps( + {b"http": {b"defaultHealthyRetryPolicy": {b"numRetries": 5}}}) + else: + policy = json.dumps({u"foo": u"bar"}) + displayname = u"My display name" + delivery = json.dumps( + {u"http": {u"defaultHealthyRetryPolicy": {u"numRetries": 5}}}) + conn.set_topic_attributes(TopicArn=topic_arn, + AttributeName="Policy", + AttributeValue=policy) + conn.set_topic_attributes(TopicArn=topic_arn, + AttributeName="DisplayName", + AttributeValue=displayname) + conn.set_topic_attributes(TopicArn=topic_arn, + AttributeName="DeliveryPolicy", + AttributeValue=delivery) + + attributes = conn.get_topic_attributes(TopicArn=topic_arn)['Attributes'] + attributes["Policy"].should.equal('{"foo": "bar"}') + attributes["DisplayName"].should.equal("My display name") + attributes["DeliveryPolicy"].should.equal( + '{"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}}') + + +@mock_sns +def test_topic_paging(): + conn = boto3.client("sns", region_name="us-east-1") + for index in range(DEFAULT_PAGE_SIZE + int(DEFAULT_PAGE_SIZE / 2)): + conn.create_topic(Name="some-topic_" + str(index)) + + response = conn.list_topics() + topics_list = response["Topics"] + next_token = response["NextToken"] + + len(topics_list).should.equal(DEFAULT_PAGE_SIZE) + int(next_token).should.equal(DEFAULT_PAGE_SIZE) + + response = conn.list_topics(NextToken=next_token) + topics_list = response["Topics"] + response.shouldnt.have("NextToken") + + topics_list.should.have.length_of(int(DEFAULT_PAGE_SIZE / 2)) + + +@mock_sns +def test_add_remove_permissions(): + conn = boto3.client('sns', region_name='us-east-1') + response = conn.create_topic(Name='testpermissions') + + conn.add_permission( + TopicArn=response['TopicArn'], + Label='Test1234', + AWSAccountId=['999999999999'], + ActionName=['AddPermission'] + ) + conn.remove_permission( + TopicArn=response['TopicArn'], + Label='Test1234' + ) diff --git a/tests/test_sts/test_sts.py b/tests/test_sts/test_sts.py index 61ab76a29..b047a8d13 100644 --- a/tests/test_sts/test_sts.py +++ b/tests/test_sts/test_sts.py @@ -1,84 +1,213 @@ -from __future__ import unicode_literals -import json - -import boto -import boto3 -from freezegun import freeze_time -import sure # noqa - -from moto import mock_sts, mock_sts_deprecated - - -@freeze_time("2012-01-01 12:00:00") -@mock_sts_deprecated -def test_get_session_token(): - conn = boto.connect_sts() - token = conn.get_session_token(duration=123) - - token.expiration.should.equal('2012-01-01T12:02:03.000Z') - token.session_token.should.equal( - "AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT+FvwqnKwRcOIfrRh3c/LTo6UDdyJwOOvEVPvLXCrrrUtdnniCEXAMPLE/IvU1dYUg2RVAJBanLiHb4IgRmpRV3zrkuWJOgQs8IZZaIv2BXIa2R4OlgkBN9bkUDNCJiBeb/AXlzBBko7b15fjrBs2+cTQtpZ3CYWFXG8C5zqx37wnOE49mRl/+OtkIKGO7fAE") - token.access_key.should.equal("AKIAIOSFODNN7EXAMPLE") - token.secret_key.should.equal("wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY") - - -@freeze_time("2012-01-01 12:00:00") -@mock_sts_deprecated -def test_get_federation_token(): - conn = boto.connect_sts() - token = conn.get_federation_token(duration=123, name="Bob") - - token.credentials.expiration.should.equal('2012-01-01T12:02:03.000Z') - token.credentials.session_token.should.equal( - "AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA==") - token.credentials.access_key.should.equal("AKIAIOSFODNN7EXAMPLE") - token.credentials.secret_key.should.equal( - "wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY") - token.federated_user_arn.should.equal( - "arn:aws:sts::123456789012:federated-user/Bob") - token.federated_user_id.should.equal("123456789012:Bob") - - -@freeze_time("2012-01-01 12:00:00") -@mock_sts_deprecated -def test_assume_role(): - conn = boto.connect_sts() - - policy = json.dumps({ - "Statement": [ - { - "Sid": "Stmt13690092345534", - "Action": [ - "S3:ListBucket" - ], - "Effect": "Allow", - "Resource": [ - "arn:aws:s3:::foobar-tester" - ] - }, - ] - }) - s3_role = "arn:aws:iam::123456789012:role/test-role" - role = conn.assume_role(s3_role, "session-name", - policy, duration_seconds=123) - - credentials = role.credentials - credentials.expiration.should.equal('2012-01-01T12:02:03.000Z') - credentials.session_token.should.equal( - "BQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT+FvwqnKwRcOIfrRh3c/LTo6UDdyJwOOvEVPvLXCrrrUtdnniCEXAMPLE/IvU1dYUg2RVAJBanLiHb4IgRmpRV3zrkuWJOgQs8IZZaIv2BXIa2R4OlgkBN9bkUDNCJiBeb/AXlzBBko7b15fjrBs2+cTQtpZ3CYWFXG8C5zqx37wnOE49mRl/+OtkIKGO7fAE") - credentials.access_key.should.equal("AKIAIOSFODNN7EXAMPLE") - credentials.secret_key.should.equal( - "aJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY") - - role.user.arn.should.equal("arn:aws:iam::123456789012:role/test-role") - role.user.assume_role_id.should.contain("session-name") - - -@mock_sts -def test_get_caller_identity(): - identity = boto3.client( - "sts", region_name='us-east-1').get_caller_identity() - - identity['Arn'].should.equal('arn:aws:sts::123456789012:user/moto') - identity['UserId'].should.equal('AKIAIOSFODNN7EXAMPLE') - identity['Account'].should.equal('123456789012') +from __future__ import unicode_literals +import json + +import boto +import boto3 +from botocore.client import ClientError +from freezegun import freeze_time +from nose.tools import assert_raises +import sure # noqa + + +from moto import mock_sts, mock_sts_deprecated, mock_iam, settings +from moto.iam.models import ACCOUNT_ID +from moto.sts.responses import MAX_FEDERATION_TOKEN_POLICY_LENGTH + + +@freeze_time("2012-01-01 12:00:00") +@mock_sts_deprecated +def test_get_session_token(): + conn = boto.connect_sts() + token = conn.get_session_token(duration=123) + + token.expiration.should.equal('2012-01-01T12:02:03.000Z') + token.session_token.should.equal( + "AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT+FvwqnKwRcOIfrRh3c/LTo6UDdyJwOOvEVPvLXCrrrUtdnniCEXAMPLE/IvU1dYUg2RVAJBanLiHb4IgRmpRV3zrkuWJOgQs8IZZaIv2BXIa2R4OlgkBN9bkUDNCJiBeb/AXlzBBko7b15fjrBs2+cTQtpZ3CYWFXG8C5zqx37wnOE49mRl/+OtkIKGO7fAE") + token.access_key.should.equal("AKIAIOSFODNN7EXAMPLE") + token.secret_key.should.equal("wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY") + + +@freeze_time("2012-01-01 12:00:00") +@mock_sts_deprecated +def test_get_federation_token(): + conn = boto.connect_sts() + token_name = "Bob" + token = conn.get_federation_token(duration=123, name=token_name) + + token.credentials.expiration.should.equal('2012-01-01T12:02:03.000Z') + token.credentials.session_token.should.equal( + "AQoDYXdzEPT//////////wEXAMPLEtc764bNrC9SAPBSM22wDOk4x4HIZ8j4FZTwdQWLWsKWHGBuFqwAeMicRXmxfpSPfIeoIYRqTflfKD8YUuwthAx7mSEI/qkPpKPi/kMcGdQrmGdeehM4IC1NtBmUpp2wUE8phUZampKsburEDy0KPkyQDYwT7WZ0wq5VSXDvp75YU9HFvlRd8Tx6q6fE8YQcHNVXAkiY9q6d+xo0rKwT38xVqr7ZD0u0iPPkUL64lIZbqBAz+scqKmlzm8FDrypNC9Yjc8fPOLn9FX9KSYvKTr4rvx3iSIlTJabIQwj2ICCR/oLxBA==") + token.credentials.access_key.should.equal("AKIAIOSFODNN7EXAMPLE") + token.credentials.secret_key.should.equal( + "wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY") + token.federated_user_arn.should.equal( + "arn:aws:sts::{account_id}:federated-user/{token_name}".format(account_id=ACCOUNT_ID, token_name=token_name)) + token.federated_user_id.should.equal(str(ACCOUNT_ID) + ":" + token_name) + + +@freeze_time("2012-01-01 12:00:00") +@mock_sts +def test_assume_role(): + client = boto3.client( + "sts", region_name='us-east-1') + + session_name = "session-name" + policy = json.dumps({ + "Statement": [ + { + "Sid": "Stmt13690092345534", + "Action": [ + "S3:ListBucket" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::foobar-tester" + ] + }, + ] + }) + role_name = "test-role" + s3_role = "arn:aws:iam::{account_id}:role/{role_name}".format(account_id=ACCOUNT_ID, role_name=role_name) + assume_role_response = client.assume_role(RoleArn=s3_role, RoleSessionName=session_name, + Policy=policy, DurationSeconds=900) + + credentials = assume_role_response['Credentials'] + if not settings.TEST_SERVER_MODE: + credentials['Expiration'].isoformat().should.equal('2012-01-01T12:15:00+00:00') + credentials['SessionToken'].should.have.length_of(356) + assert credentials['SessionToken'].startswith("FQoGZXIvYXdzE") + credentials['AccessKeyId'].should.have.length_of(20) + assert credentials['AccessKeyId'].startswith("ASIA") + credentials['SecretAccessKey'].should.have.length_of(40) + + assume_role_response['AssumedRoleUser']['Arn'].should.equal("arn:aws:sts::{account_id}:assumed-role/{role_name}/{session_name}".format( + account_id=ACCOUNT_ID, role_name=role_name, session_name=session_name)) + assert assume_role_response['AssumedRoleUser']['AssumedRoleId'].startswith("AROA") + assert assume_role_response['AssumedRoleUser']['AssumedRoleId'].endswith(":" + session_name) + assume_role_response['AssumedRoleUser']['AssumedRoleId'].should.have.length_of(21 + 1 + len(session_name)) + + +@freeze_time("2012-01-01 12:00:00") +@mock_sts_deprecated +def test_assume_role_with_web_identity(): + conn = boto.connect_sts() + + policy = json.dumps({ + "Statement": [ + { + "Sid": "Stmt13690092345534", + "Action": [ + "S3:ListBucket" + ], + "Effect": "Allow", + "Resource": [ + "arn:aws:s3:::foobar-tester" + ] + }, + ] + }) + role_name = "test-role" + s3_role = "arn:aws:iam::{account_id}:role/{role_name}".format(account_id=ACCOUNT_ID, role_name=role_name) + session_name = "session-name" + role = conn.assume_role_with_web_identity( + s3_role, session_name, policy, duration_seconds=123) + + credentials = role.credentials + credentials.expiration.should.equal('2012-01-01T12:02:03.000Z') + credentials.session_token.should.have.length_of(356) + assert credentials.session_token.startswith("FQoGZXIvYXdzE") + credentials.access_key.should.have.length_of(20) + assert credentials.access_key.startswith("ASIA") + credentials.secret_key.should.have.length_of(40) + + role.user.arn.should.equal("arn:aws:sts::{account_id}:assumed-role/{role_name}/{session_name}".format( + account_id=ACCOUNT_ID, role_name=role_name, session_name=session_name)) + role.user.assume_role_id.should.contain("session-name") + + +@mock_sts +def test_get_caller_identity_with_default_credentials(): + identity = boto3.client( + "sts", region_name='us-east-1').get_caller_identity() + + identity['Arn'].should.equal('arn:aws:sts::{account_id}:user/moto'.format(account_id=ACCOUNT_ID)) + identity['UserId'].should.equal('AKIAIOSFODNN7EXAMPLE') + identity['Account'].should.equal(str(ACCOUNT_ID)) + + +@mock_sts +@mock_iam +def test_get_caller_identity_with_iam_user_credentials(): + iam_client = boto3.client("iam", region_name='us-east-1') + iam_user_name = "new-user" + iam_user = iam_client.create_user(UserName=iam_user_name)['User'] + access_key = iam_client.create_access_key(UserName=iam_user_name)['AccessKey'] + + identity = boto3.client( + "sts", region_name='us-east-1', aws_access_key_id=access_key['AccessKeyId'], + aws_secret_access_key=access_key['SecretAccessKey']).get_caller_identity() + + identity['Arn'].should.equal(iam_user['Arn']) + identity['UserId'].should.equal(iam_user['UserId']) + identity['Account'].should.equal(str(ACCOUNT_ID)) + + +@mock_sts +@mock_iam +def test_get_caller_identity_with_assumed_role_credentials(): + iam_client = boto3.client("iam", region_name='us-east-1') + sts_client = boto3.client("sts", region_name='us-east-1') + iam_role_name = "new-user" + trust_policy_document = { + "Version": "2012-10-17", + "Statement": { + "Effect": "Allow", + "Principal": {"AWS": "arn:aws:iam::{account_id}:root".format(account_id=ACCOUNT_ID)}, + "Action": "sts:AssumeRole" + } + } + iam_role_arn = iam_client.role_arn = iam_client.create_role( + RoleName=iam_role_name, + AssumeRolePolicyDocument=json.dumps(trust_policy_document) + )['Role']['Arn'] + session_name = "new-session" + assumed_role = sts_client.assume_role(RoleArn=iam_role_arn, + RoleSessionName=session_name) + access_key = assumed_role['Credentials'] + + identity = boto3.client( + "sts", region_name='us-east-1', aws_access_key_id=access_key['AccessKeyId'], + aws_secret_access_key=access_key['SecretAccessKey']).get_caller_identity() + + identity['Arn'].should.equal(assumed_role['AssumedRoleUser']['Arn']) + identity['UserId'].should.equal(assumed_role['AssumedRoleUser']['AssumedRoleId']) + identity['Account'].should.equal(str(ACCOUNT_ID)) + + +@mock_sts +def test_federation_token_with_too_long_policy(): + "Trying to get a federation token with a policy longer than 2048 character should fail" + cli = boto3.client("sts", region_name='us-east-1') + resource_tmpl = 'arn:aws:s3:::yyyy-xxxxx-cloud-default/my_default_folder/folder-name-%s/*' + statements = [] + for num in range(30): + statements.append( + { + 'Effect': 'Allow', + 'Action': ['s3:*'], + 'Resource': resource_tmpl % str(num) + } + ) + policy = { + 'Version': '2012-10-17', + 'Statement': statements + } + json_policy = json.dumps(policy) + assert len(json_policy) > MAX_FEDERATION_TOKEN_POLICY_LENGTH + + with assert_raises(ClientError) as exc: + cli.get_federation_token(Name='foo', DurationSeconds=3600, Policy=json_policy) + exc.exception.response['Error']['Code'].should.equal('ValidationError') + exc.exception.response['Error']['Message'].should.contain( + str(MAX_FEDERATION_TOKEN_POLICY_LENGTH) + ) diff --git a/tox.ini b/tox.ini index 18809b52f..52b66711e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27, py36 +envlist = py27, py36, py37 [testenv] setenv =