appsec-tool-kit 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+ branches: [main, master]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ name: pytest
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+
23
+ - uses: astral-sh/setup-uv@v5
24
+
25
+ - run: uv sync --group dev
26
+
27
+ - run: uv run pytest --tb=short
@@ -0,0 +1,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,255 @@
1
+ Metadata-Version: 2.4
2
+ Name: appsec-tool-kit
3
+ Version: 0.1.0
4
+ Summary: Interactive CLI to configure security tools for CI/CD pipelines
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: questionary>=2.0
7
+ Requires-Dist: rich>=13.0
8
+ Description-Content-Type: text/markdown
9
+
10
+ # AppSec Kit
11
+
12
+ CLI interativo que configura ferramentas de segurança para esteiras CI/CD com um único comando. Roda no projeto do dev e gera os arquivos prontos para uso.
13
+
14
+ **Suporte:** Python · Node.js · GitHub Actions
15
+
16
+ ---
17
+
18
+ ## O que ele instala
19
+
20
+ | Camada | Python | Node.js |
21
+ |---|---|---|
22
+ | SAST | Bandit | Semgrep |
23
+ | Dependency scanning | pip-audit | npm audit |
24
+ | Secret scanning | Gitleaks + detect-secrets | Gitleaks + detect-secrets |
25
+ | Pre-commit hooks | pre-commit | pre-commit |
26
+
27
+ ---
28
+
29
+ ## Pré-requisitos
30
+
31
+ - Python 3.12+
32
+ - [uv](https://docs.astral.sh/uv/) ou pip
33
+ - Git inicializado no projeto-alvo (`git init`)
34
+
35
+ ---
36
+
37
+ ## Instalação
38
+
39
+ ### Via uv (recomendado)
40
+
41
+ ```bash
42
+ uv tool install appsec-tool-kit
43
+ ```
44
+
45
+ ### Via pip
46
+
47
+ ```bash
48
+ pip install appsec-tool-kit
49
+ ```
50
+
51
+ ### Direto do repositório (desenvolvimento)
52
+
53
+ ```bash
54
+ git clone https://github.com/seu-usuario/appsec-tool-kit.git
55
+ cd appsec-tool-kit
56
+ uv sync
57
+ uv run appsec-kit
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Tutorial passo a passo
63
+
64
+ ### Passo 1 — Acesse o diretório do seu projeto
65
+
66
+ ```bash
67
+ cd /caminho/do/seu/projeto
68
+ ```
69
+
70
+ > O kit detecta automaticamente o tipo de projeto pelo conteúdo do diretório.
71
+
72
+ ---
73
+
74
+ ### Passo 2 — Execute o wizard
75
+
76
+ ```bash
77
+ appsec-kit
78
+ ```
79
+
80
+ Você verá a tela inicial:
81
+
82
+ ```
83
+ ╭──────────────────────────────────────────────────────╮
84
+ │ AppSec Kit – Security toolkit for CI/CD pipelines │
85
+ ╰──────────────────────────────────────────────────────╯
86
+
87
+ Detected: Python project
88
+
89
+ ? Project type:
90
+ > Python
91
+ Node.js
92
+ ```
93
+
94
+ ---
95
+
96
+ ### Passo 3 — Confirme o tipo de projeto
97
+
98
+ O kit detecta automaticamente se é **Python** ou **Node.js** pelo conteúdo do diretório:
99
+
100
+ - Python → presença de `pyproject.toml`, `requirements.txt`, `setup.py` ou `Pipfile`
101
+ - Node.js → presença de `package.json`
102
+
103
+ Confirme ou altere com as setas e pressione `Enter`.
104
+
105
+ ---
106
+
107
+ ### Passo 4 — Confirme o diretório-alvo
108
+
109
+ ```
110
+ ? Target directory: [.]
111
+ ```
112
+
113
+ Pressione `Enter` para usar o diretório atual ou informe outro caminho:
114
+
115
+ ```
116
+ ? Target directory: ../meu-outro-projeto
117
+ ```
118
+
119
+ ---
120
+
121
+ ### Passo 5 — Selecione as camadas de segurança
122
+
123
+ ```
124
+ ? Security layers to configure:
125
+ > [x] SAST (Static Analysis)
126
+ [x] Dependency Scanning
127
+ [x] Secret Scanning
128
+ [x] Pre-commit Hooks
129
+ ```
130
+
131
+ Use `Espaço` para marcar/desmarcar, `Enter` para confirmar.
132
+ Por padrão todas as camadas ficam selecionadas.
133
+
134
+ ---
135
+
136
+ ### Passo 6 — Aguarde a geração dos arquivos
137
+
138
+ ```
139
+ ✓ .github/workflows/security.yml (created)
140
+ ✓ .pre-commit-config.yaml (created)
141
+ ↻ pyproject.toml (updated)
142
+ ```
143
+
144
+ ---
145
+
146
+ ### Passo 7 — Siga as instruções pós-instalação
147
+
148
+ O wizard exibe os próximos passos automaticamente:
149
+
150
+ ```
151
+ ╭─ Next steps ──────────────────────────────────────────╮
152
+ │ pip install pre-commit detect-secrets │
153
+ │ detect-secrets scan > .secrets.baseline │
154
+ │ pre-commit install │
155
+ │ │
156
+ │ # Commit e push para ativar o GitHub Actions: │
157
+ │ git add .github/ .pre-commit-config.yaml │
158
+ │ git commit -m "chore: add appsec security config" │
159
+ │ git push │
160
+ ╰───────────────────────────────────────────────────────╯
161
+ ```
162
+
163
+ Execute esses comandos na ordem.
164
+
165
+ ---
166
+
167
+ ## O que é gerado
168
+
169
+ ### `.github/workflows/security.yml`
170
+
171
+ Workflow do GitHub Actions com jobs separados por camada:
172
+
173
+ - **SAST** — análise estática roda a cada push/PR
174
+ - **Dependency scan** — verifica vulnerabilidades nas dependências
175
+ - **Secret scanning** — Gitleaks varre o histórico git em busca de segredos expostos
176
+
177
+ O workflow é acionado em push e pull requests para `main` e `master`.
178
+
179
+ ---
180
+
181
+ ### `.pre-commit-config.yaml`
182
+
183
+ Hooks que rodam localmente antes de cada commit:
184
+
185
+ **Python:**
186
+ ```yaml
187
+ repos:
188
+ - repo: https://github.com/PyCQA/bandit # SAST
189
+ - repo: https://github.com/Yelp/detect-secrets # secrets
190
+ - repo: https://github.com/pypa/pip-audit # dependências
191
+ ```
192
+
193
+ **Node.js:**
194
+ ```yaml
195
+ repos:
196
+ - repo: https://github.com/Yelp/detect-secrets # secrets
197
+ - repo: https://github.com/gitleaks/gitleaks # secrets
198
+ - repo: local # npm audit
199
+ ```
200
+
201
+ ---
202
+
203
+ ### `pyproject.toml` (apenas Python)
204
+
205
+ Adiciona configuração do Bandit ao arquivo existente:
206
+
207
+ ```toml
208
+ [tool.bandit]
209
+ exclude_dirs = ["tests", "venv", ".venv"]
210
+ skips = []
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Casos de uso comuns
216
+
217
+ ### Só quero pre-commit, sem CI
218
+
219
+ Execute o wizard e desmarque as camadas SAST, Dependency Scanning e Secret Scanning. Mantenha apenas **Pre-commit Hooks** selecionado.
220
+
221
+ ### Só quero o GitHub Actions, sem pre-commit
222
+
223
+ Desmarque **Pre-commit Hooks** e mantenha as outras camadas.
224
+
225
+ ### Projeto já tem `.pre-commit-config.yaml`
226
+
227
+ O kit sobrescreve o arquivo com status `(updated)`. Faça backup antes se necessário:
228
+
229
+ ```bash
230
+ cp .pre-commit-config.yaml .pre-commit-config.yaml.bak
231
+ appsec-kit
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Atualizando versões dos hooks
237
+
238
+ As versões dos hooks pre-commit ficam fixadas em `.pre-commit-config.yaml`. Para atualizar todas para o latest:
239
+
240
+ ```bash
241
+ pre-commit autoupdate
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Ferramentas utilizadas
247
+
248
+ | Ferramenta | Finalidade | Docs |
249
+ |---|---|---|
250
+ | [Bandit](https://bandit.readthedocs.io/) | SAST para Python | bandit.readthedocs.io |
251
+ | [Semgrep](https://semgrep.dev/) | SAST para JavaScript/TypeScript | semgrep.dev |
252
+ | [pip-audit](https://pypi.org/project/pip-audit/) | CVEs em dependências Python | pypi.org/project/pip-audit |
253
+ | [detect-secrets](https://github.com/Yelp/detect-secrets) | Detecção de segredos | github.com/Yelp/detect-secrets |
254
+ | [Gitleaks](https://gitleaks.io/) | Varredura de segredos no histórico git | gitleaks.io |
255
+ | [pre-commit](https://pre-commit.com/) | Framework de git hooks | pre-commit.com |
@@ -0,0 +1,246 @@
1
+ # AppSec Kit
2
+
3
+ CLI interativo que configura ferramentas de segurança para esteiras CI/CD com um único comando. Roda no projeto do dev e gera os arquivos prontos para uso.
4
+
5
+ **Suporte:** Python · Node.js · GitHub Actions
6
+
7
+ ---
8
+
9
+ ## O que ele instala
10
+
11
+ | Camada | Python | Node.js |
12
+ |---|---|---|
13
+ | SAST | Bandit | Semgrep |
14
+ | Dependency scanning | pip-audit | npm audit |
15
+ | Secret scanning | Gitleaks + detect-secrets | Gitleaks + detect-secrets |
16
+ | Pre-commit hooks | pre-commit | pre-commit |
17
+
18
+ ---
19
+
20
+ ## Pré-requisitos
21
+
22
+ - Python 3.12+
23
+ - [uv](https://docs.astral.sh/uv/) ou pip
24
+ - Git inicializado no projeto-alvo (`git init`)
25
+
26
+ ---
27
+
28
+ ## Instalação
29
+
30
+ ### Via uv (recomendado)
31
+
32
+ ```bash
33
+ uv tool install appsec-tool-kit
34
+ ```
35
+
36
+ ### Via pip
37
+
38
+ ```bash
39
+ pip install appsec-tool-kit
40
+ ```
41
+
42
+ ### Direto do repositório (desenvolvimento)
43
+
44
+ ```bash
45
+ git clone https://github.com/seu-usuario/appsec-tool-kit.git
46
+ cd appsec-tool-kit
47
+ uv sync
48
+ uv run appsec-kit
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Tutorial passo a passo
54
+
55
+ ### Passo 1 — Acesse o diretório do seu projeto
56
+
57
+ ```bash
58
+ cd /caminho/do/seu/projeto
59
+ ```
60
+
61
+ > O kit detecta automaticamente o tipo de projeto pelo conteúdo do diretório.
62
+
63
+ ---
64
+
65
+ ### Passo 2 — Execute o wizard
66
+
67
+ ```bash
68
+ appsec-kit
69
+ ```
70
+
71
+ Você verá a tela inicial:
72
+
73
+ ```
74
+ ╭──────────────────────────────────────────────────────╮
75
+ │ AppSec Kit – Security toolkit for CI/CD pipelines │
76
+ ╰──────────────────────────────────────────────────────╯
77
+
78
+ Detected: Python project
79
+
80
+ ? Project type:
81
+ > Python
82
+ Node.js
83
+ ```
84
+
85
+ ---
86
+
87
+ ### Passo 3 — Confirme o tipo de projeto
88
+
89
+ O kit detecta automaticamente se é **Python** ou **Node.js** pelo conteúdo do diretório:
90
+
91
+ - Python → presença de `pyproject.toml`, `requirements.txt`, `setup.py` ou `Pipfile`
92
+ - Node.js → presença de `package.json`
93
+
94
+ Confirme ou altere com as setas e pressione `Enter`.
95
+
96
+ ---
97
+
98
+ ### Passo 4 — Confirme o diretório-alvo
99
+
100
+ ```
101
+ ? Target directory: [.]
102
+ ```
103
+
104
+ Pressione `Enter` para usar o diretório atual ou informe outro caminho:
105
+
106
+ ```
107
+ ? Target directory: ../meu-outro-projeto
108
+ ```
109
+
110
+ ---
111
+
112
+ ### Passo 5 — Selecione as camadas de segurança
113
+
114
+ ```
115
+ ? Security layers to configure:
116
+ > [x] SAST (Static Analysis)
117
+ [x] Dependency Scanning
118
+ [x] Secret Scanning
119
+ [x] Pre-commit Hooks
120
+ ```
121
+
122
+ Use `Espaço` para marcar/desmarcar, `Enter` para confirmar.
123
+ Por padrão todas as camadas ficam selecionadas.
124
+
125
+ ---
126
+
127
+ ### Passo 6 — Aguarde a geração dos arquivos
128
+
129
+ ```
130
+ ✓ .github/workflows/security.yml (created)
131
+ ✓ .pre-commit-config.yaml (created)
132
+ ↻ pyproject.toml (updated)
133
+ ```
134
+
135
+ ---
136
+
137
+ ### Passo 7 — Siga as instruções pós-instalação
138
+
139
+ O wizard exibe os próximos passos automaticamente:
140
+
141
+ ```
142
+ ╭─ Next steps ──────────────────────────────────────────╮
143
+ │ pip install pre-commit detect-secrets │
144
+ │ detect-secrets scan > .secrets.baseline │
145
+ │ pre-commit install │
146
+ │ │
147
+ │ # Commit e push para ativar o GitHub Actions: │
148
+ │ git add .github/ .pre-commit-config.yaml │
149
+ │ git commit -m "chore: add appsec security config" │
150
+ │ git push │
151
+ ╰───────────────────────────────────────────────────────╯
152
+ ```
153
+
154
+ Execute esses comandos na ordem.
155
+
156
+ ---
157
+
158
+ ## O que é gerado
159
+
160
+ ### `.github/workflows/security.yml`
161
+
162
+ Workflow do GitHub Actions com jobs separados por camada:
163
+
164
+ - **SAST** — análise estática roda a cada push/PR
165
+ - **Dependency scan** — verifica vulnerabilidades nas dependências
166
+ - **Secret scanning** — Gitleaks varre o histórico git em busca de segredos expostos
167
+
168
+ O workflow é acionado em push e pull requests para `main` e `master`.
169
+
170
+ ---
171
+
172
+ ### `.pre-commit-config.yaml`
173
+
174
+ Hooks que rodam localmente antes de cada commit:
175
+
176
+ **Python:**
177
+ ```yaml
178
+ repos:
179
+ - repo: https://github.com/PyCQA/bandit # SAST
180
+ - repo: https://github.com/Yelp/detect-secrets # secrets
181
+ - repo: https://github.com/pypa/pip-audit # dependências
182
+ ```
183
+
184
+ **Node.js:**
185
+ ```yaml
186
+ repos:
187
+ - repo: https://github.com/Yelp/detect-secrets # secrets
188
+ - repo: https://github.com/gitleaks/gitleaks # secrets
189
+ - repo: local # npm audit
190
+ ```
191
+
192
+ ---
193
+
194
+ ### `pyproject.toml` (apenas Python)
195
+
196
+ Adiciona configuração do Bandit ao arquivo existente:
197
+
198
+ ```toml
199
+ [tool.bandit]
200
+ exclude_dirs = ["tests", "venv", ".venv"]
201
+ skips = []
202
+ ```
203
+
204
+ ---
205
+
206
+ ## Casos de uso comuns
207
+
208
+ ### Só quero pre-commit, sem CI
209
+
210
+ Execute o wizard e desmarque as camadas SAST, Dependency Scanning e Secret Scanning. Mantenha apenas **Pre-commit Hooks** selecionado.
211
+
212
+ ### Só quero o GitHub Actions, sem pre-commit
213
+
214
+ Desmarque **Pre-commit Hooks** e mantenha as outras camadas.
215
+
216
+ ### Projeto já tem `.pre-commit-config.yaml`
217
+
218
+ O kit sobrescreve o arquivo com status `(updated)`. Faça backup antes se necessário:
219
+
220
+ ```bash
221
+ cp .pre-commit-config.yaml .pre-commit-config.yaml.bak
222
+ appsec-kit
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Atualizando versões dos hooks
228
+
229
+ As versões dos hooks pre-commit ficam fixadas em `.pre-commit-config.yaml`. Para atualizar todas para o latest:
230
+
231
+ ```bash
232
+ pre-commit autoupdate
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Ferramentas utilizadas
238
+
239
+ | Ferramenta | Finalidade | Docs |
240
+ |---|---|---|
241
+ | [Bandit](https://bandit.readthedocs.io/) | SAST para Python | bandit.readthedocs.io |
242
+ | [Semgrep](https://semgrep.dev/) | SAST para JavaScript/TypeScript | semgrep.dev |
243
+ | [pip-audit](https://pypi.org/project/pip-audit/) | CVEs em dependências Python | pypi.org/project/pip-audit |
244
+ | [detect-secrets](https://github.com/Yelp/detect-secrets) | Detecção de segredos | github.com/Yelp/detect-secrets |
245
+ | [Gitleaks](https://gitleaks.io/) | Varredura de segredos no histórico git | gitleaks.io |
246
+ | [pre-commit](https://pre-commit.com/) | Framework de git hooks | pre-commit.com |
File without changes
@@ -0,0 +1,135 @@
1
+ import sys
2
+ from pathlib import Path
3
+
4
+ import questionary
5
+ from rich.console import Console
6
+ from rich.panel import Panel
7
+
8
+ from .detector import detect_project_type
9
+ from .versions import CI_LAYERS
10
+ from .writer import write_configs
11
+
12
+ console = Console()
13
+
14
+ _LAYER_CHOICES = [
15
+ ("SAST (Static Analysis)", "sast"),
16
+ ("Dependency Scanning", "deps"),
17
+ ("Secret Scanning", "secrets"),
18
+ ("Pre-commit Hooks", "precommit"),
19
+ ]
20
+
21
+ _STYLE = questionary.Style([
22
+ ("qmark", "fg:cyan bold"),
23
+ ("question", "bold"),
24
+ ("answer", "fg:cyan bold"),
25
+ ("pointer", "fg:cyan bold"),
26
+ ("highlighted", "fg:cyan bold"),
27
+ ("selected", "fg:green"),
28
+ ("instruction", "fg:default dim"),
29
+ ])
30
+
31
+
32
+ def _print_next_steps(lang: str, layers: list[str]) -> None:
33
+ lines: list[str] = []
34
+
35
+ if "precommit" in layers:
36
+ lines += [
37
+ "pip install pre-commit detect-secrets",
38
+ "detect-secrets scan > .secrets.baseline",
39
+ "pre-commit install",
40
+ ]
41
+
42
+ if lang == "node" and "sast" in layers:
43
+ lines += [
44
+ "",
45
+ "# SEMGREP_APP_TOKEN (free) removes API rate limits in CI:",
46
+ "# 1. Create account at https://semgrep.dev",
47
+ "# 2. Go to Settings → Tokens → Create token",
48
+ "# 3. Add to GitHub: Settings → Secrets → SEMGREP_APP_TOKEN",
49
+ ]
50
+
51
+ if any(layer in layers for layer in CI_LAYERS) or "precommit" in layers:
52
+ lines += [
53
+ "",
54
+ "# Commit and push to activate GitHub Actions:",
55
+ "git add .github/ .pre-commit-config.yaml",
56
+ 'git commit -m "chore: add appsec security configuration"',
57
+ "git push",
58
+ ]
59
+
60
+ if lines:
61
+ text = "\n".join(
62
+ f" {line}" if line and not line.startswith("#") else line for line in lines
63
+ )
64
+ console.print(Panel(
65
+ text,
66
+ title="[bold green]Next steps[/bold green]",
67
+ border_style="green",
68
+ padding=(0, 1),
69
+ ))
70
+
71
+
72
+ def run() -> None:
73
+ console.print()
74
+ console.print(Panel.fit(
75
+ "[bold cyan]AppSec Kit[/bold cyan] [dim]– Security toolkit for CI/CD pipelines[/dim]",
76
+ border_style="cyan",
77
+ padding=(0, 2),
78
+ ))
79
+ console.print()
80
+
81
+ detected = detect_project_type()
82
+ default_project = {"python": "Python", "node": "Node.js"}.get(detected or "", "Python")
83
+
84
+ if detected:
85
+ console.print(f"[dim]Detected:[/dim] [bold]{default_project}[/bold] project\n")
86
+
87
+ project_type = questionary.select(
88
+ "Project type:",
89
+ choices=["Python", "Node.js"],
90
+ default=default_project,
91
+ style=_STYLE,
92
+ ).ask()
93
+
94
+ if not project_type:
95
+ sys.exit(0)
96
+
97
+ target_dir = questionary.text(
98
+ "Target directory:",
99
+ default=".",
100
+ style=_STYLE,
101
+ ).ask()
102
+
103
+ if target_dir is None:
104
+ sys.exit(0)
105
+
106
+ target_path = Path(target_dir).expanduser().resolve()
107
+ if not target_path.is_dir():
108
+ console.print(f"[red]Error:[/red] '{target_dir}' is not a valid directory.")
109
+ sys.exit(1)
110
+
111
+ selected_layers = questionary.checkbox(
112
+ "Security layers to configure:",
113
+ choices=[
114
+ questionary.Choice(label, value=key, checked=True)
115
+ for label, key in _LAYER_CHOICES
116
+ ],
117
+ style=_STYLE,
118
+ ).ask()
119
+
120
+ if not selected_layers:
121
+ console.print("[yellow]No layers selected. Exiting.[/yellow]")
122
+ sys.exit(0)
123
+
124
+ lang = "python" if project_type == "Python" else "node"
125
+
126
+ console.print()
127
+ results = write_configs(target_path, lang, selected_layers)
128
+
129
+ for rel_path, status in results:
130
+ color = "green" if status == "created" else "yellow"
131
+ icon = "✓" if status == "created" else "↻"
132
+ console.print(f" [{color}]{icon}[/{color}] {rel_path} [dim]({status})[/dim]")
133
+
134
+ console.print()
135
+ _print_next_steps(lang, selected_layers)
@@ -0,0 +1,16 @@
1
+ from pathlib import Path
2
+
3
+ _PYTHON_MARKERS = ("pyproject.toml", "setup.py", "requirements.txt", "Pipfile")
4
+ _NODE_MARKERS = ("package.json",)
5
+
6
+
7
+ def detect_project_type(path: Path | None = None) -> str | None:
8
+ """Return 'python', 'node', or None when both or neither are detected."""
9
+ target = path or Path.cwd()
10
+ has_python = any((target / f).exists() for f in _PYTHON_MARKERS)
11
+ has_node = any((target / f).exists() for f in _NODE_MARKERS)
12
+ if has_python and not has_node:
13
+ return "python"
14
+ if has_node and not has_python:
15
+ return "node"
16
+ return None
File without changes