Skip to content

Commit fd48661

Browse files
committed
Address review comments
1 parent 0f4403a commit fd48661

File tree

6 files changed

+54
-45
lines changed

6 files changed

+54
-45
lines changed

docs/source/features.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,16 @@ digests. To avoid these false positives, enable ``exclude-entropy-patterns``. Ex
280280
apply to any strings flagged by entropy checks. This option is not available on the command line,
281281
and must be specified in your config file.
282282

283-
For example, if ``docs/README.md`` contains a git SHA, this would be flagged by entropy.
283+
For example, if ``docs/README.md`` contains a git SHA and `.github/workflows/*.yml` containes pinned git SHAs
284+
this would be flagged by entropy.
284285
To exclude this, add an entry to ``exclude-entropy-patterns`` in the config file.
285286

286287
.. code-block:: toml
287288
288289
[tool.tartufo]
289290
exclude-entropy-patterns = [
290291
{path-pattern = 'docs/.*\.md$', pattern = '^[a-zA-Z0-9]$', reason = 'exclude all git SHAs in the docs'},
292+
{path-pattern = '\.github/workflows/.*\.yml', pattern = 'uses: .*@[a-zA-Z0-9]{40}', reason = 'GitHub Actions'}
291293
]
292294
293295
Thanks to the magic of TOML, you could also split these out into their own tables

tartufo/config.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
import tomlkit
2020

2121
from tartufo import types, util
22-
from tartufo.types import ConfigException, Rule
22+
from tartufo.types import ConfigException, Rule, MatchType, Scope
2323

2424
OptionTypes = Union[str, int, bool, None, TextIO, Tuple[TextIO, ...]]
2525

2626
DEFAULT_PATTERN_FILE = pathlib.Path(__file__).parent / "data" / "default_regexes.json"
27+
EMPTY_PATTERN = re.compile("")
2728

2829

2930
def load_config_from_path(
@@ -218,16 +219,16 @@ def load_rules_from_file(rules_file: TextIO) -> Dict[str, Rule]:
218219
pattern=re.compile(rule_definition["pattern"]),
219220
path_pattern=re.compile(path_pattern)
220221
if path_pattern
221-
else re.compile(""),
222-
re_match_type="match",
222+
else EMPTY_PATTERN,
223+
re_match_type=MatchType.Match,
223224
re_match_scope=None,
224225
)
225226
except AttributeError:
226227
rule = Rule(
227228
name=rule_name,
228229
pattern=re.compile(rule_definition),
229230
path_pattern=None,
230-
re_match_type="match",
231+
re_match_type=MatchType.Match,
231232
re_match_scope=None,
232233
)
233234
rules[rule_name] = rule
@@ -262,8 +263,8 @@ def compile_rules(patterns: Iterable[Union[str, Dict[str, str]]]) -> List[Rule]:
262263
name=pattern.get("reason", None), # type: ignore[union-attr]
263264
pattern=re.compile(pattern["pattern"]), # type: ignore[index]
264265
path_pattern=re.compile(pattern.get("path-pattern", "")), # type: ignore[union-attr]
265-
re_match_type=pattern.get("match-type", "search"), # type: ignore[union-attr]
266-
re_match_scope=pattern.get("scope", "line"), # type: ignore[union-attr]
266+
re_match_type=pattern.get("match-type", MatchType.Search), # type: ignore[union-attr]
267+
re_match_scope=pattern.get("scope", Scope.Line), # type: ignore[union-attr]
267268
)
268269
for pattern in patterns
269270
}

tartufo/scanner.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@
2828
import pygit2
2929

3030
from tartufo import config, types, util
31-
from tartufo.types import BranchNotFoundException, Rule, TartufoException
31+
from tartufo.types import (
32+
BranchNotFoundException,
33+
Rule,
34+
TartufoException,
35+
MatchType,
36+
Scope,
37+
)
3238

3339
BASE64_REGEX = re.compile(r"[A-Z0-9+/_-]+={,2}", re.IGNORECASE)
3440
HEX_REGEX = re.compile(r"[0-9A-F]+", re.IGNORECASE)
@@ -356,16 +362,16 @@ def rule_matches(rule: Rule, string: str, line: str, path: str) -> bool:
356362
:return: True if string and path matched, False otherwise.
357363
"""
358364
match = False
359-
if rule.re_match_scope == "word":
365+
if rule.re_match_scope == Scope.Word:
360366
scope = string
361367
else:
362368
scope = line
363-
if rule.re_match_type == "match":
369+
if rule.re_match_type == MatchType.Match:
364370
if rule.pattern:
365371
match = rule.pattern.match(scope) is not None
366372
if rule.path_pattern:
367373
match = match and rule.path_pattern.match(path) is not None
368-
elif rule.re_match_type == "search":
374+
elif rule.re_match_type == MatchType.Search:
369375
if rule.pattern:
370376
match = rule.pattern.search(scope) is not None
371377
if rule.path_pattern:

tartufo/types.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# pylint: disable=too-many-instance-attributes
22
import enum
33
from dataclasses import dataclass
4-
from typing import Any, Dict, Optional, TextIO, Tuple, Pattern
4+
from typing import Any, Dict, Optional, TextIO, Tuple, Pattern, Union
55

66

77
@dataclass
@@ -72,31 +72,31 @@ class Chunk:
7272
metadata: Dict[str, Any]
7373

7474

75+
class MatchType(enum.Enum):
76+
Match = "match" # pylint: disable=invalid-name
77+
Search = "search" # pylint: disable=invalid-name
78+
79+
80+
class Scope(enum.Enum):
81+
Word = "word" # pylint: disable=invalid-name
82+
Line = "line" # pylint: disable=invalid-name
83+
84+
7585
@dataclass
7686
class Rule:
7787
__slots__ = ("name", "pattern", "path_pattern", "re_match_type", "re_match_scope")
7888
name: Optional[str]
7989
pattern: Pattern
8090
path_pattern: Optional[Pattern]
81-
re_match_type: str
82-
re_match_scope: Optional[str]
91+
re_match_type: Union[str, MatchType]
92+
re_match_scope: Optional[Union[str, Scope]]
8393

8494
def __hash__(self) -> int:
8595
if self.path_pattern:
8696
return hash(f"{self.pattern.pattern}::{self.path_pattern.pattern}")
8797
return hash(self.pattern.pattern)
8898

8999

90-
class MatchType(enum.Enum):
91-
Match = "match" # pylint: disable=invalid-name
92-
Search = "search" # pylint: disable=invalid-name
93-
94-
95-
class Scope(enum.Enum):
96-
Word = "word" # pylint: disable=invalid-name
97-
Line = "line" # pylint: disable=invalid-name
98-
99-
100100
class LogLevel(enum.IntEnum):
101101
ERROR = 0
102102
WARNING = 1

tests/test_base_scanner.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from tartufo import scanner, types
77
from tartufo.scanner import Issue
8-
from tartufo.types import GlobalOptions, Rule
8+
from tartufo.types import GlobalOptions, Rule, MatchType
99

1010
from tests.helpers import generate_options
1111

@@ -308,21 +308,21 @@ def test_all_regex_rules_are_checked(self):
308308
name=None,
309309
pattern=rule_1,
310310
path_pattern=None,
311-
re_match_type="match",
311+
re_match_type=MatchType.Match,
312312
re_match_scope=None,
313313
),
314314
"bar": Rule(
315315
name=None,
316316
pattern=rule_2,
317317
path_pattern=rule_2_path,
318-
re_match_type="match",
318+
re_match_type=MatchType.Match,
319319
re_match_scope=None,
320320
),
321321
"not-found": Rule(
322322
name=None,
323323
pattern=rule_3,
324324
path_pattern=rule_3_path,
325-
re_match_type="match",
325+
re_match_type=MatchType.Match,
326326
re_match_scope=None,
327327
),
328328
}
@@ -345,7 +345,7 @@ def test_issue_is_not_created_if_signature_is_excluded(
345345
name=None,
346346
pattern=re.compile("foo"),
347347
path_pattern=None,
348-
re_match_type="match",
348+
re_match_type=MatchType.Match,
349349
re_match_scope=None,
350350
)
351351
}
@@ -365,7 +365,7 @@ def test_issue_is_returned_if_signature_is_not_excluded(
365365
name=None,
366366
pattern=re.compile("foo"),
367367
path_pattern=None,
368-
re_match_type="match",
368+
re_match_type=MatchType.Match,
369369
re_match_scope=None,
370370
)
371371
}

tests/test_config.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from click.testing import CliRunner
1010

1111
from tartufo import config, types
12-
from tartufo.types import Rule
12+
from tartufo.types import Rule, MatchType, Scope
1313

1414
from tests import helpers
1515

@@ -23,14 +23,14 @@ def test_configure_regexes_rules_files_without_defaults(self):
2323
name="RSA private key 2",
2424
pattern=re.compile("-----BEGIN EC PRIVATE KEY-----"),
2525
path_pattern=None,
26-
re_match_type="match",
26+
re_match_type=MatchType.Match,
2727
re_match_scope=None,
2828
),
2929
"Complex Rule": Rule(
3030
name="Complex Rule",
3131
pattern=re.compile("complex-rule"),
3232
path_pattern=re.compile("/tmp/[a-z0-9A-Z]+\\.(py|js|json)"),
33-
re_match_type="match",
33+
re_match_type=MatchType.Match,
3434
re_match_scope=None,
3535
),
3636
}
@@ -54,14 +54,14 @@ def test_configure_regexes_rules_files_with_defaults(self):
5454
name="RSA private key 2",
5555
pattern=re.compile("-----BEGIN EC PRIVATE KEY-----"),
5656
path_pattern=None,
57-
re_match_type="match",
57+
re_match_type=MatchType.Match,
5858
re_match_scope=None,
5959
)
6060
expected_regexes["Complex Rule"] = Rule(
6161
name="Complex Rule",
6262
pattern=re.compile("complex-rule"),
6363
path_pattern=re.compile("/tmp/[a-z0-9A-Z]+\\.(py|js|json)"),
64-
re_match_type="match",
64+
re_match_type=MatchType.Match,
6565
re_match_scope=None,
6666
)
6767

@@ -144,14 +144,14 @@ def test_configure_regexes_includes_rules_from_rules_repo(self):
144144
name="RSA private key 2",
145145
pattern=re.compile("-----BEGIN EC PRIVATE KEY-----"),
146146
path_pattern=None,
147-
re_match_type="match",
147+
re_match_type=MatchType.Match,
148148
re_match_scope=None,
149149
),
150150
"Complex Rule": Rule(
151151
name="Complex Rule",
152152
pattern=re.compile("complex-rule"),
153153
path_pattern=re.compile("/tmp/[a-z0-9A-Z]+\\.(py|js|json)"),
154-
re_match_type="match",
154+
re_match_type=MatchType.Match,
155155
re_match_scope=None,
156156
),
157157
}
@@ -320,22 +320,22 @@ def test_path_is_used(self):
320320
None,
321321
re.compile(r"^[a-zA-Z0-9]{26}$"),
322322
re.compile(r"src/.*"),
323-
re_match_type="search",
324-
re_match_scope="line",
323+
re_match_type=MatchType.Search,
324+
re_match_scope=Scope.Line,
325325
),
326326
Rule(
327327
None,
328328
re.compile(r"^[a-zA-Z0-9]test$"),
329329
re.compile(r""),
330-
re_match_type="search",
331-
re_match_scope="line",
330+
re_match_type=MatchType.Search,
331+
re_match_scope=Scope.Line,
332332
),
333333
Rule(
334334
None,
335335
re.compile(r"^[a-zA-Z0-9]{26}::test$"),
336336
re.compile(r"src/.*"),
337-
re_match_type="search",
338-
re_match_scope="line",
337+
re_match_type=MatchType.Search,
338+
re_match_scope=Scope.Line,
339339
),
340340
}
341341
),
@@ -354,8 +354,8 @@ def test_match_can_contain_delimiter(self):
354354
None,
355355
re.compile(r"^[a-zA-Z0-9]::test$"),
356356
re.compile(r""),
357-
re_match_type="search",
358-
re_match_scope="line",
357+
re_match_type=MatchType.Search,
358+
re_match_scope=Scope.Line,
359359
)
360360
],
361361
)

0 commit comments

Comments
 (0)