This repository has been archived by the owner on May 6, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Matthew Fisher
committed
Aug 26, 2016
1 parent
9b8ede9
commit 50811a2
Showing
7 changed files
with
215 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# -*- coding: utf-8 -*- | ||
# Generated by Django 1.9.8 on 2016-08-22 21:03 | ||
from __future__ import unicode_literals | ||
|
||
from django.conf import settings | ||
from django.db import migrations, models | ||
import django.db.models.deletion | ||
import uuid | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
('api', '0014_appsettings_whitelist'), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name='TLS', | ||
fields=[ | ||
('uuid', models.UUIDField(auto_created=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True, verbose_name='UUID')), | ||
('created', models.DateTimeField(auto_now_add=True)), | ||
('updated', models.DateTimeField(auto_now=True)), | ||
('https_enforced', models.NullBooleanField(default=None)), | ||
('app', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.App')), | ||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), | ||
], | ||
options={ | ||
'ordering': ['-created'], | ||
'get_latest_by': 'created', | ||
}, | ||
), | ||
migrations.AlterUniqueTogether( | ||
name='tls', | ||
unique_together=set([('app', 'uuid')]), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
from django.db import models | ||
from django.conf import settings | ||
|
||
from api.exceptions import AlreadyExists | ||
from api.models import UuidAuditedModel | ||
|
||
|
||
class TLS(UuidAuditedModel): | ||
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT) | ||
app = models.ForeignKey('App', on_delete=models.CASCADE) | ||
https_enforced = models.NullBooleanField(default=None) | ||
|
||
class Meta: | ||
get_latest_by = 'created' | ||
unique_together = (('app', 'uuid')) | ||
ordering = ['-created'] | ||
|
||
def __str__(self): | ||
return "{}-{}".format(self.app.id, str(self.uuid)[:7]) | ||
|
||
def _check_previous_tls_settings(self): | ||
try: | ||
previous_tls_settings = self.app.tls_set.latest() | ||
|
||
if ( | ||
previous_tls_settings.https_enforced is not None and | ||
self.https_enforced == previous_tls_settings.https_enforced | ||
): | ||
self.delete() | ||
raise AlreadyExists("{} changed nothing".format(self.owner)) | ||
except TLS.DoesNotExist: | ||
pass | ||
|
||
def save(self, *args, **kwargs): | ||
self._check_previous_tls_settings() | ||
|
||
app = str(self.app) | ||
https_enforced = bool(self.https_enforced) | ||
|
||
# get config for the service | ||
config = self._load_service_config(app, 'router') | ||
|
||
# See if the ssl.enforce annotation is available | ||
if 'ssl.enforce' not in config: | ||
config['ssl.enforce'] = 'false' | ||
|
||
# convert from bool to string | ||
config['ssl.enforce'] = str(https_enforced) | ||
|
||
self._save_service_config(app, 'router', config) | ||
|
||
# Save to DB | ||
return super(TLS, self).save(*args, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import requests_mock | ||
|
||
from django.core.cache import cache | ||
from django.contrib.auth.models import User | ||
from rest_framework.authtoken.models import Token | ||
|
||
from api.models import App | ||
from api.tests import adapter, DeisTransactionTestCase | ||
|
||
|
||
@requests_mock.Mocker(real_http=True, adapter=adapter) | ||
class TestTLS(DeisTransactionTestCase): | ||
"""Tests setting and updating config values""" | ||
|
||
fixtures = ['tests.json'] | ||
|
||
def setUp(self): | ||
self.user = User.objects.get(username='autotest') | ||
self.token = Token.objects.get(user=self.user).key | ||
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token) | ||
|
||
def tearDown(self): | ||
# make sure every test has a clean slate for k8s mocking | ||
cache.clear() | ||
|
||
def test_tls_enforced(self, mock_requests): | ||
""" | ||
Test that tls redirection can be enforced | ||
""" | ||
app_id = self.create_app() | ||
app = App.objects.get(id=app_id) | ||
|
||
data = {'https_enforced': True} | ||
response = self.client.post( | ||
'/v2/apps/{app_id}/tls'.format(**locals()), | ||
data) | ||
self.assertEqual(response.status_code, 201, response.data) | ||
self.assertTrue(response.data.get('https_enforced'), response.data) | ||
self.assertTrue(app.tls_set.latest().https_enforced) | ||
|
||
data = {'https_enforced': False} | ||
response = self.client.post( | ||
'/v2/apps/{app_id}/tls'.format(**locals()), | ||
data) | ||
self.assertEqual(response.status_code, 201, response.data) | ||
self.assertFalse(app.tls_set.latest().https_enforced) | ||
|
||
# when the same data is sent again, a 409 is returned | ||
conflict_response = self.client.post( | ||
'/v2/apps/{app_id}/tls'.format(**locals()), | ||
data) | ||
self.assertEqual(conflict_response.status_code, 409, conflict_response.data) | ||
self.assertFalse(app.tls_set.latest().https_enforced) | ||
# also ensure that the previous tls UUID matches the latest, | ||
# confirming this conflicting TLS object was deleted | ||
self.assertEqual(response.data['uuid'], str(app.tls_set.latest().uuid)) | ||
|
||
# sending bad data returns a 400 | ||
data['https_enforced'] = "test" | ||
response = self.client.post( | ||
'/v2/apps/{app_id}/tls'.format(**locals()), | ||
data) | ||
self.assertEqual(response.status_code, 400, response.data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters