feat: split out git blame
This commit is contained in:
@@ -8,7 +8,6 @@ In this module, you will:
|
|||||||
- Use `git show` to view specific commit details
|
- Use `git show` to view specific commit details
|
||||||
- Use `git diff` to compare changes between commits
|
- Use `git diff` to compare changes between commits
|
||||||
- Use `git diff --staged` to view changes ready to be committed
|
- Use `git diff --staged` to view changes ready to be committed
|
||||||
- Use `git blame` to find who made specific changes
|
|
||||||
- Understand commit hashes and references
|
- Understand commit hashes and references
|
||||||
- Discover how `git diff` reveals changes not visible in current files
|
- Discover how `git diff` reveals changes not visible in current files
|
||||||
|
|
||||||
@@ -31,7 +30,6 @@ You'll explore an existing Git repository that contains multiple commits. Your g
|
|||||||
- Examining changes between specific commits
|
- Examining changes between specific commits
|
||||||
- Understanding staged changes
|
- Understanding staged changes
|
||||||
- **Finding a secret code hidden in the commit history!** (Only discoverable by using `git diff`)
|
- **Finding a secret code hidden in the commit history!** (Only discoverable by using `git diff`)
|
||||||
- **Tracking down who made a suspicious code change** (Using `git blame`)
|
|
||||||
|
|
||||||
The setup script will create an `answers.md` file in the challenge directory with questions for you to answer. Fill in your answers directly in that file.
|
The setup script will create an `answers.md` file in the challenge directory with questions for you to answer. Fill in your answers directly in that file.
|
||||||
|
|
||||||
@@ -45,8 +43,7 @@ The setup script will create an `answers.md` file in the challenge directory wit
|
|||||||
6. Try different log formats: `git log --stat`, `git log --graph`
|
6. Try different log formats: `git log --stat`, `git log --graph`
|
||||||
7. View specific commits: `git show <commit-hash>`
|
7. View specific commits: `git show <commit-hash>`
|
||||||
8. Compare specific commits: `git diff <commit1> <commit2> <file>`
|
8. Compare specific commits: `git diff <commit1> <commit2> <file>`
|
||||||
9. Use `git blame` to find who wrote specific lines: `git blame -e <file>`
|
9. Fill in your answers in `answers.md`
|
||||||
10. Fill in your answers in `answers.md`
|
|
||||||
|
|
||||||
> **Important Notes:**
|
> **Important Notes:**
|
||||||
> - You can use any Git commands you like to explore the repository
|
> - You can use any Git commands you like to explore the repository
|
||||||
@@ -207,19 +204,6 @@ git diff HEAD # Show all changes (staged + unstaged) vs last c
|
|||||||
- `git diff HEAD` - See all your changes since the last commit
|
- `git diff HEAD` - See all your changes since the last commit
|
||||||
- `git diff <commit1> <commit2>` - Compare any two points in history
|
- `git diff <commit1> <commit2>` - Compare any two points in history
|
||||||
|
|
||||||
### Finding Who Changed What with git blame
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git blame <file> # Show who last modified each line
|
|
||||||
git blame -e <file> # Show with email addresses
|
|
||||||
git blame -L 10,20 <file> # Blame specific line range (lines 10-20)
|
|
||||||
```
|
|
||||||
|
|
||||||
**When to use `git blame`:**
|
|
||||||
- Find who wrote a specific line of code
|
|
||||||
- Identify when a bug was introduced
|
|
||||||
- Understand the context/reason for a change by finding the author
|
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
Once you've filled in your answers in `answers.md`, verify your solution:
|
Once you've filled in your answers in `answers.md`, verify your solution:
|
||||||
|
|||||||
@@ -200,39 +200,6 @@ Set-Content -Path "app.py" -Value $appContent
|
|||||||
git add .
|
git add .
|
||||||
git commit -m "Add user profile feature" | Out-Null
|
git commit -m "Add user profile feature" | Out-Null
|
||||||
|
|
||||||
# Commit 6: Add a suspicious change (for git blame challenge)
|
|
||||||
Write-Host "Adding configuration change..." -ForegroundColor Green
|
|
||||||
# Temporarily change git user for this commit
|
|
||||||
git config user.name "Suspicious Developer"
|
|
||||||
git config user.email "guilty@email.com"
|
|
||||||
|
|
||||||
$appContent = @"
|
|
||||||
# app.py - Main application file
|
|
||||||
from auth import login, logout
|
|
||||||
from database import connect, disconnect
|
|
||||||
from profile import get_profile
|
|
||||||
|
|
||||||
def main():
|
|
||||||
print("Welcome to My App!")
|
|
||||||
connect()
|
|
||||||
# Application initialization code here
|
|
||||||
if login("admin", "admin123"): # TODO: Change default credentials!
|
|
||||||
profile = get_profile("admin")
|
|
||||||
print(f"User profile: {profile}")
|
|
||||||
pass
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
"@
|
|
||||||
Set-Content -Path "app.py" -Value $appContent
|
|
||||||
|
|
||||||
git add .
|
|
||||||
git commit -m "Update default login credentials" | Out-Null
|
|
||||||
|
|
||||||
# Reset git config back to original
|
|
||||||
git config user.name "Workshop Student"
|
|
||||||
git config user.email "student@example.com"
|
|
||||||
|
|
||||||
# Create a staged change scenario
|
# Create a staged change scenario
|
||||||
Write-Host "Creating staged changes for exploration..." -ForegroundColor Green
|
Write-Host "Creating staged changes for exploration..." -ForegroundColor Green
|
||||||
$configContent = @"
|
$configContent = @"
|
||||||
@@ -342,29 +309,6 @@ git diff <commit3-hash> <commit4-hash> database.py
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Question 6: Who changed the login credentials to hardcoded values? 🔍
|
|
||||||
|
|
||||||
**The Challenge:**
|
|
||||||
Someone on the team added hardcoded login credentials to `app.py` (username: "admin", password: "admin123"). This is a security issue! Use `git blame` to find out who made this change.
|
|
||||||
|
|
||||||
**Your task:** Find the email address of the person who wrote the line containing `login("admin", "admin123")`.
|
|
||||||
|
|
||||||
**Suggested commands:**
|
|
||||||
``````bash
|
|
||||||
# View who changed each line in app.py
|
|
||||||
git blame app.py
|
|
||||||
|
|
||||||
# For a more readable format
|
|
||||||
git blame -e app.py # Shows email addresses
|
|
||||||
|
|
||||||
# Look for the line with login("admin", "admin123")
|
|
||||||
# The format is: commit_hash (Author Name <email> date time line_number) line_content
|
|
||||||
``````
|
|
||||||
|
|
||||||
**Your Answer (provide the email address):**
|
|
||||||
|
|
||||||
<!-- Write your answer here -->
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Quick Reference - Useful Commands
|
## Quick Reference - Useful Commands
|
||||||
@@ -394,14 +338,6 @@ git diff # Show unstaged changes
|
|||||||
git diff HEAD # Show all changes since last commit
|
git diff HEAD # Show all changes since last commit
|
||||||
``````
|
``````
|
||||||
|
|
||||||
**Finding Who Changed What:**
|
|
||||||
``````bash
|
|
||||||
git blame <file> # Show who last modified each line
|
|
||||||
git blame -e <file> # Show with email addresses
|
|
||||||
git blame -L 10,20 <file> # Blame specific line range
|
|
||||||
git blame <file> | grep "pattern" # Find who changed lines matching pattern
|
|
||||||
``````
|
|
||||||
|
|
||||||
**Repository Status:**
|
**Repository Status:**
|
||||||
``````bash
|
``````bash
|
||||||
git status # Show working tree status
|
git status # Show working tree status
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ if (-not (Test-Path "answers.md")) {
|
|||||||
$answers = Get-Content "answers.md" -Raw
|
$answers = Get-Content "answers.md" -Raw
|
||||||
$answersLower = $answers.ToLower()
|
$answersLower = $answers.ToLower()
|
||||||
|
|
||||||
# Check 1: Contains "6" or "six" for commit count
|
# Check 1: Contains "5" or "five" for commit count
|
||||||
if ($answersLower -match "6|six") {
|
if ($answersLower -match "5|five") {
|
||||||
Write-Host "[PASS] Correct commit count found" -ForegroundColor Green
|
Write-Host "[PASS] Correct commit count found" -ForegroundColor Green
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[FAIL] Commit count not found or incorrect" -ForegroundColor Red
|
Write-Host "[FAIL] Commit count not found or incorrect" -ForegroundColor Red
|
||||||
@@ -93,14 +93,6 @@ if (-not (Test-Path "answers.md")) {
|
|||||||
$allChecksPassed = $false
|
$allChecksPassed = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check 6: Contains "guilty@email.com" for git blame challenge
|
|
||||||
if ($answersLower -match "guilty@email\.com") {
|
|
||||||
Write-Host "[PASS] Correct email address found using git blame!" -ForegroundColor Green
|
|
||||||
} else {
|
|
||||||
Write-Host "[FAIL] Guilty developer's email not found" -ForegroundColor Red
|
|
||||||
Write-Host "[HINT] Use 'git blame -e app.py' to see who changed each line with email addresses" -ForegroundColor Yellow
|
|
||||||
$allChecksPassed = $false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-Location ..
|
Set-Location ..
|
||||||
@@ -118,7 +110,6 @@ if ($allChecksPassed) {
|
|||||||
Write-Host " - See which files changed in commits" -ForegroundColor White
|
Write-Host " - See which files changed in commits" -ForegroundColor White
|
||||||
Write-Host " - Check staged changes with git diff --staged" -ForegroundColor White
|
Write-Host " - Check staged changes with git diff --staged" -ForegroundColor White
|
||||||
Write-Host " - Compare changes between specific commits with git diff" -ForegroundColor White
|
Write-Host " - Compare changes between specific commits with git diff" -ForegroundColor White
|
||||||
Write-Host " - Track down who made changes with git blame" -ForegroundColor White
|
|
||||||
Write-Host "`nReady for the next module!" -ForegroundColor Green
|
Write-Host "`nReady for the next module!" -ForegroundColor Green
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
169
03_advanced/05-blame/README.md
Normal file
169
03_advanced/05-blame/README.md
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
# Module 05: Git Blame - Code Archaeology
|
||||||
|
|
||||||
|
## Learning Objectives
|
||||||
|
|
||||||
|
In this module, you will:
|
||||||
|
- Use `git blame` to find who made specific changes
|
||||||
|
- Understand blame output format and information
|
||||||
|
- Track down problematic code changes
|
||||||
|
- Learn when and why to use `git blame`
|
||||||
|
- Investigate code history to understand context
|
||||||
|
|
||||||
|
## Challenge
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
Run the setup script to create your challenge environment:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\setup.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
This will create a `challenge/` directory with a Git repository that has a security issue - someone committed hardcoded credentials!
|
||||||
|
|
||||||
|
### Your Task
|
||||||
|
|
||||||
|
Your team has discovered a security vulnerability: hardcoded credentials were added to the codebase. Your job is to investigate who made this change and document your findings.
|
||||||
|
|
||||||
|
The setup script will create an `investigation.md` file in the challenge directory with questions for you to answer. Use `git blame` and other Git commands to track down the responsible developer.
|
||||||
|
|
||||||
|
**Scenario:**
|
||||||
|
- Someone added hardcoded login credentials (`username: "admin"`, `password: "admin123"`) to `app.py`
|
||||||
|
- This is a critical security issue
|
||||||
|
- You need to identify who made this change so the team can discuss it with them
|
||||||
|
|
||||||
|
**Suggested Approach:**
|
||||||
|
|
||||||
|
1. Navigate to the challenge directory: `cd challenge`
|
||||||
|
2. Open `investigation.md` to see the questions
|
||||||
|
3. Examine `app.py` to find the suspicious line
|
||||||
|
4. Use `git blame` to find who wrote that line
|
||||||
|
5. Use `git blame -e` to see email addresses
|
||||||
|
6. Use `git show` to see the full commit details
|
||||||
|
7. Document your findings in `investigation.md`
|
||||||
|
|
||||||
|
> **Important Notes:**
|
||||||
|
> - `git blame` shows who last modified each line
|
||||||
|
> - Each line shows: commit hash, author, date, line number, and content
|
||||||
|
> - Use `-e` flag to show email addresses
|
||||||
|
> - Use `-L` to focus on specific line ranges
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
- **Git Blame**: Shows the revision and author who last modified each line of a file
|
||||||
|
- **Code Archaeology**: Using Git history to understand when and why code changed
|
||||||
|
- **Author Attribution**: Identifying who wrote specific code for context, not punishment
|
||||||
|
- **Commit Context**: Understanding the full story behind a change
|
||||||
|
|
||||||
|
## Understanding Git Blame Output
|
||||||
|
|
||||||
|
When you run `git blame app.py`, you'll see output like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
a1b2c3d4 (John Doe 2024-01-15 10:30:45 +0000 1) # app.py - Main application
|
||||||
|
a1b2c3d4 (John Doe 2024-01-15 10:30:45 +0000 2)
|
||||||
|
e5f6g7h8 (Jane Smith 2024-01-16 14:20:10 +0000 3) from auth import login
|
||||||
|
e5f6g7h8 (Jane Smith 2024-01-16 14:20:10 +0000 4)
|
||||||
|
i9j0k1l2 (Bob Wilson 2024-01-17 09:15:30 +0000 5) def main():
|
||||||
|
i9j0k1l2 (Bob Wilson 2024-01-17 09:15:30 +0000 6) login("admin", "admin123")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Breaking It Down
|
||||||
|
|
||||||
|
Each line shows:
|
||||||
|
1. **Commit Hash** (`a1b2c3d4`) - The commit that last changed this line
|
||||||
|
2. **Author Name** (`John Doe`) - Who made the change
|
||||||
|
3. **Date/Time** (`2024-01-15 10:30:45 +0000`) - When it was changed
|
||||||
|
4. **Line Number** (`1`) - The line number in the current file
|
||||||
|
5. **Line Content** (`# app.py - Main application`) - The actual code
|
||||||
|
|
||||||
|
### Useful Git Blame Options
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git blame <file> # Basic blame output
|
||||||
|
git blame -e <file> # Show email addresses instead of names
|
||||||
|
git blame -L 10,20 <file> # Only show lines 10-20
|
||||||
|
git blame -L 10,+5 <file> # Show 5 lines starting from line 10
|
||||||
|
git blame -w <file> # Ignore whitespace changes
|
||||||
|
git blame <commit> <file> # Blame as of specific commit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Following Up After Blame
|
||||||
|
|
||||||
|
Once you find the commit hash:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git show <commit-hash> # See the full commit details
|
||||||
|
git log -p <commit-hash> # See commit with diff
|
||||||
|
git show <commit-hash> --stat # See which files were changed
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use Git Blame
|
||||||
|
|
||||||
|
**Good reasons to use `git blame`:**
|
||||||
|
- 🔍 Understanding why code was written a certain way
|
||||||
|
- 📚 Finding context for a piece of code
|
||||||
|
- 🐛 Identifying when a bug was introduced
|
||||||
|
- 💡 Discovering the thought process behind a decision
|
||||||
|
- 👥 Finding who to ask about specific code
|
||||||
|
|
||||||
|
**Not for blaming:**
|
||||||
|
- ❌ Finding someone to blame for mistakes
|
||||||
|
- ❌ Tracking "productivity" or code ownership
|
||||||
|
- ❌ Punishing developers for old code
|
||||||
|
|
||||||
|
**Remember:** Code archaeology is about understanding, not blaming!
|
||||||
|
|
||||||
|
## Useful Commands
|
||||||
|
|
||||||
|
### Investigation Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find who changed each line
|
||||||
|
git blame <file>
|
||||||
|
git blame -e <file> # With email addresses
|
||||||
|
|
||||||
|
# Focus on specific lines
|
||||||
|
git blame -L 10,20 <file> # Lines 10-20
|
||||||
|
git blame -L :function_name <file> # Specific function (Git 2.20+)
|
||||||
|
|
||||||
|
# See historical blame
|
||||||
|
git blame <commit>^ <file> # Blame before a specific commit
|
||||||
|
|
||||||
|
# Combine with grep
|
||||||
|
git blame <file> | grep "pattern" # Find who wrote lines matching pattern
|
||||||
|
```
|
||||||
|
|
||||||
|
### Context Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# See full commit details
|
||||||
|
git show <commit-hash>
|
||||||
|
git log -1 <commit-hash> # Just the commit message
|
||||||
|
|
||||||
|
# See all commits by author
|
||||||
|
git log --author="name"
|
||||||
|
|
||||||
|
# See what else changed in that commit
|
||||||
|
git show <commit-hash> --stat
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
Once you've completed your investigation in `investigation.md`, verify your solution:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\verify.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
The verification script will check that you've identified the correct developer.
|
||||||
|
|
||||||
|
## Need to Start Over?
|
||||||
|
|
||||||
|
If you want to reset the challenge and start fresh:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\reset.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
This will remove the challenge directory and run the setup script again, giving you a clean slate.
|
||||||
24
03_advanced/05-blame/reset.ps1
Normal file
24
03_advanced/05-blame/reset.ps1
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env pwsh
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Resets the Module 05 challenge environment.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This script removes the challenge directory and re-runs the setup script
|
||||||
|
to give you a fresh start.
|
||||||
|
#>
|
||||||
|
|
||||||
|
Write-Host "`n=== Resetting Module 05 Challenge ===" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# Remove challenge directory if it exists
|
||||||
|
if (Test-Path "challenge") {
|
||||||
|
Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow
|
||||||
|
Remove-Item -Recurse -Force "challenge"
|
||||||
|
Write-Host "Challenge directory removed." -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "No challenge directory found to remove." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run setup script
|
||||||
|
Write-Host "`nRunning setup script..." -ForegroundColor Cyan
|
||||||
|
& "./setup.ps1"
|
||||||
323
03_advanced/05-blame/setup.ps1
Normal file
323
03_advanced/05-blame/setup.ps1
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
#!/usr/bin/env pwsh
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Sets up the Module 05 challenge environment for git blame investigation.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This script creates a challenge directory with a Git repository that
|
||||||
|
contains a security vulnerability (hardcoded credentials) for students
|
||||||
|
to investigate using git blame.
|
||||||
|
#>
|
||||||
|
|
||||||
|
Write-Host "`n=== Setting up Module 05 Challenge ===" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# Remove existing challenge directory if it exists
|
||||||
|
if (Test-Path "challenge") {
|
||||||
|
Write-Host "Removing existing challenge directory..." -ForegroundColor Yellow
|
||||||
|
Remove-Item -Recurse -Force "challenge"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create fresh challenge directory
|
||||||
|
Write-Host "Creating challenge directory..." -ForegroundColor Green
|
||||||
|
New-Item -ItemType Directory -Path "challenge" | Out-Null
|
||||||
|
Set-Location "challenge"
|
||||||
|
|
||||||
|
# Initialize Git repository
|
||||||
|
Write-Host "Initializing Git repository..." -ForegroundColor Green
|
||||||
|
git init | Out-Null
|
||||||
|
|
||||||
|
# Commit 1: Initial project structure (by Alice)
|
||||||
|
Write-Host "Creating initial project structure..." -ForegroundColor Green
|
||||||
|
git config user.name "Alice Johnson"
|
||||||
|
git config user.email "alice@example.com"
|
||||||
|
|
||||||
|
$appContent = @"
|
||||||
|
# app.py - Main application file
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Welcome to My App!")
|
||||||
|
# Application initialization code here
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
"@
|
||||||
|
Set-Content -Path "app.py" -Value $appContent
|
||||||
|
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial project structure" | Out-Null
|
||||||
|
|
||||||
|
# Commit 2: Add authentication module (by Bob)
|
||||||
|
Write-Host "Adding authentication module..." -ForegroundColor Green
|
||||||
|
git config user.name "Bob Chen"
|
||||||
|
git config user.email "bob@example.com"
|
||||||
|
|
||||||
|
$authContent = @"
|
||||||
|
# auth.py - Authentication module
|
||||||
|
|
||||||
|
def login(username, password):
|
||||||
|
# Authenticate user
|
||||||
|
print(f"Logging in user: {username}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def logout(username):
|
||||||
|
# Log out user
|
||||||
|
print(f"Logging out user: {username}")
|
||||||
|
return True
|
||||||
|
"@
|
||||||
|
Set-Content -Path "auth.py" -Value $authContent
|
||||||
|
|
||||||
|
$appContent = @"
|
||||||
|
# app.py - Main application file
|
||||||
|
from auth import login, logout
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Welcome to My App!")
|
||||||
|
# Application initialization code here
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
"@
|
||||||
|
Set-Content -Path "app.py" -Value $appContent
|
||||||
|
|
||||||
|
git add .
|
||||||
|
git commit -m "Add authentication module" | Out-Null
|
||||||
|
|
||||||
|
# Commit 3: Add database connection (by Carol)
|
||||||
|
Write-Host "Adding database connection..." -ForegroundColor Green
|
||||||
|
git config user.name "Carol Martinez"
|
||||||
|
git config user.email "carol@example.com"
|
||||||
|
|
||||||
|
$databaseContent = @"
|
||||||
|
# database.py - Database connection module
|
||||||
|
|
||||||
|
def connect():
|
||||||
|
# Connect to database
|
||||||
|
print("Connecting to database...")
|
||||||
|
return True
|
||||||
|
|
||||||
|
def disconnect():
|
||||||
|
# Disconnect from database
|
||||||
|
print("Disconnecting from database...")
|
||||||
|
return True
|
||||||
|
"@
|
||||||
|
Set-Content -Path "database.py" -Value $databaseContent
|
||||||
|
|
||||||
|
$appContent = @"
|
||||||
|
# app.py - Main application file
|
||||||
|
from auth import login, logout
|
||||||
|
from database import connect, disconnect
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Welcome to My App!")
|
||||||
|
connect()
|
||||||
|
# Application initialization code here
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
"@
|
||||||
|
Set-Content -Path "app.py" -Value $appContent
|
||||||
|
|
||||||
|
git add .
|
||||||
|
git commit -m "Add database connection" | Out-Null
|
||||||
|
|
||||||
|
# Commit 4: Add hardcoded credentials (THE SECURITY ISSUE - by Suspicious Developer)
|
||||||
|
Write-Host "Adding suspicious change..." -ForegroundColor Green
|
||||||
|
git config user.name "Suspicious Developer"
|
||||||
|
git config user.email "guilty@email.com"
|
||||||
|
|
||||||
|
$appContent = @"
|
||||||
|
# app.py - Main application file
|
||||||
|
from auth import login, logout
|
||||||
|
from database import connect, disconnect
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("Welcome to My App!")
|
||||||
|
connect()
|
||||||
|
# Quick fix for testing - TODO: Remove before production!
|
||||||
|
if login("admin", "admin123"):
|
||||||
|
print("Admin logged in successfully")
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
"@
|
||||||
|
Set-Content -Path "app.py" -Value $appContent
|
||||||
|
|
||||||
|
git add .
|
||||||
|
git commit -m "Add quick test login for debugging" | Out-Null
|
||||||
|
|
||||||
|
# Commit 5: Add logging (by David - innocent commit after the security issue)
|
||||||
|
Write-Host "Adding logging module..." -ForegroundColor Green
|
||||||
|
git config user.name "David Lee"
|
||||||
|
git config user.email "david@example.com"
|
||||||
|
|
||||||
|
$loggingContent = @"
|
||||||
|
# logging_config.py - Logging configuration
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
def setup_logging():
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
|
)
|
||||||
|
return logging.getLogger(__name__)
|
||||||
|
"@
|
||||||
|
Set-Content -Path "logging_config.py" -Value $loggingContent
|
||||||
|
|
||||||
|
git add .
|
||||||
|
git commit -m "Add logging configuration" | Out-Null
|
||||||
|
|
||||||
|
# Reset git config
|
||||||
|
git config user.name "Workshop Student"
|
||||||
|
git config user.email "student@example.com"
|
||||||
|
|
||||||
|
# Create investigation.md template
|
||||||
|
Write-Host "Creating investigation template..." -ForegroundColor Green
|
||||||
|
$investigationTemplate = @"
|
||||||
|
# Security Investigation Report
|
||||||
|
|
||||||
|
## Incident Overview
|
||||||
|
|
||||||
|
A security vulnerability has been discovered in the codebase: hardcoded credentials in `app.py`.
|
||||||
|
|
||||||
|
**Your task:** Use git blame and related Git commands to investigate this security issue and document your findings.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 1: What line number contains the hardcoded password?
|
||||||
|
|
||||||
|
Look at `app.py` and find the line with `"admin123"`.
|
||||||
|
|
||||||
|
**Your Answer:**
|
||||||
|
|
||||||
|
<!-- Write the line number here -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 2: Who added the hardcoded credentials?
|
||||||
|
|
||||||
|
Use `git blame` to find the email address of the developer who wrote the line with the hardcoded credentials.
|
||||||
|
|
||||||
|
**Suggested commands:**
|
||||||
|
``````bash
|
||||||
|
# View blame with email addresses
|
||||||
|
git blame -e app.py
|
||||||
|
|
||||||
|
# Or focus on specific lines (if you know the line range)
|
||||||
|
git blame -L 8,10 app.py
|
||||||
|
|
||||||
|
# Look for the line containing login("admin", "admin123")
|
||||||
|
``````
|
||||||
|
|
||||||
|
**Your Answer (provide the email address):**
|
||||||
|
|
||||||
|
<!-- Write the email address here -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 3: What was the commit message for the change that introduced the hardcoded credentials?
|
||||||
|
|
||||||
|
Once you've found the commit hash from git blame, use `git show` or `git log` to see the full commit message.
|
||||||
|
|
||||||
|
**Suggested commands:**
|
||||||
|
``````bash
|
||||||
|
# After finding the commit hash from git blame
|
||||||
|
git show <commit-hash>
|
||||||
|
git log -1 <commit-hash>
|
||||||
|
``````
|
||||||
|
|
||||||
|
**Your Answer:**
|
||||||
|
|
||||||
|
<!-- Write the commit message here -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 4: How many files were modified in the commit that added the hardcoded credentials?
|
||||||
|
|
||||||
|
Use `git show` with the `--stat` flag to see which files were changed.
|
||||||
|
|
||||||
|
**Suggested commands:**
|
||||||
|
``````bash
|
||||||
|
git show <commit-hash> --stat
|
||||||
|
git show <commit-hash> --name-only
|
||||||
|
``````
|
||||||
|
|
||||||
|
**Your Answer:**
|
||||||
|
|
||||||
|
<!-- Write the number or list the files here -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 5: When was this security vulnerability introduced?
|
||||||
|
|
||||||
|
Use the timestamp from git blame to determine when the vulnerable code was committed.
|
||||||
|
|
||||||
|
**Your Answer (date and time):**
|
||||||
|
|
||||||
|
<!-- Write the date/time here -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommendations
|
||||||
|
|
||||||
|
Based on your investigation, what actions should the team take?
|
||||||
|
|
||||||
|
**Your Recommendations:**
|
||||||
|
|
||||||
|
<!-- Write your recommendations here, for example:
|
||||||
|
- Remove hardcoded credentials
|
||||||
|
- Implement proper environment variables
|
||||||
|
- Add pre-commit hooks to prevent secrets
|
||||||
|
- Review with the developer who made the change
|
||||||
|
-->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference - Investigation Commands
|
||||||
|
|
||||||
|
**Finding Who Changed What:**
|
||||||
|
``````bash
|
||||||
|
git blame <file> # Show who last modified each line
|
||||||
|
git blame -e <file> # Show with email addresses
|
||||||
|
git blame -L 10,20 <file> # Blame specific line range
|
||||||
|
``````
|
||||||
|
|
||||||
|
**Getting Commit Details:**
|
||||||
|
``````bash
|
||||||
|
git show <commit-hash> # See full commit details
|
||||||
|
git show <commit-hash> --stat # See files changed
|
||||||
|
git log -1 <commit-hash> # See commit message only
|
||||||
|
git log -p <commit-hash> # See commit with diff
|
||||||
|
``````
|
||||||
|
|
||||||
|
**Searching History:**
|
||||||
|
``````bash
|
||||||
|
git log --all --grep="keyword" # Search commit messages
|
||||||
|
git log --author="name" # See commits by author
|
||||||
|
git log --since="2 weeks ago" # Recent commits
|
||||||
|
``````
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
When you're done with your investigation, run ``..\verify.ps1`` to check your answers!
|
||||||
|
"@
|
||||||
|
|
||||||
|
Set-Content -Path "investigation.md" -Value $investigationTemplate
|
||||||
|
|
||||||
|
# Return to module directory
|
||||||
|
Set-Location ..
|
||||||
|
|
||||||
|
Write-Host "`n=== Setup Complete! ===" -ForegroundColor Green
|
||||||
|
Write-Host "`nYour investigation environment is ready in the 'challenge/' directory." -ForegroundColor Cyan
|
||||||
|
Write-Host "`nScenario: Someone committed hardcoded credentials to app.py!" -ForegroundColor Yellow
|
||||||
|
Write-Host "`nNext steps:" -ForegroundColor Cyan
|
||||||
|
Write-Host " 1. cd challenge" -ForegroundColor White
|
||||||
|
Write-Host " 2. Open 'investigation.md' to see the investigation questions" -ForegroundColor White
|
||||||
|
Write-Host " 3. Use 'git blame -e app.py' to start your investigation" -ForegroundColor White
|
||||||
|
Write-Host " 4. Fill in your findings in 'investigation.md'" -ForegroundColor White
|
||||||
|
Write-Host " 5. Run '..\verify.ps1' to check your investigation" -ForegroundColor White
|
||||||
|
Write-Host ""
|
||||||
114
03_advanced/05-blame/verify.ps1
Normal file
114
03_advanced/05-blame/verify.ps1
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#!/usr/bin/env pwsh
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Verifies the Module 05 challenge solution.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This script checks that:
|
||||||
|
- The challenge directory exists
|
||||||
|
- A Git repository exists
|
||||||
|
- investigation.md exists with correct findings about the security issue
|
||||||
|
#>
|
||||||
|
|
||||||
|
Write-Host "`n=== Verifying Module 05 Solution ===" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
$allChecksPassed = $true
|
||||||
|
|
||||||
|
# Check if challenge directory exists
|
||||||
|
if (-not (Test-Path "challenge")) {
|
||||||
|
Write-Host "[FAIL] Challenge directory not found. Did you run setup.ps1?" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Set-Location "challenge"
|
||||||
|
|
||||||
|
# Check if git repository exists
|
||||||
|
if (-not (Test-Path ".git")) {
|
||||||
|
Write-Host "[FAIL] Not a git repository. Did you run setup.ps1?" -ForegroundColor Red
|
||||||
|
Set-Location ..
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if investigation.md exists
|
||||||
|
if (-not (Test-Path "investigation.md")) {
|
||||||
|
Write-Host "[FAIL] investigation.md not found. Did you run setup.ps1?" -ForegroundColor Red
|
||||||
|
Write-Host "[HINT] The setup script should have created investigation.md for you" -ForegroundColor Yellow
|
||||||
|
$allChecksPassed = $false
|
||||||
|
} else {
|
||||||
|
Write-Host "[PASS] investigation.md exists" -ForegroundColor Green
|
||||||
|
|
||||||
|
# Read the investigation file
|
||||||
|
$investigation = Get-Content "investigation.md" -Raw
|
||||||
|
$investigationLower = $investigation.ToLower()
|
||||||
|
|
||||||
|
# Check 1: Line number (line 8 contains the hardcoded password)
|
||||||
|
if ($investigationLower -match "8") {
|
||||||
|
Write-Host "[PASS] Correct line number identified" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "[FAIL] Line number not found or incorrect" -ForegroundColor Red
|
||||||
|
Write-Host "[HINT] Look at app.py to find which line contains 'admin123'" -ForegroundColor Yellow
|
||||||
|
$allChecksPassed = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check 2: Email address (guilty@email.com)
|
||||||
|
if ($investigationLower -match "guilty@email\.com") {
|
||||||
|
Write-Host "[PASS] Correct email address found using git blame!" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "[FAIL] Developer's email address not found" -ForegroundColor Red
|
||||||
|
Write-Host "[HINT] Use 'git blame -e app.py' to see who changed each line with email addresses" -ForegroundColor Yellow
|
||||||
|
$allChecksPassed = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check 3: Commit message (contains "test" or "debug" or "quick")
|
||||||
|
if ($investigationLower -match "test|debug|quick") {
|
||||||
|
Write-Host "[PASS] Commit message identified" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "[FAIL] Commit message not found" -ForegroundColor Red
|
||||||
|
Write-Host "[HINT] Use 'git show <commit-hash>' to see the commit message" -ForegroundColor Yellow
|
||||||
|
$allChecksPassed = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check 4: Number of files (1 file - only app.py)
|
||||||
|
if ($investigationLower -match "1|one|app\.py") {
|
||||||
|
Write-Host "[PASS] Number of files modified identified" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "[FAIL] Number of files modified not found" -ForegroundColor Red
|
||||||
|
Write-Host "[HINT] Use 'git show <commit-hash> --stat' to see which files were changed" -ForegroundColor Yellow
|
||||||
|
$allChecksPassed = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check 5: Some mention of timestamp/date (flexible check)
|
||||||
|
# We're just checking they attempted to answer this
|
||||||
|
if ($investigationLower -match "202|date|time|\d{4}-\d{2}-\d{2}") {
|
||||||
|
Write-Host "[PASS] Timestamp/date documented" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "[FAIL] Timestamp/date not documented" -ForegroundColor Red
|
||||||
|
Write-Host "[HINT] The git blame output shows the date and time of each change" -ForegroundColor Yellow
|
||||||
|
$allChecksPassed = $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set-Location ..
|
||||||
|
|
||||||
|
# Final summary
|
||||||
|
if ($allChecksPassed) {
|
||||||
|
Write-Host "`n" -NoNewline
|
||||||
|
Write-Host "=====================================" -ForegroundColor Green
|
||||||
|
Write-Host " INVESTIGATION COMPLETE!" -ForegroundColor Green
|
||||||
|
Write-Host "=====================================" -ForegroundColor Green
|
||||||
|
Write-Host "`nExcellent detective work! You've successfully used git blame to track down the security issue." -ForegroundColor Cyan
|
||||||
|
Write-Host "`nYou now know how to:" -ForegroundColor Cyan
|
||||||
|
Write-Host " - Use git blame to find who modified each line" -ForegroundColor White
|
||||||
|
Write-Host " - Read and interpret git blame output" -ForegroundColor White
|
||||||
|
Write-Host " - Use git blame with -e flag to show email addresses" -ForegroundColor White
|
||||||
|
Write-Host " - Find commit details after identifying changes with blame" -ForegroundColor White
|
||||||
|
Write-Host " - Conduct code archaeology to understand code history" -ForegroundColor White
|
||||||
|
Write-Host "`nRemember: git blame is for understanding, not blaming!" -ForegroundColor Yellow
|
||||||
|
Write-Host "`nReady for the next module!" -ForegroundColor Green
|
||||||
|
Write-Host ""
|
||||||
|
} else {
|
||||||
|
Write-Host "`n[SUMMARY] Some checks failed. Review the hints above and try again." -ForegroundColor Red
|
||||||
|
Write-Host "[INFO] You can run this verification script as many times as needed." -ForegroundColor Yellow
|
||||||
|
Write-Host ""
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user