Skip to content

Commit f1ce024

Browse files
committed
feat: added windows script
1 parent 39d6886 commit f1ce024

5 files changed

Lines changed: 432 additions & 10 deletions

File tree

IT-DEPLOYMENT-GUIDE.md

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,52 @@ Deploy gitleaks secret scanning across developer machines. IT team runs once per
55

66
## Quick Installation
77

8-
### 1. Install Gitleaks Globally
8+
### Linux / macOS
9+
10+
#### 1. Install Gitleaks Globally
911
```bash
1012
cd /path/to/gitleaks
1113
chmod +x install-gitleaks-global.sh && ./install-gitleaks-global.sh
1214
```
1315
*Requires sudo. Installs gitleaks binary and global configuration.*
1416

15-
### 2. Update All Repositories
17+
#### 2. Update All Repositories
1618
```bash
1719
chmod +x update-all-repos.sh && ./update-all-repos.sh ~
1820
```
1921
*Installs hooks in all repos. Detects Husky automatically.*
2022

21-
### 3. Verify Installation
23+
#### 3. Uninstall
24+
```bash
25+
chmod +x uninstall-gitleaks-global.sh && ./uninstall-gitleaks-global.sh
26+
```
27+
28+
### Windows (PowerShell)
29+
30+
#### 1. Install Gitleaks Globally
31+
```powershell
32+
cd C:\path\to\gitleaks
33+
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser # if needed
34+
.\install-gitleaks-global.ps1
35+
```
36+
*No admin required. Installs gitleaks to `%LOCALAPPDATA%\gitleaks\bin` and adds it to your user PATH.*
37+
38+
#### 2. Update All Repositories
39+
```powershell
40+
.\update-all-repos.ps1 # current directory only
41+
.\update-all-repos.ps1 C:\Projects # all repos under C:\Projects
42+
$env:MAX_DEPTH = 3; .\update-all-repos.ps1 C:\Projects # limit depth
43+
```
44+
45+
#### 3. Uninstall
46+
```powershell
47+
.\uninstall-gitleaks-global.ps1
48+
```
49+
50+
---
51+
52+
## Verify Installation (all platforms)
53+
2254
```bash
2355
gitleaks version
2456

@@ -29,11 +61,6 @@ git add test.js
2961
git commit -m "test"
3062
# Should BLOCK the commit
3163
```
32-
## Uninstall
33-
34-
```bash
35-
chmod +x uninstall-gitleaks-global.sh && ./uninstall-gitleaks-global.sh
36-
```
3764

3865
## Security Note
3966

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ This fork includes **enhanced detection rules** specifically designed for blockc
4545

4646
Quick deployment for teams and organizations:
4747

48+
**Linux / macOS:**
4849
```bash
4950
# 1. Install gitleaks globally with pre-commit hooks
5051
chmod +x install-gitleaks-global.sh && ./install-gitleaks-global.sh
@@ -53,11 +54,17 @@ chmod +x install-gitleaks-global.sh && ./install-gitleaks-global.sh
5354
chmod +x update-all-repos.sh && ./update-all-repos.sh ~
5455
```
5556

57+
**Windows (PowerShell):**
58+
```powershell
59+
.\install-gitleaks-global.ps1
60+
.\update-all-repos.ps1 C:\Projects # optional: add hooks to existing repos
61+
```
62+
5663
**Features:**
57-
- ✅ Automatic detection of Husky vs native Git hooks
64+
- ✅ Automatic detection of Husky vs native Git hooks (Linux/macOS)
5865
- ✅ Safe injection into existing Husky pre-commit hooks
5966
- ✅ Works with all Git repositories
60-
-Adds PATH for Husky non-login shell compatibility
67+
-Windows install script (no admin required)
6168

6269
See `IT-DEPLOYMENT-GUIDE.md` for complete installation instructions.
6370

install-gitleaks-global.ps1

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
#Requires -Version 5.1
2+
# Script to install gitleaks globally with pre-commit hooks for all repos (Windows)
3+
# This sets up:
4+
# 1. Gitleaks binary in %LOCALAPPDATA%\gitleaks\bin (added to user PATH)
5+
# 2. Global gitleaks config in %USERPROFILE%\.config\gitleaks\
6+
# 3. Git template directory for automatic hook installation in new repos
7+
# 4. Instructions for updating existing repos
8+
#
9+
# Run in PowerShell: .\install-gitleaks-global.ps1
10+
# If you get execution policy error: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
11+
12+
$ErrorActionPreference = "Stop"
13+
$GITLEAKS_VERSION = "8.24.2"
14+
$GITLEAKS_BIN_DIR = Join-Path $env:LOCALAPPDATA "gitleaks\bin"
15+
$CONFIG_DIR = Join-Path $env:USERPROFILE ".config\gitleaks"
16+
$TEMPLATE_DIR = Join-Path $env:USERPROFILE ".git-template"
17+
$TEMPLATE_HOOKS = Join-Path $TEMPLATE_DIR "hooks")
18+
19+
function Write-Step { param($Message) Write-Host $Message -ForegroundColor Cyan }
20+
function Write-Ok { param($Message) Write-Host " OK $Message" -ForegroundColor Green }
21+
function Write-Warn { param($Message) Write-Host " !! $Message" -ForegroundColor Yellow }
22+
function Write-Fail { param($Message) Write-Host " X $Message" -ForegroundColor Red }
23+
24+
Write-Host "`nInstalling Gitleaks globally...`n" -ForegroundColor Cyan
25+
26+
# Step 1: Check and install gitleaks binary
27+
Write-Step "Step 1: Installing gitleaks binary..."
28+
29+
$SkipBinary = $false
30+
$existing = Get-Command gitleaks -ErrorAction SilentlyContinue
31+
if ($existing) {
32+
try {
33+
$currentVer = (gitleaks version 2>&1) -join " "
34+
Write-Warn "Gitleaks is already installed: $currentVer"
35+
$reply = Read-Host "Reinstall/update to v$GITLEAKS_VERSION? (y/N)"
36+
if ($reply -notmatch '^[Yy]$') {
37+
Write-Ok "Keeping existing gitleaks installation"
38+
$SkipBinary = $true
39+
}
40+
} catch {}
41+
}
42+
43+
if (-not $SkipBinary) {
44+
$zipUrl = "https://github.com/gitleaks/gitleaks/releases/download/v$GITLEAKS_VERSION/gitleaks_${GITLEAKS_VERSION}_windows_x64.zip"
45+
$tempDir = Join-Path $env:TEMP "gitleaks-install-$([Guid]::NewGuid().ToString('N').Substring(0,8))")
46+
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
47+
try {
48+
Write-Step "Downloading gitleaks v$GITLEAKS_VERSION..."
49+
$zipPath = Join-Path $tempDir "gitleaks.zip"
50+
Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath -UseBasicParsing
51+
Write-Ok "Downloaded gitleaks"
52+
53+
Expand-Archive -Path $zipPath -DestinationPath $tempDir -Force
54+
$exeSource = Join-Path $tempDir "gitleaks.exe"
55+
if (-not (Test-Path $exeSource)) {
56+
$exeSource = Get-ChildItem -Path $tempDir -Filter "gitleaks.exe" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName
57+
}
58+
if (-not $exeSource -or -not (Test-Path $exeSource)) {
59+
Write-Fail "gitleaks.exe not found in archive"
60+
exit 1
61+
}
62+
63+
New-Item -ItemType Directory -Path $GITLEAKS_BIN_DIR -Force | Out-Null
64+
Copy-Item -Path $exeSource -Destination (Join-Path $GITLEAKS_BIN_DIR "gitleaks.exe") -Force
65+
Write-Ok "Installed gitleaks to $GITLEAKS_BIN_DIR"
66+
67+
# Add to user PATH if not already present
68+
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
69+
if ($userPath -notlike "*$GITLEAKS_BIN_DIR*") {
70+
[Environment]::SetEnvironmentVariable("Path", "$userPath;$GITLEAKS_BIN_DIR", "User")
71+
$env:Path = "$env:Path;$GITLEAKS_BIN_DIR"
72+
Write-Ok "Added gitleaks to user PATH (new terminals will pick it up)"
73+
}
74+
75+
# Verify
76+
$ver = & (Join-Path $GITLEAKS_BIN_DIR "gitleaks.exe") version 2>&1
77+
Write-Ok "Verified: $ver"
78+
} finally {
79+
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
80+
}
81+
}
82+
83+
Write-Host ""
84+
85+
# Step 2: Global config
86+
Write-Step "Step 2: Setting up global configuration..."
87+
New-Item -ItemType Directory -Path $CONFIG_DIR -Force | Out-Null
88+
$configSource = Join-Path $PSScriptRoot ".gitleaks.toml"
89+
if (Test-Path $configSource) {
90+
Copy-Item -Path $configSource -Destination (Join-Path $CONFIG_DIR "gitleaks.toml") -Force
91+
Write-Ok "Copied gitleaks config to $CONFIG_DIR\gitleaks.toml"
92+
} else {
93+
Write-Warn ".gitleaks.toml not found in script dir; config not copied. Create $CONFIG_DIR\gitleaks.toml manually if needed."
94+
}
95+
96+
Write-Host ""
97+
98+
# Step 3: Git template and hooks
99+
Write-Step "Step 3: Creating git template directory..."
100+
New-Item -ItemType Directory -Path $TEMPLATE_HOOKS -Force | Out-Null
101+
102+
$preCommitHook = @'
103+
#!/bin/bash
104+
105+
# Gitleaks pre-commit hook (Smart Auto-Detecting)
106+
# Prevents committing secrets to git repository
107+
# Automatically detects and adapts to Husky or native Git hooks
108+
109+
# Colors
110+
RED='\033[0;31m'
111+
GREEN='\033[0;32m'
112+
YELLOW='\033[1;33m'
113+
NC='\033[0m' # No Color
114+
115+
# Function to run gitleaks scan
116+
run_gitleaks_scan() {
117+
# Check if gitleaks is installed
118+
if ! command -v gitleaks &> /dev/null; then
119+
echo -e "${RED}Error: gitleaks is not installed${NC}"
120+
echo "Install it from: https://github.com/gitleaks/gitleaks"
121+
echo "Or run: brew install gitleaks (macOS) or go install github.com/gitleaks/gitleaks/v8@latest"
122+
return 1
123+
fi
124+
125+
# Use global config if exists, otherwise use default
126+
GITLEAKS_CONFIG="$HOME/.config/gitleaks/gitleaks.toml"
127+
if [ ! -f "$GITLEAKS_CONFIG" ]; then
128+
GITLEAKS_CONFIG=""
129+
fi
130+
131+
# Run gitleaks on staged changes
132+
echo -e "${YELLOW}🔍 Scanning for secrets with gitleaks...${NC}"
133+
134+
if [ -n "$GITLEAKS_CONFIG" ]; then
135+
gitleaks protect --staged --redact --config="$GITLEAKS_CONFIG" --verbose
136+
else
137+
gitleaks protect --staged --redact --verbose
138+
fi
139+
140+
if [ $? -eq 0 ]; then
141+
echo -e "${GREEN}✓ No secrets detected${NC}"
142+
return 0
143+
else
144+
echo -e "${RED}✗ Secrets detected! Commit blocked.${NC}"
145+
return 1
146+
fi
147+
}
148+
149+
# SMART DETECTION: Check if Husky is managing hooks
150+
if [ -d ".husky" ] && [ -f ".husky/pre-commit" ]; then
151+
# Husky detected - check if it already has gitleaks
152+
if grep -q "gitleaks" ".husky/pre-commit" 2>/dev/null; then
153+
# Husky already has gitleaks, let it handle everything
154+
exit 0
155+
else
156+
# Husky exists but doesn't have gitleaks - run scan here
157+
run_gitleaks_scan
158+
exit $?
159+
fi
160+
else
161+
# No Husky detected - run gitleaks in native mode
162+
run_gitleaks_scan
163+
exit $?
164+
fi
165+
'@
166+
167+
$commitMsgHook = @'
168+
#!/bin/bash
169+
# Gitleaks commit-msg hook (Smart Auto-Detecting)
170+
# This is a secondary check in case pre-commit was bypassed
171+
172+
# Skip if gitleaks not installed
173+
if ! command -v gitleaks &> /dev/null; then
174+
exit 0
175+
fi
176+
177+
# Skip if Husky is managing hooks and already has gitleaks configured
178+
if [ -d ".husky" ] && [ -f ".husky/pre-commit" ]; then
179+
if grep -q "gitleaks" ".husky/pre-commit" 2>/dev/null; then
180+
# Husky is handling gitleaks, no need to run again
181+
exit 0
182+
fi
183+
fi
184+
185+
# Run gitleaks check
186+
GITLEAKS_CONFIG="$HOME/.config/gitleaks/gitleaks.toml"
187+
if [ ! -f "$GITLEAKS_CONFIG" ]; then
188+
GITLEAKS_CONFIG=""
189+
fi
190+
191+
# Silent check on commit
192+
if [ -n "$GITLEAKS_CONFIG" ]; then
193+
gitleaks protect --staged --redact --config="$GITLEAKS_CONFIG" > /dev/null 2>&1
194+
else
195+
gitleaks protect --staged --redact > /dev/null 2>&1
196+
fi
197+
198+
if [ $? -ne 0 ]; then
199+
echo "Error: Secrets detected in commit. Aborting."
200+
exit 1
201+
fi
202+
203+
exit 0
204+
'@
205+
206+
# Write hooks with LF line endings (Git for Windows runs them with bash)
207+
$preCommitPath = Join-Path $TEMPLATE_HOOKS "pre-commit"
208+
$commitMsgPath = Join-Path $TEMPLATE_HOOKS "commit-msg"
209+
[System.IO.File]::WriteAllText($preCommitPath, $preCommitHook.Replace("`r`n", "`n"))
210+
[System.IO.File]::WriteAllText($commitMsgPath, $commitMsgHook.Replace("`r`n", "`n"))
211+
Write-Ok "Created pre-commit and commit-msg hooks in $TEMPLATE_HOOKS"
212+
213+
Write-Host ""
214+
215+
# Step 4: Configure git template
216+
Write-Step "Step 4: Configuring git to use template directory..."
217+
$templateDirNorm = $TEMPLATE_DIR -replace '\\', '/'
218+
git config --global init.templateDir $templateDirNorm
219+
Write-Ok "Set global git template directory"
220+
221+
Write-Host ""
222+
Write-Host "========================================" -ForegroundColor Green
223+
Write-Host "Installation Complete!" -ForegroundColor Green
224+
Write-Host "========================================`n" -ForegroundColor Green
225+
226+
Write-Host "What was installed:" -ForegroundColor Cyan
227+
Write-Host " * Gitleaks binary: $GITLEAKS_BIN_DIR\gitleaks.exe"
228+
Write-Host " * Global config: $CONFIG_DIR\gitleaks.toml"
229+
Write-Host " * Git template: $TEMPLATE_HOOKS"
230+
Write-Host " * Hooks: pre-commit, commit-msg"
231+
232+
Write-Host "`nNext steps:" -ForegroundColor Cyan
233+
Write-Host " 1. All NEW git repositories will automatically get gitleaks hooks."
234+
Write-Host " 2. For EXISTING repos, run: .\update-all-repos.ps1 [directory]"
235+
Write-Host " 3. Or in each repo: git init (re-run to apply template)"
236+
Write-Host "`nNote: If gitleaks is not found in a new terminal, close and reopen PowerShell, or run:"
237+
Write-Host " `$env:Path += `";$GITLEAKS_BIN_DIR`""
238+
Write-Host ""

uninstall-gitleaks-global.ps1

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#Requires -Version 5.1
2+
# Script to uninstall global gitleaks configuration and hooks (Windows)
3+
# Run in PowerShell: .\uninstall-gitleaks-global.ps1
4+
5+
$ErrorActionPreference = "Stop"
6+
$CONFIG_DIR = Join-Path $env:USERPROFILE ".config\gitleaks"
7+
$TEMPLATE_DIR = Join-Path $env:USERPROFILE ".git-template"
8+
$GITLEAKS_BIN_DIR = Join-Path $env:LOCALAPPDATA "gitleaks\bin"
9+
10+
function Write-Step { param($Message) Write-Host $Message -ForegroundColor Cyan }
11+
function Write-Ok { param($Message) Write-Host " OK $Message" -ForegroundColor Green }
12+
function Write-Fail { param($Message) Write-Host " X $Message" -ForegroundColor Red }
13+
14+
Write-Host "`nUninstalling Gitleaks global configuration...`n" -ForegroundColor Cyan
15+
16+
# Remove config directory
17+
if (Test-Path $CONFIG_DIR) {
18+
Remove-Item -Path $CONFIG_DIR -Recurse -Force
19+
Write-Ok "Removed $CONFIG_DIR"
20+
} else {
21+
Write-Fail "Config directory not found: $CONFIG_DIR"
22+
}
23+
24+
# Remove git template directory and unset config
25+
if (Test-Path $TEMPLATE_DIR) {
26+
Remove-Item -Path $TEMPLATE_DIR -Recurse -Force
27+
Write-Ok "Removed $TEMPLATE_DIR"
28+
try {
29+
git config --global --unset init.templateDir
30+
Write-Ok "Unset global git template directory"
31+
} catch {}
32+
} else {
33+
Write-Fail "Template directory not found: $TEMPLATE_DIR"
34+
}
35+
36+
# Optionally remove binary and PATH entry
37+
if (Test-Path $GITLEAKS_BIN_DIR) {
38+
$reply = Read-Host "Remove gitleaks binary from $GITLEAKS_BIN_DIR and PATH? (y/N)"
39+
if ($reply -match '^[Yy]$') {
40+
Remove-Item -Path $GITLEAKS_BIN_DIR -Recurse -Force -ErrorAction SilentlyContinue
41+
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
42+
$newPath = ($userPath -split ';' | Where-Object { $_ -ne $GITLEAKS_BIN_DIR }) -join ';'
43+
[Environment]::SetEnvironmentVariable("Path", $newPath, "User")
44+
Write-Ok "Removed gitleaks binary and PATH entry"
45+
}
46+
}
47+
48+
Write-Host "`nUninstallation complete!`n" -ForegroundColor Green
49+
Write-Host "Note: Existing repositories still have the hooks installed." -ForegroundColor Cyan
50+
Write-Host "To remove hooks from individual repos, delete:"
51+
Write-Host " * .git\hooks\pre-commit"
52+
Write-Host " * .git\hooks\commit-msg"
53+
Write-Host ""

0 commit comments

Comments
 (0)