diff --git a/precli/cli/init.py b/precli/cli/init.py new file mode 100644 index 00000000..ce769d25 --- /dev/null +++ b/precli/cli/init.py @@ -0,0 +1,70 @@ +# Copyright 2024 Secure Sauce LLC +# SPDX-License-Identifier: BUSL-1.1 +import argparse +from argparse import Namespace +import sys + +import tomli_w + +from precli.core import loader + + +def setup_arg_parser() -> Namespace: + parser = argparse.ArgumentParser( + description="precli-init - create default configuration file", + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + + parser.add_argument( + "-o", + "--output", + dest="output", + action="store", + default=".precli.toml", + help="output the config to given file", + ) + + args = parser.parse_args() + + return args + + +def get_config() -> dict: + parsers = loader.load_extension(group="precli.parsers") + rules = [r for p in parsers.values() for r in p.rules.values()] + + config = {"rule": {}} + + for rule in rules: + config["rule"][rule.id] = { + "enabled": rule.config.enabled, + "level": rule.config.level, + } + if rule.config.parameters: + for parameter, value in rule.config.parameters.items(): + config["rule"][rule.id][parameter] = value + + return config + +def main(): + # Setup the command line arguments + args = setup_arg_parser() + + # Fetch the default configuration + config = get_config() + + # Write to the given file + try: + # TODO: check if file already exists and prompt to overwrite + with open(args.output, "wb") as f: + tomli_w.dump(config, f) + except OSError: + print(f"Error writing to file: {args.output}") + return 1 + else: + print(f"Default config written to file: {args.output}") + + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/precli/cli/main.py b/precli/cli/main.py index 46723646..4b1a8e4f 100644 --- a/precli/cli/main.py +++ b/precli/cli/main.py @@ -144,6 +144,7 @@ def setup_arg_parser(): f"License BUSL-1.1: Business Source License 1.1 <{BUSL_URL}>\n" f" Python {python_ver}", ) + args = parser.parse_args() if not args.targets: diff --git a/precli/rules/__init__.py b/precli/rules/__init__.py index f818cc6f..9e6a2440 100644 --- a/precli/rules/__init__.py +++ b/precli/rules/__init__.py @@ -58,7 +58,10 @@ def __init__( self._config = Config() self._config.enabled = metadata.get("enabled") self._config.level = Level(metadata.get("level")) - self._config.parameters = metadata.get("parameters") + self._config.parameters = {} + for parameter, value in metadata.items(): + if parameter not in ("enabled", "level"): + self._config.parameters[parameter] = value except tomllib.TOMLDecodeError as err: print(err) print("Invalid config in documentation") diff --git a/precli/rules/go/stdlib/crypto_weak_key.py b/precli/rules/go/stdlib/crypto_weak_key.py index c6636938..c269046b 100644 --- a/precli/rules/go/stdlib/crypto_weak_key.py +++ b/precli/rules/go/stdlib/crypto_weak_key.py @@ -124,10 +124,10 @@ ```toml enabled = true level = "warning" -parameters.warning_dsa_key_size = 2048 -parameters.error_dsa_key_size = 1024 -parameters.warning_rsa_key_size = 2048 -parameters.error_rsa_key_size = 1024 +warning_dsa_key_size = 2048 +error_dsa_key_size = 1024 +warning_rsa_key_size = 2048 +error_rsa_key_size = 1024 ``` # See also diff --git a/precli/rules/java/stdlib/java_security_weak_hash.py b/precli/rules/java/stdlib/java_security_weak_hash.py index 6ae56cb9..e3445a27 100644 --- a/precli/rules/java/stdlib/java_security_weak_hash.py +++ b/precli/rules/java/stdlib/java_security_weak_hash.py @@ -63,7 +63,7 @@ ```toml enabled = true level = "error" -parameters.weak_hashes = [ +weak_hashes = [ "MD2", "MD5", "SHA", diff --git a/precli/rules/java/stdlib/java_security_weak_key.py b/precli/rules/java/stdlib/java_security_weak_key.py index dae209d1..a409998d 100644 --- a/precli/rules/java/stdlib/java_security_weak_key.py +++ b/precli/rules/java/stdlib/java_security_weak_key.py @@ -82,8 +82,8 @@ ```toml enabled = true level = "warning" -parameters.warning_key_size = 2048 -parameters.error_key_size = 1024 +warning_key_size = 2048 +error_key_size = 1024 ``` # See also diff --git a/precli/rules/java/stdlib/javax_crypto_weak_cipher.py b/precli/rules/java/stdlib/javax_crypto_weak_cipher.py index 2fde1fed..cb56ddce 100644 --- a/precli/rules/java/stdlib/javax_crypto_weak_cipher.py +++ b/precli/rules/java/stdlib/javax_crypto_weak_cipher.py @@ -117,7 +117,7 @@ ```toml enabled = true level = "error" -parameters.weak_ciphers = [ +weak_ciphers = [ "ARCFOUR", "Blowfish", "DES", diff --git a/precli/rules/python/stdlib/argparse_sensitive_info.py b/precli/rules/python/stdlib/argparse_sensitive_info.py index 66418182..566d070f 100644 --- a/precli/rules/python/stdlib/argparse_sensitive_info.py +++ b/precli/rules/python/stdlib/argparse_sensitive_info.py @@ -70,7 +70,7 @@ ```toml enabled = true level = "error" -parameters.sensitive_arguments = [ +sensitive_arguments = [ "--api-key", "--password", "--token" diff --git a/precli/rules/python/stdlib/http_url_secret.py b/precli/rules/python/stdlib/http_url_secret.py index 6f5c5a0c..5e3f0704 100644 --- a/precli/rules/python/stdlib/http_url_secret.py +++ b/precli/rules/python/stdlib/http_url_secret.py @@ -55,7 +55,7 @@ ```toml enabled = true level = "error" -parameters.sensitive_params = [ +sensitive_params = [ "apiKey", "pass", "password", diff --git a/precli/rules/python/stdlib/os_loose_file_perm.py b/precli/rules/python/stdlib/os_loose_file_perm.py index 0eac2327..755814be 100644 --- a/precli/rules/python/stdlib/os_loose_file_perm.py +++ b/precli/rules/python/stdlib/os_loose_file_perm.py @@ -77,7 +77,7 @@ ```toml enabled = true level = "warning" -parameters.umask = 0o022 +umask = 0o022 ``` ## See also diff --git a/precli/rules/python/stdlib/pathlib_loose_file_perm.py b/precli/rules/python/stdlib/pathlib_loose_file_perm.py index 32f29b57..b3e9d734 100644 --- a/precli/rules/python/stdlib/pathlib_loose_file_perm.py +++ b/precli/rules/python/stdlib/pathlib_loose_file_perm.py @@ -77,7 +77,7 @@ ```toml enabled = true level = "warning" -parameters.umask = 0o022 +umask = 0o022 ``` ## See also diff --git a/precli/rules/python/stdlib/secrets_weak_token.py b/precli/rules/python/stdlib/secrets_weak_token.py index 02a07e58..cb661b68 100644 --- a/precli/rules/python/stdlib/secrets_weak_token.py +++ b/precli/rules/python/stdlib/secrets_weak_token.py @@ -50,8 +50,8 @@ ```toml enabled = true level = "warning" -parameters.warning_token_size = 32 -parameters.error_token_size = 16 +warning_token_size = 32 +error_token_size = 16 ``` # See also diff --git a/precli/rules/python/stdlib/ssl_context_weak_key.py b/precli/rules/python/stdlib/ssl_context_weak_key.py index acdd1968..b2c6ecfe 100644 --- a/precli/rules/python/stdlib/ssl_context_weak_key.py +++ b/precli/rules/python/stdlib/ssl_context_weak_key.py @@ -54,8 +54,8 @@ ```toml enabled = true level = "warning" -parameters.warning_ec_key_size = 224 -parameters.error_ec_key_size = 160 +warning_ec_key_size = 224 +error_ec_key_size = 160 ``` # See also diff --git a/requirements.txt b/requirements.txt index f6152f4e..d8cc3ef0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ # Copyright 2024 Secure Sauce LLC # SPDX-License-Identifier: BUSL-1.1 typing-extensions==4.12.2;python_version<"3.11" -tomli>=1.1.0; python_version<"3.11" +tomli==1.1.0; python_version<"3.11" +tomli_w==1.1.0 rich==13.9.3 tree-sitter==0.23.2 ignorelib==0.3.0 diff --git a/setup.cfg b/setup.cfg index 4e1898ce..4ef252bb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -39,6 +39,7 @@ project_urls = [entry_points] console_scripts = precli = precli.cli.main:main + precli-init = precli.cli.init:main precli.renderers = # precli/renderers/detailed.py