Repository: getmoto/moto

Issue:
Error with adding IPv6 CIDR Rules to Security Group
I see the following error when mocking the authorization of an IPv6 address block in a security group:

```
$ python test.py
python version: 3.6.3 (v3.6.3:2c5fed86e0, Oct  3 2017, 00:32:08)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
moto version: 1.3.3
boto3 version: 1.7.33
botocore version: 1.10.33
Traceback (most recent call last):
  File "test.py", line 25, in <module>
    exit(main())
  File "/path/package/lib/python3.6/site-packages/moto/core/models.py", line 71, in wrapper
    result = func(*args, **kwargs)
  File "test.py", line 16, in main
    {"CidrIpv6": "2607:fb10::/32"}]}],
  File "/path/package/lib/python3.6/site-packages/botocore/client.py", line 314, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/path/package/lib/python3.6/site-packages/botocore/client.py", line 599, in _make_api_call
    operation_model, request_dict)
  File "/path/package/lib/python3.6/site-packages/botocore/endpoint.py", line 148, in make_request
    return self._send_request(request_dict, operation_model)
  File "/path/package/lib/python3.6/site-packages/botocore/endpoint.py", line 177, in _send_request
    success_response, exception):
  File "/path/package/lib/python3.6/site-packages/botocore/endpoint.py", line 273, in _needs_retry
    caught_exception=caught_exception, request_dict=request_dict)
  File "/path/package/lib/python3.6/site-packages/botocore/hooks.py", line 227, in emit
    return self._emit(event_name, kwargs)
  File "/path/package/lib/python3.6/site-packages/botocore/hooks.py", line 210, in _emit
    response = handler(**kwargs)
  File "/path/package/lib/python3.6/site-packages/botocore/retryhandler.py", line 183, in __call__
    if self._checker(attempts, response, caught_exception):
  File "/path/package/lib/python3.6/site-packages/botocore/retryhandler.py", line 251, in __call__
    caught_exception)
  File "/path/package/lib/python3.6/site-packages/botocore/retryhandler.py", line 269, in _should_retry
    return self._checker(attempt_number, response, caught_exception)
  File "/path/package/lib/python3.6/site-packages/botocore/retryhandler.py", line 317, in __call__
    caught_exception)
  File "/path/package/lib/python3.6/site-packages/botocore/retryhandler.py", line 223, in __call__
    attempt_number, caught_exception)
  File "/path/package/lib/python3.6/site-packages/botocore/retryhandler.py", line 359, in _check_caught_exception
    raise caught_exception
  File "/path/package/lib/python3.6/site-packages/botocore/endpoint.py", line 222, in _get_response
    proxies=self.proxies, timeout=self.timeout)
  File "/path/package/lib/python3.6/site-packages/botocore/vendored/requests/sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "/path/package/lib/python3.6/site-packages/responses.py", line 572, in unbound_on_send
    return self._on_request(adapter, request, *a, **kwargs)
  File "/path/package/lib/python3.6/site-packages/responses.py", line 548, in _on_request
    match.get_response(request), )
  File "/path/package/lib/python3.6/site-packages/moto/core/models.py", line 137, in get_response
    result = self.callback(request)
  File "/path/package/lib/python3.6/site-packages/moto/core/utils.py", line 172, in __call__
    result = self.callback(request, request.url, request.headers)
  File "/path/package/lib/python3.6/site-packages/moto/core/responses.py", line 116, in dispatch
    return cls()._dispatch(*args, **kwargs)
  File "/path/package/lib/python3.6/site-packages/moto/core/responses.py", line 199, in _dispatch
    return self.call_action()
  File "/path/package/lib/python3.6/site-packages/moto/core/responses.py", line 273, in call_action
    response = method()
  File "/path/package/lib/python3.6/site-packages/moto/ec2/responses/security_groups.py", line 67, in authorize_security_group_ingress
    self.ec2_backend.authorize_security_group_ingress(*args)
  File "/path/package/lib/python3.6/site-packages/moto/ec2/models.py", line 1562, in authorize_security_group_ingress
    group, group.get_number_of_ingress_rules(),
AttributeError: 'NoneType' object has no attribute 'get_number_of_ingress_rules'
``` 

Here's a simple script to repo:
```
import json, boto3, sys, moto, botocore

@moto.mock_ec2
def main():
    print('python version:', sys.version)
    print('moto version:', moto.__version__)
    print('boto3 version:', boto3.__version__)
    print('botocore version:', botocore.__version__)

    client = boto3.client('ec2', 'us-east-1')
    _id = 'sg-123abc'
    client.authorize_security_group_ingress(
        GroupId=_id, IpPermissions=[{"IpProtocol": "-1", "Ipv6Ranges": [ {"CidrIpv6": "fe80::/10"}]}],
    )

    response = client.describe_security_groups(GroupIds=[_id])
    print(json.dumps(response, indent=4))

if __name__ == '__main__':
    exit(main())
```





Discussion:
It looks like the issue is that the security group hasn't been created. You'll need to create it and pass the returned security group id.

Now, we obviously shouldn't throw an error like that. I'm guessing the right behavior is some type of 400 response.

Resolving patch:
diff --git a/moto/ec2/models.py b/moto/ec2/models.py
--- a/moto/ec2/models.py
+++ b/moto/ec2/models.py
@@ -2265,6 +2265,8 @@ def authorize_security_group_ingress(
         vpc_id=None,
     ):
         group = self.get_security_group_by_name_or_id(group_name_or_id, vpc_id)
+        if group is None:
+            raise InvalidSecurityGroupNotFoundError(group_name_or_id)
         if ip_ranges:
             if isinstance(ip_ranges, str) or (
                 six.PY2 and isinstance(ip_ranges, unicode)  # noqa
@@ -2353,6 +2355,8 @@ def authorize_security_group_egress(
     ):
 
         group = self.get_security_group_by_name_or_id(group_name_or_id, vpc_id)
+        if group is None:
+            raise InvalidSecurityGroupNotFoundError(group_name_or_id)
         if ip_ranges and not isinstance(ip_ranges, list):
 
             if isinstance(ip_ranges, str) and "CidrIp" not in ip_ranges:


Test patch:
diff --git a/tests/test_ec2/test_security_groups.py b/tests/test_ec2/test_security_groups.py
--- a/tests/test_ec2/test_security_groups.py
+++ b/tests/test_ec2/test_security_groups.py
@@ -969,3 +969,19 @@ def test_revoke_security_group_egress():
 
     sg.reload()
     sg.ip_permissions_egress.should.have.length_of(0)
+
+
+@mock_ec2
+def test_non_existent_security_group_raises_error_on_authorize():
+    client = boto3.client("ec2", "us-east-1")
+    non_existent_sg = "sg-123abc"
+    expected_error = "The security group '{}' does not exist".format(non_existent_sg)
+    authorize_funcs = [
+        client.authorize_security_group_egress,
+        client.authorize_security_group_ingress,
+    ]
+    for authorize_func in authorize_funcs:
+        with pytest.raises(ClientError) as ex:
+            authorize_func(GroupId=non_existent_sg, IpPermissions=[{}])
+        ex.value.response["Error"]["Code"].should.equal("InvalidGroup.NotFound")
+        ex.value.response["Error"]["Message"].should.equal(expected_error)