Skip to content
Permalink
Browse files

Stricter cron validation, reject schedules like "At midnight of Febru…

…ary 31"
  • Loading branch information
cuu508 committed Feb 7, 2020
1 parent 4f6f1d9 commit ccd30ac239c620022f6d2aeeca32a721a728f963
@@ -20,6 +20,7 @@ All notable changes to this project will be documented in this file.
- Make sure Check.last_ping and Ping.created timestamps match exactly
- Don't trigger "down" notifications when changing schedule interactively in web UI
- Fix sendalerts crash loop when encountering a bad cron schedule
- Stricter cron validation, reject schedules like "At midnight of February 31"

## v1.12.0 - 2020-01-02

@@ -166,10 +166,20 @@ def test_it_rejects_non_string_channels_key(self):
self.assertEqual(r.status_code, 400)

def test_it_rejects_non_string_desc(self):
r = self.post(
self.check.code, {"api_key": "X" * 32, "desc": 123}
)
r = self.post(self.check.code, {"api_key": "X" * 32, "desc": 123})

self.assertEqual(r.status_code, 400)

def test_it_validates_cron_expression(self):
self.check.kind = "cron"
self.check.schedule = "5 * * * *"
self.check.save()

samples = ["* invalid *", "1,2 3,* * * *", "0 0 31 2 *"]
for sample in samples:
r = self.post(self.check.code, {"api_key": "X" * 32, "schedule": sample})
self.assertEqual(r.status_code, 400, "Did not reject '%s'" % sample)

# Schedule should be unchanged
self.check.refresh_from_db()
self.assertEqual(self.check.schedule, "5 * * * *")
@@ -74,7 +74,7 @@ def test_it_saves_cron_expression(self):

def test_it_validates_cron_expression(self):
self.client.login(username="alice@example.org", password="password")
samples = ["* invalid *", "1,2 3,* * * *"]
samples = ["* invalid *", "1,2 3,* * * *", "0 0 31 2 *"]

for sample in samples:
payload = {"kind": "cron", "schedule": sample, "tz": "UTC", "grace": 60}
@@ -25,7 +25,10 @@ def __call__(self, value):
raise ValidationError(message=self.message)

try:
croniter(value)
# Does croniter accept the schedule?
it = croniter(value)
# Can it calculate the next datetime?
it.next()
except:
raise ValidationError(message=self.message)

@@ -22,7 +22,10 @@ def validate(obj, schema, obj_name="value"):
raise ValidationError("%s is too long" % obj_name)
if schema.get("format") == "cron":
try:
croniter(obj)
# Does croniter accept the schedule?
it = croniter(obj)
# Can it calculate the next datetime?
it.next()
except:
raise ValidationError("%s is not a valid cron expression" % obj_name)
if schema.get("format") == "timezone" and obj not in all_timezones:
@@ -74,8 +74,10 @@ def test_it_rejects_a_value_not_in_enum(self):
validate("baz", {"enum": ["foo", "bar"]})

def test_it_checks_cron_format(self):
with self.assertRaises(ValidationError):
validate("x * * * *", {"type": "string", "format": "cron"})
samples = ["x * * * *", "0 0 31 2 *"]
for sample in samples:
with self.assertRaises(ValidationError):
validate(sample, {"type": "string", "format": "cron"})

def test_it_checks_timezone_format(self):
with self.assertRaises(ValidationError):
@@ -4,4 +4,4 @@ django-compressor==2.4
psycopg2==2.8.4
pytz==2019.3
requests==2.22.0
statsd==3.3.0
statsd==3.3.0

0 comments on commit ccd30ac

Please sign in to comment.
You can’t perform that action at this time.