ELBv2 - Allow IAM certificates when calling modify_listener (#4823)
This commit is contained in:
parent
e1ffd27201
commit
bb6fb1200f
@ -11,7 +11,6 @@ from moto.core.utils import (
|
|||||||
BackendDict,
|
BackendDict,
|
||||||
)
|
)
|
||||||
from moto.ec2.models import ec2_backends
|
from moto.ec2.models import ec2_backends
|
||||||
from moto.acm.models import acm_backends
|
|
||||||
from .utils import make_arn_for_target_group
|
from .utils import make_arn_for_target_group
|
||||||
from .utils import make_arn_for_load_balancer
|
from .utils import make_arn_for_load_balancer
|
||||||
from .exceptions import (
|
from .exceptions import (
|
||||||
@ -582,16 +581,6 @@ class ELBv2Backend(BaseBackend):
|
|||||||
"""
|
"""
|
||||||
return ec2_backends[self.region_name]
|
return ec2_backends[self.region_name]
|
||||||
|
|
||||||
@property
|
|
||||||
def acm_backend(self):
|
|
||||||
"""
|
|
||||||
ACM backend
|
|
||||||
|
|
||||||
:return: ACM Backend
|
|
||||||
:rtype: moto.acm.models.AWSCertificateManagerBackend
|
|
||||||
"""
|
|
||||||
return acm_backends[self.region_name]
|
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
region_name = self.region_name
|
region_name = self.region_name
|
||||||
self.__dict__ = {}
|
self.__dict__ = {}
|
||||||
@ -1420,9 +1409,7 @@ Member must satisfy regular expression pattern: {}".format(
|
|||||||
if certificates:
|
if certificates:
|
||||||
default_cert = certificates[0]
|
default_cert = certificates[0]
|
||||||
default_cert_arn = default_cert["certificate_arn"]
|
default_cert_arn = default_cert["certificate_arn"]
|
||||||
try:
|
if not self._certificate_exists(certificate_arn=default_cert_arn):
|
||||||
self.acm_backend.get_certificate(default_cert_arn)
|
|
||||||
except Exception:
|
|
||||||
raise RESTError(
|
raise RESTError(
|
||||||
"CertificateNotFound",
|
"CertificateNotFound",
|
||||||
"Certificate {0} not found".format(default_cert_arn),
|
"Certificate {0} not found".format(default_cert_arn),
|
||||||
@ -1449,6 +1436,30 @@ Member must satisfy regular expression pattern: {}".format(
|
|||||||
|
|
||||||
return listener
|
return listener
|
||||||
|
|
||||||
|
def _certificate_exists(self, certificate_arn):
|
||||||
|
"""
|
||||||
|
Verify the provided certificate exists in either ACM or IAM
|
||||||
|
"""
|
||||||
|
from moto.acm import acm_backends
|
||||||
|
from moto.acm.models import AWSResourceNotFoundException
|
||||||
|
|
||||||
|
try:
|
||||||
|
acm_backend = acm_backends[self.region_name]
|
||||||
|
acm_backend.get_certificate(certificate_arn)
|
||||||
|
return True
|
||||||
|
except AWSResourceNotFoundException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
from moto.iam import iam_backend
|
||||||
|
|
||||||
|
cert = iam_backend.get_certificate_by_arn(certificate_arn)
|
||||||
|
if cert is not None:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# ACM threw an error, and IAM did not return a certificate
|
||||||
|
# Safe to assume it doesn't exist when we get here
|
||||||
|
return False
|
||||||
|
|
||||||
def _any_listener_using(self, target_group_arn):
|
def _any_listener_using(self, target_group_arn):
|
||||||
for load_balancer in self.load_balancers.values():
|
for load_balancer in self.load_balancers.values():
|
||||||
for listener in load_balancer.listeners.values():
|
for listener in load_balancer.listeners.values():
|
||||||
|
@ -2054,6 +2054,12 @@ class IAMBackend(BaseBackend):
|
|||||||
"The Server Certificate with name {0} cannot be " "found.".format(name)
|
"The Server Certificate with name {0} cannot be " "found.".format(name)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_certificate_by_arn(self, arn):
|
||||||
|
for cert in self.certificates.values():
|
||||||
|
if arn == cert.arn:
|
||||||
|
return cert
|
||||||
|
return None
|
||||||
|
|
||||||
def delete_server_certificate(self, name):
|
def delete_server_certificate(self, name):
|
||||||
cert_id = None
|
cert_id = None
|
||||||
for key, cert in self.certificates.items():
|
for key, cert in self.certificates.items():
|
||||||
|
68
tests/test_elbv2/test_elbv2_integration.py
Normal file
68
tests/test_elbv2/test_elbv2_integration.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import boto3
|
||||||
|
|
||||||
|
from moto import mock_acm, mock_ec2, mock_elbv2, mock_iam
|
||||||
|
|
||||||
|
|
||||||
|
@mock_acm
|
||||||
|
@mock_iam
|
||||||
|
@mock_ec2
|
||||||
|
@mock_elbv2
|
||||||
|
def test_modify_listener_using_iam_certificate():
|
||||||
|
# Verify we can add a listener for a TargetGroup that is already HTTPS
|
||||||
|
client = boto3.client("elbv2", region_name="eu-central-1")
|
||||||
|
acm = boto3.client("acm", region_name="eu-central-1")
|
||||||
|
ec2 = boto3.resource("ec2", region_name="eu-central-1")
|
||||||
|
iam = boto3.client("iam", region_name="us-east-1")
|
||||||
|
|
||||||
|
security_group = ec2.create_security_group(
|
||||||
|
GroupName="a-security-group", Description="First One"
|
||||||
|
)
|
||||||
|
vpc = ec2.create_vpc(CidrBlock="172.28.7.0/24", InstanceTenancy="default")
|
||||||
|
subnet1 = ec2.create_subnet(
|
||||||
|
VpcId=vpc.id, CidrBlock="172.28.7.192/26", AvailabilityZone="eu-central-1a"
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.create_load_balancer(
|
||||||
|
Name="my-lb",
|
||||||
|
Subnets=[subnet1.id],
|
||||||
|
SecurityGroups=[security_group.id],
|
||||||
|
Scheme="internal",
|
||||||
|
Tags=[{"Key": "key_name", "Value": "a_value"}],
|
||||||
|
)
|
||||||
|
|
||||||
|
load_balancer_arn = response.get("LoadBalancers")[0].get("LoadBalancerArn")
|
||||||
|
|
||||||
|
response = client.create_target_group(
|
||||||
|
Name="a-target", Protocol="HTTPS", Port=8443, VpcId=vpc.id,
|
||||||
|
)
|
||||||
|
target_group = response.get("TargetGroups")[0]
|
||||||
|
target_group_arn = target_group["TargetGroupArn"]
|
||||||
|
|
||||||
|
# HTTPS listener
|
||||||
|
response = acm.request_certificate(
|
||||||
|
DomainName="google.com", SubjectAlternativeNames=["google.com"],
|
||||||
|
)
|
||||||
|
google_arn = response["CertificateArn"]
|
||||||
|
response = client.create_listener(
|
||||||
|
LoadBalancerArn=load_balancer_arn,
|
||||||
|
Protocol="HTTPS",
|
||||||
|
Port=443,
|
||||||
|
Certificates=[{"CertificateArn": google_arn}],
|
||||||
|
DefaultActions=[{"Type": "forward", "TargetGroupArn": target_group_arn}],
|
||||||
|
)
|
||||||
|
listener_arn = response["Listeners"][0]["ListenerArn"]
|
||||||
|
|
||||||
|
# Now modify the HTTPS listener with an IAM certificate
|
||||||
|
resp = iam.upload_server_certificate(
|
||||||
|
ServerCertificateName="certname",
|
||||||
|
CertificateBody="certbody",
|
||||||
|
PrivateKey="privatekey",
|
||||||
|
)
|
||||||
|
iam_arn = resp["ServerCertificateMetadata"]["Arn"]
|
||||||
|
|
||||||
|
listener = client.modify_listener(
|
||||||
|
ListenerArn=listener_arn,
|
||||||
|
Certificates=[{"CertificateArn": iam_arn,},],
|
||||||
|
DefaultActions=[{"Type": "forward", "TargetGroupArn": target_group_arn}],
|
||||||
|
)["Listeners"][0]
|
||||||
|
listener["Certificates"].should.equal([{"CertificateArn": iam_arn}])
|
Loading…
Reference in New Issue
Block a user