Merge branch 'master' into add-organizations-tags

This commit is contained in:
Anton Grübel 2019-11-22 16:35:20 +01:00 committed by GitHub
commit 57c97e367e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 819 additions and 86 deletions

View File

@ -1,4 +1,4 @@
dist: xenial dist: bionic
language: python language: python
services: services:
- docker - docker
@ -54,7 +54,7 @@ deploy:
on: on:
branch: branch:
- master - master
cleanup: false skip_cleanup: true
skip_existing: true skip_existing: true
# - provider: pypi # - provider: pypi
# distributions: sdist bdist_wheel # distributions: sdist bdist_wheel

View File

@ -171,7 +171,7 @@
- [ ] update_webhook - [ ] update_webhook
## apigateway ## apigateway
24% implemented 25% implemented
- [ ] create_api_key - [ ] create_api_key
- [ ] create_authorizer - [ ] create_authorizer
- [ ] create_base_path_mapping - [ ] create_base_path_mapping
@ -204,7 +204,7 @@
- [ ] delete_request_validator - [ ] delete_request_validator
- [X] delete_resource - [X] delete_resource
- [X] delete_rest_api - [X] delete_rest_api
- [ ] delete_stage - [X] delete_stage
- [X] delete_usage_plan - [X] delete_usage_plan
- [X] delete_usage_plan_key - [X] delete_usage_plan_key
- [ ] delete_vpc_link - [ ] delete_vpc_link
@ -687,12 +687,17 @@
## ce ## ce
0% implemented 0% implemented
- [ ] get_cost_and_usage - [ ] get_cost_and_usage
- [ ] get_cost_and_usage_with_resources
- [ ] get_cost_forecast - [ ] get_cost_forecast
- [ ] get_dimension_values - [ ] get_dimension_values
- [ ] get_reservation_coverage - [ ] get_reservation_coverage
- [ ] get_reservation_purchase_recommendation - [ ] get_reservation_purchase_recommendation
- [ ] get_reservation_utilization - [ ] get_reservation_utilization
- [ ] get_rightsizing_recommendation - [ ] get_rightsizing_recommendation
- [ ] get_savings_plans_coverage
- [ ] get_savings_plans_purchase_recommendation
- [ ] get_savings_plans_utilization
- [ ] get_savings_plans_utilization_details
- [ ] get_tags - [ ] get_tags
- [ ] get_usage_forecast - [ ] get_usage_forecast
@ -701,6 +706,7 @@
- [ ] associate_phone_number_with_user - [ ] associate_phone_number_with_user
- [ ] associate_phone_numbers_with_voice_connector - [ ] associate_phone_numbers_with_voice_connector
- [ ] associate_phone_numbers_with_voice_connector_group - [ ] associate_phone_numbers_with_voice_connector_group
- [ ] batch_create_room_membership
- [ ] batch_delete_phone_number - [ ] batch_delete_phone_number
- [ ] batch_suspend_user - [ ] batch_suspend_user
- [ ] batch_unsuspend_user - [ ] batch_unsuspend_user
@ -709,11 +715,15 @@
- [ ] create_account - [ ] create_account
- [ ] create_bot - [ ] create_bot
- [ ] create_phone_number_order - [ ] create_phone_number_order
- [ ] create_room
- [ ] create_room_membership
- [ ] create_voice_connector - [ ] create_voice_connector
- [ ] create_voice_connector_group - [ ] create_voice_connector_group
- [ ] delete_account - [ ] delete_account
- [ ] delete_events_configuration - [ ] delete_events_configuration
- [ ] delete_phone_number - [ ] delete_phone_number
- [ ] delete_room
- [ ] delete_room_membership
- [ ] delete_voice_connector - [ ] delete_voice_connector
- [ ] delete_voice_connector_group - [ ] delete_voice_connector_group
- [ ] delete_voice_connector_origination - [ ] delete_voice_connector_origination
@ -731,6 +741,7 @@
- [ ] get_phone_number - [ ] get_phone_number
- [ ] get_phone_number_order - [ ] get_phone_number_order
- [ ] get_phone_number_settings - [ ] get_phone_number_settings
- [ ] get_room
- [ ] get_user - [ ] get_user
- [ ] get_user_settings - [ ] get_user_settings
- [ ] get_voice_connector - [ ] get_voice_connector
@ -745,6 +756,8 @@
- [ ] list_bots - [ ] list_bots
- [ ] list_phone_number_orders - [ ] list_phone_number_orders
- [ ] list_phone_numbers - [ ] list_phone_numbers
- [ ] list_room_memberships
- [ ] list_rooms
- [ ] list_users - [ ] list_users
- [ ] list_voice_connector_groups - [ ] list_voice_connector_groups
- [ ] list_voice_connector_termination_credentials - [ ] list_voice_connector_termination_credentials
@ -766,6 +779,8 @@
- [ ] update_global_settings - [ ] update_global_settings
- [ ] update_phone_number - [ ] update_phone_number
- [ ] update_phone_number_settings - [ ] update_phone_number_settings
- [ ] update_room
- [ ] update_room_membership
- [ ] update_user - [ ] update_user
- [ ] update_user_settings - [ ] update_user_settings
- [ ] update_voice_connector - [ ] update_voice_connector
@ -1003,6 +1018,7 @@
- [ ] delete_suggester - [ ] delete_suggester
- [ ] describe_analysis_schemes - [ ] describe_analysis_schemes
- [ ] describe_availability_options - [ ] describe_availability_options
- [ ] describe_domain_endpoint_options
- [ ] describe_domains - [ ] describe_domains
- [ ] describe_expressions - [ ] describe_expressions
- [ ] describe_index_fields - [ ] describe_index_fields
@ -1012,6 +1028,7 @@
- [ ] index_documents - [ ] index_documents
- [ ] list_domain_names - [ ] list_domain_names
- [ ] update_availability_options - [ ] update_availability_options
- [ ] update_domain_endpoint_options
- [ ] update_scaling_parameters - [ ] update_scaling_parameters
- [ ] update_service_access_policies - [ ] update_service_access_policies
@ -1028,9 +1045,11 @@
- [ ] delete_trail - [ ] delete_trail
- [ ] describe_trails - [ ] describe_trails
- [ ] get_event_selectors - [ ] get_event_selectors
- [ ] get_trail
- [ ] get_trail_status - [ ] get_trail_status
- [ ] list_public_keys - [ ] list_public_keys
- [ ] list_tags - [ ] list_tags
- [ ] list_trails
- [ ] lookup_events - [ ] lookup_events
- [ ] put_event_selectors - [ ] put_event_selectors
- [ ] remove_tags - [ ] remove_tags
@ -1252,6 +1271,22 @@
- [ ] update_team_member - [ ] update_team_member
- [ ] update_user_profile - [ ] update_user_profile
## codestar-notifications
0% implemented
- [ ] create_notification_rule
- [ ] delete_notification_rule
- [ ] delete_target
- [ ] describe_notification_rule
- [ ] list_event_types
- [ ] list_notification_rules
- [ ] list_tags_for_resource
- [ ] list_targets
- [ ] subscribe
- [ ] tag_resource
- [ ] unsubscribe
- [ ] untag_resource
- [ ] update_notification_rule
## cognito-identity ## cognito-identity
28% implemented 28% implemented
- [X] create_identity_pool - [X] create_identity_pool
@ -1545,10 +1580,13 @@
- [ ] list_queues - [ ] list_queues
- [ ] list_routing_profiles - [ ] list_routing_profiles
- [ ] list_security_profiles - [ ] list_security_profiles
- [ ] list_tags_for_resource
- [ ] list_user_hierarchy_groups - [ ] list_user_hierarchy_groups
- [ ] list_users - [ ] list_users
- [ ] start_outbound_voice_contact - [ ] start_outbound_voice_contact
- [ ] stop_contact - [ ] stop_contact
- [ ] tag_resource
- [ ] untag_resource
- [ ] update_contact_attributes - [ ] update_contact_attributes
- [ ] update_user_hierarchy - [ ] update_user_hierarchy
- [ ] update_user_identity_info - [ ] update_user_identity_info
@ -1563,6 +1601,31 @@
- [ ] modify_report_definition - [ ] modify_report_definition
- [ ] put_report_definition - [ ] put_report_definition
## dataexchange
0% implemented
- [ ] cancel_job
- [ ] create_data_set
- [ ] create_job
- [ ] create_revision
- [ ] delete_asset
- [ ] delete_data_set
- [ ] delete_revision
- [ ] get_asset
- [ ] get_data_set
- [ ] get_job
- [ ] get_revision
- [ ] list_data_set_revisions
- [ ] list_data_sets
- [ ] list_jobs
- [ ] list_revision_assets
- [ ] list_tags_for_resource
- [ ] start_job
- [ ] tag_resource
- [ ] untag_resource
- [ ] update_asset
- [ ] update_data_set
- [ ] update_revision
## datapipeline ## datapipeline
42% implemented 42% implemented
- [X] activate_pipeline - [X] activate_pipeline
@ -1586,17 +1649,17 @@
- [ ] validate_pipeline_definition - [ ] validate_pipeline_definition
## datasync ## datasync
0% implemented 22% implemented
- [ ] cancel_task_execution - [X] cancel_task_execution
- [ ] create_agent - [ ] create_agent
- [ ] create_location_efs - [ ] create_location_efs
- [ ] create_location_nfs - [ ] create_location_nfs
- [ ] create_location_s3 - [ ] create_location_s3
- [ ] create_location_smb - [ ] create_location_smb
- [ ] create_task - [X] create_task
- [ ] delete_agent - [ ] delete_agent
- [ ] delete_location - [X] delete_location
- [ ] delete_task - [X] delete_task
- [ ] describe_agent - [ ] describe_agent
- [ ] describe_location_efs - [ ] describe_location_efs
- [ ] describe_location_nfs - [ ] describe_location_nfs
@ -1609,11 +1672,11 @@
- [ ] list_tags_for_resource - [ ] list_tags_for_resource
- [ ] list_task_executions - [ ] list_task_executions
- [ ] list_tasks - [ ] list_tasks
- [ ] start_task_execution - [X] start_task_execution
- [ ] tag_resource - [ ] tag_resource
- [ ] untag_resource - [ ] untag_resource
- [ ] update_agent - [ ] update_agent
- [ ] update_task - [X] update_task
## dax ## dax
0% implemented 0% implemented
@ -1799,6 +1862,9 @@
- [ ] delete_lifecycle_policy - [ ] delete_lifecycle_policy
- [ ] get_lifecycle_policies - [ ] get_lifecycle_policies
- [ ] get_lifecycle_policy - [ ] get_lifecycle_policy
- [ ] list_tags_for_resource
- [ ] tag_resource
- [ ] untag_resource
- [ ] update_lifecycle_policy - [ ] update_lifecycle_policy
## dms ## dms
@ -2461,16 +2527,22 @@
## eks ## eks
0% implemented 0% implemented
- [ ] create_cluster - [ ] create_cluster
- [ ] create_nodegroup
- [ ] delete_cluster - [ ] delete_cluster
- [ ] delete_nodegroup
- [ ] describe_cluster - [ ] describe_cluster
- [ ] describe_nodegroup
- [ ] describe_update - [ ] describe_update
- [ ] list_clusters - [ ] list_clusters
- [ ] list_nodegroups
- [ ] list_tags_for_resource - [ ] list_tags_for_resource
- [ ] list_updates - [ ] list_updates
- [ ] tag_resource - [ ] tag_resource
- [ ] untag_resource - [ ] untag_resource
- [ ] update_cluster_config - [ ] update_cluster_config
- [ ] update_cluster_version - [ ] update_cluster_version
- [ ] update_nodegroup_config
- [ ] update_nodegroup_version
## elasticache ## elasticache
0% implemented 0% implemented
@ -3217,6 +3289,7 @@
- [ ] create_filter - [ ] create_filter
- [ ] create_ip_set - [ ] create_ip_set
- [ ] create_members - [ ] create_members
- [ ] create_publishing_destination
- [ ] create_sample_findings - [ ] create_sample_findings
- [ ] create_threat_intel_set - [ ] create_threat_intel_set
- [ ] decline_invitations - [ ] decline_invitations
@ -3225,7 +3298,9 @@
- [ ] delete_invitations - [ ] delete_invitations
- [ ] delete_ip_set - [ ] delete_ip_set
- [ ] delete_members - [ ] delete_members
- [ ] delete_publishing_destination
- [ ] delete_threat_intel_set - [ ] delete_threat_intel_set
- [ ] describe_publishing_destination
- [ ] disassociate_from_master_account - [ ] disassociate_from_master_account
- [ ] disassociate_members - [ ] disassociate_members
- [ ] get_detector - [ ] get_detector
@ -3244,6 +3319,7 @@
- [ ] list_invitations - [ ] list_invitations
- [ ] list_ip_sets - [ ] list_ip_sets
- [ ] list_members - [ ] list_members
- [ ] list_publishing_destinations
- [ ] list_tags_for_resource - [ ] list_tags_for_resource
- [ ] list_threat_intel_sets - [ ] list_threat_intel_sets
- [ ] start_monitoring_members - [ ] start_monitoring_members
@ -3255,6 +3331,7 @@
- [ ] update_filter - [ ] update_filter
- [ ] update_findings_feedback - [ ] update_findings_feedback
- [ ] update_ip_set - [ ] update_ip_set
- [ ] update_publishing_destination
- [ ] update_threat_intel_set - [ ] update_threat_intel_set
## health ## health
@ -3267,7 +3344,7 @@
- [ ] describe_events - [ ] describe_events
## iam ## iam
62% implemented 65% implemented
- [ ] add_client_id_to_open_id_connect_provider - [ ] add_client_id_to_open_id_connect_provider
- [X] add_role_to_instance_profile - [X] add_role_to_instance_profile
- [X] add_user_to_group - [X] add_user_to_group
@ -3293,7 +3370,7 @@
- [X] delete_access_key - [X] delete_access_key
- [X] delete_account_alias - [X] delete_account_alias
- [X] delete_account_password_policy - [X] delete_account_password_policy
- [ ] delete_group - [X] delete_group
- [ ] delete_group_policy - [ ] delete_group_policy
- [ ] delete_instance_profile - [ ] delete_instance_profile
- [X] delete_login_profile - [X] delete_login_profile
@ -3323,7 +3400,7 @@
- [X] get_access_key_last_used - [X] get_access_key_last_used
- [X] get_account_authorization_details - [X] get_account_authorization_details
- [X] get_account_password_policy - [X] get_account_password_policy
- [ ] get_account_summary - [X] get_account_summary
- [ ] get_context_keys_for_custom_policy - [ ] get_context_keys_for_custom_policy
- [ ] get_context_keys_for_principal_policy - [ ] get_context_keys_for_principal_policy
- [X] get_credential_report - [X] get_credential_report
@ -3405,7 +3482,7 @@
- [X] update_signing_certificate - [X] update_signing_certificate
- [ ] update_ssh_public_key - [ ] update_ssh_public_key
- [X] update_user - [X] update_user
- [ ] upload_server_certificate - [X] upload_server_certificate
- [X] upload_signing_certificate - [X] upload_signing_certificate
- [ ] upload_ssh_public_key - [ ] upload_ssh_public_key
@ -3459,7 +3536,7 @@
- [ ] update_assessment_target - [ ] update_assessment_target
## iot ## iot
23% implemented 22% implemented
- [ ] accept_certificate_transfer - [ ] accept_certificate_transfer
- [ ] add_thing_to_billing_group - [ ] add_thing_to_billing_group
- [X] add_thing_to_thing_group - [X] add_thing_to_thing_group
@ -3544,11 +3621,13 @@
- [X] detach_thing_principal - [X] detach_thing_principal
- [ ] disable_topic_rule - [ ] disable_topic_rule
- [ ] enable_topic_rule - [ ] enable_topic_rule
- [ ] get_cardinality
- [ ] get_effective_policies - [ ] get_effective_policies
- [ ] get_indexing_configuration - [ ] get_indexing_configuration
- [ ] get_job_document - [ ] get_job_document
- [ ] get_logging_options - [ ] get_logging_options
- [ ] get_ota_update - [ ] get_ota_update
- [ ] get_percentiles
- [X] get_policy - [X] get_policy
- [ ] get_policy_version - [ ] get_policy_version
- [ ] get_registration_code - [ ] get_registration_code
@ -4295,6 +4374,15 @@
- [ ] reject_invitation - [ ] reject_invitation
- [ ] vote_on_proposal - [ ] vote_on_proposal
## marketplace-catalog
0% implemented
- [ ] cancel_change_set
- [ ] describe_change_set
- [ ] describe_entity
- [ ] list_change_sets
- [ ] list_entities
- [ ] start_change_set
## marketplace-entitlement ## marketplace-entitlement
0% implemented 0% implemented
- [ ] get_entitlements - [ ] get_entitlements
@ -4773,6 +4861,7 @@
## personalize ## personalize
0% implemented 0% implemented
- [ ] create_batch_inference_job
- [ ] create_campaign - [ ] create_campaign
- [ ] create_dataset - [ ] create_dataset
- [ ] create_dataset_group - [ ] create_dataset_group
@ -4788,6 +4877,7 @@
- [ ] delete_schema - [ ] delete_schema
- [ ] delete_solution - [ ] delete_solution
- [ ] describe_algorithm - [ ] describe_algorithm
- [ ] describe_batch_inference_job
- [ ] describe_campaign - [ ] describe_campaign
- [ ] describe_dataset - [ ] describe_dataset
- [ ] describe_dataset_group - [ ] describe_dataset_group
@ -4799,6 +4889,7 @@
- [ ] describe_solution - [ ] describe_solution
- [ ] describe_solution_version - [ ] describe_solution_version
- [ ] get_solution_metrics - [ ] get_solution_metrics
- [ ] list_batch_inference_jobs
- [ ] list_campaigns - [ ] list_campaigns
- [ ] list_dataset_groups - [ ] list_dataset_groups
- [ ] list_dataset_import_jobs - [ ] list_dataset_import_jobs
@ -4831,6 +4922,7 @@
- [ ] create_email_template - [ ] create_email_template
- [ ] create_export_job - [ ] create_export_job
- [ ] create_import_job - [ ] create_import_job
- [ ] create_journey
- [ ] create_push_template - [ ] create_push_template
- [ ] create_segment - [ ] create_segment
- [ ] create_sms_template - [ ] create_sms_template
@ -4847,6 +4939,7 @@
- [ ] delete_endpoint - [ ] delete_endpoint
- [ ] delete_event_stream - [ ] delete_event_stream
- [ ] delete_gcm_channel - [ ] delete_gcm_channel
- [ ] delete_journey
- [ ] delete_push_template - [ ] delete_push_template
- [ ] delete_segment - [ ] delete_segment
- [ ] delete_sms_channel - [ ] delete_sms_channel
@ -4879,6 +4972,10 @@
- [ ] get_gcm_channel - [ ] get_gcm_channel
- [ ] get_import_job - [ ] get_import_job
- [ ] get_import_jobs - [ ] get_import_jobs
- [ ] get_journey
- [ ] get_journey_date_range_kpi
- [ ] get_journey_execution_activity_metrics
- [ ] get_journey_execution_metrics
- [ ] get_push_template - [ ] get_push_template
- [ ] get_segment - [ ] get_segment
- [ ] get_segment_export_jobs - [ ] get_segment_export_jobs
@ -4890,6 +4987,7 @@
- [ ] get_sms_template - [ ] get_sms_template
- [ ] get_user_endpoints - [ ] get_user_endpoints
- [ ] get_voice_channel - [ ] get_voice_channel
- [ ] list_journeys
- [ ] list_tags_for_resource - [ ] list_tags_for_resource
- [ ] list_templates - [ ] list_templates
- [ ] phone_number_validate - [ ] phone_number_validate
@ -4913,6 +5011,8 @@
- [ ] update_endpoint - [ ] update_endpoint
- [ ] update_endpoints_batch - [ ] update_endpoints_batch
- [ ] update_gcm_channel - [ ] update_gcm_channel
- [ ] update_journey
- [ ] update_journey_state
- [ ] update_push_template - [ ] update_push_template
- [ ] update_segment - [ ] update_segment
- [ ] update_sms_channel - [ ] update_sms_channel
@ -5661,6 +5761,17 @@
0% implemented 0% implemented
- [ ] invoke_endpoint - [ ] invoke_endpoint
## savingsplans
0% implemented
- [ ] create_savings_plan
- [ ] describe_savings_plan_rates
- [ ] describe_savings_plans
- [ ] describe_savings_plans_offering_rates
- [ ] describe_savings_plans_offerings
- [ ] list_tags_for_resource
- [ ] tag_resource
- [ ] untag_resource
## sdb ## sdb
0% implemented 0% implemented
- [ ] batch_delete_attributes - [ ] batch_delete_attributes
@ -5954,6 +6065,51 @@
- [X] verify_email_address - [X] verify_email_address
- [X] verify_email_identity - [X] verify_email_identity
## sesv2
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
## shield ## shield
0% implemented 0% implemented
- [ ] associate_drt_log_bucket - [ ] associate_drt_log_bucket
@ -5984,8 +6140,11 @@
- [ ] list_signing_jobs - [ ] list_signing_jobs
- [ ] list_signing_platforms - [ ] list_signing_platforms
- [ ] list_signing_profiles - [ ] list_signing_profiles
- [ ] list_tags_for_resource
- [ ] put_signing_profile - [ ] put_signing_profile
- [ ] start_signing_job - [ ] start_signing_job
- [ ] tag_resource
- [ ] untag_resource
## sms ## sms
0% implemented 0% implemented
@ -6111,7 +6270,7 @@
- [X] untag_queue - [X] untag_queue
## ssm ## ssm
10% implemented 11% implemented
- [X] add_tags_to_resource - [X] add_tags_to_resource
- [ ] cancel_command - [ ] cancel_command
- [ ] cancel_maintenance_window_execution - [ ] cancel_maintenance_window_execution
@ -6184,7 +6343,7 @@
- [ ] get_ops_item - [ ] get_ops_item
- [ ] get_ops_summary - [ ] get_ops_summary
- [X] get_parameter - [X] get_parameter
- [ ] get_parameter_history - [X] get_parameter_history
- [X] get_parameters - [X] get_parameters
- [X] get_parameters_by_path - [X] get_parameters_by_path
- [ ] get_patch_baseline - [ ] get_patch_baseline
@ -6233,6 +6392,19 @@
- [ ] update_patch_baseline - [ ] update_patch_baseline
- [ ] update_service_setting - [ ] update_service_setting
## sso
0% implemented
- [ ] get_role_credentials
- [ ] list_account_roles
- [ ] list_accounts
- [ ] logout
## sso-oidc
0% implemented
- [ ] create_token
- [ ] register_client
- [ ] start_device_authorization
## stepfunctions ## stepfunctions
36% implemented 36% implemented
- [ ] create_activity - [ ] create_activity
@ -6742,6 +6914,7 @@
- [ ] delete_ip_group - [ ] delete_ip_group
- [ ] delete_tags - [ ] delete_tags
- [ ] delete_workspace_image - [ ] delete_workspace_image
- [ ] deregister_workspace_directory
- [ ] describe_account - [ ] describe_account
- [ ] describe_account_modifications - [ ] describe_account_modifications
- [ ] describe_client_properties - [ ] describe_client_properties
@ -6758,10 +6931,14 @@
- [ ] list_available_management_cidr_ranges - [ ] list_available_management_cidr_ranges
- [ ] modify_account - [ ] modify_account
- [ ] modify_client_properties - [ ] modify_client_properties
- [ ] modify_selfservice_permissions
- [ ] modify_workspace_access_properties
- [ ] modify_workspace_creation_properties
- [ ] modify_workspace_properties - [ ] modify_workspace_properties
- [ ] modify_workspace_state - [ ] modify_workspace_state
- [ ] reboot_workspaces - [ ] reboot_workspaces
- [ ] rebuild_workspaces - [ ] rebuild_workspaces
- [ ] register_workspace_directory
- [ ] restore_workspace - [ ] restore_workspace
- [ ] revoke_ip_rules - [ ] revoke_ip_rules
- [ ] start_workspaces - [ ] start_workspaces

View File

@ -46,8 +46,9 @@ try:
except ImportError: except ImportError:
from backports.tempfile import TemporaryDirectory from backports.tempfile import TemporaryDirectory
# The lambci container is returning a special escape character for the "RequestID" fields. Unicode 033:
_stderr_regex = re.compile(r"START|END|REPORT RequestId: .*") # _stderr_regex = re.compile(r"START|END|REPORT RequestId: .*")
_stderr_regex = re.compile(r"\033\[\d+.*")
_orig_adapter_send = requests.adapters.HTTPAdapter.send _orig_adapter_send = requests.adapters.HTTPAdapter.send
docker_3 = docker.__version__[0] >= "3" docker_3 = docker.__version__[0] >= "3"
@ -444,7 +445,7 @@ class LambdaFunction(BaseModel):
if exit_code != 0: if exit_code != 0:
raise Exception("lambda invoke failed output: {}".format(output)) raise Exception("lambda invoke failed output: {}".format(output))
# strip out RequestId lines # strip out RequestId lines (TODO: This will return an additional '\n' in the response)
output = os.linesep.join( output = os.linesep.join(
[ [
line line

View File

@ -624,7 +624,7 @@ class BatchBackend(BaseBackend):
def get_job_definition(self, identifier): def get_job_definition(self, identifier):
""" """
Get job defintiion by name or ARN Get job definitions by name or ARN
:param identifier: Name or ARN :param identifier: Name or ARN
:type identifier: str :type identifier: str
@ -643,7 +643,7 @@ class BatchBackend(BaseBackend):
def get_job_definitions(self, identifier): def get_job_definitions(self, identifier):
""" """
Get job defintiion by name or ARN Get job definitions by name or ARN
:param identifier: Name or ARN :param identifier: Name or ARN
:type identifier: str :type identifier: str
@ -934,7 +934,7 @@ class BatchBackend(BaseBackend):
self.ecs_backend.delete_cluster(compute_env.ecs_name) self.ecs_backend.delete_cluster(compute_env.ecs_name)
if compute_env.env_type == "MANAGED": if compute_env.env_type == "MANAGED":
# Delete compute envrionment # Delete compute environment
instance_ids = [instance.id for instance in compute_env.instances] instance_ids = [instance.id for instance in compute_env.instances]
self.ec2_backend.terminate_instances(instance_ids) self.ec2_backend.terminate_instances(instance_ids)
@ -1195,7 +1195,7 @@ class BatchBackend(BaseBackend):
depends_on=None, depends_on=None,
container_overrides=None, container_overrides=None,
): ):
# TODO parameters, retries (which is a dict raw from request), job dependancies and container overrides are ignored for now # TODO parameters, retries (which is a dict raw from request), job dependencies and container overrides are ignored for now
# Look for job definition # Look for job definition
job_def = self.get_job_definition(job_def_id) job_def = self.get_job_definition(job_def_id)

View File

@ -44,6 +44,7 @@ class BaseMockAWS(object):
"AWS_ACCESS_KEY_ID": "foobar_key", "AWS_ACCESS_KEY_ID": "foobar_key",
"AWS_SECRET_ACCESS_KEY": "foobar_secret", "AWS_SECRET_ACCESS_KEY": "foobar_secret",
} }
self.default_session_mock = mock.patch("boto3.DEFAULT_SESSION", None)
self.env_variables_mocks = mock.patch.dict(os.environ, FAKE_KEYS) self.env_variables_mocks = mock.patch.dict(os.environ, FAKE_KEYS)
if self.__class__.nested_count == 0: if self.__class__.nested_count == 0:
@ -62,6 +63,7 @@ class BaseMockAWS(object):
self.stop() self.stop()
def start(self, reset=True): def start(self, reset=True):
self.default_session_mock.start()
self.env_variables_mocks.start() self.env_variables_mocks.start()
self.__class__.nested_count += 1 self.__class__.nested_count += 1
@ -72,6 +74,7 @@ class BaseMockAWS(object):
self.enable_patching() self.enable_patching()
def stop(self): def stop(self):
self.default_session_mock.stop()
self.env_variables_mocks.stop() self.env_variables_mocks.stop()
self.__class__.nested_count -= 1 self.__class__.nested_count -= 1

View File

@ -307,7 +307,7 @@ class BaseResponse(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
def _convert(elem, is_last): def _convert(elem, is_last):
if not re.match("^{.*}$", elem): if not re.match("^{.*}$", elem):
return elem return elem
name = elem.replace("{", "").replace("}", "") name = elem.replace("{", "").replace("}", "").replace("+", "")
if is_last: if is_last:
return "(?P<%s>[^/]*)" % name return "(?P<%s>[^/]*)" % name
return "(?P<%s>.*)" % name return "(?P<%s>.*)" % name

View File

@ -153,7 +153,7 @@ class DataSyncResponse(BaseResponse):
task_execution_arn = self._get_param("TaskExecutionArn") task_execution_arn = self._get_param("TaskExecutionArn")
task_execution = self.datasync_backend._get_task_execution(task_execution_arn) task_execution = self.datasync_backend._get_task_execution(task_execution_arn)
result = json.dumps( result = json.dumps(
{"TaskExecutionArn": task_execution.arn, "Status": task_execution.status,} {"TaskExecutionArn": task_execution.arn, "Status": task_execution.status}
) )
if task_execution.status == "SUCCESS": if task_execution.status == "SUCCESS":
self.datasync_backend.tasks[task_execution.task_arn].status = "AVAILABLE" self.datasync_backend.tasks[task_execution.task_arn].status = "AVAILABLE"

View File

@ -4,6 +4,4 @@ from .responses import DataSyncResponse
url_bases = ["https?://(.*?)(datasync)(.*?).amazonaws.com"] url_bases = ["https?://(.*?)(datasync)(.*?).amazonaws.com"]
url_paths = { url_paths = {"{0}/$": DataSyncResponse.dispatch}
"{0}/$": DataSyncResponse.dispatch,
}

View File

@ -316,8 +316,7 @@ class EventsBackend(BaseBackend):
if not event_bus: if not event_bus:
raise JsonRESTError( raise JsonRESTError(
"ResourceNotFoundException", "ResourceNotFoundException", "Event bus {} does not exist.".format(name)
"Event bus {} does not exist.".format(name),
) )
return event_bus return event_bus

View File

@ -261,10 +261,7 @@ class EventsHandler(BaseResponse):
name = self._get_param("Name") name = self._get_param("Name")
event_bus = self.events_backend.describe_event_bus(name) event_bus = self.events_backend.describe_event_bus(name)
response = { response = {"Name": event_bus.name, "Arn": event_bus.arn}
"Name": event_bus.name,
"Arn": event_bus.arn,
}
if event_bus.policy: if event_bus.policy:
response["Policy"] = event_bus.policy response["Policy"] = event_bus.policy
@ -285,10 +282,7 @@ class EventsHandler(BaseResponse):
response = [] response = []
for event_bus in self.events_backend.list_event_buses(name_prefix): for event_bus in self.events_backend.list_event_buses(name_prefix):
event_bus_response = { event_bus_response = {"Name": event_bus.name, "Arn": event_bus.arn}
"Name": event_bus.name,
"Arn": event_bus.arn,
}
if event_bus.policy: if event_bus.policy:
event_bus_response["Policy"] = event_bus.policy event_bus_response["Policy"] = event_bus.policy

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import base64 import base64
import hashlib
import os import os
import random import random
import string import string
@ -475,6 +476,20 @@ class AccessKey(BaseModel):
raise UnformattedGetAttTemplateException() raise UnformattedGetAttTemplateException()
class SshPublicKey(BaseModel):
def __init__(self, user_name, ssh_public_key_body):
self.user_name = user_name
self.ssh_public_key_body = ssh_public_key_body
self.ssh_public_key_id = "APKA" + random_access_key()
self.fingerprint = hashlib.md5(ssh_public_key_body.encode()).hexdigest()
self.status = "Active"
self.upload_date = datetime.utcnow()
@property
def uploaded_iso_8601(self):
return iso_8601_datetime_without_milliseconds(self.upload_date)
class Group(BaseModel): class Group(BaseModel):
def __init__(self, name, path="/"): def __init__(self, name, path="/"):
self.name = name self.name = name
@ -536,6 +551,7 @@ class User(BaseModel):
self.policies = {} self.policies = {}
self.managed_policies = {} self.managed_policies = {}
self.access_keys = [] self.access_keys = []
self.ssh_public_keys = []
self.password = None self.password = None
self.password_reset_required = False self.password_reset_required = False
self.signing_certificates = {} self.signing_certificates = {}
@ -605,6 +621,33 @@ class User(BaseModel):
"The Access Key with id {0} cannot be found".format(access_key_id) "The Access Key with id {0} cannot be found".format(access_key_id)
) )
def upload_ssh_public_key(self, ssh_public_key_body):
pubkey = SshPublicKey(self.name, ssh_public_key_body)
self.ssh_public_keys.append(pubkey)
return pubkey
def get_ssh_public_key(self, ssh_public_key_id):
for key in self.ssh_public_keys:
if key.ssh_public_key_id == ssh_public_key_id:
return key
else:
raise IAMNotFoundException(
"The SSH Public Key with id {0} cannot be found".format(
ssh_public_key_id
)
)
def get_all_ssh_public_keys(self):
return self.ssh_public_keys
def update_ssh_public_key(self, ssh_public_key_id, status):
key = self.get_ssh_public_key(ssh_public_key_id)
key.status = status
def delete_ssh_public_key(self, ssh_public_key_id):
key = self.get_ssh_public_key(ssh_public_key_id)
self.ssh_public_keys.remove(key)
def get_cfn_attribute(self, attribute_name): def get_cfn_attribute(self, attribute_name):
from moto.cloudformation.exceptions import UnformattedGetAttTemplateException from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
@ -736,6 +779,134 @@ class AccountPasswordPolicy(BaseModel):
) )
class AccountSummary(BaseModel):
def __init__(self, iam_backend):
self._iam_backend = iam_backend
self._group_policy_size_quota = 5120
self._instance_profiles_quota = 1000
self._groups_per_user_quota = 10
self._attached_policies_per_user_quota = 10
self._policies_quota = 1500
self._account_mfa_enabled = 0 # Haven't found any information being able to activate MFA for the root account programmatically
self._access_keys_per_user_quota = 2
self._assume_role_policy_size_quota = 2048
self._policy_versions_in_use_quota = 10000
self._global_endpoint_token_version = (
1 # ToDo: Implement set_security_token_service_preferences()
)
self._versions_per_policy_quota = 5
self._attached_policies_per_group_quota = 10
self._policy_size_quota = 6144
self._account_signing_certificates_present = 0 # valid values: 0 | 1
self._users_quota = 5000
self._server_certificates_quota = 20
self._user_policy_size_quota = 2048
self._roles_quota = 1000
self._signing_certificates_per_user_quota = 2
self._role_policy_size_quota = 10240
self._attached_policies_per_role_quota = 10
self._account_access_keys_present = 0 # valid values: 0 | 1
self._groups_quota = 300
@property
def summary_map(self):
return {
"GroupPolicySizeQuota": self._group_policy_size_quota,
"InstanceProfilesQuota": self._instance_profiles_quota,
"Policies": self._policies,
"GroupsPerUserQuota": self._groups_per_user_quota,
"InstanceProfiles": self._instance_profiles,
"AttachedPoliciesPerUserQuota": self._attached_policies_per_user_quota,
"Users": self._users,
"PoliciesQuota": self._policies_quota,
"Providers": self._providers,
"AccountMFAEnabled": self._account_mfa_enabled,
"AccessKeysPerUserQuota": self._access_keys_per_user_quota,
"AssumeRolePolicySizeQuota": self._assume_role_policy_size_quota,
"PolicyVersionsInUseQuota": self._policy_versions_in_use_quota,
"GlobalEndpointTokenVersion": self._global_endpoint_token_version,
"VersionsPerPolicyQuota": self._versions_per_policy_quota,
"AttachedPoliciesPerGroupQuota": self._attached_policies_per_group_quota,
"PolicySizeQuota": self._policy_size_quota,
"Groups": self._groups,
"AccountSigningCertificatesPresent": self._account_signing_certificates_present,
"UsersQuota": self._users_quota,
"ServerCertificatesQuota": self._server_certificates_quota,
"MFADevices": self._mfa_devices,
"UserPolicySizeQuota": self._user_policy_size_quota,
"PolicyVersionsInUse": self._policy_versions_in_use,
"ServerCertificates": self._server_certificates,
"Roles": self._roles,
"RolesQuota": self._roles_quota,
"SigningCertificatesPerUserQuota": self._signing_certificates_per_user_quota,
"MFADevicesInUse": self._mfa_devices_in_use,
"RolePolicySizeQuota": self._role_policy_size_quota,
"AttachedPoliciesPerRoleQuota": self._attached_policies_per_role_quota,
"AccountAccessKeysPresent": self._account_access_keys_present,
"GroupsQuota": self._groups_quota,
}
@property
def _groups(self):
return len(self._iam_backend.groups)
@property
def _instance_profiles(self):
return len(self._iam_backend.instance_profiles)
@property
def _mfa_devices(self):
# Don't know, if hardware devices are also counted here
return len(self._iam_backend.virtual_mfa_devices)
@property
def _mfa_devices_in_use(self):
devices = 0
for user in self._iam_backend.users.values():
devices += len(user.mfa_devices)
return devices
@property
def _policies(self):
customer_policies = [
policy
for policy in self._iam_backend.managed_policies
if not policy.startswith("arn:aws:iam::aws:policy")
]
return len(customer_policies)
@property
def _policy_versions_in_use(self):
attachments = 0
for policy in self._iam_backend.managed_policies.values():
attachments += policy.attachment_count
return attachments
@property
def _providers(self):
providers = len(self._iam_backend.saml_providers) + len(
self._iam_backend.open_id_providers
)
return providers
@property
def _roles(self):
return len(self._iam_backend.roles)
@property
def _server_certificates(self):
return len(self._iam_backend.certificates)
@property
def _users(self):
return len(self._iam_backend.users)
class IAMBackend(BaseBackend): class IAMBackend(BaseBackend):
def __init__(self): def __init__(self):
self.instance_profiles = {} self.instance_profiles = {}
@ -751,6 +922,7 @@ class IAMBackend(BaseBackend):
self.policy_arn_regex = re.compile(r"^arn:aws:iam::[0-9]*:policy/.*$") self.policy_arn_regex = re.compile(r"^arn:aws:iam::[0-9]*:policy/.*$")
self.virtual_mfa_devices = {} self.virtual_mfa_devices = {}
self.account_password_policy = None self.account_password_policy = None
self.account_summary = AccountSummary(self)
super(IAMBackend, self).__init__() super(IAMBackend, self).__init__()
def _init_managed_policies(self): def _init_managed_policies(self):
@ -1162,7 +1334,7 @@ class IAMBackend(BaseBackend):
def get_all_server_certs(self, marker=None): def get_all_server_certs(self, marker=None):
return self.certificates.values() return self.certificates.values()
def upload_server_cert( def upload_server_certificate(
self, cert_name, cert_body, private_key, cert_chain=None, path=None self, cert_name, cert_body, private_key, cert_chain=None, path=None
): ):
certificate_id = random_resource_id() certificate_id = random_resource_id()
@ -1455,6 +1627,26 @@ class IAMBackend(BaseBackend):
user = self.get_user(user_name) user = self.get_user(user_name)
user.delete_access_key(access_key_id) user.delete_access_key(access_key_id)
def upload_ssh_public_key(self, user_name, ssh_public_key_body):
user = self.get_user(user_name)
return user.upload_ssh_public_key(ssh_public_key_body)
def get_ssh_public_key(self, user_name, ssh_public_key_id):
user = self.get_user(user_name)
return user.get_ssh_public_key(ssh_public_key_id)
def get_all_ssh_public_keys(self, user_name):
user = self.get_user(user_name)
return user.get_all_ssh_public_keys()
def update_ssh_public_key(self, user_name, ssh_public_key_id, status):
user = self.get_user(user_name)
return user.update_ssh_public_key(ssh_public_key_id, status)
def delete_ssh_public_key(self, user_name, ssh_public_key_id):
user = self.get_user(user_name)
return user.delete_ssh_public_key(ssh_public_key_id)
def enable_mfa_device( def enable_mfa_device(
self, user_name, serial_number, authentication_code_1, authentication_code_2 self, user_name, serial_number, authentication_code_1, authentication_code_2
): ):
@ -1741,5 +1933,8 @@ class IAMBackend(BaseBackend):
self.account_password_policy = None self.account_password_policy = None
def get_account_summary(self):
return self.account_summary
iam_backend = IAMBackend() iam_backend = IAMBackend()

View File

@ -351,7 +351,7 @@ class IamResponse(BaseResponse):
private_key = self._get_param("PrivateKey") private_key = self._get_param("PrivateKey")
cert_chain = self._get_param("CertificateName") cert_chain = self._get_param("CertificateName")
cert = iam_backend.upload_server_cert( cert = iam_backend.upload_server_certificate(
cert_name, cert_body, private_key, cert_chain=cert_chain, path=path cert_name, cert_body, private_key, cert_chain=cert_chain, path=path
) )
template = self.response_template(UPLOAD_CERT_TEMPLATE) template = self.response_template(UPLOAD_CERT_TEMPLATE)
@ -590,6 +590,46 @@ class IamResponse(BaseResponse):
template = self.response_template(GENERIC_EMPTY_TEMPLATE) template = self.response_template(GENERIC_EMPTY_TEMPLATE)
return template.render(name="DeleteAccessKey") return template.render(name="DeleteAccessKey")
def upload_ssh_public_key(self):
user_name = self._get_param("UserName")
ssh_public_key_body = self._get_param("SSHPublicKeyBody")
key = iam_backend.upload_ssh_public_key(user_name, ssh_public_key_body)
template = self.response_template(UPLOAD_SSH_PUBLIC_KEY_TEMPLATE)
return template.render(key=key)
def get_ssh_public_key(self):
user_name = self._get_param("UserName")
ssh_public_key_id = self._get_param("SSHPublicKeyId")
key = iam_backend.get_ssh_public_key(user_name, ssh_public_key_id)
template = self.response_template(GET_SSH_PUBLIC_KEY_TEMPLATE)
return template.render(key=key)
def list_ssh_public_keys(self):
user_name = self._get_param("UserName")
keys = iam_backend.get_all_ssh_public_keys(user_name)
template = self.response_template(LIST_SSH_PUBLIC_KEYS_TEMPLATE)
return template.render(keys=keys)
def update_ssh_public_key(self):
user_name = self._get_param("UserName")
ssh_public_key_id = self._get_param("SSHPublicKeyId")
status = self._get_param("Status")
iam_backend.update_ssh_public_key(user_name, ssh_public_key_id, status)
template = self.response_template(UPDATE_SSH_PUBLIC_KEY_TEMPLATE)
return template.render()
def delete_ssh_public_key(self):
user_name = self._get_param("UserName")
ssh_public_key_id = self._get_param("SSHPublicKeyId")
iam_backend.delete_ssh_public_key(user_name, ssh_public_key_id)
template = self.response_template(DELETE_SSH_PUBLIC_KEY_TEMPLATE)
return template.render()
def deactivate_mfa_device(self): def deactivate_mfa_device(self):
user_name = self._get_param("UserName") user_name = self._get_param("UserName")
serial_number = self._get_param("SerialNumber") serial_number = self._get_param("SerialNumber")
@ -888,6 +928,12 @@ class IamResponse(BaseResponse):
template = self.response_template(DELETE_ACCOUNT_PASSWORD_POLICY_TEMPLATE) template = self.response_template(DELETE_ACCOUNT_PASSWORD_POLICY_TEMPLATE)
return template.render() return template.render()
def get_account_summary(self):
account_summary = iam_backend.get_account_summary()
template = self.response_template(GET_ACCOUNT_SUMMARY_TEMPLATE)
return template.render(summary_map=account_summary.summary_map)
LIST_ENTITIES_FOR_POLICY_TEMPLATE = """<ListEntitiesForPolicyResponse> LIST_ENTITIES_FOR_POLICY_TEMPLATE = """<ListEntitiesForPolicyResponse>
<ListEntitiesForPolicyResult> <ListEntitiesForPolicyResult>
@ -1690,6 +1736,73 @@ GET_ACCESS_KEY_LAST_USED_TEMPLATE = """
</GetAccessKeyLastUsedResponse> </GetAccessKeyLastUsedResponse>
""" """
UPLOAD_SSH_PUBLIC_KEY_TEMPLATE = """<UploadSSHPublicKeyResponse>
<UploadSSHPublicKeyResult>
<SSHPublicKey>
<UserName>{{ key.user_name }}</UserName>
<SSHPublicKeyBody>{{ key.ssh_public_key_body }}</SSHPublicKeyBody>
<SSHPublicKeyId>{{ key.ssh_public_key_id }}</SSHPublicKeyId>
<Fingerprint>{{ key.fingerprint }}</Fingerprint>
<Status>{{ key.status }}</Status>
<UploadDate>{{ key.uploaded_iso_8601 }}</UploadDate>
</SSHPublicKey>
</UploadSSHPublicKeyResult>
<ResponseMetadata>
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ResponseMetadata>
</UploadSSHPublicKeyResponse>"""
GET_SSH_PUBLIC_KEY_TEMPLATE = """<GetSSHPublicKeyResponse>
<GetSSHPublicKeyResult>
<SSHPublicKey>
<UserName>{{ key.user_name }}</UserName>
<SSHPublicKeyBody>{{ key.ssh_public_key_body }}</SSHPublicKeyBody>
<SSHPublicKeyId>{{ key.ssh_public_key_id }}</SSHPublicKeyId>
<Fingerprint>{{ key.fingerprint }}</Fingerprint>
<Status>{{ key.status }}</Status>
<UploadDate>{{ key.uploaded_iso_8601 }}</UploadDate>
</SSHPublicKey>
</GetSSHPublicKeyResult>
<ResponseMetadata>
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ResponseMetadata>
</GetSSHPublicKeyResponse>"""
LIST_SSH_PUBLIC_KEYS_TEMPLATE = """<ListSSHPublicKeysResponse>
<ListSSHPublicKeysResult>
<SSHPublicKeys>
{% for key in keys %}
<member>
<UserName>{{ key.user_name }}</UserName>
<SSHPublicKeyId>{{ key.ssh_public_key_id }}</SSHPublicKeyId>
<Status>{{ key.status }}</Status>
<UploadDate>{{ key.uploaded_iso_8601 }}</UploadDate>
</member>
{% endfor %}
</SSHPublicKeys>
<IsTruncated>false</IsTruncated>
</ListSSHPublicKeysResult>
<ResponseMetadata>
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ResponseMetadata>
</ListSSHPublicKeysResponse>"""
UPDATE_SSH_PUBLIC_KEY_TEMPLATE = """<UpdateSSHPublicKeyResponse>
<UpdateSSHPublicKeyResult>
</UpdateSSHPublicKeyResult>
<ResponseMetadata>
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ResponseMetadata>
</UpdateSSHPublicKeyResponse>"""
DELETE_SSH_PUBLIC_KEY_TEMPLATE = """<DeleteSSHPublicKeyResponse>
<DeleteSSHPublicKeyResult>
</DeleteSSHPublicKeyResult>
<ResponseMetadata>
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ResponseMetadata>
</DeleteSSHPublicKeyResponse>"""
CREDENTIAL_REPORT_GENERATING = """ CREDENTIAL_REPORT_GENERATING = """
<GenerateCredentialReportResponse> <GenerateCredentialReportResponse>
<GenerateCredentialReportResult> <GenerateCredentialReportResult>
@ -2261,3 +2374,20 @@ DELETE_ACCOUNT_PASSWORD_POLICY_TEMPLATE = """<DeleteAccountPasswordPolicyRespons
<RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId> <RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DeleteAccountPasswordPolicyResponse>""" </DeleteAccountPasswordPolicyResponse>"""
GET_ACCOUNT_SUMMARY_TEMPLATE = """<GetAccountSummaryResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<GetAccountSummaryResult>
<SummaryMap>
{% for key, value in summary_map.items() %}
<entry>
<key>{{ key }}</key>
<value>{{ value }}</value>
</entry>
{% endfor %}
</SummaryMap>
</GetAccountSummaryResult>
<ResponseMetadata>
<RequestId>85cb9b90-ac28-11e4-a88d-97964EXAMPLE</RequestId>
</ResponseMetadata>
</GetAccountSummaryResponse>"""

View File

@ -125,7 +125,7 @@ class HTTPrettyRequest(BaseHTTPRequestHandler, BaseClass):
internal `parse_request` method. internal `parse_request` method.
It also replaces the `rfile` and `wfile` attributes with StringIO It also replaces the `rfile` and `wfile` attributes with StringIO
instances so that we garantee that it won't make any I/O, neighter instances so that we guarantee that it won't make any I/O, neighter
for writing nor reading. for writing nor reading.
It has some convenience attributes: It has some convenience attributes:

View File

@ -190,7 +190,7 @@ def create_backend_app(service):
index = 2 index = 2
while endpoint in backend_app.view_functions: while endpoint in backend_app.view_functions:
# HACK: Sometimes we map the same view to multiple url_paths. Flask # HACK: Sometimes we map the same view to multiple url_paths. Flask
# requries us to have different names. # requires us to have different names.
endpoint = original_endpoint + str(index) endpoint = original_endpoint + str(index)
index += 1 index += 1

View File

@ -147,7 +147,7 @@ class SESBackend(BaseBackend):
def __type_of_message__(self, destinations): def __type_of_message__(self, destinations):
"""Checks the destination for any special address that could indicate delivery, """Checks the destination for any special address that could indicate delivery,
complaint or bounce like in SES simualtor""" complaint or bounce like in SES simulator"""
alladdress = ( alladdress = (
destinations.get("ToAddresses", []) destinations.get("ToAddresses", [])
+ destinations.get("CcAddresses", []) + destinations.get("CcAddresses", [])

View File

@ -227,7 +227,7 @@ class Subscription(BaseModel):
return False return False
for attribute_values in attribute_values: for attribute_values in attribute_values:
# Even the offical documentation states a 5 digits of accuracy after the decimal point for numerics, in reality it is 6 # Even the official documentation states a 5 digits of accuracy after the decimal point for numerics, in reality it is 6
# https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html#subscription-filter-policy-constraints # https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html#subscription-filter-policy-constraints
if int(attribute_values * 1000000) == int(rule * 1000000): if int(attribute_values * 1000000) == int(rule * 1000000):
return True return True
@ -573,7 +573,7 @@ class SNSBackend(BaseBackend):
combinations = 1 combinations = 1
for rules in six.itervalues(value): for rules in six.itervalues(value):
combinations *= len(rules) combinations *= len(rules)
# Even the offical documentation states the total combination of values must not exceed 100, in reality it is 150 # Even the official documentation states the total combination of values must not exceed 100, in reality it is 150
# https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html#subscription-filter-policy-constraints # https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html#subscription-filter-policy-constraints
if combinations > 150: if combinations > 150:
raise SNSInvalidParameter( raise SNSInvalidParameter(

View File

@ -761,7 +761,7 @@ class SQSBackend(BaseBackend):
new_messages = [] new_messages = []
for message in queue._messages: for message in queue._messages:
# Only delete message if it is not visible and the reciept_handle # Only delete message if it is not visible and the receipt_handle
# matches. # matches.
if message.receipt_handle == receipt_handle: if message.receipt_handle == receipt_handle:
queue.pending_messages.remove(message) queue.pending_messages.remove(message)

View File

@ -430,7 +430,7 @@ class WorkflowExecution(BaseModel):
) )
def fail(self, event_id, details=None, reason=None): def fail(self, event_id, details=None, reason=None):
# TODO: implement lenght constraints on details/reason # TODO: implement length constraints on details/reason
self.execution_status = "CLOSED" self.execution_status = "CLOSED"
self.close_status = "FAILED" self.close_status = "FAILED"
self.close_timestamp = unix_time() self.close_timestamp = unix_time()

View File

@ -563,7 +563,7 @@ def test_create_stage():
api_id = response["id"] api_id = response["id"]
create_method_integration(client, api_id) create_method_integration(client, api_id)
response = client.create_deployment(restApiId=api_id, stageName=stage_name,) response = client.create_deployment(restApiId=api_id, stageName=stage_name)
deployment_id = response["id"] deployment_id = response["id"]
response = client.get_deployment(restApiId=api_id, deploymentId=deployment_id) response = client.get_deployment(restApiId=api_id, deploymentId=deployment_id)

View File

@ -162,7 +162,7 @@ if settings.TEST_SERVER_MODE:
conn = boto3.client("lambda", "us-west-2") conn = boto3.client("lambda", "us-west-2")
conn.create_function( conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python3.7",
Role="test-iam-role", Role="test-iam-role",
Handler="lambda_function.lambda_handler", Handler="lambda_function.lambda_handler",
Code={"ZipFile": get_test_zip_file2()}, Code={"ZipFile": get_test_zip_file2()},
@ -184,18 +184,20 @@ if settings.TEST_SERVER_MODE:
vol.id, vol.id,
vol.state, vol.state,
vol.size, vol.size,
json.dumps(in_data), json.dumps(in_data).replace(
" ", ""
), # Makes the tests pass as the result is missing the whitespace
) )
log_result = base64.b64decode(result["LogResult"]).decode("utf-8") log_result = base64.b64decode(result["LogResult"]).decode("utf-8")
# fix for running under travis (TODO: investigate why it has an extra newline) # The Docker lambda invocation will return an additional '\n', so need to replace it:
log_result = log_result.replace("\n\n", "\n") log_result = log_result.replace("\n\n", "\n")
log_result.should.equal(msg) log_result.should.equal(msg)
payload = result["Payload"].read().decode("utf-8") payload = result["Payload"].read().decode("utf-8")
# fix for running under travis (TODO: investigate why it has an extra newline) # The Docker lambda invocation will return an additional '\n', so need to replace it:
payload = payload.replace("\n\n", "\n") payload = payload.replace("\n\n", "\n")
payload.should.equal(msg) payload.should.equal(msg)
@ -999,10 +1001,10 @@ def test_list_versions_by_function_for_nonexistent_function():
@mock_lambda @mock_lambda
@mock_sqs @mock_sqs
def test_create_event_source_mapping(): def test_create_event_source_mapping():
sqs = boto3.resource("sqs") sqs = boto3.resource("sqs", region_name="us-east-1")
queue = sqs.create_queue(QueueName="test-sqs-queue1") queue = sqs.create_queue(QueueName="test-sqs-queue1")
conn = boto3.client("lambda") conn = boto3.client("lambda", region_name="us-east-1")
func = conn.create_function( func = conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python2.7",
@ -1028,11 +1030,11 @@ def test_create_event_source_mapping():
@mock_lambda @mock_lambda
@mock_sqs @mock_sqs
def test_invoke_function_from_sqs(): def test_invoke_function_from_sqs():
logs_conn = boto3.client("logs") logs_conn = boto3.client("logs", region_name="us-east-1")
sqs = boto3.resource("sqs") sqs = boto3.resource("sqs", region_name="us-east-1")
queue = sqs.create_queue(QueueName="test-sqs-queue1") queue = sqs.create_queue(QueueName="test-sqs-queue1")
conn = boto3.client("lambda") conn = boto3.client("lambda", region_name="us-east-1")
func = conn.create_function( func = conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python2.7",
@ -1052,7 +1054,7 @@ def test_invoke_function_from_sqs():
assert response["EventSourceArn"] == queue.attributes["QueueArn"] assert response["EventSourceArn"] == queue.attributes["QueueArn"]
assert response["State"] == "Enabled" assert response["State"] == "Enabled"
sqs_client = boto3.client("sqs") sqs_client = boto3.client("sqs", region_name="us-east-1")
sqs_client.send_message(QueueUrl=queue.url, MessageBody="test") sqs_client.send_message(QueueUrl=queue.url, MessageBody="test")
start = time.time() start = time.time()
while (time.time() - start) < 30: while (time.time() - start) < 30:
@ -1079,8 +1081,8 @@ def test_invoke_function_from_sqs():
@mock_lambda @mock_lambda
@mock_dynamodb2 @mock_dynamodb2
def test_invoke_function_from_dynamodb(): def test_invoke_function_from_dynamodb():
logs_conn = boto3.client("logs") logs_conn = boto3.client("logs", region_name="us-east-1")
dynamodb = boto3.client("dynamodb") dynamodb = boto3.client("dynamodb", region_name="us-east-1")
table_name = "table_with_stream" table_name = "table_with_stream"
table = dynamodb.create_table( table = dynamodb.create_table(
TableName=table_name, TableName=table_name,
@ -1092,7 +1094,7 @@ def test_invoke_function_from_dynamodb():
}, },
) )
conn = boto3.client("lambda") conn = boto3.client("lambda", region_name="us-east-1")
func = conn.create_function( func = conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python2.7",
@ -1139,11 +1141,11 @@ def test_invoke_function_from_dynamodb():
@mock_lambda @mock_lambda
@mock_sqs @mock_sqs
def test_invoke_function_from_sqs_exception(): def test_invoke_function_from_sqs_exception():
logs_conn = boto3.client("logs") logs_conn = boto3.client("logs", region_name="us-east-1")
sqs = boto3.resource("sqs") sqs = boto3.resource("sqs", region_name="us-east-1")
queue = sqs.create_queue(QueueName="test-sqs-queue1") queue = sqs.create_queue(QueueName="test-sqs-queue1")
conn = boto3.client("lambda") conn = boto3.client("lambda", region_name="us-east-1")
func = conn.create_function( func = conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python2.7",
@ -1199,10 +1201,10 @@ def test_invoke_function_from_sqs_exception():
@mock_lambda @mock_lambda
@mock_sqs @mock_sqs
def test_list_event_source_mappings(): def test_list_event_source_mappings():
sqs = boto3.resource("sqs") sqs = boto3.resource("sqs", region_name="us-east-1")
queue = sqs.create_queue(QueueName="test-sqs-queue1") queue = sqs.create_queue(QueueName="test-sqs-queue1")
conn = boto3.client("lambda") conn = boto3.client("lambda", region_name="us-east-1")
func = conn.create_function( func = conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python2.7",
@ -1231,10 +1233,10 @@ def test_list_event_source_mappings():
@mock_lambda @mock_lambda
@mock_sqs @mock_sqs
def test_get_event_source_mapping(): def test_get_event_source_mapping():
sqs = boto3.resource("sqs") sqs = boto3.resource("sqs", region_name="us-east-1")
queue = sqs.create_queue(QueueName="test-sqs-queue1") queue = sqs.create_queue(QueueName="test-sqs-queue1")
conn = boto3.client("lambda") conn = boto3.client("lambda", region_name="us-east-1")
func = conn.create_function( func = conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python2.7",
@ -1261,10 +1263,10 @@ def test_get_event_source_mapping():
@mock_lambda @mock_lambda
@mock_sqs @mock_sqs
def test_update_event_source_mapping(): def test_update_event_source_mapping():
sqs = boto3.resource("sqs") sqs = boto3.resource("sqs", region_name="us-east-1")
queue = sqs.create_queue(QueueName="test-sqs-queue1") queue = sqs.create_queue(QueueName="test-sqs-queue1")
conn = boto3.client("lambda") conn = boto3.client("lambda", region_name="us-east-1")
func1 = conn.create_function( func1 = conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python2.7",
@ -1305,10 +1307,10 @@ def test_update_event_source_mapping():
@mock_lambda @mock_lambda
@mock_sqs @mock_sqs
def test_delete_event_source_mapping(): def test_delete_event_source_mapping():
sqs = boto3.resource("sqs") sqs = boto3.resource("sqs", region_name="us-east-1")
queue = sqs.create_queue(QueueName="test-sqs-queue1") queue = sqs.create_queue(QueueName="test-sqs-queue1")
conn = boto3.client("lambda") conn = boto3.client("lambda", region_name="us-east-1")
func1 = conn.create_function( func1 = conn.create_function(
FunctionName="testFunction", FunctionName="testFunction",
Runtime="python2.7", Runtime="python2.7",

View File

@ -3119,8 +3119,8 @@ def test_sorted_query_with_numerical_sort_key():
# https://github.com/spulec/moto/issues/1874 # https://github.com/spulec/moto/issues/1874
@mock_dynamodb2 @mock_dynamodb2
def test_item_size_is_under_400KB(): def test_item_size_is_under_400KB():
dynamodb = boto3.resource("dynamodb") dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
client = boto3.client("dynamodb") client = boto3.client("dynamodb", region_name="us-east-1")
dynamodb.create_table( dynamodb.create_table(
TableName="moto-test", TableName="moto-test",
@ -3172,7 +3172,7 @@ def assert_failure_due_to_item_size(func, **kwargs):
@mock_dynamodb2 @mock_dynamodb2
# https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#DDB-Query-request-KeyConditionExpression # https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#DDB-Query-request-KeyConditionExpression
def test_hash_key_cannot_use_begins_with_operations(): def test_hash_key_cannot_use_begins_with_operations():
dynamodb = boto3.resource("dynamodb") dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
table = dynamodb.create_table( table = dynamodb.create_table(
TableName="test-table", TableName="test-table",
KeySchema=[{"AttributeName": "key", "KeyType": "HASH"}], KeySchema=[{"AttributeName": "key", "KeyType": "HASH"}],
@ -3201,7 +3201,7 @@ def test_hash_key_cannot_use_begins_with_operations():
@mock_dynamodb2 @mock_dynamodb2
def test_update_supports_complex_expression_attribute_values(): def test_update_supports_complex_expression_attribute_values():
client = boto3.client("dynamodb") client = boto3.client("dynamodb", region_name="us-east-1")
client.create_table( client.create_table(
AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}], AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}],
@ -3237,7 +3237,7 @@ def test_update_supports_complex_expression_attribute_values():
@mock_dynamodb2 @mock_dynamodb2
def test_update_supports_list_append(): def test_update_supports_list_append():
client = boto3.client("dynamodb") client = boto3.client("dynamodb", region_name="us-east-1")
client.create_table( client.create_table(
AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}], AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}],
@ -3272,7 +3272,7 @@ def test_update_supports_list_append():
@mock_dynamodb2 @mock_dynamodb2
def test_update_catches_invalid_list_append_operation(): def test_update_catches_invalid_list_append_operation():
client = boto3.client("dynamodb") client = boto3.client("dynamodb", region_name="us-east-1")
client.create_table( client.create_table(
AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}], AttributeDefinitions=[{"AttributeName": "SHA256", "AttributeType": "S"}],
@ -3335,7 +3335,7 @@ def test_update_item_if_original_value_is_none():
table.update_item( table.update_item(
Key={"job_id": "a"}, Key={"job_id": "a"},
UpdateExpression="SET job_name = :output", UpdateExpression="SET job_name = :output",
ExpressionAttributeValues={":output": "updated",}, ExpressionAttributeValues={":output": "updated"},
) )
table.scan()["Items"][0]["job_name"].should.equal("updated") table.scan()["Items"][0]["job_name"].should.equal("updated")
@ -3354,7 +3354,7 @@ def test_update_nested_item_if_original_value_is_none():
table.update_item( table.update_item(
Key={"job_id": "a"}, Key={"job_id": "a"},
UpdateExpression="SET job_details.job_name = :output", UpdateExpression="SET job_details.job_name = :output",
ExpressionAttributeValues={":output": "updated",}, ExpressionAttributeValues={":output": "updated"},
) )
table.scan()["Items"][0]["job_details"]["job_name"].should.equal("updated") table.scan()["Items"][0]["job_details"]["job_name"].should.equal("updated")

View File

@ -213,7 +213,7 @@ class TestEdges:
resp = conn.update_table( resp = conn.update_table(
TableName="test-streams", TableName="test-streams",
StreamSpecification={"StreamEnabled": True, "StreamViewType": "KEYS_ONLY"}, StreamSpecification={"StreamViewType": "KEYS_ONLY", "StreamEnabled": True},
) )
assert "StreamSpecification" in resp["TableDescription"] assert "StreamSpecification" in resp["TableDescription"]
assert resp["TableDescription"]["StreamSpecification"] == { assert resp["TableDescription"]["StreamSpecification"] == {
@ -227,8 +227,8 @@ class TestEdges:
resp = conn.update_table( resp = conn.update_table(
TableName="test-streams", TableName="test-streams",
StreamSpecification={ StreamSpecification={
"StreamEnabled": True,
"StreamViewType": "OLD_IMAGES", "StreamViewType": "OLD_IMAGES",
"StreamEnabled": True,
}, },
) )
@ -246,7 +246,7 @@ class TestEdges:
{"AttributeName": "color", "AttributeType": "S"}, {"AttributeName": "color", "AttributeType": "S"},
], ],
ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1}, ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1},
StreamSpecification={"StreamEnabled": True, "StreamViewType": "NEW_IMAGES"}, StreamSpecification={"StreamViewType": "NEW_IMAGES", "StreamEnabled": True},
) )
stream_arn = resp["TableDescription"]["LatestStreamArn"] stream_arn = resp["TableDescription"]["LatestStreamArn"]

View File

@ -1316,6 +1316,122 @@ def test_get_access_key_last_used():
resp["UserName"].should.equal(create_key_response["UserName"]) resp["UserName"].should.equal(create_key_response["UserName"])
@mock_iam
def test_upload_ssh_public_key():
iam = boto3.resource("iam", region_name="us-east-1")
client = iam.meta.client
username = "test-user"
iam.create_user(UserName=username)
public_key = MOCK_CERT
resp = client.upload_ssh_public_key(UserName=username, SSHPublicKeyBody=public_key)
pubkey = resp["SSHPublicKey"]
pubkey["SSHPublicKeyBody"].should.equal(public_key)
pubkey["UserName"].should.equal(username)
pubkey["SSHPublicKeyId"].should.have.length_of(20)
assert pubkey["SSHPublicKeyId"].startswith("APKA")
pubkey.should.have.key("Fingerprint")
pubkey["Status"].should.equal("Active")
(
datetime.utcnow() - pubkey["UploadDate"].replace(tzinfo=None)
).seconds.should.be.within(0, 10)
@mock_iam
def test_get_ssh_public_key():
iam = boto3.resource("iam", region_name="us-east-1")
client = iam.meta.client
username = "test-user"
iam.create_user(UserName=username)
public_key = MOCK_CERT
with assert_raises(ClientError):
client.get_ssh_public_key(
UserName=username, SSHPublicKeyId="xxnon-existent-keyxx", Encoding="SSH"
)
resp = client.upload_ssh_public_key(UserName=username, SSHPublicKeyBody=public_key)
ssh_public_key_id = resp["SSHPublicKey"]["SSHPublicKeyId"]
resp = client.get_ssh_public_key(
UserName=username, SSHPublicKeyId=ssh_public_key_id, Encoding="SSH"
)
resp["SSHPublicKey"]["SSHPublicKeyBody"].should.equal(public_key)
@mock_iam
def test_list_ssh_public_keys():
iam = boto3.resource("iam", region_name="us-east-1")
client = iam.meta.client
username = "test-user"
iam.create_user(UserName=username)
public_key = MOCK_CERT
resp = client.list_ssh_public_keys(UserName=username)
resp["SSHPublicKeys"].should.have.length_of(0)
resp = client.upload_ssh_public_key(UserName=username, SSHPublicKeyBody=public_key)
ssh_public_key_id = resp["SSHPublicKey"]["SSHPublicKeyId"]
resp = client.list_ssh_public_keys(UserName=username)
resp["SSHPublicKeys"].should.have.length_of(1)
resp["SSHPublicKeys"][0]["SSHPublicKeyId"].should.equal(ssh_public_key_id)
@mock_iam
def test_update_ssh_public_key():
iam = boto3.resource("iam", region_name="us-east-1")
client = iam.meta.client
username = "test-user"
iam.create_user(UserName=username)
public_key = MOCK_CERT
with assert_raises(ClientError):
client.update_ssh_public_key(
UserName=username, SSHPublicKeyId="xxnon-existent-keyxx", Status="Inactive"
)
resp = client.upload_ssh_public_key(UserName=username, SSHPublicKeyBody=public_key)
ssh_public_key_id = resp["SSHPublicKey"]["SSHPublicKeyId"]
resp["SSHPublicKey"]["Status"].should.equal("Active")
resp = client.update_ssh_public_key(
UserName=username, SSHPublicKeyId=ssh_public_key_id, Status="Inactive"
)
resp = client.get_ssh_public_key(
UserName=username, SSHPublicKeyId=ssh_public_key_id, Encoding="SSH"
)
resp["SSHPublicKey"]["Status"].should.equal("Inactive")
@mock_iam
def test_delete_ssh_public_key():
iam = boto3.resource("iam", region_name="us-east-1")
client = iam.meta.client
username = "test-user"
iam.create_user(UserName=username)
public_key = MOCK_CERT
with assert_raises(ClientError):
client.delete_ssh_public_key(
UserName=username, SSHPublicKeyId="xxnon-existent-keyxx"
)
resp = client.upload_ssh_public_key(UserName=username, SSHPublicKeyBody=public_key)
ssh_public_key_id = resp["SSHPublicKey"]["SSHPublicKeyId"]
resp = client.list_ssh_public_keys(UserName=username)
resp["SSHPublicKeys"].should.have.length_of(1)
resp = client.delete_ssh_public_key(
UserName=username, SSHPublicKeyId=ssh_public_key_id
)
resp = client.list_ssh_public_keys(UserName=username)
resp["SSHPublicKeys"].should.have.length_of(0)
@mock_iam @mock_iam
def test_get_account_authorization_details(): def test_get_account_authorization_details():
test_policy = json.dumps( test_policy = json.dumps(
@ -2362,3 +2478,121 @@ def test_delete_account_password_policy_errors():
client.delete_account_password_policy.when.called_with().should.throw( client.delete_account_password_policy.when.called_with().should.throw(
ClientError, "The account policy with name PasswordPolicy cannot be found." ClientError, "The account policy with name PasswordPolicy cannot be found."
) )
@mock_iam
def test_get_account_summary():
client = boto3.client("iam", region_name="us-east-1")
iam = boto3.resource("iam", region_name="us-east-1")
account_summary = iam.AccountSummary()
account_summary.summary_map.should.equal(
{
"GroupPolicySizeQuota": 5120,
"InstanceProfilesQuota": 1000,
"Policies": 0,
"GroupsPerUserQuota": 10,
"InstanceProfiles": 0,
"AttachedPoliciesPerUserQuota": 10,
"Users": 0,
"PoliciesQuota": 1500,
"Providers": 0,
"AccountMFAEnabled": 0,
"AccessKeysPerUserQuota": 2,
"AssumeRolePolicySizeQuota": 2048,
"PolicyVersionsInUseQuota": 10000,
"GlobalEndpointTokenVersion": 1,
"VersionsPerPolicyQuota": 5,
"AttachedPoliciesPerGroupQuota": 10,
"PolicySizeQuota": 6144,
"Groups": 0,
"AccountSigningCertificatesPresent": 0,
"UsersQuota": 5000,
"ServerCertificatesQuota": 20,
"MFADevices": 0,
"UserPolicySizeQuota": 2048,
"PolicyVersionsInUse": 0,
"ServerCertificates": 0,
"Roles": 0,
"RolesQuota": 1000,
"SigningCertificatesPerUserQuota": 2,
"MFADevicesInUse": 0,
"RolePolicySizeQuota": 10240,
"AttachedPoliciesPerRoleQuota": 10,
"AccountAccessKeysPresent": 0,
"GroupsQuota": 300,
}
)
client.create_instance_profile(InstanceProfileName="test-profile")
client.create_open_id_connect_provider(Url="https://example.com", ThumbprintList=[])
response_policy = client.create_policy(
PolicyName="test-policy", PolicyDocument=MOCK_POLICY
)
client.create_role(RoleName="test-role", AssumeRolePolicyDocument="test policy")
client.attach_role_policy(
RoleName="test-role", PolicyArn=response_policy["Policy"]["Arn"]
)
client.create_saml_provider(
Name="TestSAMLProvider", SAMLMetadataDocument="a" * 1024
)
client.create_group(GroupName="test-group")
client.attach_group_policy(
GroupName="test-group", PolicyArn=response_policy["Policy"]["Arn"]
)
client.create_user(UserName="test-user")
client.attach_user_policy(
UserName="test-user", PolicyArn=response_policy["Policy"]["Arn"]
)
client.enable_mfa_device(
UserName="test-user",
SerialNumber="123456789",
AuthenticationCode1="234567",
AuthenticationCode2="987654",
)
client.create_virtual_mfa_device(VirtualMFADeviceName="test-device")
client.upload_server_certificate(
ServerCertificateName="test-cert",
CertificateBody="cert-body",
PrivateKey="private-key",
)
account_summary.load()
account_summary.summary_map.should.equal(
{
"GroupPolicySizeQuota": 5120,
"InstanceProfilesQuota": 1000,
"Policies": 1,
"GroupsPerUserQuota": 10,
"InstanceProfiles": 1,
"AttachedPoliciesPerUserQuota": 10,
"Users": 1,
"PoliciesQuota": 1500,
"Providers": 2,
"AccountMFAEnabled": 0,
"AccessKeysPerUserQuota": 2,
"AssumeRolePolicySizeQuota": 2048,
"PolicyVersionsInUseQuota": 10000,
"GlobalEndpointTokenVersion": 1,
"VersionsPerPolicyQuota": 5,
"AttachedPoliciesPerGroupQuota": 10,
"PolicySizeQuota": 6144,
"Groups": 1,
"AccountSigningCertificatesPresent": 0,
"UsersQuota": 5000,
"ServerCertificatesQuota": 20,
"MFADevices": 1,
"UserPolicySizeQuota": 2048,
"PolicyVersionsInUse": 3,
"ServerCertificates": 1,
"Roles": 1,
"RolesQuota": 1000,
"SigningCertificatesPerUserQuota": 2,
"MFADevicesInUse": 1,
"RolePolicySizeQuota": 10240,
"AttachedPoliciesPerRoleQuota": 10,
"AccountAccessKeysPresent": 0,
"GroupsQuota": 300,
}
)

View File

@ -524,7 +524,7 @@ def _get_account_id():
global account_id global account_id
if account_id: if account_id:
return account_id return account_id
sts = boto3.client("sts") sts = boto3.client("sts", region_name=region)
identity = sts.get_caller_identity() identity = sts.get_caller_identity()
account_id = identity["Account"] account_id = identity["Account"]
return account_id return account_id