Revision b436bd51
b/ChangeLog | ||
---|---|---|
1 | 1 |
=========== |
2 | 2 |
1.1.2 RELEASE |
3 | 3 |
Updates and enhancements. Check documentation for updating from previous versions |
4 |
|
|
4 | 5 |
- Rest Api |
6 |
- Use Django signals for notifications |
|
5 | 7 |
|
6 | 8 |
======= |
7 | 9 |
1.1.1 RELEASE |
b/flowspec/helpers.py | ||
---|---|---|
1 |
from django.core.mail.message import EmailMessage |
|
2 |
from django.conf import settings |
|
3 |
|
|
4 |
|
|
5 |
def send_new_mail(subject, message, from_email, recipient_list, bcc_list): |
|
6 |
return EmailMessage(subject, message, from_email, recipient_list, bcc_list).send() |
|
7 |
|
|
8 |
|
|
9 |
def get_peer_techc_mails(user): |
|
10 |
mail = [] |
|
11 |
additional_mail = [] |
|
12 |
techmails_list = [] |
|
13 |
user_mail = '%s' % user.email |
|
14 |
user_mail = user_mail.split(';') |
|
15 |
techmails = user.get_profile().peer.techc_emails.all() |
|
16 |
if techmails: |
|
17 |
for techmail in techmails: |
|
18 |
techmails_list.append(techmail.email) |
|
19 |
if settings.NOTIFY_ADMIN_MAILS: |
|
20 |
additional_mail = settings.NOTIFY_ADMIN_MAILS |
|
21 |
mail.extend(additional_mail) |
|
22 |
mail.extend(techmails_list) |
|
23 |
return mail |
b/flowspec/migrations/0006_auto__add_field_route_requesters_address.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
import datetime |
|
3 |
from south.db import db |
|
4 |
from south.v2 import SchemaMigration |
|
5 |
from django.db import models |
|
6 |
|
|
7 |
|
|
8 |
class Migration(SchemaMigration): |
|
9 |
|
|
10 |
def forwards(self, orm): |
|
11 |
# Adding field 'Route.requesters_address' |
|
12 |
db.add_column(u'route', 'requesters_address', |
|
13 |
self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True), |
|
14 |
keep_default=False) |
|
15 |
|
|
16 |
|
|
17 |
def backwards(self, orm): |
|
18 |
# Deleting field 'Route.requesters_address' |
|
19 |
db.delete_column(u'route', 'requesters_address') |
|
20 |
|
|
21 |
|
|
22 |
models = { |
|
23 |
'auth.group': { |
|
24 |
'Meta': {'object_name': 'Group'}, |
|
25 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
26 |
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), |
|
27 |
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) |
|
28 |
}, |
|
29 |
'auth.permission': { |
|
30 |
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, |
|
31 |
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
|
32 |
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), |
|
33 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
34 |
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) |
|
35 |
}, |
|
36 |
'auth.user': { |
|
37 |
'Meta': {'object_name': 'User'}, |
|
38 |
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
|
39 |
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), |
|
40 |
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
|
41 |
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), |
|
42 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
43 |
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
|
44 |
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
45 |
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
46 |
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
|
47 |
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
|
48 |
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
|
49 |
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), |
|
50 |
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) |
|
51 |
}, |
|
52 |
'contenttypes.contenttype': { |
|
53 |
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, |
|
54 |
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
|
55 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
56 |
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
|
57 |
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
|
58 |
}, |
|
59 |
'flowspec.fragmenttype': { |
|
60 |
'Meta': {'object_name': 'FragmentType'}, |
|
61 |
'fragmenttype': ('django.db.models.fields.CharField', [], {'max_length': '20'}), |
|
62 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) |
|
63 |
}, |
|
64 |
'flowspec.matchdscp': { |
|
65 |
'Meta': {'object_name': 'MatchDscp', 'db_table': "u'match_dscp'"}, |
|
66 |
'dscp': ('django.db.models.fields.CharField', [], {'max_length': '24'}), |
|
67 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) |
|
68 |
}, |
|
69 |
'flowspec.matchport': { |
|
70 |
'Meta': {'object_name': 'MatchPort', 'db_table': "u'match_port'"}, |
|
71 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
72 |
'port': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '24'}) |
|
73 |
}, |
|
74 |
'flowspec.matchprotocol': { |
|
75 |
'Meta': {'object_name': 'MatchProtocol', 'db_table': "u'match_protocol'"}, |
|
76 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
77 |
'protocol': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '24'}) |
|
78 |
}, |
|
79 |
'flowspec.route': { |
|
80 |
'Meta': {'object_name': 'Route', 'db_table': "u'route'"}, |
|
81 |
'applier': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), |
|
82 |
'comments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), |
|
83 |
'destination': ('django.db.models.fields.CharField', [], {'max_length': '32'}), |
|
84 |
'destinationport': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'matchDestinationPort'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['flowspec.MatchPort']"}), |
|
85 |
'dscp': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.MatchDscp']", 'null': 'True', 'blank': 'True'}), |
|
86 |
'expires': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2015, 1, 15, 0, 0)'}), |
|
87 |
'filed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
|
88 |
'fragmenttype': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.FragmentType']", 'null': 'True', 'blank': 'True'}), |
|
89 |
'icmpcode': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), |
|
90 |
'icmptype': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), |
|
91 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
92 |
'last_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), |
|
93 |
'name': ('django.db.models.fields.SlugField', [], {'max_length': '128'}), |
|
94 |
'packetlength': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), |
|
95 |
'port': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'matchPort'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['flowspec.MatchPort']"}), |
|
96 |
'protocol': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['flowspec.MatchProtocol']", 'null': 'True', 'blank': 'True'}), |
|
97 |
'requesters_address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
|
98 |
'response': ('django.db.models.fields.CharField', [], {'max_length': '512', 'null': 'True', 'blank': 'True'}), |
|
99 |
'source': ('django.db.models.fields.CharField', [], {'max_length': '32'}), |
|
100 |
'sourceport': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'matchSourcePort'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['flowspec.MatchPort']"}), |
|
101 |
'status': ('django.db.models.fields.CharField', [], {'default': "'PENDING'", 'max_length': '20', 'null': 'True', 'blank': 'True'}), |
|
102 |
'tcpflag': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), |
|
103 |
'then': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['flowspec.ThenAction']", 'symmetrical': 'False'}) |
|
104 |
}, |
|
105 |
'flowspec.thenaction': { |
|
106 |
'Meta': {'ordering': "['action', 'action_value']", 'unique_together': "(('action', 'action_value'),)", 'object_name': 'ThenAction', 'db_table': "u'then_action'"}, |
|
107 |
'action': ('django.db.models.fields.CharField', [], {'max_length': '60'}), |
|
108 |
'action_value': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
|
109 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) |
|
110 |
} |
|
111 |
} |
|
112 |
|
|
113 |
complete_apps = ['flowspec'] |
b/flowspec/models.py | ||
---|---|---|
20 | 20 |
from django.db import models |
21 | 21 |
from django.conf import settings |
22 | 22 |
from django.contrib.auth.models import User |
23 |
from django.contrib.sites.models import Site |
|
24 |
from django.db.models.signals import post_save |
|
23 | 25 |
from django.utils.translation import ugettext_lazy as _ |
26 |
from django.core.urlresolvers import reverse |
|
27 |
|
|
28 |
from flowspec.helpers import send_new_mail, get_peer_techc_mails |
|
24 | 29 |
from utils import proxy as PR |
25 | 30 |
from ipaddr import * |
26 | 31 |
import datetime |
27 | 32 |
import logging |
28 | 33 |
from time import sleep |
29 |
from junos import create_junos_name, policer_name
|
|
34 |
from junos import create_junos_name |
|
30 | 35 |
|
31 | 36 |
import beanstalkc |
32 | 37 |
from utils.randomizer import id_generator as id_gen |
... | ... | |
167 | 172 |
expires = models.DateField(default=days_offset, verbose_name=_("Expires")) |
168 | 173 |
response = models.CharField(max_length=512, blank=True, null=True, verbose_name=_("Response")) |
169 | 174 |
comments = models.TextField(null=True, blank=True, verbose_name=_("Comments")) |
170 |
|
|
175 |
requesters_address = models.CharField(max_length=255, blank=True, null=True) |
|
171 | 176 |
|
172 | 177 |
def __unicode__(self): |
173 | 178 |
return self.name |
... | ... | |
183 | 188 |
self.name = "%s_%s" %(self.name, hash) |
184 | 189 |
super(Route, self).save(*args, **kwargs) # Call the "real" save() method. |
185 | 190 |
|
186 |
|
|
187 | 191 |
def clean(self, *args, **kwargs): |
188 | 192 |
from django.core.exceptions import ValidationError |
189 | 193 |
if self.destination: |
... | ... | |
201 | 205 |
|
202 | 206 |
def commit_add(self, *args, **kwargs): |
203 | 207 |
peer = self.applier.get_profile().peer.peer_tag |
204 |
send_message("[%s] Adding rule %s. Please wait..." %(self.applier.username, self.name), peer) |
|
208 |
send_message("[%s] Adding rule %s. Please wait..." % (self.applier.username, self.name), peer)
|
|
205 | 209 |
response = add.delay(self) |
206 |
logger.info("Got add job id: %s" %response) |
|
210 |
logger.info('Got add job id: %s' % response) |
|
211 |
fqdn = Site.objects.get_current().domain |
|
212 |
admin_url = 'https://%s%s' % ( |
|
213 |
fqdn, |
|
214 |
reverse('edit-route', kwargs={'route_slug': self.name}) |
|
215 |
) |
|
216 |
mail_body = render_to_string( |
|
217 |
'rule_action.txt', |
|
218 |
{ |
|
219 |
'route': self, |
|
220 |
'address': self.requesters_address, |
|
221 |
'action': 'creation', |
|
222 |
'url': admin_url |
|
223 |
} |
|
224 |
) |
|
225 |
user_mail = '%s' % self.applier.email |
|
226 |
user_mail = user_mail.split(';') |
|
227 |
send_new_mail( |
|
228 |
settings.EMAIL_SUBJECT_PREFIX + 'Rule %s creation request submitted by %s' % (self.name, self.applier.username), |
|
229 |
mail_body, |
|
230 |
settings.SERVER_EMAIL, user_mail, |
|
231 |
get_peer_techc_mails(self.applier) |
|
232 |
) |
|
233 |
d = { |
|
234 |
'clientip': '%s' % self.requesters_address, |
|
235 |
'user': self.applier.username |
|
236 |
} |
|
237 |
logger.info(mail_body, extra=d) |
|
207 | 238 |
|
208 | 239 |
def commit_edit(self, *args, **kwargs): |
209 | 240 |
peer = self.applier.get_profile().peer.peer_tag |
210 |
send_message("[%s] Editing rule %s. Please wait..." %(self.applier.username, self.name), peer) |
|
241 |
send_message( |
|
242 |
'[%s] Editing rule %s. Please wait...' % |
|
243 |
( |
|
244 |
self.applier.username, |
|
245 |
self.name |
|
246 |
), peer |
|
247 |
) |
|
211 | 248 |
response = edit.delay(self) |
212 |
logger.info("Got edit job id: %s" %response) |
|
249 |
logger.info('Got edit job id: %s' % response) |
|
250 |
fqdn = Site.objects.get_current().domain |
|
251 |
admin_url = 'https://%s%s' % ( |
|
252 |
fqdn, |
|
253 |
reverse( |
|
254 |
'edit-route', |
|
255 |
kwargs={'route_slug': self.name} |
|
256 |
) |
|
257 |
) |
|
258 |
mail_body = render_to_string( |
|
259 |
'rule_action.txt', |
|
260 |
{ |
|
261 |
'route': self, |
|
262 |
'address': self.requesters_address, |
|
263 |
'action': 'edit', |
|
264 |
'url': admin_url |
|
265 |
} |
|
266 |
) |
|
267 |
user_mail = '%s' % self.applier.email |
|
268 |
user_mail = user_mail.split(';') |
|
269 |
send_new_mail( |
|
270 |
settings.EMAIL_SUBJECT_PREFIX + 'Rule %s edit request submitted by %s' % (self.name, self.applier.username), |
|
271 |
mail_body, settings.SERVER_EMAIL, user_mail, |
|
272 |
get_peer_techc_mails(self.applier) |
|
273 |
) |
|
274 |
d = { |
|
275 |
'clientip': self.requesters_address, |
|
276 |
'user': self.applier.username |
|
277 |
} |
|
278 |
logger.info(mail_body, extra=d) |
|
213 | 279 |
|
214 | 280 |
def commit_delete(self, *args, **kwargs): |
215 | 281 |
reason_text = '' |
216 | 282 |
reason = '' |
217 | 283 |
if "reason" in kwargs: |
218 | 284 |
reason = kwargs['reason'] |
219 |
reason_text = "Reason: %s. " %reason
|
|
285 |
reason_text = 'Reason: %s.' % reason
|
|
220 | 286 |
peer = self.applier.get_profile().peer.peer_tag |
221 |
send_message("[%s] Suspending rule %s. %sPlease wait..." %(self.applier.username, self.name, reason_text), peer) |
|
287 |
send_message( |
|
288 |
'[%s] Suspending rule %s. %sPlease wait...' % ( |
|
289 |
self.applier.username, |
|
290 |
self.name, |
|
291 |
reason_text |
|
292 |
), peer |
|
293 |
) |
|
222 | 294 |
response = delete.delay(self, reason=reason) |
223 |
logger.info("Got delete job id: %s" %response) |
|
295 |
logger.info('Got delete job id: %s' % response) |
|
296 |
fqdn = Site.objects.get_current().domain |
|
297 |
admin_url = 'https://%s%s' % ( |
|
298 |
fqdn, |
|
299 |
reverse( |
|
300 |
'edit-route', |
|
301 |
kwargs={'route_slug': self.name} |
|
302 |
) |
|
303 |
) |
|
304 |
mail_body = render_to_string( |
|
305 |
'rule_action.txt', |
|
306 |
{ |
|
307 |
'route': self, |
|
308 |
'address': self.requesters_address, |
|
309 |
'action': 'removal', |
|
310 |
'url': admin_url |
|
311 |
} |
|
312 |
) |
|
313 |
user_mail = '%' % self.applier.email |
|
314 |
user_mail = user_mail.split(';') |
|
315 |
send_new_mail( |
|
316 |
settings.EMAIL_SUBJECT_PREFIX + 'Rule %s removal request submitted by %s' % (self.name, self.applier.username), |
|
317 |
mail_body, |
|
318 |
settings.SERVER_EMAIL, |
|
319 |
user_mail, |
|
320 |
get_peer_techc_mails(self.applier) |
|
321 |
) |
|
322 |
d = { |
|
323 |
'clientip': self.requesters_address, |
|
324 |
'user': self.applier.username |
|
325 |
} |
|
326 |
logger.info(mail_body, extra=d) |
|
224 | 327 |
|
225 | 328 |
def has_expired(self): |
226 | 329 |
today = datetime.date.today() |
... | ... | |
242 | 345 |
except Exception as e: |
243 | 346 |
self.status = "EXPIRED" |
244 | 347 |
self.save() |
245 |
logger.error("No routing options on device. Exception: %s" %e)
|
|
348 |
logger.error('No routing options on device. Exception: %s' % e)
|
|
246 | 349 |
return True |
247 | 350 |
for route in routes: |
248 | 351 |
if route.name == self.name: |
... | ... | |
478 | 581 |
tube_message = json.dumps({'message': str(msg), 'username':peer}) |
479 | 582 |
b.put(tube_message) |
480 | 583 |
b.close() |
584 |
|
|
585 |
|
|
586 |
def notify_user(sender, instance, created, **kwargs): |
|
587 |
if created: |
|
588 |
instance.commit_add() |
|
589 |
else: |
|
590 |
if instance.has_expired(): |
|
591 |
instance.commit_delete() |
|
592 |
else: |
|
593 |
instance.commit_edit() |
|
594 |
|
|
595 |
|
|
596 |
post_save.connect(notify_user, sender=Route) |
b/flowspec/views.py | ||
---|---|---|
54 | 54 |
|
55 | 55 |
from django.views.decorators.cache import never_cache |
56 | 56 |
from django.conf import settings |
57 |
from django.core.mail.message import EmailMessage |
|
58 | 57 |
from django.template.defaultfilters import slugify |
58 |
from flowspec.helpers import send_new_mail, get_peer_techc_mails |
|
59 | 59 |
import datetime |
60 | 60 |
import os |
61 | 61 |
|
... | ... | |
127 | 127 |
jresp['aaData'] = routes |
128 | 128 |
return HttpResponse(json.dumps(jresp), mimetype='application/json') |
129 | 129 |
|
130 |
|
|
130 | 131 |
@login_required |
131 | 132 |
@never_cache |
132 | 133 |
def overview_routes_ajax(request): |
... | ... | |
147 | 148 |
jresp['aaData'] = routes |
148 | 149 |
return HttpResponse(json.dumps(jresp), mimetype='application/json') |
149 | 150 |
|
151 |
|
|
150 | 152 |
def build_routes_json(groutes): |
151 | 153 |
routes = [] |
152 | 154 |
for r in groutes: |
... | ... | |
170 | 172 |
routes.append(rd) |
171 | 173 |
return routes |
172 | 174 |
|
175 |
|
|
173 | 176 |
@login_required |
174 | 177 |
@never_cache |
175 | 178 |
def add_route(request): |
... | ... | |
178 | 181 |
if request.user.is_superuser: |
179 | 182 |
applier_peer_networks = PeerRange.objects.all() |
180 | 183 |
if not applier_peer_networks: |
181 |
messages.add_message(request, messages.WARNING, |
|
182 |
_("Insufficient rights on administrative networks. Cannot add rule. Contact your administrator")) |
|
183 |
return HttpResponseRedirect(reverse("group-routes")) |
|
184 |
messages.add_message( |
|
185 |
request, |
|
186 |
messages.WARNING, |
|
187 |
('Insufficient rights on administrative networks. Cannot add rule. Contact your administrator') |
|
188 |
) |
|
189 |
return HttpResponseRedirect(reverse("group-routes")) |
|
184 | 190 |
if request.method == "GET": |
185 | 191 |
form = RouteForm(initial={'applier': applier}) |
186 | 192 |
if not request.user.is_superuser: |
... | ... | |
201 | 207 |
pass |
202 | 208 |
form = RouteForm(request_data) |
203 | 209 |
if form.is_valid(): |
204 |
route=form.save(commit=False)
|
|
210 |
route = form.save(commit=False)
|
|
205 | 211 |
if not request.user.is_superuser: |
206 | 212 |
route.applier = request.user |
207 | 213 |
route.status = "PENDING" |
208 | 214 |
route.response = "Applying" |
209 |
route.source = IPNetwork("%s/%s" %(IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed |
|
210 |
route.destination = IPNetwork("%s/%s" %(IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed |
|
215 |
route.source = IPNetwork('%s/%s' % (IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed |
|
216 |
route.destination = IPNetwork('%s/%s' % (IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed |
|
217 |
route.requesters_address = request.META['HTTP_X_FORWARDED_FOR'] |
|
211 | 218 |
route.save() |
212 | 219 |
form.save_m2m() |
213 |
route.commit_add() |
|
214 |
requesters_address = request.META['HTTP_X_FORWARDED_FOR'] |
|
215 |
fqdn = Site.objects.get_current().domain |
|
216 |
admin_url = "https://%s%s" % (fqdn, reverse("edit-route", kwargs={'route_slug': route.name })) |
|
217 |
mail_body = render_to_string("rule_action.txt", |
|
218 |
{"route": route, "address": requesters_address, "action": "creation", "url": admin_url}) |
|
219 |
user_mail = "%s" %route.applier.email |
|
220 |
user_mail = user_mail.split(';') |
|
221 |
send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s creation request submitted by %s" %(route.name, route.applier.username), |
|
222 |
mail_body, settings.SERVER_EMAIL, user_mail, |
|
223 |
get_peer_techc_mails(route.applier)) |
|
224 |
d = { 'clientip' : "%s"%requesters_address, 'user' : route.applier.username } |
|
225 |
logger.info(mail_body, extra=d) |
|
226 | 220 |
return HttpResponseRedirect(reverse("group-routes")) |
227 | 221 |
else: |
228 | 222 |
if not request.user.is_superuser: |
229 | 223 |
form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True) |
230 | 224 |
form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False) |
231 |
return render_to_response('apply.html', {'form': form, 'applier':applier}, |
|
232 |
context_instance=RequestContext(request)) |
|
225 |
return render_to_response( |
|
226 |
'apply.html', |
|
227 |
{ |
|
228 |
'form': form, |
|
229 |
'applier': applier |
|
230 |
}, |
|
231 |
context_instance=RequestContext(request) |
|
232 |
) |
|
233 |
|
|
233 | 234 |
|
234 | 235 |
@login_required |
235 | 236 |
@never_cache |
... | ... | |
239 | 240 |
route_edit = get_object_or_404(Route, name=route_slug) |
240 | 241 |
route_edit_applier_peer = route_edit.applier.get_profile().peer |
241 | 242 |
if applier_peer != route_edit_applier_peer and (not request.user.is_superuser): |
242 |
messages.add_message(request, messages.WARNING, |
|
243 |
_("Insufficient rights to edit rule %s") %(route_slug)) |
|
243 |
messages.add_message( |
|
244 |
request, |
|
245 |
messages.WARNING, |
|
246 |
('Insufficient rights to edit rule %s') % (route_slug) |
|
247 |
) |
|
244 | 248 |
return HttpResponseRedirect(reverse("group-routes")) |
245 | 249 |
# if route_edit.status == "ADMININACTIVE" : |
246 | 250 |
# messages.add_message(request, messages.WARNING, |
... | ... | |
250 | 254 |
# messages.add_message(request, messages.WARNING, |
251 | 255 |
# "Cannot edit the expired rule %s. Contact helpdesk to enable it" %(route_slug)) |
252 | 256 |
# return HttpResponseRedirect(reverse("group-routes")) |
253 |
if route_edit.status == "PENDING" : |
|
254 |
messages.add_message(request, messages.WARNING, |
|
255 |
_("Cannot edit a pending rule: %s.") %(route_slug)) |
|
257 |
if route_edit.status == 'PENDING': |
|
258 |
messages.add_message( |
|
259 |
request, |
|
260 |
messages.WARNING, |
|
261 |
('Cannot edit a pending rule: %s.') % (route_slug) |
|
262 |
) |
|
256 | 263 |
return HttpResponseRedirect(reverse("group-routes")) |
257 | 264 |
route_original = deepcopy(route_edit) |
258 | 265 |
if request.POST: |
... | ... | |
265 | 272 |
del request_data['issuperuser'] |
266 | 273 |
except: |
267 | 274 |
pass |
268 |
form = RouteForm(request_data, instance = route_edit) |
|
275 |
form = RouteForm( |
|
276 |
request_data, |
|
277 |
instance=route_edit |
|
278 |
) |
|
269 | 279 |
critical_changed_values = ['source', 'destination', 'sourceport', 'destinationport', 'port', 'protocol', 'then', 'fragmenttype'] |
270 | 280 |
if form.is_valid(): |
271 | 281 |
changed_data = form.changed_data |
272 |
route=form.save(commit=False)
|
|
282 |
route = form.save(commit=False)
|
|
273 | 283 |
route.name = route_original.name |
274 | 284 |
route.status = route_original.status |
275 | 285 |
route.response = route_original.response |
... | ... | |
278 | 288 |
if bool(set(changed_data) & set(critical_changed_values)) or (not route_original.status == 'ACTIVE'): |
279 | 289 |
route.status = "PENDING" |
280 | 290 |
route.response = "Applying" |
281 |
route.source = IPNetwork("%s/%s" %(IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed |
|
282 |
route.destination = IPNetwork("%s/%s" %(IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed |
|
291 |
route.source = IPNetwork('%s/%s' % (IPNetwork(route.source).network.compressed, IPNetwork(route.source).prefixlen)).compressed |
|
292 |
route.destination = IPNetwork('%s/%s' % (IPNetwork(route.destination).network.compressed, IPNetwork(route.destination).prefixlen)).compressed |
|
293 |
route.requesters_address = self.request.META['HTTP_X_FORWARDED_FOR'] |
|
283 | 294 |
route.save() |
284 | 295 |
if bool(set(changed_data) & set(critical_changed_values)) or (not route_original.status == 'ACTIVE'): |
285 | 296 |
form.save_m2m() |
286 |
route.commit_edit() |
|
287 |
requesters_address = request.META['HTTP_X_FORWARDED_FOR'] |
|
288 |
fqdn = Site.objects.get_current().domain |
|
289 |
admin_url = "https://%s%s" % (fqdn, reverse("edit-route", kwargs={'route_slug': route.name })) |
|
290 |
mail_body = render_to_string("rule_action.txt", |
|
291 |
{"route": route, "address": requesters_address, "action": "edit", "url": admin_url}) |
|
292 |
user_mail = "%s" %route.applier.email |
|
293 |
user_mail = user_mail.split(';') |
|
294 |
send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s edit request submitted by %s" %(route.name, route.applier.username), |
|
295 |
mail_body, settings.SERVER_EMAIL, user_mail, |
|
296 |
get_peer_techc_mails(route.applier)) |
|
297 |
d = { 'clientip' : requesters_address, 'user' : route.applier.username } |
|
298 |
logger.info(mail_body, extra=d) |
|
297 |
# route.commit_edit() |
|
299 | 298 |
return HttpResponseRedirect(reverse("group-routes")) |
300 | 299 |
else: |
301 | 300 |
if not request.user.is_superuser: |
302 | 301 |
form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True) |
303 | 302 |
form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False) |
304 |
return render_to_response('apply.html', {'form': form, 'edit':True, 'applier': applier}, |
|
305 |
context_instance=RequestContext(request)) |
|
303 |
return render_to_response( |
|
304 |
'apply.html', |
|
305 |
{ |
|
306 |
'form': form, |
|
307 |
'edit': True, |
|
308 |
'applier': applier |
|
309 |
}, |
|
310 |
context_instance=RequestContext(request) |
|
311 |
) |
|
306 | 312 |
else: |
307 | 313 |
if (not route_original.status == 'ACTIVE'): |
308 |
route_edit.expires = datetime.date.today() + datetime.timedelta(days = settings.EXPIRATION_DAYS_OFFSET)
|
|
314 |
route_edit.expires = datetime.date.today() + datetime.timedelta(days=settings.EXPIRATION_DAYS_OFFSET)
|
|
309 | 315 |
dictionary = model_to_dict(route_edit, fields=[], exclude=[]) |
310 | 316 |
if request.user.is_superuser: |
311 | 317 |
dictionary['issuperuser'] = request.user.username |
... | ... | |
318 | 324 |
if not request.user.is_superuser: |
319 | 325 |
form.fields['then'] = forms.ModelMultipleChoiceField(queryset=ThenAction.objects.filter(action__in=settings.UI_USER_THEN_ACTIONS).order_by('action'), required=True) |
320 | 326 |
form.fields['protocol'] = forms.ModelMultipleChoiceField(queryset=MatchProtocol.objects.filter(protocol__in=settings.UI_USER_PROTOCOLS).order_by('protocol'), required=False) |
321 |
return render_to_response('apply.html', {'form': form, 'edit':True, 'applier': applier}, |
|
322 |
context_instance=RequestContext(request)) |
|
327 |
return render_to_response( |
|
328 |
'apply.html', |
|
329 |
{ |
|
330 |
'form': form, |
|
331 |
'edit': True, |
|
332 |
'applier': applier |
|
333 |
}, |
|
334 |
context_instance=RequestContext(request) |
|
335 |
) |
|
336 |
|
|
323 | 337 |
|
324 | 338 |
@login_required |
325 | 339 |
@never_cache |
... | ... | |
334 | 348 |
if not request.user.is_superuser: |
335 | 349 |
route.applier = request.user |
336 | 350 |
route.response = "Deactivating" |
351 |
route.requesters_address = request.META['HTTP_X_FORWARDED_FOR'] |
|
337 | 352 |
route.save() |
338 |
route.commit_delete() |
|
339 |
requesters_address = request.META['HTTP_X_FORWARDED_FOR'] |
|
340 |
fqdn = Site.objects.get_current().domain |
|
341 |
admin_url = "https://%s%s" % (fqdn, reverse("edit-route", kwargs={'route_slug': route.name })) |
|
342 |
mail_body = render_to_string("rule_action.txt", |
|
343 |
{"route": route, "address": requesters_address, "action": "removal", "url": admin_url}) |
|
344 |
user_mail = "%s" %route.applier.email |
|
345 |
user_mail = user_mail.split(';') |
|
346 |
send_new_mail(settings.EMAIL_SUBJECT_PREFIX + "Rule %s removal request submitted by %s" %(route.name, route.applier.username), |
|
347 |
mail_body, settings.SERVER_EMAIL, user_mail, |
|
348 |
get_peer_techc_mails(route.applier)) |
|
349 |
d = { 'clientip' : requesters_address, 'user' : route.applier.username } |
|
350 |
logger.info(mail_body, extra=d) |
|
353 |
# route.commit_delete() |
|
351 | 354 |
html = "<html><body>Done</body></html>" |
352 | 355 |
return HttpResponse(html) |
353 | 356 |
else: |
354 | 357 |
return HttpResponseRedirect(reverse("group-routes")) |
355 | 358 |
|
359 |
|
|
356 | 360 |
@login_required |
357 | 361 |
@never_cache |
358 | 362 |
def user_profile(request): |
... | ... | |
577 | 581 |
return render_to_response('%s.js' % file, {'timeout': long_polling_timeout}, context_instance=RequestContext(request), mimetype="text/javascript") |
578 | 582 |
|
579 | 583 |
|
580 |
def get_peer_techc_mails(user): |
|
581 |
mail = [] |
|
582 |
additional_mail = [] |
|
583 |
techmails_list = [] |
|
584 |
user_mail = "%s" %user.email |
|
585 |
user_mail = user_mail.split(';') |
|
586 |
techmails = user.get_profile().peer.techc_emails.all() |
|
587 |
if techmails: |
|
588 |
for techmail in techmails: |
|
589 |
techmails_list.append(techmail.email) |
|
590 |
if settings.NOTIFY_ADMIN_MAILS: |
|
591 |
additional_mail = settings.NOTIFY_ADMIN_MAILS |
|
592 |
mail.extend(additional_mail) |
|
593 |
mail.extend(techmails_list) |
|
594 |
return mail |
|
595 |
|
|
596 |
def send_new_mail(subject, message, from_email, recipient_list, bcc_list): |
|
597 |
return EmailMessage(subject, message, from_email, recipient_list, bcc_list).send() |
|
598 |
|
|
599 |
|
|
600 | 584 |
def lookupShibAttr(attrmap, requestMeta): |
601 | 585 |
for attr in attrmap: |
602 | 586 |
if (attr in requestMeta.keys()): |
b/flowspec/viewsets.py | ||
---|---|---|
36 | 36 |
queryset = Route.objects.all() |
37 | 37 |
serializer_class = RouteSerializer |
38 | 38 |
|
39 |
def pre_save(self, obj): |
|
40 |
obj.requesters_address = self.request.META['HTTP_X_FORWARDED_FOR'] |
|
41 |
|
|
39 | 42 |
|
40 | 43 |
class PortViewSet(viewsets.ModelViewSet): |
41 | 44 |
queryset = MatchPort.objects.all() |
Also available in: Unified diff