Skip to content

Commit adf6cc1

Browse files
committed
fix(controller): validate Cluster.domain field
1 parent 6ccd7e0 commit adf6cc1

3 files changed

Lines changed: 39 additions & 9 deletions

File tree

controller/api/models.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ def _inner(*args, **kwargs):
5252
return _inner
5353

5454

55+
def validate_app_structure(value):
56+
"""Error if the dict values aren't ints >= 0."""
57+
try:
58+
for k, v in value.iteritems():
59+
if int(v) < 0:
60+
raise ValueError("Must be greater than or equal to zero")
61+
except ValueError, err:
62+
raise ValidationError(err)
63+
64+
5565
def validate_comma_separated(value):
5666
"""Error if the value doesn't look like a list of hostnames or IP addresses
5767
separated by commas.
@@ -61,14 +71,10 @@ def validate_comma_separated(value):
6171
"{} should be a comma-separated list".format(value))
6272

6373

64-
def validate_app_structure(value):
65-
"""Error if the dict values aren't ints >= 0."""
66-
try:
67-
for k, v in value.iteritems():
68-
if int(v) < 0:
69-
raise ValueError("Must be greater than or equal to zero")
70-
except ValueError, err:
71-
raise ValidationError(err)
74+
def validate_domain(value):
75+
"""Error if the domain contains unexpected characters."""
76+
if not re.search(r'^[a-zA-Z0-9-\.]+$', value):
77+
raise ValidationError('"{}" contains unexpected characters'.format(value))
7278

7379

7480
class AuditedModel(models.Model):
@@ -106,7 +112,7 @@ class Cluster(UuidAuditedModel):
106112
id = models.CharField(max_length=128, unique=True)
107113
type = models.CharField(max_length=16, choices=CLUSTER_TYPES, default='coreos')
108114

109-
domain = models.CharField(max_length=128)
115+
domain = models.CharField(max_length=128, validators=[validate_domain])
110116
hosts = models.CharField(max_length=256, validators=[validate_comma_separated])
111117
auth = models.TextField()
112118
options = JSONField(default={}, blank=True)

controller/api/serializers.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ class Meta:
6868
model = models.Cluster
6969
read_only_fields = ('created', 'updated')
7070

71+
def validate_domain(self, attrs, source):
72+
value = attrs[source]
73+
models.validate_domain(value)
74+
return attrs
75+
7176
def validate_hosts(self, attrs, source):
7277
value = attrs[source]
7378
models.validate_comma_separated(value)

controller/api/tests/test_cluster.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,22 @@ def test_cluster_perms_denied(self):
8585
'hosts': 'host1,host2', 'auth': 'base64string', 'options': options}
8686
response = self.client.post(url, json.dumps(body), content_type='application/json')
8787
self.assertEqual(response.status_code, 403)
88+
89+
def test_cluster_errors(self):
90+
"""
91+
Tests bad inputs to clusters:create and clusters:update.
92+
"""
93+
url = '/api/clusters'
94+
options = {'key': 'val'}
95+
body = {'id': 'autotest', 'domain': 'http://bad.domain', 'type': 'mock',
96+
'hosts': 'host1,host2', 'auth': 'base64string', 'options': options}
97+
response = self.client.post(url, json.dumps(body), content_type='application/json')
98+
self.assertEqual(response.status_code, 400)
99+
body['domain'] = 'autotest.local'
100+
response = self.client.post(url, json.dumps(body), content_type='application/json')
101+
self.assertEqual(response.status_code, 201)
102+
cluster_id = response.data['id'] # noqa
103+
url = '/api/clusters/{cluster_id}'.format(**locals())
104+
body = {'domain': 'http://bad.domain'}
105+
response = self.client.patch(url, json.dumps(body), content_type='application/json')
106+
self.assertEqual(response.status_code, 400)

0 commit comments

Comments
 (0)