diff --git a/awx/api/serializers.py b/awx/api/serializers.py index d8015c90e2..f198566c55 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -979,6 +979,12 @@ class CustomInventoryScriptSerializer(BaseSerializer): model = CustomInventoryScript fields = ('*', "script", "organization") + def validate_script(self, attrs, source): + script_contents = attrs.get(source, '') + if not script_contents.startswith("#!"): + raise serializers.ValidationError('Script must begin with a hashbang sequence: i.e.... #!/usr/bin/env python') + return attrs + def to_native(self, obj): ret = super(CustomInventoryScriptSerializer, self).to_native(obj) if obj is None: diff --git a/awx/main/tests/inventory.py b/awx/main/tests/inventory.py index f7ccbd1016..d8785b23d9 100644 --- a/awx/main/tests/inventory.py +++ b/awx/main/tests/inventory.py @@ -22,6 +22,7 @@ from awx.main.tests.base import BaseTest, BaseTransactionTest __all__ = ['InventoryTest', 'InventoryUpdatesTest'] TEST_SIMPLE_INVENTORY_SCRIPT = "#!/usr/bin/env python\nimport json\nprint json.dumps({'hosts': ['ahost-01', 'ahost-02', 'ahost-03', 'ahost-04']})" +TEST_SIMPLE_INVENTORY_SCRIPT_WITHOUT_HASHBANG = "import json\nprint json.dumps({'hosts': ['ahost-01', 'ahost-02', 'ahost-03', 'ahost-04']})" TEST_UNICODE_INVENTORY_SCRIPT = u"""#!/usr/bin/env python # -*- coding: utf-8 -*- @@ -299,6 +300,10 @@ class InventoryTest(BaseTest): new_failed_script = dict(name="Shouldfail", description="This test should fail", script=TEST_SIMPLE_INVENTORY_SCRIPT, organization=self.organizations[0].id) self.post(inventory_scripts, data=new_failed_script, expect=403, auth=self.get_normal_credentials()) + failed_no_shebang = dict(name="ShouldAlsoFail", descript="This test should also fail", script=TEST_SIMPLE_INVENTORY_SCRIPT_WITHOUT_HASHBANG, + organization=self.organizations[0].id) + self.post(inventory_scripts, data=failed_no_shebang, expect=400, auth=self.get_super_credentials()) + def test_main_line(self): # some basic URLs...