blob: 97c781bd557a8f48162c9680ac1f2c952698f57d [file] [log] [blame]
Jeremy Mowery8b664f72015-12-04 11:52:16 -07001from core.models import Service, TenantWithContainer
2from django.db import transaction
3
4VPN_KIND = "vpn"
5
Jeremy Mowery82760822016-01-08 16:36:22 -07006
Jeremy Mowery8b664f72015-12-04 11:52:16 -07007class VPNService(Service):
Jeremy Mowery82760822016-01-08 16:36:22 -07008 """Defines the Service for creating VPN servers."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -07009 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 Mowery82760822016-01-08 16:36:22 -070017
Jeremy Mowery7ced7382015-12-04 23:58:38 -070018class VPNTenant(TenantWithContainer):
Jeremy Mowery82760822016-01-08 16:36:22 -070019 """Defines the Tenant for creating VPN servers."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -070020
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 Mowery71aec162016-01-24 17:40:44 -070029 default_attributes = {'server_key': None,
Jeremy Moweryfd081292016-02-07 17:07:55 -070030 'vpn_subnet': None,
31 'server_network': None,
32 'clients_can_see_each_other': True,
Jeremy Mowerye02d4b62016-01-10 15:21:52 -070033 'is_persistent': True,
Jeremy Mowery1eab4fa2016-02-02 17:17:20 -070034 'script': None,
Jeremy Mowery3b1caba2016-02-02 23:53:50 -070035 'ca_crt': None,
36 'server_crt': None,
Jeremy Moweryfd081292016-02-07 17:07:55 -070037 'server_key': None,
38 'dh': None}
Jeremy Mowery8b664f72015-12-04 11:52:16 -070039
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 Mowery82760822016-01-08 16:36:22 -070057 """str: The server_key used to connect to the VPN server."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -070058 return self.get_attribute(
59 "server_key",
60 self.default_attributes['server_key'])
61
Jeremy Mowery00dc8e72015-12-04 15:28:40 -070062 @server_key.setter
Jeremy Mowerya8ce9372015-12-07 13:38:15 -070063 def server_key(self, value):
Jeremy Mowery8b664f72015-12-04 11:52:16 -070064 self.set_attribute("server_key", value)
65
66 @property
67 def addresses(self):
Jeremy Mowery5055c7b2016-01-08 17:25:33 -070068 """Mapping[str, str]: The ip, mac address, and subnet of the NAT network of this Tenant."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -070069 if (not self.id) or (not self.instance):
70 return {}
71
72 addresses = {}
Jeremy Mowery8b664f72015-12-04 11:52:16 -070073 for ns in self.instance.ports.all():
74 if "nat" in ns.network.name.lower():
Jeremy Mowery5055c7b2016-01-08 17:25:33 -070075 addresses["ip"] = ns.ip
76 addresses["mac"] = ns.mac
77 addresses["subnet"] = ns.network.subnet
78 break
79
Jeremy Mowery8b664f72015-12-04 11:52:16 -070080 return addresses
81
82 # This getter is necessary because nat_ip is a sync_attribute
83 @property
84 def nat_ip(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070085 """str: The IP of this Tenant on the NAT network."""
Jeremy Mowery5055c7b2016-01-08 17:25:33 -070086 return self.addresses.get("ip", None)
Jeremy Mowery8b664f72015-12-04 11:52:16 -070087
88 # This getter is necessary because nat_mac is a sync_attribute
89 @property
90 def nat_mac(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070091 """str: The MAC address of this Tenant on the NAT network."""
Jeremy Mowery5055c7b2016-01-08 17:25:33 -070092 return self.addresses.get("mac", None)
Jeremy Mowerya9b673b2016-01-07 21:25:50 -070093
94 @property
95 def subnet(self):
Jeremy Mowery82760822016-01-08 16:36:22 -070096 """str: The subnet of this Tenant on the NAT network."""
Jeremy Mowery5055c7b2016-01-08 17:25:33 -070097 return self.addresses.get("subnet", None)
Jeremy Mowery8b664f72015-12-04 11:52:16 -070098
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -070099 @property
Jeremy Moweryfd081292016-02-07 17:07:55 -0700100 def server_network(self):
Jeremy Mowery82760822016-01-08 16:36:22 -0700101 """str: The IP address of the server on the VPN."""
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -0700102 return self.get_attribute(
Jeremy Moweryfd081292016-02-07 17:07:55 -0700103 'server_network',
104 self.default_attributes['server_network'])
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -0700105
Jeremy Moweryfd081292016-02-07 17:07:55 -0700106 @server_network.setter
107 def server_network(self, value):
108 self.set_attribute("server_network", value)
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -0700109
110 @property
Jeremy Moweryfd081292016-02-07 17:07:55 -0700111 def vpn_subnet(self):
Jeremy Mowery82760822016-01-08 16:36:22 -0700112 """str: The IP address of the client on the VPN."""
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -0700113 return self.get_attribute(
Jeremy Moweryfd081292016-02-07 17:07:55 -0700114 'vpn_subnet',
115 self.default_attributes['vpn_subnet'])
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -0700116
Jeremy Moweryfd081292016-02-07 17:07:55 -0700117 @vpn_subnet.setter
118 def vpn_subnet(self, value):
119 self.set_attribute("vpn_subnet", value)
Jeremy Mowerybd2ed3a2016-01-05 16:52:43 -0700120
121 @property
Jeremy Mowery4a23e7d2016-01-06 15:16:33 -0700122 def is_persistent(self):
Jeremy Mowery82760822016-01-08 16:36:22 -0700123 """bool: True if the VPN connection is persistence, false otherwise."""
Jeremy Mowery4a23e7d2016-01-06 15:16:33 -0700124 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 Moweryfd081292016-02-07 17:07:55 -0700133 def clients_can_see_each_other(self):
Jeremy Mowery82760822016-01-08 16:36:22 -0700134 """bool: True if the client can see the subnet of the server, false otherwise."""
Jeremy Mowery4a23e7d2016-01-06 15:16:33 -0700135 return self.get_attribute(
Jeremy Moweryfd081292016-02-07 17:07:55 -0700136 "clients_can_see_each_other",
137 self.default_attributes['clients_can_see_each_other'])
Jeremy Mowery4a23e7d2016-01-06 15:16:33 -0700138
Jeremy Moweryfd081292016-02-07 17:07:55 -0700139 @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 Mowery4a23e7d2016-01-06 15:16:33 -0700142
Jeremy Mowerye02d4b62016-01-10 15:21:52 -0700143 @property
Jeremy Mowery28223392016-01-25 20:51:11 -0700144 def script(self):
145 """string: The file name of the client script"""
Jeremy Mowery34aef752016-01-26 17:58:16 -0700146 return self.get_attribute("script", self.default_attributes['script'])
Jeremy Mowerye02d4b62016-01-10 15:21:52 -0700147
Jeremy Mowery28223392016-01-25 20:51:11 -0700148 @script.setter
149 def script(self, value):
150 self.set_attribute("script", value)
Jeremy Mowerye02d4b62016-01-10 15:21:52 -0700151
Jeremy Mowery1eab4fa2016-02-02 17:17:20 -0700152 @property
Jeremy Mowery3b1caba2016-02-02 23:53:50 -0700153 def ca_crt(self):
Jeremy Mowery1eab4fa2016-02-02 17:17:20 -0700154 """str: the string for the ca certificate"""
Jeremy Mowery3b1caba2016-02-02 23:53:50 -0700155 return self.get_attribute("ca_crt", self.default_attributes['ca_crt'])
Jeremy Mowery1eab4fa2016-02-02 17:17:20 -0700156
Jeremy Mowery3b1caba2016-02-02 23:53:50 -0700157 @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 Mowery1eab4fa2016-02-02 17:17:20 -0700178
Jeremy Moweryfd081292016-02-07 17:07:55 -0700179 @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 Mowery8b664f72015-12-04 11:52:16 -0700188
189def model_policy_vpn_tenant(pk):
Jeremy Mowery82760822016-01-08 16:36:22 -0700190 """Manages the contain for the VPN Tenant."""
Jeremy Mowery8b664f72015-12-04 11:52:16 -0700191 # 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()