Repository: getmoto/moto

Issue:
NotImplementedError: The get_account_summary action has not been implemented
Hi. i tried to test iam `get_account_summary()` but got this error:

```
  File "/home/z/pproj/ecs-refarch-cloudformation/services/ken/src/clients/celery/default/tasks.py", line 1117, in check_root_user_mfa_project
    compliant = iam_conn.get_account_summary()['SummaryMap']['AccountMFAEnabled'] == 1
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/client.py", line 253, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/client.py", line 530, in _make_api_call
    operation_model, request_dict)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/endpoint.py", line 141, in make_request
    return self._send_request(request_dict, operation_model)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/endpoint.py", line 170, in _send_request
    success_response, exception):
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/endpoint.py", line 249, in _needs_retry
    caught_exception=caught_exception, request_dict=request_dict)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/hooks.py", line 227, in emit
    return self._emit(event_name, kwargs)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/hooks.py", line 210, in _emit
    response = handler(**kwargs)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/retryhandler.py", line 183, in __call__
    if self._checker(attempts, response, caught_exception):
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/retryhandler.py", line 251, in __call__
    caught_exception)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/retryhandler.py", line 269, in _should_retry
    return self._checker(attempt_number, response, caught_exception)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/retryhandler.py", line 317, in __call__
    caught_exception)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/retryhandler.py", line 223, in __call__
    attempt_number, caught_exception)
  File "/home/u1/.virtualenvs/ken/lib/python2.7/site-packages/botocore/retryhandler.py", line 359, in _check_caught_exception
    raise caught_exception
NotImplementedError: The get_account_summary action has not been implemented
```


Discussion:

Resolving patch:
diff --git a/moto/iam/models.py b/moto/iam/models.py
--- a/moto/iam/models.py
+++ b/moto/iam/models.py
@@ -736,6 +736,134 @@ def _raise_errors(self):
             )
 
 
+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):
     def __init__(self):
         self.instance_profiles = {}
@@ -751,6 +879,7 @@ def __init__(self):
         self.policy_arn_regex = re.compile(r"^arn:aws:iam::[0-9]*:policy/.*$")
         self.virtual_mfa_devices = {}
         self.account_password_policy = None
+        self.account_summary = AccountSummary(self)
         super(IAMBackend, self).__init__()
 
     def _init_managed_policies(self):
@@ -1158,7 +1287,7 @@ def remove_role_from_instance_profile(self, profile_name, role_name):
     def get_all_server_certs(self, marker=None):
         return self.certificates.values()
 
-    def upload_server_cert(
+    def upload_server_certificate(
         self, cert_name, cert_body, private_key, cert_chain=None, path=None
     ):
         certificate_id = random_resource_id()
@@ -1737,5 +1866,8 @@ def delete_account_password_policy(self):
 
         self.account_password_policy = None
 
+    def get_account_summary(self):
+        return self.account_summary
+
 
 iam_backend = IAMBackend()
diff --git a/moto/iam/responses.py b/moto/iam/responses.py
--- a/moto/iam/responses.py
+++ b/moto/iam/responses.py
@@ -351,7 +351,7 @@ def upload_server_certificate(self):
         private_key = self._get_param("PrivateKey")
         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
         )
         template = self.response_template(UPLOAD_CERT_TEMPLATE)
@@ -888,6 +888,12 @@ def delete_account_password_policy(self):
         template = self.response_template(DELETE_ACCOUNT_PASSWORD_POLICY_TEMPLATE)
         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>
  <ListEntitiesForPolicyResult>
@@ -2261,3 +2267,20 @@ def delete_account_password_policy(self):
     <RequestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</RequestId>
   </ResponseMetadata>
 </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>"""


Test patch:
diff --git a/tests/test_iam/test_iam.py b/tests/test_iam/test_iam.py
--- a/tests/test_iam/test_iam.py
+++ b/tests/test_iam/test_iam.py
@@ -2325,3 +2325,123 @@ def test_delete_account_password_policy_errors():
     client.delete_account_password_policy.when.called_with().should.throw(
         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,
+        }
+    )