chore: Sync MokoStandards workflows and configurations #85
758
.github/workflows/enterprise-firewall-setup.yml
vendored
Normal file
758
.github/workflows/enterprise-firewall-setup.yml
vendored
Normal file
@@ -0,0 +1,758 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
#
|
||||
# This file is part of a Moko Consulting project.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: GitHub.Workflow
|
||||
# INGROUP: MokoStandards.Firewall
|
||||
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
||||
# PATH: /templates/workflows/shared/enterprise-firewall-setup.yml
|
||||
# VERSION: 01.00.00
|
||||
# BRIEF: Enterprise firewall configuration — generates outbound allow-rules including SFTP deployment server
|
||||
# NOTE: Reads DEV_FTP_HOST / DEV_FTP_PORT variables to include SFTP egress rules alongside HTTPS rules.
|
||||
|
||||
name: Enterprise Firewall Configuration
|
||||
|
||||
# This workflow provides firewall configuration guidance for enterprise-ready sites
|
||||
# It generates firewall rules for allowing outbound access to trusted domains
|
||||
# including license providers, documentation sources, package registries,
|
||||
# and the SFTP deployment server (DEV_FTP_HOST / DEV_FTP_PORT).
|
||||
#
|
||||
# Runs automatically when:
|
||||
# - Coding agent workflows are triggered (pull requests with copilot/ prefix)
|
||||
# - Manual workflow dispatch for custom configurations
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
firewall_type:
|
||||
description: 'Target firewall type'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- 'iptables'
|
||||
- 'ufw'
|
||||
- 'firewalld'
|
||||
- 'aws-security-group'
|
||||
- 'azure-nsg'
|
||||
- 'gcp-firewall'
|
||||
- 'cloudflare'
|
||||
- 'all'
|
||||
default: 'all'
|
||||
output_format:
|
||||
description: 'Output format'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- 'shell-script'
|
||||
- 'json'
|
||||
- 'yaml'
|
||||
- 'markdown'
|
||||
- 'all'
|
||||
default: 'markdown'
|
||||
|
||||
# Auto-run when coding agent creates or updates PRs
|
||||
pull_request:
|
||||
branches:
|
||||
- 'copilot/**'
|
||||
- 'agent/**'
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
# Auto-run on push to coding agent branches
|
||||
push:
|
||||
branches:
|
||||
- 'copilot/**'
|
||||
- 'agent/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
|
||||
jobs:
|
||||
generate-firewall-rules:
|
||||
name: Generate Firewall Rules
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Apply Firewall Rules to Runner (Auto-run only)
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
env:
|
||||
DEV_FTP_HOST: ${{ vars.DEV_FTP_HOST }}
|
||||
DEV_FTP_PORT: ${{ vars.DEV_FTP_PORT }}
|
||||
run: |
|
||||
echo "🔥 Applying firewall rules for coding agent environment..."
|
||||
echo ""
|
||||
echo "This step ensures the GitHub Actions runner can access trusted domains"
|
||||
echo "including license providers, package registries, and documentation sources."
|
||||
echo ""
|
||||
|
||||
# Note: GitHub Actions runners are ephemeral and run in controlled environments
|
||||
# This step documents what domains are being accessed during the workflow
|
||||
# Actual firewall configuration is managed by GitHub
|
||||
|
||||
cat > /tmp/trusted-domains.txt << 'EOF'
|
||||
# Trusted domains for coding agent environment
|
||||
# License Providers
|
||||
www.gnu.org
|
||||
opensource.org
|
||||
choosealicense.com
|
||||
spdx.org
|
||||
creativecommons.org
|
||||
apache.org
|
||||
fsf.org
|
||||
|
||||
# Documentation & Standards
|
||||
semver.org
|
||||
keepachangelog.com
|
||||
conventionalcommits.org
|
||||
|
||||
# GitHub & Related
|
||||
github.com
|
||||
api.github.com
|
||||
docs.github.com
|
||||
raw.githubusercontent.com
|
||||
ghcr.io
|
||||
|
||||
# Package Registries
|
||||
npmjs.com
|
||||
registry.npmjs.org
|
||||
pypi.org
|
||||
files.pythonhosted.org
|
||||
packagist.org
|
||||
repo.packagist.org
|
||||
rubygems.org
|
||||
|
||||
# Platform-Specific
|
||||
joomla.org
|
||||
downloads.joomla.org
|
||||
docs.joomla.org
|
||||
php.net
|
||||
getcomposer.org
|
||||
dolibarr.org
|
||||
wiki.dolibarr.org
|
||||
docs.dolibarr.org
|
||||
|
||||
# Moko Consulting
|
||||
mokoconsulting.tech
|
||||
|
||||
# SFTP Deployment Server (DEV_FTP_HOST)
|
||||
${DEV_FTP_HOST:-<not configured>}
|
||||
|
||||
# Google Services
|
||||
drive.google.com
|
||||
docs.google.com
|
||||
sheets.google.com
|
||||
accounts.google.com
|
||||
storage.googleapis.com
|
||||
fonts.googleapis.com
|
||||
fonts.gstatic.com
|
||||
|
||||
# GitHub Extended
|
||||
upload.github.com
|
||||
objects.githubusercontent.com
|
||||
user-images.githubusercontent.com
|
||||
codeload.github.com
|
||||
pkg.github.com
|
||||
|
||||
# Developer Reference
|
||||
developer.mozilla.org
|
||||
stackoverflow.com
|
||||
git-scm.com
|
||||
|
||||
# CDN & Infrastructure
|
||||
cdn.jsdelivr.net
|
||||
unpkg.com
|
||||
cdnjs.cloudflare.com
|
||||
img.shields.io
|
||||
|
||||
# Container Registries
|
||||
hub.docker.com
|
||||
registry-1.docker.io
|
||||
|
||||
# CI & Code Quality
|
||||
codecov.io
|
||||
sonarcloud.io
|
||||
|
||||
# Terraform & Infrastructure
|
||||
registry.terraform.io
|
||||
releases.hashicorp.com
|
||||
checkpoint-api.hashicorp.com
|
||||
EOF
|
||||
|
||||
echo "✓ Trusted domains documented for this runner"
|
||||
echo "✓ GitHub Actions runners have network access to these domains"
|
||||
echo ""
|
||||
|
||||
# Test connectivity to key domains
|
||||
echo "Testing connectivity to key domains..."
|
||||
for domain in "github.com" "www.gnu.org" "npmjs.com" "pypi.org"; do
|
||||
if curl -s --max-time 3 -o /dev/null -w "%{http_code}" "https://$domain" | grep -q "200\|301\|302"; then
|
||||
echo " ✓ $domain is accessible"
|
||||
else
|
||||
echo " ⚠️ $domain connectivity check failed (may be expected)"
|
||||
fi
|
||||
done
|
||||
|
||||
# Test SFTP server connectivity (TCP port check)
|
||||
SFTP_HOST="${DEV_FTP_HOST:-}"
|
||||
SFTP_PORT="${DEV_FTP_PORT:-22}"
|
||||
if [ -n "$SFTP_HOST" ]; then
|
||||
# Strip any embedded :port suffix
|
||||
SFTP_HOST="${SFTP_HOST%%:*}"
|
||||
echo ""
|
||||
echo "Testing SFTP deployment server connectivity..."
|
||||
if timeout 5 bash -c "echo >/dev/tcp/${SFTP_HOST}/${SFTP_PORT}" 2>/dev/null; then
|
||||
echo " ✓ SFTP server ${SFTP_HOST}:${SFTP_PORT} is reachable"
|
||||
else
|
||||
echo " ⚠️ SFTP server ${SFTP_HOST}:${SFTP_PORT} is not reachable from runner (firewall rule needed)"
|
||||
fi
|
||||
else
|
||||
echo ""
|
||||
echo " ℹ️ DEV_FTP_HOST not configured — skipping SFTP connectivity check"
|
||||
fi
|
||||
|
||||
- name: Generate Firewall Configuration
|
||||
id: generate
|
||||
env:
|
||||
DEV_FTP_HOST: ${{ vars.DEV_FTP_HOST }}
|
||||
DEV_FTP_PORT: ${{ vars.DEV_FTP_PORT }}
|
||||
run: |
|
||||
cat > generate_firewall_config.py << 'PYTHON_EOF'
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Enterprise Firewall Configuration Generator
|
||||
|
||||
Generates firewall rules for enterprise-ready deployments allowing
|
||||
access to trusted domains including license providers, documentation
|
||||
sources, package registries, and platform-specific sites.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import yaml
|
||||
import sys
|
||||
from typing import List, Dict
|
||||
|
||||
# SFTP deployment server from org variables
|
||||
_sftp_host_raw = os.environ.get("DEV_FTP_HOST", "").strip()
|
||||
_sftp_port = os.environ.get("DEV_FTP_PORT", "").strip() or "22"
|
||||
# Strip embedded :port suffix if present
|
||||
_sftp_host = _sftp_host_raw.split(":")[0] if _sftp_host_raw else ""
|
||||
if ":" in _sftp_host_raw and not _sftp_port:
|
||||
_sftp_port = _sftp_host_raw.split(":")[1]
|
||||
|
||||
SFTP_HOST = _sftp_host
|
||||
SFTP_PORT = int(_sftp_port) if _sftp_port.isdigit() else 22
|
||||
|
||||
# Trusted domains from .github/copilot.yml
|
||||
TRUSTED_DOMAINS = {
|
||||
"license_providers": [
|
||||
"www.gnu.org",
|
||||
"opensource.org",
|
||||
"choosealicense.com",
|
||||
"spdx.org",
|
||||
"creativecommons.org",
|
||||
"apache.org",
|
||||
"fsf.org",
|
||||
],
|
||||
"documentation_standards": [
|
||||
"semver.org",
|
||||
"keepachangelog.com",
|
||||
"conventionalcommits.org",
|
||||
],
|
||||
"github_related": [
|
||||
"github.com",
|
||||
"api.github.com",
|
||||
"docs.github.com",
|
||||
"raw.githubusercontent.com",
|
||||
"ghcr.io",
|
||||
],
|
||||
"package_registries": [
|
||||
"npmjs.com",
|
||||
"registry.npmjs.org",
|
||||
"pypi.org",
|
||||
"files.pythonhosted.org",
|
||||
"packagist.org",
|
||||
"repo.packagist.org",
|
||||
"rubygems.org",
|
||||
],
|
||||
"standards_organizations": [
|
||||
"json-schema.org",
|
||||
"w3.org",
|
||||
"ietf.org",
|
||||
],
|
||||
"platform_specific": [
|
||||
"joomla.org",
|
||||
"downloads.joomla.org",
|
||||
"docs.joomla.org",
|
||||
"php.net",
|
||||
"getcomposer.org",
|
||||
"dolibarr.org",
|
||||
"wiki.dolibarr.org",
|
||||
"docs.dolibarr.org",
|
||||
],
|
||||
"moko_consulting": [
|
||||
"mokoconsulting.tech",
|
||||
],
|
||||
"google_services": [
|
||||
"drive.google.com",
|
||||
"docs.google.com",
|
||||
"sheets.google.com",
|
||||
"accounts.google.com",
|
||||
"storage.googleapis.com",
|
||||
"fonts.googleapis.com",
|
||||
"fonts.gstatic.com",
|
||||
],
|
||||
"github_extended": [
|
||||
"upload.github.com",
|
||||
"objects.githubusercontent.com",
|
||||
"user-images.githubusercontent.com",
|
||||
"codeload.github.com",
|
||||
"pkg.github.com",
|
||||
],
|
||||
"developer_reference": [
|
||||
"developer.mozilla.org",
|
||||
"stackoverflow.com",
|
||||
"git-scm.com",
|
||||
],
|
||||
"cdn_and_infrastructure": [
|
||||
"cdn.jsdelivr.net",
|
||||
"unpkg.com",
|
||||
"cdnjs.cloudflare.com",
|
||||
"img.shields.io",
|
||||
],
|
||||
"container_registries": [
|
||||
"hub.docker.com",
|
||||
"registry-1.docker.io",
|
||||
],
|
||||
"ci_code_quality": [
|
||||
"codecov.io",
|
||||
"sonarcloud.io",
|
||||
],
|
||||
"terraform_infrastructure": [
|
||||
"registry.terraform.io",
|
||||
"releases.hashicorp.com",
|
||||
"checkpoint-api.hashicorp.com",
|
||||
],
|
||||
}
|
||||
|
||||
# Inject SFTP deployment server as a separate category (port 22, not 443)
|
||||
if SFTP_HOST:
|
||||
TRUSTED_DOMAINS["sftp_deployment_server"] = [SFTP_HOST]
|
||||
print(f"ℹ️ SFTP deployment server: {SFTP_HOST}:{SFTP_PORT}")
|
||||
|
||||
def generate_sftp_iptables_rules(host: str, port: int) -> str:
|
||||
"""Generate iptables rules specifically for SFTP egress"""
|
||||
return (
|
||||
f"# Allow SFTP to deployment server {host}:{port}\n"
|
||||
f"iptables -A OUTPUT -p tcp -d $(dig +short {host} | head -1)"
|
||||
f" --dport {port} -j ACCEPT # SFTP deploy\n"
|
||||
)
|
||||
|
||||
def generate_sftp_ufw_rules(host: str, port: int) -> str:
|
||||
"""Generate UFW rules for SFTP egress"""
|
||||
return (
|
||||
f"# Allow SFTP to deployment server\n"
|
||||
f"ufw allow out to $(dig +short {host} | head -1)"
|
||||
f" port {port} proto tcp comment 'SFTP deploy to {host}'\n"
|
||||
)
|
||||
|
||||
def generate_sftp_firewalld_rules(host: str, port: int) -> str:
|
||||
"""Generate firewalld rules for SFTP egress"""
|
||||
return (
|
||||
f"# Allow SFTP to deployment server\n"
|
||||
f"firewall-cmd --permanent --add-rich-rule='"
|
||||
f"rule family=ipv4 destination address=$(dig +short {host} | head -1)"
|
||||
f" port port={port} protocol=tcp accept' # SFTP deploy\n"
|
||||
)
|
||||
|
||||
def generate_iptables_rules(domains: List[str]) -> str:
|
||||
"""Generate iptables firewall rules"""
|
||||
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - iptables", ""]
|
||||
rules.append("# Allow outbound HTTPS to trusted domains")
|
||||
rules.append("")
|
||||
|
||||
for domain in domains:
|
||||
rules.append(f"# Allow {domain}")
|
||||
rules.append(f"iptables -A OUTPUT -p tcp -d $(dig +short {domain} | head -1) --dport 443 -j ACCEPT")
|
||||
|
||||
rules.append("")
|
||||
rules.append("# Allow DNS lookups")
|
||||
rules.append("iptables -A OUTPUT -p udp --dport 53 -j ACCEPT")
|
||||
rules.append("iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT")
|
||||
|
||||
return "\n".join(rules)
|
||||
|
||||
def generate_ufw_rules(domains: List[str]) -> str:
|
||||
"""Generate UFW firewall rules"""
|
||||
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - UFW", ""]
|
||||
rules.append("# Allow outbound HTTPS to trusted domains")
|
||||
rules.append("")
|
||||
|
||||
for domain in domains:
|
||||
rules.append(f"# Allow {domain}")
|
||||
rules.append(f"ufw allow out to $(dig +short {domain} | head -1) port 443 proto tcp comment 'Allow {domain}'")
|
||||
|
||||
rules.append("")
|
||||
rules.append("# Allow DNS")
|
||||
rules.append("ufw allow out 53/udp comment 'Allow DNS UDP'")
|
||||
rules.append("ufw allow out 53/tcp comment 'Allow DNS TCP'")
|
||||
|
||||
return "\n".join(rules)
|
||||
|
||||
def generate_firewalld_rules(domains: List[str]) -> str:
|
||||
"""Generate firewalld rules"""
|
||||
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - firewalld", ""]
|
||||
rules.append("# Add trusted domains to firewall")
|
||||
rules.append("")
|
||||
|
||||
for domain in domains:
|
||||
rules.append(f"# Allow {domain}")
|
||||
rules.append(f"firewall-cmd --permanent --add-rich-rule='rule family=ipv4 destination address=$(dig +short {domain} | head -1) port port=443 protocol=tcp accept'")
|
||||
|
||||
rules.append("")
|
||||
rules.append("# Reload firewall")
|
||||
rules.append("firewall-cmd --reload")
|
||||
|
||||
return "\n".join(rules)
|
||||
|
||||
def generate_aws_security_group(domains: List[str]) -> Dict:
|
||||
"""Generate AWS Security Group rules (JSON format)"""
|
||||
rules = {
|
||||
"SecurityGroupRules": {
|
||||
"Egress": []
|
||||
}
|
||||
}
|
||||
|
||||
for domain in domains:
|
||||
rules["SecurityGroupRules"]["Egress"].append({
|
||||
"Description": f"Allow HTTPS to {domain}",
|
||||
"IpProtocol": "tcp",
|
||||
"FromPort": 443,
|
||||
"ToPort": 443,
|
||||
"CidrIp": "0.0.0.0/0", # In practice, resolve to specific IPs
|
||||
"Tags": [{
|
||||
"Key": "Domain",
|
||||
"Value": domain
|
||||
}]
|
||||
})
|
||||
|
||||
# Add DNS
|
||||
rules["SecurityGroupRules"]["Egress"].append({
|
||||
"Description": "Allow DNS",
|
||||
"IpProtocol": "udp",
|
||||
"FromPort": 53,
|
||||
"ToPort": 53,
|
||||
"CidrIp": "0.0.0.0/0"
|
||||
})
|
||||
|
||||
return rules
|
||||
|
||||
def generate_markdown_documentation(domains_by_category: Dict[str, List[str]]) -> str:
|
||||
"""Generate markdown documentation"""
|
||||
md = ["# Enterprise Firewall Configuration Guide", ""]
|
||||
md.append("## Overview")
|
||||
md.append("")
|
||||
md.append("This document provides firewall configuration guidance for enterprise-ready deployments.")
|
||||
md.append("It lists trusted domains that should be whitelisted for outbound access to ensure")
|
||||
md.append("proper functionality of license validation, package management, and documentation access.")
|
||||
md.append("")
|
||||
|
||||
md.append("## Trusted Domains by Category")
|
||||
md.append("")
|
||||
|
||||
all_domains = []
|
||||
for category, domains in domains_by_category.items():
|
||||
category_name = category.replace("_", " ").title()
|
||||
md.append(f"### {category_name}")
|
||||
md.append("")
|
||||
md.append("| Domain | Purpose |")
|
||||
md.append("|--------|---------|")
|
||||
|
||||
for domain in domains:
|
||||
all_domains.append(domain)
|
||||
purpose = get_domain_purpose(domain)
|
||||
md.append(f"| `{domain}` | {purpose} |")
|
||||
|
||||
md.append("")
|
||||
|
||||
md.append("## Implementation Examples")
|
||||
md.append("")
|
||||
|
||||
md.append("### iptables Example")
|
||||
md.append("")
|
||||
md.append("```bash")
|
||||
md.append("# Allow HTTPS to trusted domain")
|
||||
md.append(f"iptables -A OUTPUT -p tcp -d $(dig +short {all_domains[0]}) --dport 443 -j ACCEPT")
|
||||
md.append("```")
|
||||
md.append("")
|
||||
|
||||
md.append("### UFW Example")
|
||||
md.append("")
|
||||
md.append("```bash")
|
||||
md.append("# Allow HTTPS to trusted domain")
|
||||
md.append(f"ufw allow out to {all_domains[0]} port 443 proto tcp")
|
||||
md.append("```")
|
||||
md.append("")
|
||||
|
||||
md.append("### AWS Security Group Example")
|
||||
md.append("")
|
||||
md.append("```json")
|
||||
md.append("{")
|
||||
md.append(' "IpPermissions": [{')
|
||||
md.append(' "IpProtocol": "tcp",')
|
||||
md.append(' "FromPort": 443,')
|
||||
md.append(' "ToPort": 443,')
|
||||
md.append(' "IpRanges": [{"CidrIp": "0.0.0.0/0", "Description": "HTTPS to trusted domains"}]')
|
||||
md.append(" }]")
|
||||
md.append("}")
|
||||
md.append("```")
|
||||
md.append("")
|
||||
|
||||
md.append("## Ports Required")
|
||||
md.append("")
|
||||
md.append("| Port | Protocol | Purpose |")
|
||||
md.append("|------|----------|---------|")
|
||||
md.append("| 443 | TCP | HTTPS (secure web access) |")
|
||||
md.append("| 80 | TCP | HTTP (redirects to HTTPS) |")
|
||||
md.append("| 53 | UDP/TCP | DNS resolution |")
|
||||
md.append("")
|
||||
|
||||
md.append("## Security Considerations")
|
||||
md.append("")
|
||||
md.append("1. **DNS Resolution**: Ensure DNS queries are allowed (port 53 UDP/TCP)")
|
||||
md.append("2. **Certificate Validation**: HTTPS requires ability to reach certificate authorities")
|
||||
md.append("3. **Dynamic IPs**: Some domains use CDNs with dynamic IPs - consider using FQDNs in rules")
|
||||
md.append("4. **Regular Updates**: Review and update whitelist as services change")
|
||||
md.append("5. **Logging**: Enable logging for blocked connections to identify missing rules")
|
||||
md.append("")
|
||||
|
||||
md.append("## Compliance Notes")
|
||||
md.append("")
|
||||
md.append("- All listed domains provide read-only access to public information")
|
||||
md.append("- License providers enable GPL compliance verification")
|
||||
md.append("- Package registries support dependency security scanning")
|
||||
md.append("- No authentication credentials are transmitted to these domains")
|
||||
md.append("")
|
||||
|
||||
return "\n".join(md)
|
||||
|
||||
def get_domain_purpose(domain: str) -> str:
|
||||
"""Get human-readable purpose for a domain"""
|
||||
purposes = {
|
||||
"www.gnu.org": "GNU licenses and documentation",
|
||||
"opensource.org": "Open Source Initiative resources",
|
||||
"choosealicense.com": "GitHub license selection tool",
|
||||
"spdx.org": "Software Package Data Exchange identifiers",
|
||||
"creativecommons.org": "Creative Commons licenses",
|
||||
"apache.org": "Apache Software Foundation licenses",
|
||||
"fsf.org": "Free Software Foundation resources",
|
||||
"semver.org": "Semantic versioning specification",
|
||||
"keepachangelog.com": "Changelog format standards",
|
||||
"conventionalcommits.org": "Commit message conventions",
|
||||
"github.com": "GitHub platform access",
|
||||
"api.github.com": "GitHub API access",
|
||||
"docs.github.com": "GitHub documentation",
|
||||
"raw.githubusercontent.com": "GitHub raw content access",
|
||||
"npmjs.com": "npm package registry",
|
||||
"pypi.org": "Python Package Index",
|
||||
"packagist.org": "PHP Composer package registry",
|
||||
"rubygems.org": "Ruby gems registry",
|
||||
"joomla.org": "Joomla CMS platform",
|
||||
"php.net": "PHP documentation and downloads",
|
||||
"dolibarr.org": "Dolibarr ERP/CRM platform",
|
||||
}
|
||||
return purposes.get(domain, "Trusted resource")
|
||||
|
||||
def main():
|
||||
# Use inputs if provided (manual dispatch), otherwise use defaults (auto-run)
|
||||
firewall_type = "${{ github.event.inputs.firewall_type }}" or "all"
|
||||
output_format = "${{ github.event.inputs.output_format }}" or "markdown"
|
||||
|
||||
print(f"Running in {'manual' if '${{ github.event.inputs.firewall_type }}' else 'automatic'} mode")
|
||||
print(f"Firewall type: {firewall_type}")
|
||||
print(f"Output format: {output_format}")
|
||||
print("")
|
||||
|
||||
# Collect all domains
|
||||
all_domains = []
|
||||
for domains in TRUSTED_DOMAINS.values():
|
||||
all_domains.extend(domains)
|
||||
|
||||
# Remove duplicates and sort
|
||||
all_domains = sorted(set(all_domains))
|
||||
|
||||
print(f"Generating firewall rules for {len(all_domains)} trusted domains...")
|
||||
print("")
|
||||
|
||||
# Exclude SFTP server from HTTPS rule generation (different port)
|
||||
https_domains = [d for d in all_domains if d != SFTP_HOST]
|
||||
|
||||
# Generate based on firewall type
|
||||
if firewall_type in ["iptables", "all"]:
|
||||
rules = generate_iptables_rules(https_domains)
|
||||
if SFTP_HOST:
|
||||
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
|
||||
rules += generate_sftp_iptables_rules(SFTP_HOST, SFTP_PORT)
|
||||
with open("firewall-rules-iptables.sh", "w") as f:
|
||||
f.write(rules)
|
||||
print("✓ Generated iptables rules: firewall-rules-iptables.sh")
|
||||
|
||||
if firewall_type in ["ufw", "all"]:
|
||||
rules = generate_ufw_rules(https_domains)
|
||||
if SFTP_HOST:
|
||||
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
|
||||
rules += generate_sftp_ufw_rules(SFTP_HOST, SFTP_PORT)
|
||||
with open("firewall-rules-ufw.sh", "w") as f:
|
||||
f.write(rules)
|
||||
print("✓ Generated UFW rules: firewall-rules-ufw.sh")
|
||||
|
||||
if firewall_type in ["firewalld", "all"]:
|
||||
rules = generate_firewalld_rules(https_domains)
|
||||
if SFTP_HOST:
|
||||
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
|
||||
rules += generate_sftp_firewalld_rules(SFTP_HOST, SFTP_PORT)
|
||||
with open("firewall-rules-firewalld.sh", "w") as f:
|
||||
f.write(rules)
|
||||
print("✓ Generated firewalld rules: firewall-rules-firewalld.sh")
|
||||
|
||||
if firewall_type in ["aws-security-group", "all"]:
|
||||
rules = generate_aws_security_group(all_domains)
|
||||
with open("firewall-rules-aws-sg.json", "w") as f:
|
||||
json.dump(rules, f, indent=2)
|
||||
print("✓ Generated AWS Security Group rules: firewall-rules-aws-sg.json")
|
||||
|
||||
if output_format in ["yaml", "all"]:
|
||||
with open("trusted-domains.yml", "w") as f:
|
||||
yaml.dump(TRUSTED_DOMAINS, f, default_flow_style=False)
|
||||
print("✓ Generated YAML domain list: trusted-domains.yml")
|
||||
|
||||
if output_format in ["json", "all"]:
|
||||
with open("trusted-domains.json", "w") as f:
|
||||
json.dump(TRUSTED_DOMAINS, f, indent=2)
|
||||
print("✓ Generated JSON domain list: trusted-domains.json")
|
||||
|
||||
if output_format in ["markdown", "all"]:
|
||||
md = generate_markdown_documentation(TRUSTED_DOMAINS)
|
||||
with open("FIREWALL_CONFIGURATION.md", "w") as f:
|
||||
f.write(md)
|
||||
print("✓ Generated documentation: FIREWALL_CONFIGURATION.md")
|
||||
|
||||
print("")
|
||||
print("Domain Categories:")
|
||||
for category, domains in TRUSTED_DOMAINS.items():
|
||||
print(f" - {category}: {len(domains)} domains")
|
||||
|
||||
print("")
|
||||
print("Total unique domains: ", len(all_domains))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
PYTHON_EOF
|
||||
|
||||
chmod +x generate_firewall_config.py
|
||||
pip install PyYAML
|
||||
python3 generate_firewall_config.py
|
||||
|
||||
- name: Upload Firewall Configuration Artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: firewall-configurations
|
||||
path: |
|
||||
firewall-rules-*.sh
|
||||
firewall-rules-*.json
|
||||
trusted-domains.*
|
||||
FIREWALL_CONFIGURATION.md
|
||||
retention-days: 90
|
||||
|
||||
- name: Display Summary
|
||||
run: |
|
||||
echo "## Firewall Configuration" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "**Mode**: Manual Execution" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Firewall rules have been generated for enterprise-ready deployments." >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "**Mode**: Automatic Execution (Coding Agent Active)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "This workflow ran automatically because a coding agent (GitHub Copilot) is active." >> $GITHUB_STEP_SUMMARY
|
||||
echo "Firewall configuration has been validated for the coding agent environment." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Files Generated" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
if ls firewall-rules-* trusted-domains.* FIREWALL_CONFIGURATION.md 2>/dev/null; then
|
||||
ls -lh firewall-rules-* trusted-domains.* FIREWALL_CONFIGURATION.md 2>/dev/null | awk '{print "- " $9 " (" $5 ")"}' >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "- Documentation generated" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "### Download Artifacts" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Download the generated firewall configurations from the workflow artifacts." >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "### Trusted Domains Active" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "The coding agent has access to:" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- License providers (GPL, OSI, SPDX, Apache, etc.)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Package registries (npm, PyPI, Packagist, RubyGems)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Documentation sources (GitHub, Joomla, Dolibarr, PHP)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Standards organizations (W3C, IETF, JSON Schema)" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# Usage Instructions:
|
||||
#
|
||||
# This workflow runs in two modes:
|
||||
#
|
||||
# 1. AUTOMATIC MODE (Coding Agent):
|
||||
# - Triggers when coding agent branches (copilot/**, agent/**) are pushed or PR'd
|
||||
# - Validates firewall configuration for the coding agent environment
|
||||
# - Documents accessible domains for compliance
|
||||
# - Ensures license sources and package registries are available
|
||||
#
|
||||
# 2. MANUAL MODE (Enterprise Configuration):
|
||||
# - Manually trigger from the Actions tab
|
||||
# - Select desired firewall type and output format
|
||||
# - Download generated artifacts
|
||||
# - Apply firewall rules to your enterprise environment
|
||||
#
|
||||
# Configuration:
|
||||
# - Trusted domains are sourced from .github/copilot.yml
|
||||
# - Modify copilot.yml to add/remove trusted domains
|
||||
# - Changes automatically propagate to firewall rules
|
||||
#
|
||||
# Important Notes:
|
||||
# - Review generated rules before applying to production
|
||||
# - Some domains may use CDNs with dynamic IPs
|
||||
# - Consider using FQDN-based rules where supported
|
||||
# - Test thoroughly in staging environment first
|
||||
# - Monitor logs for blocked connections
|
||||
# - Update rules as domains/services change
|
||||
Reference in New Issue
Block a user