mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
docs(github_actions): migrate docs format to mdx
This commit is contained in:
@@ -221,6 +221,13 @@
|
||||
"user-guide/providers/iac/authentication"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "GitHub Actions",
|
||||
"pages": [
|
||||
"user-guide/providers/github-actions/getting-started-github-actions",
|
||||
"user-guide/providers/github-actions/authentication"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "MongoDB Atlas",
|
||||
"pages": [
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: "GitHub Actions Authentication in Prowler"
|
||||
---
|
||||
|
||||
Prowler's GitHub Actions provider enables scanning of local or remote GitHub Actions workflows for security and compliance issues using [zizmor](https://github.com/woodruffw/zizmor).
|
||||
|
||||
## Authentication
|
||||
|
||||
- For local scans, no authentication is required.
|
||||
- For remote repository scans, authentication can be provided via:
|
||||
- [**GitHub Username and Personal Access Token (PAT)**](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic)
|
||||
- [**GitHub OAuth App Token**](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token)
|
||||
+56
-50
@@ -1,12 +1,13 @@
|
||||
# GitHub Actions Security Scanning with Prowler
|
||||
---
|
||||
title: "Getting Started with the GitHub Actions Provider"
|
||||
---
|
||||
import { VersionBadge } from "/snippets/version-badge.mdx"
|
||||
|
||||
Prowler integrates with [zizmor](https://github.com/woodruffw/zizmor) to provide comprehensive security scanning for GitHub Actions workflows. This feature helps identify security vulnerabilities and misconfigurations in your CI/CD pipelines.
|
||||
Prowler's GitHub Actions provider enables comprehensive security scanning for GitHub Actions workflows using [zizmor](https://github.com/woodruffw/zizmor). This provider helps identify security vulnerabilities and misconfigurations in CI/CD pipelines.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before using the GitHub Actions provider, you need to install zizmor:
|
||||
|
||||
### Install Zizmor
|
||||
Before using the GitHub Actions provider, zizmor must be installed:
|
||||
|
||||
```bash
|
||||
# Using Cargo (Rust package manager)
|
||||
@@ -26,77 +27,84 @@ The GitHub Actions provider scans for:
|
||||
- **Impostor commits and confusable git references** - Spots suspicious references
|
||||
- **Other GitHub Actions security best practices**
|
||||
|
||||
## Basic Usage
|
||||
## How It Works
|
||||
|
||||
### Scan Local Workflows
|
||||
- The GitHub Actions provider scans `.github/workflows/` directories for workflow files.
|
||||
- Local scans require no authentication.
|
||||
- Remote repository scans support authentication via GitHub credentials.
|
||||
- Check the [GitHub Actions Authentication](/user-guide/providers/github-actions/authentication) page for more details.
|
||||
- Results are output in the same formats as other Prowler providers (CSV, JSON, HTML, etc.).
|
||||
|
||||
To scan GitHub Actions workflows in your current directory:
|
||||
## Prowler CLI
|
||||
|
||||
<VersionBadge version="5.14.0" />
|
||||
|
||||
### Basic Usage
|
||||
|
||||
#### Scan Local Workflows
|
||||
|
||||
Scan GitHub Actions workflows in the current directory:
|
||||
|
||||
```bash
|
||||
prowler github_actions
|
||||
```
|
||||
|
||||
To scan workflows in a specific directory:
|
||||
Scan workflows in a specific directory:
|
||||
|
||||
```bash
|
||||
prowler github_actions --workflow-path /path/to/repository
|
||||
```
|
||||
|
||||
### Scan Remote Repository
|
||||
#### Scan Remote Repository
|
||||
|
||||
To scan a GitHub repository directly:
|
||||
Scan a public GitHub repository:
|
||||
|
||||
```bash
|
||||
# Public repository
|
||||
prowler github_actions --repository-url https://github.com/user/repo
|
||||
```
|
||||
|
||||
# Private repository with authentication
|
||||
Scan a private repository with authentication:
|
||||
|
||||
```bash
|
||||
prowler github_actions --repository-url https://github.com/user/private-repo \
|
||||
--github-username YOUR_USERNAME \
|
||||
--personal-access-token YOUR_TOKEN
|
||||
```
|
||||
|
||||
## Authentication Options
|
||||
### Authentication for Private Repositories
|
||||
|
||||
For scanning private repositories, Prowler supports multiple authentication methods:
|
||||
Authentication for private repositories can be provided using one of the following methods:
|
||||
|
||||
### Personal Access Token
|
||||
- **Personal Access Token:**
|
||||
```bash
|
||||
prowler github_actions --repository-url https://github.com/org/private-repo \
|
||||
--github-username YOUR_USERNAME \
|
||||
--personal-access-token YOUR_PAT
|
||||
```
|
||||
- **OAuth App Token:**
|
||||
```bash
|
||||
prowler github_actions --repository-url https://github.com/org/private-repo \
|
||||
--oauth-app-token YOUR_OAUTH_TOKEN
|
||||
```
|
||||
- If not provided via CLI, the following environment variables will be used:
|
||||
```bash
|
||||
export GITHUB_USERNAME=your-username
|
||||
export GITHUB_PERSONAL_ACCESS_TOKEN=your-token
|
||||
# or
|
||||
export GITHUB_OAUTH_APP_TOKEN=your-oauth-token
|
||||
|
||||
```bash
|
||||
prowler github_actions --repository-url https://github.com/org/private-repo \
|
||||
--github-username YOUR_USERNAME \
|
||||
--personal-access-token YOUR_PAT
|
||||
```
|
||||
prowler github_actions --repository-url https://github.com/org/private-repo
|
||||
```
|
||||
|
||||
### OAuth App Token
|
||||
### Excluding Workflows
|
||||
|
||||
```bash
|
||||
prowler github_actions --repository-url https://github.com/org/private-repo \
|
||||
--oauth-app-token YOUR_OAUTH_TOKEN
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
You can also set authentication via environment variables:
|
||||
|
||||
```bash
|
||||
export GITHUB_USERNAME=your-username
|
||||
export GITHUB_PERSONAL_ACCESS_TOKEN=your-token
|
||||
# or
|
||||
export GITHUB_OAUTH_APP_TOKEN=your-oauth-token
|
||||
|
||||
prowler github_actions --repository-url https://github.com/org/private-repo
|
||||
```
|
||||
|
||||
## Excluding Workflows
|
||||
|
||||
To exclude specific workflows or patterns from scanning:
|
||||
Exclude specific workflows or patterns from scanning:
|
||||
|
||||
```bash
|
||||
prowler github_actions --exclude-workflows "test-*.yml" "experimental/*"
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
### Output Formats
|
||||
|
||||
The GitHub Actions provider supports all standard Prowler output formats:
|
||||
|
||||
@@ -111,8 +119,6 @@ prowler github_actions --output-directory ./security-reports
|
||||
prowler github_actions --output-filename github-actions-security-scan
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Complete Security Scan with Full Reporting
|
||||
|
||||
```bash
|
||||
@@ -138,7 +144,7 @@ done
|
||||
|
||||
## Understanding Results
|
||||
|
||||
The scanner will identify issues with different severity levels:
|
||||
The scanner identifies issues with different severity levels:
|
||||
|
||||
- **CRITICAL/HIGH**: Immediate security risks that should be addressed urgently
|
||||
- **MEDIUM**: Potential security issues that should be reviewed
|
||||
@@ -152,7 +158,7 @@ Each finding includes:
|
||||
|
||||
## Integration with CI/CD
|
||||
|
||||
You can integrate Prowler's GitHub Actions scanning into your CI/CD pipeline:
|
||||
Integrate Prowler's GitHub Actions scanning into CI/CD pipelines:
|
||||
|
||||
```yaml
|
||||
name: Security Scan
|
||||
@@ -196,11 +202,11 @@ jobs:
|
||||
|
||||
### Zizmor Not Found
|
||||
|
||||
If you get an error about zizmor not being found:
|
||||
If an error about zizmor not being found occurs:
|
||||
|
||||
1. Ensure zizmor is installed: `which zizmor`
|
||||
2. Install it using: `cargo install zizmor`
|
||||
3. Make sure it's in your PATH
|
||||
3. Verify it is in your PATH
|
||||
|
||||
### Authentication Issues
|
||||
|
||||
@@ -3,29 +3,31 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from prowler.providers.github_action.github_action_provider import GithubActionProvider
|
||||
from prowler.providers.github_actions.github_actions_provider import (
|
||||
GithubActionsProvider,
|
||||
)
|
||||
|
||||
|
||||
class TestGithubActionProvider:
|
||||
"""Test cases for the GitHub Action Provider"""
|
||||
class TestGithubActionsProvider:
|
||||
"""Test cases for the GitHub Actions Provider"""
|
||||
|
||||
def test_github_action_provider_init_default(self):
|
||||
def test_github_actions_provider_init_default(self):
|
||||
"""Test provider initialization with default values"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider()
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider()
|
||||
|
||||
assert provider.type == "github_action"
|
||||
assert provider.type == "github_actions"
|
||||
assert provider.workflow_path == "."
|
||||
assert provider.repository_url is None
|
||||
assert provider.exclude_workflows == []
|
||||
assert provider.auth_method == "No auth"
|
||||
assert provider.region == "global"
|
||||
assert provider.audited_account == "github-actions"
|
||||
assert provider.audited_account == "github_actions"
|
||||
|
||||
def test_github_action_provider_init_with_repository_url(self):
|
||||
def test_github_actions_provider_init_with_repository_url(self):
|
||||
"""Test provider initialization with repository URL"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider(
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider(
|
||||
repository_url="https://github.com/test/repo",
|
||||
github_username="testuser",
|
||||
personal_access_token="token123",
|
||||
@@ -36,10 +38,10 @@ class TestGithubActionProvider:
|
||||
assert provider.personal_access_token == "token123"
|
||||
assert provider.auth_method == "Personal Access Token"
|
||||
|
||||
def test_github_action_provider_init_with_oauth_token(self):
|
||||
def test_github_actions_provider_init_with_oauth_token(self):
|
||||
"""Test provider initialization with OAuth token"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider(
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider(
|
||||
repository_url="https://github.com/test/repo",
|
||||
oauth_app_token="oauth_token123",
|
||||
)
|
||||
@@ -49,50 +51,65 @@ class TestGithubActionProvider:
|
||||
assert provider.github_username is None
|
||||
assert provider.personal_access_token is None
|
||||
|
||||
def test_process_finding(self):
|
||||
def test_process_zizmor_finding(self):
|
||||
"""Test processing a zizmor finding"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider()
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider()
|
||||
|
||||
# Sample zizmor finding
|
||||
# Sample zizmor v1.x+ finding
|
||||
finding = {
|
||||
"id": "template-injection",
|
||||
"title": "Template Injection Vulnerability",
|
||||
"level": "HIGH",
|
||||
"description": "Potential code injection in workflow",
|
||||
"documentation_url": "https://example.com/docs",
|
||||
"location": {"line": 10, "column": 5},
|
||||
"risk": "High risk of code execution",
|
||||
"remediation": "Use environment variables instead",
|
||||
"ident": "template-injection",
|
||||
"desc": "Template Injection Vulnerability",
|
||||
"determinations": {"severity": "high", "confidence": "High"},
|
||||
"url": "https://example.com/docs",
|
||||
}
|
||||
|
||||
report = provider._process_finding(finding, ".github/workflows/test.yml")
|
||||
location = {
|
||||
"symbolic": {
|
||||
"annotation": "High risk of code execution",
|
||||
"key": {
|
||||
"Local": {
|
||||
"given_path": ".github/workflows/test.yml"
|
||||
}
|
||||
}
|
||||
},
|
||||
"concrete": {
|
||||
"location": {
|
||||
"start_point": {"row": 10, "column": 5},
|
||||
"end_point": {"row": 10, "column": 15}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
report = provider._process_zizmor_finding(
|
||||
finding, ".github/workflows/test.yml", location
|
||||
)
|
||||
|
||||
assert report.resource_name == ".github/workflows/test.yml"
|
||||
assert report.status == "FAIL"
|
||||
assert "line 10, column 5" in report.status_extended
|
||||
assert "line 10" in report.resource_line_range
|
||||
|
||||
# Check metadata
|
||||
assert (
|
||||
report.check_metadata.CheckID == "githubaction_template_injection"
|
||||
) # Prefixed with githubaction_
|
||||
report.check_metadata.CheckID == "githubactions_template_injection"
|
||||
) # Prefixed with githubactions_
|
||||
assert report.check_metadata.Severity == "high"
|
||||
assert report.check_metadata.Provider == "github_action"
|
||||
assert report.check_metadata.Provider == "github_actions"
|
||||
|
||||
def test_run_scan_no_issues(self):
|
||||
"""Test scanning when no issues are found"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider()
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider()
|
||||
|
||||
# Mock subprocess to return empty findings
|
||||
# Mock subprocess to return empty findings (zizmor v1.x+ format)
|
||||
mock_process = MagicMock()
|
||||
mock_process.stdout = '{"findings": {}}'
|
||||
mock_process.stdout = "[]"
|
||||
mock_process.stderr = ""
|
||||
mock_process.returncode = 0
|
||||
|
||||
with patch("subprocess.run", return_value=mock_process):
|
||||
with patch(
|
||||
"prowler.providers.github_action.github_action_provider.alive_bar"
|
||||
"prowler.providers.github_actions.github_actions_provider.alive_bar"
|
||||
):
|
||||
reports = provider.run_scan(".", [])
|
||||
|
||||
@@ -100,24 +117,36 @@ class TestGithubActionProvider:
|
||||
|
||||
def test_run_scan_with_findings(self):
|
||||
"""Test scanning with security findings"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider()
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider()
|
||||
|
||||
# Mock subprocess to return findings
|
||||
mock_output = {
|
||||
"findings": {
|
||||
".github/workflows/ci.yml": [
|
||||
# Mock subprocess to return findings (zizmor v1.x+ format)
|
||||
mock_output = [
|
||||
{
|
||||
"ident": "excessive-permissions",
|
||||
"desc": "Workflow has write-all permissions",
|
||||
"determinations": {"severity": "medium", "confidence": "High"},
|
||||
"url": "https://docs.example.com",
|
||||
"locations": [
|
||||
{
|
||||
"id": "excessive-permissions",
|
||||
"title": "Excessive Permissions",
|
||||
"level": "MEDIUM",
|
||||
"description": "Workflow has write-all permissions",
|
||||
"documentation_url": "https://docs.example.com",
|
||||
"location": {"line": 5},
|
||||
"symbolic": {
|
||||
"annotation": "Excessive permissions detected",
|
||||
"key": {
|
||||
"Local": {
|
||||
"given_path": ".github/workflows/ci.yml"
|
||||
}
|
||||
}
|
||||
},
|
||||
"concrete": {
|
||||
"location": {
|
||||
"start_point": {"row": 5, "column": 1},
|
||||
"end_point": {"row": 5, "column": 20}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
mock_process = MagicMock()
|
||||
mock_process.stdout = json.dumps(mock_output)
|
||||
@@ -126,7 +155,7 @@ class TestGithubActionProvider:
|
||||
|
||||
with patch("subprocess.run", return_value=mock_process):
|
||||
with patch(
|
||||
"prowler.providers.github_action.github_action_provider.alive_bar"
|
||||
"prowler.providers.github_actions.github_actions_provider.alive_bar"
|
||||
):
|
||||
reports = provider.run_scan(".", [])
|
||||
|
||||
@@ -135,28 +164,28 @@ class TestGithubActionProvider:
|
||||
|
||||
def test_run_scan_zizmor_not_found(self):
|
||||
"""Test error handling when zizmor is not installed"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider()
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider()
|
||||
|
||||
with patch(
|
||||
"subprocess.run",
|
||||
side_effect=FileNotFoundError("No such file or directory: 'zizmor'"),
|
||||
):
|
||||
with patch(
|
||||
"prowler.providers.github_action.github_action_provider.alive_bar"
|
||||
"prowler.providers.github_actions.github_actions_provider.alive_bar"
|
||||
):
|
||||
with pytest.raises(SystemExit):
|
||||
provider.run_scan(".", [])
|
||||
|
||||
def test_clone_repository_with_pat(self):
|
||||
"""Test cloning repository with personal access token"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider()
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider()
|
||||
|
||||
with patch("tempfile.mkdtemp", return_value="/tmp/test"):
|
||||
with patch("dulwich.porcelain.clone"):
|
||||
with patch(
|
||||
"prowler.providers.github_action.github_action_provider.alive_bar"
|
||||
"prowler.providers.github_actions.github_actions_provider.alive_bar"
|
||||
):
|
||||
temp_dir = provider._clone_repository(
|
||||
"https://github.com/test/repo",
|
||||
@@ -168,10 +197,12 @@ class TestGithubActionProvider:
|
||||
|
||||
def test_print_credentials_local_scan(self):
|
||||
"""Test printing credentials for local scan"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider(workflow_path="/path/to/workflows")
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider(workflow_path="/path/to/workflows")
|
||||
|
||||
with patch("prowler.lib.utils.utils.print_boxes") as mock_print:
|
||||
with patch(
|
||||
"prowler.providers.github_actions.github_actions_provider.print_boxes"
|
||||
) as mock_print:
|
||||
provider.print_credentials()
|
||||
|
||||
# Verify print_boxes was called with expected content
|
||||
@@ -181,13 +212,15 @@ class TestGithubActionProvider:
|
||||
|
||||
def test_print_credentials_remote_scan(self):
|
||||
"""Test printing credentials for remote repository scan"""
|
||||
with patch.object(GithubActionProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionProvider(
|
||||
with patch.object(GithubActionsProvider, "setup_session", return_value=None):
|
||||
provider = GithubActionsProvider(
|
||||
repository_url="https://github.com/test/repo",
|
||||
exclude_workflows=["test*.yml"],
|
||||
)
|
||||
|
||||
with patch("prowler.lib.utils.utils.print_boxes") as mock_print:
|
||||
with patch(
|
||||
"prowler.providers.github_actions.github_actions_provider.print_boxes"
|
||||
) as mock_print:
|
||||
provider.print_credentials()
|
||||
|
||||
# Verify print_boxes was called with expected content
|
||||
|
||||
Reference in New Issue
Block a user