| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 1 | from core.models import Service, TenantWithContainer |
| 2 | from django.db import transaction |
| 3 | |
| 4 | VPN_KIND = "vpn" |
| 5 | |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 6 | |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 7 | class VPNService(Service): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 8 | """Defines the Service for creating VPN servers.""" |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 9 | KIND = VPN_KIND |
| 10 | |
| 11 | class Meta: |
| 12 | proxy = True |
| 13 | # The name used to find this service, all directories are named this |
| 14 | app_label = "vpn" |
| 15 | verbose_name = "VPN Service" |
| 16 | |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 17 | |
| Jeremy Mowery | 7ced738 | 2015-12-04 23:58:38 -0700 | [diff] [blame] | 18 | class VPNTenant(TenantWithContainer): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 19 | """Defines the Tenant for creating VPN servers.""" |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 20 | |
| 21 | class Meta: |
| 22 | proxy = True |
| 23 | verbose_name = "VPN Tenant" |
| 24 | |
| 25 | KIND = VPN_KIND |
| 26 | |
| 27 | sync_attributes = ("nat_ip", "nat_mac",) |
| 28 | |
| Jeremy Mowery | 71aec16 | 2016-01-24 17:40:44 -0700 | [diff] [blame] | 29 | default_attributes = {'server_key': None, |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 30 | 'vpn_subnet': None, |
| 31 | 'server_network': None, |
| 32 | 'clients_can_see_each_other': True, |
| Jeremy Mowery | e02d4b6 | 2016-01-10 15:21:52 -0700 | [diff] [blame] | 33 | 'is_persistent': True, |
| Jeremy Mowery | 1eab4fa | 2016-02-02 17:17:20 -0700 | [diff] [blame] | 34 | 'script': None, |
| Jeremy Mowery | 3b1caba | 2016-02-02 23:53:50 -0700 | [diff] [blame] | 35 | 'ca_crt': None, |
| 36 | 'server_crt': None, |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 37 | 'server_key': None, |
| 38 | 'dh': None} |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 39 | |
| 40 | def __init__(self, *args, **kwargs): |
| 41 | vpn_services = VPNService.get_service_objects().all() |
| 42 | if vpn_services: |
| 43 | self._meta.get_field( |
| 44 | "provider_service").default = vpn_services[0].id |
| 45 | super(VPNTenant, self).__init__(*args, **kwargs) |
| 46 | |
| 47 | def save(self, *args, **kwargs): |
| 48 | super(VPNTenant, self).save(*args, **kwargs) |
| 49 | model_policy_vpn_tenant(self.pk) |
| 50 | |
| 51 | def delete(self, *args, **kwargs): |
| 52 | self.cleanup_container() |
| 53 | super(VPNTenant, self).delete(*args, **kwargs) |
| 54 | |
| 55 | @property |
| 56 | def server_key(self): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 57 | """str: The server_key used to connect to the VPN server.""" |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 58 | return self.get_attribute( |
| 59 | "server_key", |
| 60 | self.default_attributes['server_key']) |
| 61 | |
| Jeremy Mowery | 00dc8e7 | 2015-12-04 15:28:40 -0700 | [diff] [blame] | 62 | @server_key.setter |
| Jeremy Mowery | a8ce937 | 2015-12-07 13:38:15 -0700 | [diff] [blame] | 63 | def server_key(self, value): |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 64 | self.set_attribute("server_key", value) |
| 65 | |
| 66 | @property |
| 67 | def addresses(self): |
| Jeremy Mowery | 5055c7b | 2016-01-08 17:25:33 -0700 | [diff] [blame] | 68 | """Mapping[str, str]: The ip, mac address, and subnet of the NAT network of this Tenant.""" |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 69 | if (not self.id) or (not self.instance): |
| 70 | return {} |
| 71 | |
| 72 | addresses = {} |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 73 | for ns in self.instance.ports.all(): |
| 74 | if "nat" in ns.network.name.lower(): |
| Jeremy Mowery | 5055c7b | 2016-01-08 17:25:33 -0700 | [diff] [blame] | 75 | addresses["ip"] = ns.ip |
| 76 | addresses["mac"] = ns.mac |
| 77 | addresses["subnet"] = ns.network.subnet |
| 78 | break |
| 79 | |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 80 | return addresses |
| 81 | |
| 82 | # This getter is necessary because nat_ip is a sync_attribute |
| 83 | @property |
| 84 | def nat_ip(self): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 85 | """str: The IP of this Tenant on the NAT network.""" |
| Jeremy Mowery | 5055c7b | 2016-01-08 17:25:33 -0700 | [diff] [blame] | 86 | return self.addresses.get("ip", None) |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 87 | |
| 88 | # This getter is necessary because nat_mac is a sync_attribute |
| 89 | @property |
| 90 | def nat_mac(self): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 91 | """str: The MAC address of this Tenant on the NAT network.""" |
| Jeremy Mowery | 5055c7b | 2016-01-08 17:25:33 -0700 | [diff] [blame] | 92 | return self.addresses.get("mac", None) |
| Jeremy Mowery | a9b673b | 2016-01-07 21:25:50 -0700 | [diff] [blame] | 93 | |
| 94 | @property |
| 95 | def subnet(self): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 96 | """str: The subnet of this Tenant on the NAT network.""" |
| Jeremy Mowery | 5055c7b | 2016-01-08 17:25:33 -0700 | [diff] [blame] | 97 | return self.addresses.get("subnet", None) |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 98 | |
| Jeremy Mowery | bd2ed3a | 2016-01-05 16:52:43 -0700 | [diff] [blame] | 99 | @property |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 100 | def server_network(self): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 101 | """str: The IP address of the server on the VPN.""" |
| Jeremy Mowery | bd2ed3a | 2016-01-05 16:52:43 -0700 | [diff] [blame] | 102 | return self.get_attribute( |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 103 | 'server_network', |
| 104 | self.default_attributes['server_network']) |
| Jeremy Mowery | bd2ed3a | 2016-01-05 16:52:43 -0700 | [diff] [blame] | 105 | |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 106 | @server_network.setter |
| 107 | def server_network(self, value): |
| 108 | self.set_attribute("server_network", value) |
| Jeremy Mowery | bd2ed3a | 2016-01-05 16:52:43 -0700 | [diff] [blame] | 109 | |
| 110 | @property |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 111 | def vpn_subnet(self): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 112 | """str: The IP address of the client on the VPN.""" |
| Jeremy Mowery | bd2ed3a | 2016-01-05 16:52:43 -0700 | [diff] [blame] | 113 | return self.get_attribute( |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 114 | 'vpn_subnet', |
| 115 | self.default_attributes['vpn_subnet']) |
| Jeremy Mowery | bd2ed3a | 2016-01-05 16:52:43 -0700 | [diff] [blame] | 116 | |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 117 | @vpn_subnet.setter |
| 118 | def vpn_subnet(self, value): |
| 119 | self.set_attribute("vpn_subnet", value) |
| Jeremy Mowery | bd2ed3a | 2016-01-05 16:52:43 -0700 | [diff] [blame] | 120 | |
| 121 | @property |
| Jeremy Mowery | 4a23e7d | 2016-01-06 15:16:33 -0700 | [diff] [blame] | 122 | def is_persistent(self): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 123 | """bool: True if the VPN connection is persistence, false otherwise.""" |
| Jeremy Mowery | 4a23e7d | 2016-01-06 15:16:33 -0700 | [diff] [blame] | 124 | return self.get_attribute( |
| 125 | "is_persistent", |
| 126 | self.default_attributes['is_persistent']) |
| 127 | |
| 128 | @is_persistent.setter |
| 129 | def is_persistent(self, value): |
| 130 | self.set_attribute("is_persistent", value) |
| 131 | |
| 132 | @property |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 133 | def clients_can_see_each_other(self): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 134 | """bool: True if the client can see the subnet of the server, false otherwise.""" |
| Jeremy Mowery | 4a23e7d | 2016-01-06 15:16:33 -0700 | [diff] [blame] | 135 | return self.get_attribute( |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 136 | "clients_can_see_each_other", |
| 137 | self.default_attributes['clients_can_see_each_other']) |
| Jeremy Mowery | 4a23e7d | 2016-01-06 15:16:33 -0700 | [diff] [blame] | 138 | |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 139 | @clients_can_see_each_other.setter |
| 140 | def clients_can_see_each_other(self, value): |
| 141 | self.set_attribute("clients_can_see_each_other", value) |
| Jeremy Mowery | 4a23e7d | 2016-01-06 15:16:33 -0700 | [diff] [blame] | 142 | |
| Jeremy Mowery | e02d4b6 | 2016-01-10 15:21:52 -0700 | [diff] [blame] | 143 | @property |
| Jeremy Mowery | 2822339 | 2016-01-25 20:51:11 -0700 | [diff] [blame] | 144 | def script(self): |
| 145 | """string: The file name of the client script""" |
| Jeremy Mowery | 34aef75 | 2016-01-26 17:58:16 -0700 | [diff] [blame] | 146 | return self.get_attribute("script", self.default_attributes['script']) |
| Jeremy Mowery | e02d4b6 | 2016-01-10 15:21:52 -0700 | [diff] [blame] | 147 | |
| Jeremy Mowery | 2822339 | 2016-01-25 20:51:11 -0700 | [diff] [blame] | 148 | @script.setter |
| 149 | def script(self, value): |
| 150 | self.set_attribute("script", value) |
| Jeremy Mowery | e02d4b6 | 2016-01-10 15:21:52 -0700 | [diff] [blame] | 151 | |
| Jeremy Mowery | 1eab4fa | 2016-02-02 17:17:20 -0700 | [diff] [blame] | 152 | @property |
| Jeremy Mowery | 3b1caba | 2016-02-02 23:53:50 -0700 | [diff] [blame] | 153 | def ca_crt(self): |
| Jeremy Mowery | 1eab4fa | 2016-02-02 17:17:20 -0700 | [diff] [blame] | 154 | """str: the string for the ca certificate""" |
| Jeremy Mowery | 3b1caba | 2016-02-02 23:53:50 -0700 | [diff] [blame] | 155 | return self.get_attribute("ca_crt", self.default_attributes['ca_crt']) |
| Jeremy Mowery | 1eab4fa | 2016-02-02 17:17:20 -0700 | [diff] [blame] | 156 | |
| Jeremy Mowery | 3b1caba | 2016-02-02 23:53:50 -0700 | [diff] [blame] | 157 | @ca_crt.setter |
| 158 | def ca_crt(self, value): |
| 159 | self.set_attribute("ca_crt", value) |
| 160 | |
| 161 | @property |
| 162 | def server_crt(self): |
| 163 | """str: the string for the server certificate""" |
| 164 | return self.get_attribute("server_crt", self.default_attributes['server_crt']) |
| 165 | |
| 166 | @server_crt.setter |
| 167 | def server_crt(self, value): |
| 168 | self.set_attribute("server_crt", value) |
| 169 | |
| 170 | @property |
| 171 | def server_key(self): |
| 172 | """str: the string for the server certificate""" |
| 173 | return self.get_attribute("server_key", self.default_attributes['server_key']) |
| 174 | |
| 175 | @server_key.setter |
| 176 | def server_key(self, value): |
| 177 | self.set_attribute("server_key", value) |
| Jeremy Mowery | 1eab4fa | 2016-02-02 17:17:20 -0700 | [diff] [blame] | 178 | |
| Jeremy Mowery | fd08129 | 2016-02-07 17:07:55 -0700 | [diff] [blame^] | 179 | @property |
| 180 | def dh(self): |
| 181 | """str: the string for the server certificate""" |
| 182 | return self.get_attribute("dh", self.default_attributes['dh']) |
| 183 | |
| 184 | @dh.setter |
| 185 | def server_key(self, value): |
| 186 | self.set_attribute("dh", value) |
| 187 | |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 188 | |
| 189 | def model_policy_vpn_tenant(pk): |
| Jeremy Mowery | 8276082 | 2016-01-08 16:36:22 -0700 | [diff] [blame] | 190 | """Manages the contain for the VPN Tenant.""" |
| Jeremy Mowery | 8b664f7 | 2015-12-04 11:52:16 -0700 | [diff] [blame] | 191 | # This section of code is atomic to prevent race conditions |
| 192 | with transaction.atomic(): |
| 193 | # We find all of the tenants that are waiting to update |
| 194 | tenant = VPNTenant.objects.select_for_update().filter(pk=pk) |
| 195 | if not tenant: |
| 196 | return |
| 197 | # Since this code is atomic it is safe to always use the first tenant |
| 198 | tenant = tenant[0] |
| 199 | tenant.manage_container() |