Repository: getmoto/moto

Issue:
IAM get-role-policy HTTP status-code 500 Internal Service Error on non-existent policy
Version: 1.3.8

### Steps to duplicate

1. Start moto server: ``moto_server iam``

2. Create a role: ``aws --endpoint-url http://localhost:5000 iam create-role --role-name SPAM --assume-role-policy-document sample_policy.json``

    1. ``sample_policy.json`` contains: ``{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "apigateway.amazonaws.com",
          "lambda.amazonaws.com",
          "events.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
``

    2. Output: ``ROLE	arn:aws:iam::123456789012:role/SPAM	/Users/lanhel/.aws/sample_policy.json	2019-06-20 18:02:08.281434+00:00	/	7wm7nv9xoeoul7mpkbt3	SPAM``

3. Get non-existent policy: ``aws --endpoint-url http://localhost:5000 iam get-role-policy --role-name SPAM --policy-name PARROT``

    1. Output: ``Unable to parse response (syntax error: line 1, column 54), invalid XML received:
b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n<title>500 Internal Server Error</title>\n<h1>Internal Server Error</h1>\n<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>\n'``


### moto_server stack trace

For step 3 the moto_server printed the following to stderr:
> 127.0.0.1 - - [20/Jun/2019 12:07:23] "POST / HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/werkzeug/serving.py", line 303, in run_wsgi
    execute(self.server.app)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/werkzeug/serving.py", line 291, in execute
    application_iter = app(environ, start_response)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/moto/server.py", line 104, in __call__
    return backend_app(environ, start_response)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/moto/core/utils.py", line 140, in __call__
    result = self.callback(request, request.url, {})
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/moto/core/responses.py", line 117, in dispatch
    return cls()._dispatch(*args, **kwargs)
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/moto/core/responses.py", line 200, in _dispatch
    return self.call_action()
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/moto/core/responses.py", line 274, in call_action
    response = method()
  File "/Users/lanhel/Developer/GunIO/Ziff/src/localstack/.venv/lib/python3.7/site-packages/moto/iam/responses.py", line 222, in get_role_policy
    role_name, policy_name)
TypeError: cannot unpack non-iterable NoneType object







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
@@ -685,6 +685,7 @@ def get_role_policy(self, role_name, policy_name):
         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)


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
@@ -311,6 +311,15 @@ def test_put_role_policy():
     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()