feat(list-groups): List available groups (#1213)

This commit is contained in:
Pepe Fagoaga
2022-06-22 09:59:48 +02:00
committed by GitHub
parent ecefda11c7
commit b07b7f3f26
5 changed files with 115 additions and 27 deletions

View File

@@ -1,12 +1,18 @@
{ {
"aws": { "aws": {
"gdpr": [ "gdpr": {
"check11", "checks": [
"check12" "check11",
], "check12"
"iam": [ ],
"iam_disable_30_days_credentials", "description": "GDPR Readiness"
"iam_disable_90_days_credentials" },
] "iam": {
"checks": [
"iam_disable_30_days_credentials",
"iam_disable_90_days_credentials"
],
"description": "Identity and Access Management"
}
} }
} }

View File

@@ -3,6 +3,7 @@ import pkgutil
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass from dataclasses import dataclass
from types import ModuleType from types import ModuleType
from typing import Any
from colorama import Fore, Style from colorama import Fore, Style
@@ -24,8 +25,10 @@ def exclude_groups_to_run(
checks_to_execute: set, excluded_groups: list, provider: str checks_to_execute: set, excluded_groups: list, provider: str
) -> set: ) -> set:
# Recover checks from the input groups # Recover checks from the input groups
available_groups = parse_groups_from_file(groups_file)
checks_from_groups = parse_groups_from_file(groups_file, excluded_groups, provider) checks_from_groups = load_checks_to_execute_from_groups(
available_groups, excluded_groups, provider
)
for check_name in checks_from_groups: for check_name in checks_from_groups:
checks_to_execute.discard(check_name) checks_to_execute.discard(check_name)
return checks_to_execute return checks_to_execute
@@ -61,15 +64,32 @@ def parse_checks_from_file(input_file: str, provider: str) -> set:
return checks_to_execute return checks_to_execute
# Load checks from groups.json # List available groups
def parse_groups_from_file(group_file: str, group_list: list, provider: str) -> set: def list_groups(provider: str) -> list:
checks_to_execute = set() groups = parse_groups_from_file(groups_file)
print(f"Available Groups:")
for group, value in groups[provider].items():
group_description = value["description"]
print(f"\t - {group_description} -- [{group}] ")
# Parse groups from groups.json
def parse_groups_from_file(group_file: str) -> Any:
f = open_file(group_file) f = open_file(group_file)
available_groups = parse_json_file(f) available_groups = parse_json_file(f)
return available_groups
# Parse checks from groups to execute
def load_checks_to_execute_from_groups(
available_groups: Any, group_list: list, provider: str
) -> set:
checks_to_execute = set()
for group in group_list: for group in group_list:
if group in available_groups[provider]: if group in available_groups[provider]:
for check_name in available_groups[provider][group]: for check_name in available_groups[provider][group]["checks"]:
checks_to_execute.add(check_name) checks_to_execute.add(check_name)
else: else:
logger.error( logger.error(
@@ -120,8 +140,9 @@ def load_checks_to_execute(
# Handle if there are groups passed using -g/--groups # Handle if there are groups passed using -g/--groups
elif group_list: elif group_list:
try: try:
checks_to_execute = parse_groups_from_file( available_groups = parse_groups_from_file(groups_file)
groups_file, group_list, provider checks_to_execute = load_checks_to_execute_from_groups(
available_groups, group_list, provider
) )
except Exception as e: except Exception as e:
logger.error(f"{e.__class__.__name__} -- {e}") logger.error(f"{e.__class__.__name__} -- {e}")

View File

@@ -4,6 +4,7 @@ from lib.check.check import (
exclude_checks_to_run, exclude_checks_to_run,
exclude_groups_to_run, exclude_groups_to_run,
exclude_services_to_run, exclude_services_to_run,
load_checks_to_execute_from_groups,
parse_checks_from_file, parse_checks_from_file,
parse_groups_from_file, parse_groups_from_file,
) )
@@ -19,7 +20,35 @@ class Test_Check:
# } # }
# ] # ]
# for test in test_cases: # for test in test_cases:
# assert importlib.import_module(test["input"]).__name__ == test["expected"] # assert importlib.import_module(test["input"]).__name__ == test["expected"
def test_parse_groups_from_file(self):
test_cases = [
{
"input": {
"path": f"{os.path.dirname(os.path.realpath(__file__))}/fixtures/groupsA.json",
"provider": "aws",
},
"expected": {
"aws": {
"gdpr": {
"description": "GDPR Readiness",
"checks": ["check11", "check12"],
},
"iam": {
"description": "Identity and Access Management",
"checks": [
"iam_disable_30_days_credentials",
"iam_disable_90_days_credentials",
],
},
}
},
}
]
for test in test_cases:
check_file = test["input"]["path"]
assert parse_groups_from_file(check_file) == test["expected"]
def test_parse_checks_from_file(self): def test_parse_checks_from_file(self):
test_cases = [ test_cases = [
@@ -36,23 +65,40 @@ class Test_Check:
provider = test["input"]["provider"] provider = test["input"]["provider"]
assert parse_checks_from_file(check_file, provider) == test["expected"] assert parse_checks_from_file(check_file, provider) == test["expected"]
def test_parse_groups_from_file(self): def test_load_checks_to_execute_from_groups(self):
test_cases = [ test_cases = [
{ {
"input": { "input": {
"groups": ["gdpr"], "groups_json": {
"aws": {
"gdpr": {
"description": "GDPR Readiness",
"checks": ["check11", "check12"],
},
"iam": {
"description": "Identity and Access Management",
"checks": [
"iam_disable_30_days_credentials",
"iam_disable_90_days_credentials",
],
},
}
},
"provider": "aws", "provider": "aws",
"group_file": f"{os.path.dirname(os.path.realpath(__name__))}/groups.json", "groups": ["gdpr"],
}, },
"expected": {"check11", "check12"}, "expected": {"check11", "check12"},
} }
] ]
for test in test_cases: for test in test_cases:
provider = test["input"]["provider"] provider = test["input"]["provider"]
groups = test["input"]["groups"] groups = test["input"]["groups"]
group_file = test["input"]["group_file"] group_file = test["input"]["groups_json"]
assert ( assert (
parse_groups_from_file(group_file, groups, provider) == test["expected"] load_checks_to_execute_from_groups(group_file, groups, provider)
== test["expected"]
) )
def test_exclude_checks_to_run(self): def test_exclude_checks_to_run(self):

View File

@@ -1,8 +1,18 @@
{ {
"aws": { "aws": {
"gdpr": [ "gdpr": {
"check11", "checks": [
"check12" "check11",
] "check12"
],
"description": "GDPR Readiness"
},
"iam": {
"checks": [
"iam_disable_30_days_credentials",
"iam_disable_90_days_credentials"
],
"description": "Identity and Access Management"
}
} }
} }

View File

@@ -9,6 +9,7 @@ from lib.check.check import (
exclude_groups_to_run, exclude_groups_to_run,
exclude_services_to_run, exclude_services_to_run,
import_check, import_check,
list_groups,
load_checks_to_execute, load_checks_to_execute,
run_check, run_check,
set_output_options, set_output_options,
@@ -28,7 +29,7 @@ if __name__ == "__main__":
group.add_argument("-C", "--checks-file", nargs="?", help="List of checks") group.add_argument("-C", "--checks-file", nargs="?", help="List of checks")
group.add_argument("-s", "--services", nargs="+", help="List of services") group.add_argument("-s", "--services", nargs="+", help="List of services")
group.add_argument("-g", "--groups", nargs="+", help="List of groups") group.add_argument("-g", "--groups", nargs="+", help="List of groups")
group.add_argument("-L", "--list-groups", action="store_true", help="List groups")
parser.add_argument("-e", "--excluded-checks", nargs="+", help="Checks to exclude") parser.add_argument("-e", "--excluded-checks", nargs="+", help="Checks to exclude")
parser.add_argument("-E", "--excluded-groups", nargs="+", help="Groups to exclude") parser.add_argument("-E", "--excluded-groups", nargs="+", help="Groups to exclude")
parser.add_argument( parser.add_argument(
@@ -123,6 +124,10 @@ if __name__ == "__main__":
if args.no_banner: if args.no_banner:
print_banner() print_banner()
if args.list_groups:
list_groups(provider)
quit()
# Setting output options # Setting output options
set_output_options(args.quiet) set_output_options(args.quiet)