audit-labs/audit-tools

A collection of scripts, queries, and other goodies you can use in an audit.

clone: git clone https://gitbay.org/audit-labs/audit-tools.git

main: tui/platforms.py · raw

  1"""
  2Platform descriptors that let the TUI drive any collector runner.
  3
  4Each Platform declares its connection form (``fields``), its checks, and how to
  5compute the output directory and run the audit. The screens in app.py are
  6written against this interface, so adding a platform is data, not new UI.
  7"""
  8
  9import os
 10from collections.abc import Callable
 11from dataclasses import dataclass, field
 12
 13from tui import aws_runner, github_runner, gitlab_runner
 14from tui.common import Check
 15
 16
 17@dataclass(frozen=True)
 18class Field:
 19    """One input on the connection screen."""
 20
 21    key: str
 22    label: str
 23    placeholder: str = ""
 24    default: str = ""
 25    password: bool = False
 26    required: bool = False
 27    env: str | None = None  # environment variable used to pre-fill the value
 28
 29
 30@dataclass(frozen=True)
 31class Platform:
 32    key: str
 33    label: str
 34    subject: Callable[
 35        [dict], str
 36    ]  # (settings) -> audit subject shown on the run screen
 37    fields: list[Field]
 38    checks: list[Check]
 39    default_selection: list[str]
 40    output_dir: Callable[[dict], str]  # (settings) -> path
 41    run: Callable[..., object]  # (settings, output_dir, selected_keys, on_event)
 42    enabled: bool = True
 43    note: str = field(default="")
 44
 45
 46# Shared connection fields reused across platforms.
 47_OUT_FIELD = Field("out", "Output directory", default="./output")
 48
 49
 50def _prefill(f: Field) -> str:
 51    if f.env:
 52        value = os.environ.get(f.env, "").strip()
 53        if value:
 54            return value
 55    return f.default
 56
 57
 58def _github_output_dir(s: dict) -> str:
 59    return github_runner.default_output_dir(s["out"], s["org"])
 60
 61
 62def _github_run(s: dict, output_dir, selected_keys, on_event):
 63    return github_runner.run_audit(
 64        org=s["org"],
 65        token=s["token"],
 66        output_dir=output_dir,
 67        branch=s["branch"],
 68        selected_keys=selected_keys,
 69        on_event=on_event,
 70    )
 71
 72
 73def _gitlab_output_dir(s: dict) -> str:
 74    return gitlab_runner.default_output_dir(s["out"], s["group"])
 75
 76
 77def _gitlab_run(s: dict, output_dir, selected_keys, on_event):
 78    return gitlab_runner.run_audit(
 79        group=s["group"],
 80        token=s["token"],
 81        base_url=s["base_url"],
 82        output_dir=output_dir,
 83        selected_keys=selected_keys,
 84        on_event=on_event,
 85    )
 86
 87
 88def _aws_output_dir(s: dict) -> str:
 89    return aws_runner.default_output_dir(s["out"], s["profile"])
 90
 91
 92def _aws_run(s: dict, output_dir, selected_keys, on_event):
 93    return aws_runner.run_audit(
 94        profile=s["profile"],
 95        region=s["region"],
 96        account=s["account"],
 97        output_dir=output_dir,
 98        selected_keys=selected_keys,
 99        on_event=on_event,
100    )
101
102
103GITHUB = Platform(
104    key="github",
105    label="GitHub",
106    subject=lambda s: s["org"],
107    fields=[
108        Field("org", "Organization", "my-org", required=True, env="GITHUB_ORG"),
109        Field(
110            "token",
111            "Personal access token",
112            "ghp_… (read:org, repo)",
113            password=True,
114            required=True,
115            env="GITHUB_TOKEN",
116        ),
117        _OUT_FIELD,
118        Field("branch", "Branch (for commit history)", default="main"),
119    ],
120    checks=github_runner.CHECKS,
121    default_selection=github_runner.DEFAULT_SELECTION,
122    output_dir=_github_output_dir,
123    run=_github_run,
124)
125
126GITLAB = Platform(
127    key="gitlab",
128    label="GitLab",
129    subject=lambda s: s["group"],
130    fields=[
131        Field(
132            "group",
133            "Group ID or path",
134            "e.g. 1234567 or my-group",
135            required=True,
136            env="GITLAB_GROUP",
137        ),
138        Field(
139            "token",
140            "Personal access token",
141            "glpat-… (read_api)",
142            password=True,
143            required=True,
144            env="GITLAB_TOKEN",
145        ),
146        Field(
147            "base_url",
148            "API base URL (self-hosted)",
149            default="https://gitlab.com/api/v4",
150            env="GITLAB_URL",
151        ),
152        _OUT_FIELD,
153    ],
154    checks=gitlab_runner.CHECKS,
155    default_selection=gitlab_runner.DEFAULT_SELECTION,
156    output_dir=_gitlab_output_dir,
157    run=_gitlab_run,
158)
159
160AWS = Platform(
161    key="aws",
162    label="AWS",
163    subject=lambda s: s["profile"] or "default",
164    fields=[
165        Field(
166            "profile",
167            "AWS profile",
168            "default chain, or a named / SSO profile",
169            env="AWS_PROFILE",
170        ),
171        Field("region", "Region", "e.g. us-east-1", env="AWS_DEFAULT_REGION"),
172        Field(
173            "account",
174            "Account name (SSO check only)",
175            "optional; defaults to current account",
176            env="AWS_AUDIT_ACCOUNT",
177        ),
178        _OUT_FIELD,
179    ],
180    checks=aws_runner.CHECKS,
181    default_selection=aws_runner.DEFAULT_SELECTION,
182    output_dir=_aws_output_dir,
183    run=_aws_run,
184)
185
186PLATFORMS = [GITHUB, GITLAB, AWS]
187
188
189def prefill(f: Field) -> str:
190    """Public accessor for a field's pre-filled value (env var or default)."""
191    return _prefill(f)