Repository: roaldnefs/salt-lint

Issue:
Missing rule for leading zero in file mode
Missing rule in to check for leading zero in file mode. When using a mode that includes a leading zero it must be wrapped in single quotes. If the value is not wrapped in quotes it will be read by YAML as an integer and evaluated as an octal.

**Source:** https://docs.saltstack.com/en/latest/ref/states/all/salt.states.file.html#module-salt.states.file

**Possible Solution**
Create a regex to check if the mode has a leading zero and doesn't use quotes. Simple example for a regex rule: [lib/saltlint/rules/JinjaVariableHasSpacesRule.py](https://github.com/roaldnefs/salt-lint/blob/master/lib/saltlint/rules/JinjaVariableHasSpacesRule.py). Don't forget to add a test, e.g.: [tests/unit/TestJinjaVariableHasSpaces.py](https://github.com/roaldnefs/salt-lint/blob/master/tests/unit/TestJinjaVariableHasSpaces.py).

Comments:

Patch:
diff --git a/lib/saltlint/rules/FileModeQuotationRule.py b/lib/saltlint/rules/FileModeQuotationRule.py
new file mode 100644
index 0000000..e9f1d87
--- /dev/null
+++ b/lib/saltlint/rules/FileModeQuotationRule.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2016, Will Thames and contributors
+# Copyright (c) 2018, Ansible Project
+# Modified work Copyright (c) 2019 Jeffrey Bouter
+
+from saltlint import SaltLintRule
+import re
+
+
+class FileModeQuotationRule(SaltLintRule):
+    id = '207'
+    shortdesc = 'File modes should always be encapsulated in quotation marks'
+    description = 'File modes should always be encapsulated in quotation marks'
+    severity = 'HIGH'
+    tags = ['formatting']
+    version_added = 'v0.0.1'
+
+    bracket_regex = re.compile(r"^\s+- ((dir_)|(file_))?mode: [0-9]{3,4}")
+
+    def match(self, file, line):
+        return self.bracket_regex.search(line)


Test patch:
diff --git a/tests/unit/TestFileModeQuotationRule.py b/tests/unit/TestFileModeQuotationRule.py
new file mode 100644
index 0000000..4f7998e
--- /dev/null
+++ b/tests/unit/TestFileModeQuotationRule.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2013-2018 Will Thames <will@thames.id.au>
+# Copyright (c) 2018 Ansible by Red Hat
+# Modified work Copyright (c) 2019 Jeffrey Bouter
+
+import unittest
+
+from saltlint import RulesCollection
+from saltlint.rules.FileModeQuotationRule import FileModeQuotationRule
+from tests import RunFromText
+
+
+GOOD_MODE_QUOTATION_LINE = '''
+testfile:
+  file.managed:
+    - name: /tmp/testfile
+    - user: root
+    - group: root
+    - mode: '0700'
+'''
+
+BAD_MODE_QUOTATION_LINE = '''
+testfile:
+  file.managed:
+    - name: /tmp/badfile
+    - user: root
+    - group: root
+    - mode: 0700
+    - file_mode: 0660
+    - dir_mode: 0775
+'''
+
+class TestLineTooLongRule(unittest.TestCase):
+    collection = RulesCollection()
+
+    def setUp(self):
+        self.collection.register(FileModeQuotationRule())
+        self.runner = RunFromText(self.collection)
+
+    def test_statement_positive(self):
+        results = self.runner.run_state(GOOD_MODE_QUOTATION_LINE)
+        self.assertEqual(0, len(results))
+
+    def test_statement_negative(self):
+        results = self.runner.run_state(BAD_MODE_QUOTATION_LINE)
+        self.assertEqual(3, len(results))