cloudstack-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF GitHub Bot (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (CLOUDSTACK-10010) Some S2S VPN configurations fail to establish a connection
Date Sat, 02 Dec 2017 13:51:01 GMT

    [ https://issues.apache.org/jira/browse/CLOUDSTACK-10010?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16275563#comment-16275563
] 

ASF GitHub Bot commented on CLOUDSTACK-10010:
---------------------------------------------

rhtyd commented on a change in pull request #2190: CLOUDSTACK-10010: Fixed the negotiation
of S2S VPN connections
URL: https://github.com/apache/cloudstack/pull/2190#discussion_r154496827
 
 

 ##########
 File path: test/integration/smoke/test_vpc_vpn.py
 ##########
 @@ -1177,3 +1178,447 @@ def tearDownClass(cls):
             cleanup_resources(cls.apiclient, cls.cleanup)
         except Exception, e:
             raise Exception("Cleanup failed with %s" % e)
+
+
+class TestVPCSite2SiteVPNMultipleOptions(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.logger = logging.getLogger('TestVPCSite2SiteVPNMultipleOptions')
+        cls.stream_handler = logging.StreamHandler()
+        cls.logger.setLevel(logging.DEBUG)
+        cls.logger.addHandler(cls.stream_handler)
+
+        testClient = super(TestVPCSite2SiteVPNMultipleOptions, cls).getClsTestClient()
+        cls.apiclient = testClient.getApiClient()
+        cls.services = Services().services
+
+        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+        cls.domain = get_domain(cls.apiclient)
+
+        cls.compute_offering = ServiceOffering.create(
+            cls.apiclient,
+            cls.services["compute_offering"]
+        )
+
+        cls.account = Account.create(
+            cls.apiclient, services=cls.services["account"])
+
+        cls.hypervisor = testClient.getHypervisorInfo()
+
+        cls.logger.debug("Downloading Template: %s from: %s" % (cls.services["template"][
+                         cls.hypervisor.lower()], cls.services["template"][cls.hypervisor.lower()]["url"]))
+        cls.template = Template.register(cls.apiclient, cls.services["template"][cls.hypervisor.lower(
+        )], cls.zone.id, hypervisor=cls.hypervisor.lower(), account=cls.account.name, domainid=cls.domain.id)
+        cls.template.download(cls.apiclient)
+
+        if cls.template == FAILED:
+            assert False, "get_template() failed to return template"
+
+        cls.logger.debug("Successfully created account: %s, id: \
+                   %s" % (cls.account.name,
+                          cls.account.id))
+
+        cls.cleanup = [cls.account, cls.compute_offering]
+        return
+
+    def _get_ssh_client(self, virtual_machine, services, retries):
+        """ Setup ssh client connection and return connection
+        vm requires attributes public_ip, public_port, username, password """
+
+        try:
+            ssh_client = SshClient(
+                virtual_machine.public_ip,
+                services["virtual_machine"]["ssh_port"],
+                services["virtual_machine"]["username"],
+                services["virtual_machine"]["password"],
+                retries)
+
+        except Exception as e:
+            self.fail("Unable to create ssh connection: " % e)
+
+        self.assertIsNotNone(
+            ssh_client, "Failed to setup ssh connection to vm=%s on public_ip=%s" % (virtual_machine.name,
virtual_machine.public_ip))
+
+        return ssh_client
+
+    def _create_natrule(self, vpc, vm, public_port, private_port, public_ip, network, services=None):
+        self.logger.debug("Creating NAT rule in network for vm with public IP")
+        if not services:
+            self.services["natrule"]["privateport"] = private_port
+            self.services["natrule"]["publicport"] = public_port
+            self.services["natrule"]["startport"] = public_port
+            self.services["natrule"]["endport"] = public_port
+            services = self.services["natrule"]
+
+        nat_rule = NATRule.create(
+            apiclient=self.apiclient,
+            services=services,
+            ipaddressid=public_ip.ipaddress.id,
+            virtual_machine=vm,
+            networkid=network.id
+        )
+        self.assertIsNotNone(
+            nat_rule, "Failed to create NAT Rule for %s" % public_ip.ipaddress.ipaddress)
+        self.logger.debug(
+            "Adding NetworkACL rules to make NAT rule accessible")
+
+        vm.ssh_ip = nat_rule.ipaddress
+        vm.public_ip = nat_rule.ipaddress
+        vm.public_port = int(public_port)
+        return nat_rule
+
+    def _validate_vpc_offering(self, vpc_offering):
+
+        self.logger.debug("Check if the VPC offering is created successfully?")
+        vpc_offs = VpcOffering.list(
+            self.apiclient,
+            id=vpc_offering.id
+        )
+        offering_list = validateList(vpc_offs)
+        self.assertEqual(offering_list[0],
+                         PASS,
+                         "List VPC offerings should return a valid list"
+                         )
+        self.assertEqual(
+            vpc_offering.name,
+            vpc_offs[0].name,
+            "Name of the VPC offering should match with listVPCOff data"
+        )
+        self.logger.debug(
+            "VPC offering is created successfully - %s" %
+            vpc_offering.name)
+        return
+
+    def _create_vpc_offering(self, offering_name):
+
+        vpc_off = None
+        if offering_name is not None:
+
+            self.logger.debug("Creating VPC offering: %s", offering_name)
+            vpc_off = VpcOffering.create(
+                self.apiclient,
+                self.services[offering_name]
+            )
+
+            self._validate_vpc_offering(vpc_off)
+            self.cleanup.append(vpc_off)
+
+        return vpc_off
+
+    @attr(tags=["advanced"], required_hardware="true")
+    def test_01_vpc_site2site_vpn_multiple_options(self):
+        """Test Site 2 Site VPN Across VPCs"""
+        self.logger.debug("Starting test: test_01_vpc_site2site_vpn_multiple_options")
+        # 0) Get the default network offering for VPC
+        networkOffering = NetworkOffering.list(
+            self.apiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks")
+        self.assert_(networkOffering is not None and len(
+            networkOffering) > 0, "No VPC based network offering")
+
+        # Create and Enable VPC offering
+        vpc_offering = self._create_vpc_offering('vpc_offering')
+        self.assert_(vpc_offering is not None, "Failed to create VPC Offering")
+        vpc_offering.update(self.apiclient, state='Enabled')
+
+        vpc1 = None
+        # Create VPC 1
+        try:
+            vpc1 = VPC.create(
+                apiclient=self.apiclient,
+                services=self.services["vpc"],
+                networkDomain="vpc1.vpn",
+                vpcofferingid=vpc_offering.id,
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.domain.id
+            )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(vpc1 is not None, "VPC1 creation failed")
+
+        self.logger.debug("VPC1 %s created" % vpc1.id)
+
+        vpc2 = None
+        # Create VPC 2
+        try:
+            vpc2 = VPC.create(
+                apiclient=self.apiclient,
+                services=self.services["vpc2"],
+                networkDomain="vpc2.vpn",
+                vpcofferingid=vpc_offering.id,
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.domain.id
+            )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(vpc2 is not None, "VPC2 creation failed")
+
+        self.logger.debug("VPC2 %s created" % vpc2.id)
+
+        default_acl = NetworkACLList.list(
+            self.apiclient, name="default_allow")[0]
+
+        ntwk1 = None
+        # Create network in VPC 1
+        try:
+            ntwk1 = Network.create(
+                apiclient=self.apiclient,
+                services=self.services["network_1"],
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                networkofferingid=networkOffering[0].id,
+                zoneid=self.zone.id,
+                vpcid=vpc1.id,
+                aclid=default_acl.id
+            )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assertIsNotNone(ntwk1, "Network failed to create")
+
+        self.logger.debug("Network %s created in VPC %s" % (ntwk1.id, vpc1.id))
+
+        ntwk2 = None
+        # Create network in VPC 2
+        try:
+            ntwk2 = Network.create(
+                apiclient=self.apiclient,
+                services=self.services["network_2"],
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                networkofferingid=networkOffering[0].id,
+                zoneid=self.zone.id,
+                vpcid=vpc2.id,
+                aclid=default_acl.id
+            )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assertIsNotNone(ntwk2, "Network failed to create")
+
+        self.logger.debug("Network %s created in VPC %s" % (ntwk2.id, vpc2.id))
+
+        vm1 = None
+        # Deploy a vm in network 2
+        try:
+            vm1 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
+                                        templateid=self.template.id,
+                                        zoneid=self.zone.id,
+                                        accountid=self.account.name,
+                                        domainid=self.account.domainid,
+                                        serviceofferingid=self.compute_offering.id,
+                                        networkids=ntwk1.id,
+                                        hypervisor=self.hypervisor
+                                        )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(vm1 is not None, "VM failed to deploy")
+            self.assert_(vm1.state == 'Running', "VM is not running")
+
+        self.logger.debug("VM %s deployed in VPC %s" % (vm1.id, vpc1.id))
+
+        vm2 = None
+        # Deploy a vm in network 2
+        try:
+            vm2 = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"],
+                                        templateid=self.template.id,
+                                        zoneid=self.zone.id,
+                                        accountid=self.account.name,
+                                        domainid=self.account.domainid,
+                                        serviceofferingid=self.compute_offering.id,
+                                        networkids=ntwk2.id,
+                                        hypervisor=self.hypervisor
+                                        )
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(vm2 is not None, "VM failed to deploy")
+            self.assert_(vm2.state == 'Running', "VM is not running")
+
+        self.debug("VM %s deployed in VPC %s" % (vm2.id, vpc2.id))
+
+        # default config
+        config = {
+            'ike_enc'       :'aes128',
+            'ike_hash'      :'sha1',
+            'ike_dh'        :'modp1536',
+            'esp_enc'       :'aes128',
+            'esp_hash'      :'sha1',
+            'esp_pfs'       :'modp1536',
+            'psk'           :'secreatKey',
+            'ike_life'      :86400,
+            'esp_life'      :3600,
+            'dpd'           :True,
+            'force_encap'   :False,
+            'passive_1'     :False,
+            'passive_2'     :False
+        }
+        test_confs = [
+            {}, # default
+            {'force_encap': True},
+            {'ike_life': ''},
+            {'esp_life': ''},
+            {'ike_life': '', 'esp_life': ''},
+            {'passive_1': True, 'passive_2': True},
+            {'passive_1': False, 'passive_2': True},
+            {'passive_1': True, 'passive_2': False},
+            {'passive_1': False, 'passive_2': False, 'dpd': False},
+            {'passive_1': True, 'passive_2': True, 'dpd': False},
+            {'passive_1': True, 'passive_2': False, 'dpd': False},
+            {'passive_1': False, 'passive_2': True, 'dpd': False},
+            {'passive_1': True, 'passive_2': False, 'esp_pfs': ''},
+            {'ike_dh': 'modp3072', 'ike_hash': 'sha256', 'esp_pfs': 'modp2048', 'esp_hash':'sha384'},
+            {'ike_dh': 'modp4096', 'ike_hash': 'sha384', 'esp_pfs': 'modp6144', 'esp_hash':'sha512'},
+            {'ike_dh': 'modp8192', 'ike_hash': 'sha512', 'esp_pfs': 'modp8192', 'esp_hash':'sha384'}
+        ]
+
+        # 4) Enable Site-to-Site VPN for VPC
+        vpn1_response = Vpn.createVpnGateway(self.apiclient, vpc1.id)
+        self.assert_(
+            vpn1_response is not None, "Failed to enable VPN Gateway 1")
+        self.logger.debug("VPN gateway for VPC %s enabled" % vpc1.id)
+
+        vpn2_response = Vpn.createVpnGateway(self.apiclient, vpc2.id)
+        self.assert_(
+            vpn2_response is not None, "Failed to enable VPN Gateway 2")
+        self.logger.debug("VPN gateway for VPC %s enabled" % vpc2.id)
+
+        # 5) Add VPN Customer gateway info
+        src_nat_list = PublicIPAddress.list(
+            self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            listall=True,
+            issourcenat=True,
+            vpcid=vpc1.id
+        )
+        ip1 = src_nat_list[0]
+        src_nat_list = PublicIPAddress.list(
+            self.apiclient,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            listall=True,
+            issourcenat=True,
+            vpcid=vpc2.id
+        )
+        ip2 = src_nat_list[0]
+
+        # acquire an extra ip address to use to ssh into vm2
+        try:
+            services = self.services.copy()
+            del services["account"]
+            vm2.public_ip = PublicIPAddress.create(
+                apiclient=self.apiclient,
+                zoneid=self.zone.id,
+                account=self.account.name,
+                domainid=self.account.domainid,
+                services=services,
+                networkid=ntwk2.id,
+                vpcid=vpc2.id)
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(
+                vm2.public_ip is not None, "Failed to aqcuire public ip for vm2")
+
+        natrule = None
+        # Create port forward to be able to ssh into vm2
+        try:
+            natrule = self._create_natrule(
+                vpc2, vm2, 22, 22, vm2.public_ip, ntwk2)
+        except Exception as e:
+            self.fail(e)
+        finally:
+            self.assert_(
+                natrule is not None, "Failed to create portforward for vm2")
+            time.sleep(20)
+
+        # setup ssh connection to vm2
+        ssh_client = self._get_ssh_client(vm2, self.services, 10)
+        if not ssh_client:
+            self.fail("Failed to setup ssh connection to %s" % vm2.public_ip)
+
+        for test_c in test_confs:
+            c = config.copy()
+            c.update(test_c)
+            services = self._get_vpn_config(c)
+            self.logger.debug(services)
+            customer1_response = VpnCustomerGateway.create(
+                self.apiclient,
+                services,
+                "Peer VPC1",
+                ip1.ipaddress,
+                vpc1.cidr,
+                account=self.account.name,
+                domainid=self.account.domainid)
+            self.logger.debug("VPN customer gateway added for VPC %s enabled" % vpc1.id)
+            self.logger.debug(vars(customer1_response))
+
+            customer2_response = VpnCustomerGateway.create(
+                self.apiclient,
+                services,
+                "Peer VPC2",
+                ip2.ipaddress,
+                vpc2.cidr,
+                account=self.account.name,
+                domainid=self.account.domainid)
+            self.logger.debug("VPN customer gateway added for VPC %s enabled" % vpc2.id)
+            self.logger.debug(vars(customer2_response))
+
+            # 6) Connect two VPCs
+            vpnconn1_response = Vpn.createVpnConnection(
+                self.apiclient, customer1_response.id, vpn2_response['id'], c['passive_1'])
+            self.logger.debug("VPN connection created for VPC %s" % vpc2.id)
+            time.sleep(5)
+            vpnconn2_response = Vpn.createVpnConnection(
+                self.apiclient, customer2_response.id, vpn1_response['id'], c['passive_2'])
+            self.logger.debug("VPN connection created for VPC %s" % vpc1.id)
+
+            # Wait for config
+            time.sleep(15)
 
 Review comment:
   Instead of blind `sleeping`, use wait until. Per the docs it may take upto 30 seconds for
the passive connection to become Connected, we can wait upto 60 seconds in that case.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


> Some S2S VPN configurations fail to establish a connection
> ----------------------------------------------------------
>
>                 Key: CLOUDSTACK-10010
>                 URL: https://issues.apache.org/jira/browse/CLOUDSTACK-10010
>             Project: CloudStack
>          Issue Type: Bug
>      Security Level: Public(Anyone can view this level - this is the default.) 
>          Components: Virtual Router
>    Affects Versions: 4.10.0.0
>            Reporter: Will Stevens
>
> I am not sure if a regression was introduced with this PR #2062, but we have found issues
with this configuration now that we have it in production.
> The core of this change is to change the S2S VPN config from {{auto=start}} to {{auto=route}}.
Read more about this setting here: https://wiki.strongswan.org/projects/strongswan/wiki/ConnSection
> We found there to be issues when using {{auto=start}} for both sides of the connection
as there was problem negotiating the connection. Instead the {{auto=route}} config will only
establish a connection once there is an attempt to send traffic over the connection. In order
to attempt to open the connection as soon as the VPN connection is configured, a ping to the
other side of the connection has been added to establish the connection.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Mime
View raw message