diff --git a/docs/guides/software-lifecycle/security/github-security/README.md b/docs/guides/software-lifecycle/security/github-security/README.md index 75bdd7ff3..c10aa69c4 100644 --- a/docs/guides/software-lifecycle/security/github-security/README.md +++ b/docs/guides/software-lifecycle/security/github-security/README.md @@ -11,9 +11,10 @@ **Background:** GitHub offers a suite of security features to help maintainers and developers protect their code and ensure the safety of their repositories. From automatically detecting vulnerabilities in dependencies to scanning for secrets and setting security policies, these tools are essential for any project, especially in today’s security-conscious environment. **Use Cases:** -- Being alerted over e-mail or GitHub notifications about known vulnerabilities in your dependencies and having pull-requests automatically created to resolve the issues. +- Being alerted over e-mail or GitHub notifications about known vulnerabilities in your dependencies and having pull-requests automatically created to resolve the issues. - Being alerted if your dependencies have updated versions available. -- Being alerted if your commits have potentially harmful secrets or sensitive information within the code - including being blocked from pushing your commits. +- Being alerted if your commits have potentially harmful secrets or sensitive information within the code - including being blocked from pushing your commits. +- Allowing your community to privately report security vulnerabilities to maintainers and repository owners. ## Prerequisites @@ -24,33 +25,76 @@ ## Quick Start -The fastest way to enable recommended GitHub Security features is to perform it in bulk for _all_ of your repositories within a given organization. Consult [Enabling security features for multiple repositories](https://docs.github.com/en/enterprise-cloud@latest/code-security/security-overview/enabling-security-features-for-multiple-repositories) for details. Organization administrative-level access is required. +The fastest way to enable recommended GitHub Security features is to perform it in bulk for _all_ of your repositories within a given organization. Consult [Enabling security features for multiple repositories](https://docs.github.com/en/enterprise-cloud@latest/code-security/security-overview/enabling-security-features-for-multiple-repositories) for details. Organization administrative-level access is required. We recommend enabling the below features for all your repositories: -![img](https://github.com/NASA-AMMOS/slim/assets/3129134/be02ee5f-74cb-4869-bdf2-020c184516ec) - -Specifically: -- Dependency graphs (select "Enable All") +- **Private vulnerability reporting** (select "Enable All") + - Allows community members to privately report security vulnerabilities +- **Dependency graphs** (select "Enable All") - Select "Automatically enable for new private repositories" -- Dependabot Alerts (select "Enable All") +- **Dependabot Alerts** (select "Enable All") + - Select "Automatically enable for new repositories" +- **Dependabot Security Updates** (select "Enable All") - Select "Automatically enable for new repositories" -- Dependabot Security Updates (select "Enable All") +- **Secret Scanning** (select "Enable All") - Select "Automatically enable for new repositories" -- Code Scanning (select "Enable All") - - Select the default "CodeQL high-precision queries" option + - Enable "Push protection" to block commits containing secrets + +⬇️ **Use our GitHub Security Settings automation script:** For automated configuration of security settings on individual repositories, you can also use our [GitHub Security Settings Script](pathname:///assets/software-lifecycle/security/github-security/gh-security-settings.py). + +If you do not have organizational permissions or if you wish to customize security features per repository, see our Step-by-Step guide below for repository-specific guidance. -If you do not have organizational permissions or if you wish to customize security features per repository, see our Step-by-Step guide below for repository-specific guidance. - ## Step-by-Step Guide per Repository -1. **Set Up Dependabot:** +### Option A: Using the Automation Script + +For automated setup, use our [GitHub Security Settings Script](pathname:///assets/software-lifecycle/security/github-security/gh-security-settings.py): + +1. **Prerequisites:** + - Python 3.6+ with `requests` and `rich` packages installed + - GitHub Personal Access Token with required permissions (repo, security_events, admin:repo_hook) + +2. **Basic Usage:** + ```bash + # Check current security settings + python gh-security-settings.py -o OWNER -r REPO -t TOKEN + + # Enable all security features + python gh-security-settings.py -o OWNER -r REPO -t TOKEN -a enable + + # Enable specific features only + python gh-security-settings.py -o OWNER -r REPO -t TOKEN -a enable -f dependabot-alerts + ``` + +3. **Available Features:** + - `all` - All supported security features + - `private-reporting` - Private vulnerability reporting + - `dependency-graph` - Dependency graph + - `dependabot-alerts` - Dependabot vulnerability alerts + - `dependabot-updates` - Dependabot security updates + - `secret-scanning` - Secret scanning + - `secret-protection` - Secret scanning push protection + +### Option B: Manual Configuration + +1. **Enable Private Vulnerability Reporting:** - Navigate to your repository and click on the `Settings` tab. - From the left sidebar, select the `Code security and analysis` menu. + - Under the "Private vulnerability reporting" section: + - Click the "Enable" button to allow your community to privately report potential security vulnerabilities to maintainers and repository owners. + +2. **Set Up Dependency Graph:** + - In the `Code security and analysis` menu from the `Settings` tab: + - Under the "Dependency graph" section, click "Enable" to understand your dependencies. + - This feature is automatically enabled for public repositories and must be enabled for private repositories. + +3. **Set Up Dependabot:** + - In the `Code security and analysis` menu: - Under the "Dependabot" section: - - We recommend enabling Dependabot alerts to stay informed about insecure dependencies in your project. - - For added security, we suggest turning on Dependabot security updates to automatically generate pull requests for known vulnerabilities in your dependencies. - - We also recommend enabling Dependabot version updates _if you are using a package manager for your project_. This will help you keep your dependencies up-to-date. To configure Dependabot version updates: + - **Dependabot alerts:** Enable to stay informed about insecure dependencies in your project. + - **Dependabot security updates:** Enable to automatically generate pull requests for known vulnerabilities in your dependencies. + - **Dependabot version updates:** Enable if you are using a package manager for your project. This will help you keep your dependencies up-to-date. To configure Dependabot version updates: 1. Create a `.github/dependabot.yml` file in your repository. 2. Specify the package-ecosystem, directory, schedule and branch to update. For example, the below demonstrates a Python [dependabot.yml](https://github.com/NASA-AMMOS/slim-starterkit-python/blob/main/.github/dependabot.yml) example from the [SLIM Python Starter Kit](https://nasa-ammos.github.io/slim/docs/guides/software-lifecycle/application-starter-kits/python-starter-kit/): ```yml @@ -70,15 +114,7 @@ If you do not have organizational permissions or if you wish to customize securi - Head back to the main page of your repository. - Click on the `Security` tab. Here, you can select `Dependabot alerts` to view security alerts, and you can see version updates in the `Pull requests` tab labeled with "Dependabot". - -2. **Enable Code Scanning:** - - In the `Code security and analysis` menu from the `Settings` tab, click the "Set Up" or enable the following workflows: - - _CodeQL Analysis workflow:_ a free tool provided by GitHub that scans your code for vulnerabilities across a variety of languages. Simply choose a CodeQL Analysis template (default is acceptable) and follow the instructions. - - To view Code scanning alerts: - - Return to the repository main page. - - Click on the `Security` tab and select `Code scanning alerts`. - -3. **Enable Secret Scanning:** +4. **Enable Secret Scanning:** - In the `Code security and analysis` menu from the `Settings` tab: - Click on the `Secret scanning` enable button. - We recommend enabling "Push protection" for blocking commits containing secrets @@ -94,12 +130,12 @@ If you do not have organizational permissions or if you wish to customize securi - **Q: Are these security features available on GitHub Enterprise?** - A: It depends on your institution's particular version of GitHub deployed. You'll have to check your Settings tab to view the features that are provided. GitHub.com is the most up-to-date version we recommend for. + A: It depends on your institution's particular version of GitHub deployed. You'll have to check your Settings tab to view the features that are provided. GitHub.com is the most up-to-date version we recommend for. - **Q: If I receive security alerts, what should I do and how soon should I act?** A: When you receive a security alert, it indicates a potential vulnerability in your repository. First, review the details of the alert to understand the severity and the affected component. Address critical vulnerabilities immediately, as they can pose a significant risk to your project. For less severe alerts, plan to address them in a timely manner. Always keep in mind that the sooner you act on security alerts, the better you can protect your code and users from potential threats. - + ## Credits **Authorship:** @@ -109,7 +145,7 @@ If you do not have organizational permissions or if you wish to customize securi **Acknowledgements:** - GitHub for providing the security features and related documentation. See [GitHub’s Security Features](https://docs.github.com/en/code-security) to access an overview of the suite of security features GitHub provides for repositories. - [OWASP DevSecOps Guideline](https://owasp.org/www-project-devsecops-guideline/latest/) for providing a Shift Left strategy to secure all phases of development. - + ## Feedback and Contributions We welcome feedback and contributions to help improve and grow this guide. Please see our [contribution guidelines](https://nasa-ammos.github.io/slim/docs/contribute/contributing/). diff --git a/static/assets/software-lifecycle/security/github-security/gh-security-settings.py b/static/assets/software-lifecycle/security/github-security/gh-security-settings.py new file mode 100644 index 000000000..3e327c08c --- /dev/null +++ b/static/assets/software-lifecycle/security/github-security/gh-security-settings.py @@ -0,0 +1,531 @@ +#!/usr/bin/env python3 + +""" +GitHub Security Settings Manager +Manages specific GitHub security settings for a repository: +- Private vulnerability reporting +- Dependency graph +- Dependabot alerts +- Dependabot security updates +- Code scanning +- Secret scanning push protection +""" + +import argparse +import json +import logging +import sys +from typing import Dict, Optional, Tuple + +import requests +from requests.adapters import HTTPAdapter +from urllib3.util.retry import Retry +from rich.console import Console +from rich.table import Table +from rich import print as rprint + +# Setup logging +logging.basicConfig(level=logging.WARNING) +logger = logging.getLogger(__name__) + +# Initialize Rich console +console = Console() + + +class GitHubSecurityManager: + """Manages GitHub security settings for a repository""" + + def __init__(self, owner: str, repo: str, token: str): + self.owner = owner + self.repo = repo + self.token = token + self.base_url = "https://api.github.com" + self.session = self._create_session() + + def _create_session(self) -> requests.Session: + """Create a requests session with retry strategy""" + session = requests.Session() + retry_strategy = Retry( + total=3, + backoff_factor=1, + status_forcelist=[429, 500, 502, 503, 504], + ) + adapter = HTTPAdapter(max_retries=retry_strategy) + session.mount("http://", adapter) + session.mount("https://", adapter) + + session.headers.update({ + 'Authorization': f'token {self.token}', + 'Accept': 'application/vnd.github.v3+json', + 'Content-Type': 'application/json' + }) + return session + + def github_api(self, method: str, endpoint: str, data: Optional[Dict] = None) -> Tuple[int, Dict]: + """Make GitHub API calls and return status code and response body""" + url = f"{self.base_url}{endpoint}" + + try: + if data: + response = self.session.request(method, url, json=data) + else: + response = self.session.request(method, url) + + # Try to parse JSON response, return empty dict if not JSON + try: + response_data = response.json() + except (json.JSONDecodeError, ValueError): + response_data = {} + + return response.status_code, response_data + + except requests.RequestException as e: + console.print(f"[red]✗[/red] Request failed: {e}") + return 0, {} + + def check_repository(self) -> bool: + """Check if repository exists and is accessible""" + status_code, data = self.github_api('GET', f'/repos/{self.owner}/{self.repo}') + + if status_code == 200: + return True + else: + console.print(f"[red]✗[/red] Repository not found or no access (HTTP {status_code})") + return False + + def check_private_reporting(self) -> bool: + """Check if private vulnerability reporting is enabled""" + # Try the dedicated endpoint first + status_code, data = self.github_api('GET', f'/repos/{self.owner}/{self.repo}/private-vulnerability-reporting') + + if status_code == 200: + return data.get('enabled', False) + elif status_code == 404 or status_code == 422: + # Feature not available or disabled + return False + + # Fallback to repository endpoint + status_code, data = self.github_api('GET', f'/repos/{self.owner}/{self.repo}') + + if status_code == 200: + security_analysis = data.get('security_and_analysis', {}) + private_reporting = security_analysis.get('private_vulnerability_reporting', {}) + return private_reporting.get('status') == 'enabled' + else: + return False + + def check_dependency_graph(self) -> bool: + """Check if dependency graph is enabled""" + # Try the repository endpoint first + status_code, data = self.github_api('GET', f'/repos/{self.owner}/{self.repo}') + + if status_code == 200: + # Check if the repository is private + is_private = data.get('private', False) + + # For private repos, check security_and_analysis + if is_private: + security_analysis = data.get('security_and_analysis', {}) + dependency_graph = security_analysis.get('dependency_graph', {}) + if dependency_graph: + return dependency_graph.get('status') == 'enabled' + + # For public repos, we need to check the vulnerability alerts + # If vulnerability alerts are enabled, dependency graph is enabled + status_code, _ = self.github_api('GET', f'/repos/{self.owner}/{self.repo}/vulnerability-alerts') + return status_code == 204 + + return False + + def check_dependabot_alerts(self) -> bool: + """Check if Dependabot alerts are enabled""" + status_code, _ = self.github_api('GET', f'/repos/{self.owner}/{self.repo}/vulnerability-alerts') + return status_code == 204 + + def check_dependabot_updates(self) -> bool: + """Check if Dependabot security updates are enabled""" + status_code, response_data = self.github_api('GET', f'/repos/{self.owner}/{self.repo}/automated-security-fixes') + logger.debug(f"Dependabot security updates check: status_code={status_code}, response={response_data}") + + if status_code == 200: + # GitHub returns 200 with JSON response containing enabled status + return response_data.get('enabled', False) + elif status_code == 204: + # Some repositories might still return 204 for enabled + return True + else: + # Any other status code means disabled or error + return False + + def check_secret_scanning(self) -> bool: + """Check if secret scanning is enabled""" + status_code, data = self.github_api('GET', f'/repos/{self.owner}/{self.repo}') + + if status_code == 200: + security_analysis = data.get('security_and_analysis', {}) + secret_scanning = security_analysis.get('secret_scanning', {}) + return secret_scanning.get('status') == 'enabled' + else: + return False + + def check_secret_protection(self) -> bool: + """Check if secret scanning push protection is enabled""" + status_code, data = self.github_api('GET', f'/repos/{self.owner}/{self.repo}') + + if status_code == 200: + security_analysis = data.get('security_and_analysis', {}) + push_protection = security_analysis.get('secret_scanning_push_protection', {}) + return push_protection.get('status') == 'enabled' + else: + return False + + def check_settings(self) -> None: + """Check and display current security settings""" + if not self.check_repository(): + return + + # Create Rich table + table = Table(show_header=True, header_style="bold blue") + table.add_column("Repo", style="cyan", no_wrap=True) + table.add_column("Status", justify="center") + table.add_column("Setting", style="magenta") + + repo_name = f"{self.owner}/{self.repo}" + + # Check all security settings + settings = [ + ("Private Repository Reporting", self.check_private_reporting()), + ("Dependency Graph", self.check_dependency_graph()), + ("Dependabot Alerts", self.check_dependabot_alerts()), + ("Dependabot Security Updates", self.check_dependabot_updates()), + ("Secret Scanning", self.check_secret_scanning()), + ("Secret Scanning Push Protection", self.check_secret_protection()) + ] + + for setting_name, is_enabled in settings: + status = "[green]✓[/green]" if is_enabled else "[red]✗[/red]" + table.add_row(repo_name, status, setting_name) + + console.print() + console.print(table) + console.print() + + def enable_private_reporting(self) -> None: + """Enable private vulnerability reporting""" + logger.debug("Enabling private vulnerability reporting...") + + # Use the dedicated endpoint + data = {"enabled": True} + status_code, _ = self.github_api('PUT', f'/repos/{self.owner}/{self.repo}/private-vulnerability-reporting', data) + + if status_code == 204: + console.print(f"[green]✓[/green] Private vulnerability reporting enabled") + else: + console.print(f"[red]✗[/red] Failed to enable private vulnerability reporting (HTTP {status_code})") + + def enable_dependency_graph(self) -> None: + """Enable dependency graph""" + logger.debug("Enabling dependency graph...") + data = { + "security_and_analysis": { + "dependency_graph": {"status": "enabled"} + } + } + status_code, _ = self.github_api('PATCH', f'/repos/{self.owner}/{self.repo}', data) + + if status_code == 200: + console.print(f"[green]✓[/green] Dependency graph enabled") + else: + console.print(f"[red]✗[/red] Failed to enable dependency graph (HTTP {status_code})") + + def enable_dependabot_alerts(self) -> None: + """Enable Dependabot alerts""" + logger.debug("Enabling Dependabot alerts...") + status_code, _ = self.github_api('PUT', f'/repos/{self.owner}/{self.repo}/vulnerability-alerts') + + if status_code == 204: + console.print(f"[green]✓[/green] Dependabot alerts enabled") + else: + console.print(f"[red]✗[/red] Failed to enable Dependabot alerts (HTTP {status_code})") + + def enable_dependabot_updates(self) -> None: + """Enable Dependabot security updates""" + logger.debug("Enabling Dependabot security updates...") + status_code, _ = self.github_api('PUT', f'/repos/{self.owner}/{self.repo}/automated-security-fixes') + + if status_code == 204: + console.print(f"[green]✓[/green] Dependabot security updates enabled") + else: + console.print(f"[red]✗[/red] Failed to enable Dependabot security updates (HTTP {status_code})") + + def enable_secret_scanning(self) -> None: + """Enable secret scanning""" + logger.debug("Enabling secret scanning...") + data = { + "security_and_analysis": { + "secret_scanning": {"status": "enabled"} + } + } + status_code, _ = self.github_api('PATCH', f'/repos/{self.owner}/{self.repo}', data) + + if status_code == 200: + console.print(f"[green]✓[/green] Secret scanning enabled") + else: + console.print(f"[red]✗[/red] Failed to enable secret scanning (HTTP {status_code})") + + def enable_secret_protection(self) -> None: + """Enable secret scanning push protection""" + logger.debug("Enabling secret scanning push protection...") + + # First make sure secret scanning is enabled + data = { + "security_and_analysis": { + "secret_scanning": {"status": "enabled"}, + "secret_scanning_push_protection": {"status": "enabled"} + } + } + status_code, _ = self.github_api('PATCH', f'/repos/{self.owner}/{self.repo}', data) + + if status_code == 200: + console.print(f"[green]✓[/green] Secret scanning push protection enabled") + else: + console.print(f"[red]✗[/red] Failed to enable secret scanning push protection (HTTP {status_code})") + + def disable_private_reporting(self) -> None: + """Disable private vulnerability reporting""" + logger.debug("Disabling private vulnerability reporting...") + + # Use the dedicated endpoint + status_code, response_data = self.github_api('DELETE', f'/repos/{self.owner}/{self.repo}/private-vulnerability-reporting') + + if status_code == 204: + console.print(f"[green]✓[/green] Private vulnerability reporting disabled") + elif status_code == 404: + # If 404, the feature might already be disabled or not available + console.print(f"[green]✓[/green] Private vulnerability reporting is already disabled or not available") + elif status_code == 422: + # 422 can happen when the feature is already disabled + console.print(f"[green]✓[/green] Private vulnerability reporting is already disabled") + else: + console.print(f"[red]✗[/red] Failed to disable private vulnerability reporting (HTTP {status_code})") + + def disable_dependency_graph(self) -> None: + """Disable dependency graph""" + logger.debug("Disabling dependency graph...") + + # Try to disable dependency graph via vulnerability alerts endpoint + status_code, _ = self.github_api('DELETE', f'/repos/{self.owner}/{self.repo}/vulnerability-alerts') + + if status_code == 204: + console.print(f"[green]✓[/green] Dependency graph disabled") + elif status_code == 404: + # If 404, the feature might already be disabled or not available + console.print(f"[green]✓[/green] Dependency graph is already disabled or not available") + else: + console.print(f"[red]✗[/red] Failed to disable dependency graph (HTTP {status_code})") + + def disable_dependabot_alerts(self) -> None: + """Disable Dependabot alerts""" + logger.debug("Disabling Dependabot alerts...") + status_code, _ = self.github_api('DELETE', f'/repos/{self.owner}/{self.repo}/vulnerability-alerts') + + if status_code == 204: + console.print(f"[green]✓[/green] Dependabot alerts disabled") + elif status_code == 404: + # If 404, the feature might already be disabled or not available + console.print(f"[green]✓[/green] Dependabot alerts are already disabled or not available") + else: + console.print(f"[red]✗[/red] Failed to disable Dependabot alerts (HTTP {status_code})") + + def disable_dependabot_updates(self) -> None: + """Disable Dependabot security updates""" + logger.debug("Disabling Dependabot security updates...") + status_code, response_data = self.github_api('DELETE', f'/repos/{self.owner}/{self.repo}/automated-security-fixes') + + if status_code == 204: + console.print(f"[green]✓[/green] Dependabot security updates disabled") + elif status_code == 404: + # If 404, the feature might already be disabled or not available + console.print(f"[green]✓[/green] Dependabot security updates are already disabled or not available") + elif status_code == 422: + # 422 can happen when the feature is already disabled or when Dependabot alerts are disabled + # In this case, we should consider it a success since the end state is what we want + console.print(f"[green]✓[/green] Dependabot security updates are already disabled") + else: + console.print(f"[red]✗[/red] Failed to disable Dependabot security updates (HTTP {status_code})") + + # CodeQL/Code scanning methods removed - functionality no longer supported + + def disable_secret_scanning(self) -> None: + """Disable secret scanning""" + logger.debug("Disabling secret scanning...") + data = { + "security_and_analysis": { + "secret_scanning": {"status": "disabled"} + } + } + status_code, _ = self.github_api('PATCH', f'/repos/{self.owner}/{self.repo}', data) + + if status_code == 200: + console.print(f"[green]✓[/green] Secret scanning disabled") + elif status_code == 404: + # If 404, the feature might already be disabled or not available + console.print(f"[green]✓[/green] Secret scanning is already disabled or not available") + else: + console.print(f"[red]✗[/red] Failed to disable secret scanning (HTTP {status_code})") + + def disable_secret_protection(self) -> None: + """Disable secret scanning push protection""" + logger.debug("Disabling secret scanning push protection...") + data = { + "security_and_analysis": { + "secret_scanning_push_protection": {"status": "disabled"} + } + } + status_code, _ = self.github_api('PATCH', f'/repos/{self.owner}/{self.repo}', data) + + if status_code == 200: + console.print(f"[green]✓[/green] Secret scanning push protection disabled") + elif status_code == 404: + # If 404, the feature might already be disabled or not available + console.print(f"[green]✓[/green] Secret scanning push protection is already disabled or not available") + else: + console.print(f"[red]✗[/red] Failed to disable secret scanning push protection (HTTP {status_code})") + + def enable_features(self, features: str) -> None: + """Enable specified security features""" + feature_methods = { + 'all': [ + self.enable_private_reporting, + self.enable_dependency_graph, + self.enable_dependabot_alerts, + self.enable_dependabot_updates, + self.enable_secret_scanning, + self.enable_secret_protection + ], + 'private-reporting': [self.enable_private_reporting], + 'dependency-graph': [self.enable_dependency_graph], + 'dependabot-alerts': [self.enable_dependabot_alerts], + 'dependabot-updates': [self.enable_dependabot_updates], + 'secret-scanning': [self.enable_secret_scanning], + 'secret-protection': [self.enable_secret_protection] + } + + methods = feature_methods.get(features) + if not methods: + self.print_status('error', f"Unknown feature: {features}") + return + + for method in methods: + method() + + def disable_features(self, features: str) -> None: + """Disable specified security features""" + feature_methods = { + 'all': [ + self.disable_private_reporting, + self.disable_dependency_graph, + self.disable_dependabot_alerts, + self.disable_dependabot_updates, + self.disable_secret_scanning, + self.disable_secret_protection + ], + 'private-reporting': [self.disable_private_reporting], + 'dependency-graph': [self.disable_dependency_graph], + 'dependabot-alerts': [self.disable_dependabot_alerts], + 'dependabot-updates': [self.disable_dependabot_updates], + 'secret-scanning': [self.disable_secret_scanning], + 'secret-protection': [self.disable_secret_protection] + } + + methods = feature_methods.get(features) + if not methods: + self.print_status('error', f"Unknown feature: {features}") + return + + for method in methods: + method() + + +def main(): + """Main function to handle command line arguments and execute actions""" + parser = argparse.ArgumentParser( + description='GitHub Security Settings Manager', + epilog=''' +Examples: + # Check all security settings + %(prog)s -o myorg -r myrepo -t ghp_xxxxx + + # Enable all security features + %(prog)s -o myorg -r myrepo -t ghp_xxxxx -a enable + + # Enable only Dependabot alerts + %(prog)s -o myorg -r myrepo -t ghp_xxxxx -a enable -f dependabot-alerts + + # Disable secret scanning push protection + %(prog)s -o myorg -r myrepo -t ghp_xxxxx -a disable -f secret-protection + +Features: + all - All supported security features + private-reporting - Private vulnerability reporting + dependency-graph - Dependency graph + dependabot-alerts - Dependabot vulnerability alerts + dependabot-updates - Dependabot security updates + secret-scanning - Secret scanning + secret-protection - Secret scanning push protection + +Required Token Permissions: + - repo (for private repositories) + - public_repo (for public repositories) + - security_events (for security features) + - admin:repo_hook (for some security settings) + ''', + formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.add_argument('-o', '--owner', required=True, + help='GitHub repository owner/organization') + parser.add_argument('-r', '--repo', required=True, + help='GitHub repository name') + parser.add_argument('-t', '--token', required=True, + help='GitHub personal access token') + parser.add_argument('-a', '--action', choices=['check', 'enable', 'disable'], + default='check', help='Action to perform (default: check)') + parser.add_argument('-f', '--features', + choices=['all', 'private-reporting', 'dependency-graph', + 'dependabot-alerts', 'dependabot-updates', + 'secret-scanning', 'secret-protection'], + default='all', help='Features to manage (default: all)') + parser.add_argument('-v', '--verbose', action='store_true', + help='Enable verbose debug logging') + + args = parser.parse_args() + + # Set logging level based on verbose flag + if args.verbose: + logging.getLogger().setLevel(logging.DEBUG) + + # Create GitHub security manager instance + manager = GitHubSecurityManager(args.owner, args.repo, args.token) + + # Execute the requested action + try: + if args.action == 'check': + manager.check_settings() + elif args.action == 'enable': + console.print(f"\n[bold blue]Enabling Security Features for {args.owner}/{args.repo}[/bold blue]\n") + manager.enable_features(args.features) + elif args.action == 'disable': + console.print(f"\n[bold blue]Disabling Security Features for {args.owner}/{args.repo}[/bold blue]\n") + manager.disable_features(args.features) + + except KeyboardInterrupt: + console.print(f"\n[yellow]Operation cancelled by user[/yellow]") + sys.exit(1) + except Exception as e: + console.print(f"\n[red]Error: {e}[/red]") + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/static/data/slim-registry.json b/static/data/slim-registry.json index 2971f1762..e6c929c3d 100644 --- a/static/data/slim-registry.json +++ b/static/data/slim-registry.json @@ -306,6 +306,13 @@ "tools", "dependabot", "codeql" + ], + "assets": [ + { + "name": "GitHub Security Settings Script", + "type": "text/python", + "uri": "https://raw.githubusercontent.com/NASA-AMMOS/slim/main/static/assets/software-lifecycle/security/github-security/gh-security-settings.py" + } ] }, { @@ -377,4 +384,4 @@ "ci-cd" ] } -] \ No newline at end of file +] diff --git a/static/img/gh-security-screen.png b/static/img/gh-security-screen.png index 5be0cd929..e23bfd993 100644 Binary files a/static/img/gh-security-screen.png and b/static/img/gh-security-screen.png differ