@mokoconsulting/mcp-mokogitea-api 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +94 -0
- package/.gitmessage +9 -0
- package/.mokogitea/ISSUE_TEMPLATE/adr.md +110 -0
- package/.mokogitea/ISSUE_TEMPLATE/bug_report.md +48 -0
- package/.mokogitea/ISSUE_TEMPLATE/config.yml +18 -0
- package/.mokogitea/ISSUE_TEMPLATE/documentation.md +52 -0
- package/.mokogitea/ISSUE_TEMPLATE/enterprise_support.md +85 -0
- package/.mokogitea/ISSUE_TEMPLATE/feature_request.md +51 -0
- package/.mokogitea/ISSUE_TEMPLATE/firewall-request.md +190 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_api_integration.md +48 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_connection_issue.md +67 -0
- package/.mokogitea/ISSUE_TEMPLATE/mcp_tool_request.md +49 -0
- package/.mokogitea/ISSUE_TEMPLATE/question.md +82 -0
- package/.mokogitea/ISSUE_TEMPLATE/rfc.md +126 -0
- package/.mokogitea/ISSUE_TEMPLATE/security.md +51 -0
- package/.mokogitea/ISSUE_TEMPLATE/version.md +24 -0
- package/.mokogitea/auto-assign.yml +76 -0
- package/.mokogitea/auto-dev-issue.yml +207 -0
- package/.mokogitea/auto-release.yml +337 -0
- package/.mokogitea/branch-protection.yml +251 -0
- package/.mokogitea/changelog-validation.yml +101 -0
- package/.mokogitea/codeql-analysis.yml +115 -0
- package/.mokogitea/copilot-agent.yml +44 -0
- package/.mokogitea/deploy-demo.yml +734 -0
- package/.mokogitea/deploy-dev.yml +700 -0
- package/.mokogitea/enterprise-firewall-setup.yml +758 -0
- package/.mokogitea/manifest.xml +25 -0
- package/.mokogitea/mcp-auto-release.yml +278 -0
- package/.mokogitea/mcp-build-test.yml +65 -0
- package/.mokogitea/mcp-sdk-check.yml +109 -0
- package/.mokogitea/mcp-tool-inventory.yml +61 -0
- package/.mokogitea/pr-branch-check.yml +90 -0
- package/.mokogitea/repository-cleanup.yml +525 -0
- package/.mokogitea/standards-compliance.yml +2614 -0
- package/.mokogitea/sync-version-on-merge.yml +133 -0
- package/.mokogitea/workflows/auto-assign.yml +76 -0
- package/.mokogitea/workflows/auto-bump.yml +66 -0
- package/.mokogitea/workflows/auto-dev-issue.yml +207 -0
- package/.mokogitea/workflows/auto-release.yml +341 -0
- package/.mokogitea/workflows/branch-cleanup.yml +48 -0
- package/.mokogitea/workflows/cascade-dev.yml +10 -0
- package/.mokogitea/workflows/changelog-validation.yml +101 -0
- package/.mokogitea/workflows/ci-generic.yml +204 -0
- package/.mokogitea/workflows/cleanup.yml +87 -0
- package/.mokogitea/workflows/codeql-analysis.yml +115 -0
- package/.mokogitea/workflows/copilot-agent.yml +44 -0
- package/.mokogitea/workflows/deploy-manual.yml +126 -0
- package/.mokogitea/workflows/enterprise-firewall-setup.yml +758 -0
- package/.mokogitea/workflows/gitleaks.yml +96 -0
- package/.mokogitea/workflows/issue-branch.yml +73 -0
- package/.mokogitea/workflows/mcp-auto-release.yml +280 -0
- package/.mokogitea/workflows/mcp-build-test.yml +65 -0
- package/.mokogitea/workflows/mcp-sdk-check.yml +109 -0
- package/.mokogitea/workflows/mcp-tool-inventory.yml +61 -0
- package/.mokogitea/workflows/notify.yml +70 -0
- package/.mokogitea/workflows/npm-publish.yml +51 -0
- package/.mokogitea/workflows/pr-check.yml +508 -0
- package/.mokogitea/workflows/pre-release.yml +11 -0
- package/.mokogitea/workflows/repo-health.yml +711 -0
- package/.mokogitea/workflows/repository-cleanup.yml +525 -0
- package/.mokogitea/workflows/security-audit.yml +82 -0
- package/.mokogitea/workflows/standards-compliance.yml +2614 -0
- package/.mokogitea/workflows/sync-version-on-merge.yml +130 -0
- package/.mokogitea/workflows/update-server.yml +312 -0
- package/CHANGELOG.md +145 -0
- package/CLAUDE.md +43 -0
- package/CONTRIBUTING.md +161 -0
- package/README.md +286 -0
- package/SECURITY.md +91 -0
- package/automation/ci-issue-reporter.sh +237 -0
- package/config.example.json +13 -0
- package/dist/client.d.ts +15 -0
- package/dist/client.js +104 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.js +48 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1119 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.js +16 -0
- package/package.json +34 -0
- package/scripts/setup.mjs +40 -0
- package/src/client.ts +120 -0
- package/src/config.ts +58 -0
- package/src/index.ts +1712 -0
- package/src/types.ts +37 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,758 @@
|
|
|
1
|
+
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
2
|
+
#
|
|
3
|
+
# This file is part of a Moko Consulting project.
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
6
|
+
#
|
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
19
|
+
|
|
20
|
+
# FILE INFORMATION
|
|
21
|
+
# DEFGROUP: GitHub.Workflow
|
|
22
|
+
# INGROUP: MokoStandards.Firewall
|
|
23
|
+
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
|
|
24
|
+
# PATH: /templates/workflows/shared/enterprise-firewall-setup.yml.template
|
|
25
|
+
# VERSION: 04.06.00
|
|
26
|
+
# BRIEF: Enterprise firewall configuration — generates outbound allow-rules including SFTP deployment server
|
|
27
|
+
# NOTE: Reads DEV_FTP_HOST / DEV_FTP_PORT variables to include SFTP egress rules alongside HTTPS rules.
|
|
28
|
+
|
|
29
|
+
name: Enterprise Firewall Configuration
|
|
30
|
+
|
|
31
|
+
# This workflow provides firewall configuration guidance for enterprise-ready sites
|
|
32
|
+
# It generates firewall rules for allowing outbound access to trusted domains
|
|
33
|
+
# including license providers, documentation sources, package registries,
|
|
34
|
+
# and the SFTP deployment server (DEV_FTP_HOST / DEV_FTP_PORT).
|
|
35
|
+
#
|
|
36
|
+
# Runs automatically when:
|
|
37
|
+
# - Coding agent workflows are triggered (pull requests with copilot/ prefix)
|
|
38
|
+
# - Manual workflow dispatch for custom configurations
|
|
39
|
+
|
|
40
|
+
on:
|
|
41
|
+
workflow_dispatch:
|
|
42
|
+
inputs:
|
|
43
|
+
firewall_type:
|
|
44
|
+
description: 'Target firewall type'
|
|
45
|
+
required: true
|
|
46
|
+
type: choice
|
|
47
|
+
options:
|
|
48
|
+
- 'iptables'
|
|
49
|
+
- 'ufw'
|
|
50
|
+
- 'firewalld'
|
|
51
|
+
- 'aws-security-group'
|
|
52
|
+
- 'azure-nsg'
|
|
53
|
+
- 'gcp-firewall'
|
|
54
|
+
- 'cloudflare'
|
|
55
|
+
- 'all'
|
|
56
|
+
default: 'all'
|
|
57
|
+
output_format:
|
|
58
|
+
description: 'Output format'
|
|
59
|
+
required: true
|
|
60
|
+
type: choice
|
|
61
|
+
options:
|
|
62
|
+
- 'shell-script'
|
|
63
|
+
- 'json'
|
|
64
|
+
- 'yaml'
|
|
65
|
+
- 'markdown'
|
|
66
|
+
- 'all'
|
|
67
|
+
default: 'markdown'
|
|
68
|
+
|
|
69
|
+
# Auto-run when coding agent creates or updates PRs
|
|
70
|
+
pull_request:
|
|
71
|
+
branches:
|
|
72
|
+
- 'copilot/**'
|
|
73
|
+
- 'agent/**'
|
|
74
|
+
types: [opened, synchronize, reopened]
|
|
75
|
+
|
|
76
|
+
# Auto-run on push to coding agent branches
|
|
77
|
+
push:
|
|
78
|
+
branches:
|
|
79
|
+
- 'copilot/**'
|
|
80
|
+
- 'agent/**'
|
|
81
|
+
|
|
82
|
+
permissions:
|
|
83
|
+
contents: read
|
|
84
|
+
actions: read
|
|
85
|
+
|
|
86
|
+
jobs:
|
|
87
|
+
generate-firewall-rules:
|
|
88
|
+
name: Generate Firewall Rules
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
|
|
91
|
+
steps:
|
|
92
|
+
- name: Checkout repository
|
|
93
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
94
|
+
|
|
95
|
+
- name: Set up Python
|
|
96
|
+
uses: actions/setup-python@v6
|
|
97
|
+
with:
|
|
98
|
+
python-version: '3.11'
|
|
99
|
+
|
|
100
|
+
- name: Apply Firewall Rules to Runner (Auto-run only)
|
|
101
|
+
if: github.event_name != 'workflow_dispatch'
|
|
102
|
+
env:
|
|
103
|
+
DEV_FTP_HOST: ${{ vars.DEV_FTP_HOST }}
|
|
104
|
+
DEV_FTP_PORT: ${{ vars.DEV_FTP_PORT }}
|
|
105
|
+
run: |
|
|
106
|
+
echo "🔥 Applying firewall rules for coding agent environment..."
|
|
107
|
+
echo ""
|
|
108
|
+
echo "This step ensures the GitHub Actions runner can access trusted domains"
|
|
109
|
+
echo "including license providers, package registries, and documentation sources."
|
|
110
|
+
echo ""
|
|
111
|
+
|
|
112
|
+
# Note: GitHub Actions runners are ephemeral and run in controlled environments
|
|
113
|
+
# This step documents what domains are being accessed during the workflow
|
|
114
|
+
# Actual firewall configuration is managed by GitHub
|
|
115
|
+
|
|
116
|
+
cat > /tmp/trusted-domains.txt << 'EOF'
|
|
117
|
+
# Trusted domains for coding agent environment
|
|
118
|
+
# License Providers
|
|
119
|
+
www.gnu.org
|
|
120
|
+
opensource.org
|
|
121
|
+
choosealicense.com
|
|
122
|
+
spdx.org
|
|
123
|
+
creativecommons.org
|
|
124
|
+
apache.org
|
|
125
|
+
fsf.org
|
|
126
|
+
|
|
127
|
+
# Documentation & Standards
|
|
128
|
+
semver.org
|
|
129
|
+
keepachangelog.com
|
|
130
|
+
conventionalcommits.org
|
|
131
|
+
|
|
132
|
+
# GitHub & Related
|
|
133
|
+
github.com
|
|
134
|
+
api.github.com
|
|
135
|
+
docs.github.com
|
|
136
|
+
raw.githubusercontent.com
|
|
137
|
+
ghcr.io
|
|
138
|
+
|
|
139
|
+
# Package Registries
|
|
140
|
+
npmjs.com
|
|
141
|
+
registry.npmjs.org
|
|
142
|
+
pypi.org
|
|
143
|
+
files.pythonhosted.org
|
|
144
|
+
packagist.org
|
|
145
|
+
repo.packagist.org
|
|
146
|
+
rubygems.org
|
|
147
|
+
|
|
148
|
+
# Platform-Specific
|
|
149
|
+
joomla.org
|
|
150
|
+
downloads.joomla.org
|
|
151
|
+
docs.joomla.org
|
|
152
|
+
php.net
|
|
153
|
+
getcomposer.org
|
|
154
|
+
dolibarr.org
|
|
155
|
+
wiki.dolibarr.org
|
|
156
|
+
docs.dolibarr.org
|
|
157
|
+
|
|
158
|
+
# Moko Consulting
|
|
159
|
+
mokoconsulting.tech
|
|
160
|
+
|
|
161
|
+
# SFTP Deployment Server (DEV_FTP_HOST)
|
|
162
|
+
${DEV_FTP_HOST:-<not configured>}
|
|
163
|
+
|
|
164
|
+
# Google Services
|
|
165
|
+
drive.google.com
|
|
166
|
+
docs.google.com
|
|
167
|
+
sheets.google.com
|
|
168
|
+
accounts.google.com
|
|
169
|
+
storage.googleapis.com
|
|
170
|
+
fonts.googleapis.com
|
|
171
|
+
fonts.gstatic.com
|
|
172
|
+
|
|
173
|
+
# GitHub Extended
|
|
174
|
+
upload.github.com
|
|
175
|
+
objects.githubusercontent.com
|
|
176
|
+
user-images.githubusercontent.com
|
|
177
|
+
codeload.github.com
|
|
178
|
+
pkg.github.com
|
|
179
|
+
|
|
180
|
+
# Developer Reference
|
|
181
|
+
developer.mozilla.org
|
|
182
|
+
stackoverflow.com
|
|
183
|
+
git-scm.com
|
|
184
|
+
|
|
185
|
+
# CDN & Infrastructure
|
|
186
|
+
cdn.jsdelivr.net
|
|
187
|
+
unpkg.com
|
|
188
|
+
cdnjs.cloudflare.com
|
|
189
|
+
img.shields.io
|
|
190
|
+
|
|
191
|
+
# Container Registries
|
|
192
|
+
hub.docker.com
|
|
193
|
+
registry-1.docker.io
|
|
194
|
+
|
|
195
|
+
# CI & Code Quality
|
|
196
|
+
codecov.io
|
|
197
|
+
sonarcloud.io
|
|
198
|
+
|
|
199
|
+
# Terraform & Infrastructure
|
|
200
|
+
registry.terraform.io
|
|
201
|
+
releases.hashicorp.com
|
|
202
|
+
checkpoint-api.hashicorp.com
|
|
203
|
+
EOF
|
|
204
|
+
|
|
205
|
+
echo "✓ Trusted domains documented for this runner"
|
|
206
|
+
echo "✓ GitHub Actions runners have network access to these domains"
|
|
207
|
+
echo ""
|
|
208
|
+
|
|
209
|
+
# Test connectivity to key domains
|
|
210
|
+
echo "Testing connectivity to key domains..."
|
|
211
|
+
for domain in "github.com" "www.gnu.org" "npmjs.com" "pypi.org"; do
|
|
212
|
+
if curl -s --max-time 3 -o /dev/null -w "%{http_code}" "https://$domain" | grep -q "200\|301\|302"; then
|
|
213
|
+
echo " ✓ $domain is accessible"
|
|
214
|
+
else
|
|
215
|
+
echo " ⚠️ $domain connectivity check failed (may be expected)"
|
|
216
|
+
fi
|
|
217
|
+
done
|
|
218
|
+
|
|
219
|
+
# Test SFTP server connectivity (TCP port check)
|
|
220
|
+
SFTP_HOST="${DEV_FTP_HOST:-}"
|
|
221
|
+
SFTP_PORT="${DEV_FTP_PORT:-22}"
|
|
222
|
+
if [ -n "$SFTP_HOST" ]; then
|
|
223
|
+
# Strip any embedded :port suffix
|
|
224
|
+
SFTP_HOST="${SFTP_HOST%%:*}"
|
|
225
|
+
echo ""
|
|
226
|
+
echo "Testing SFTP deployment server connectivity..."
|
|
227
|
+
if timeout 5 bash -c "echo >/dev/tcp/${SFTP_HOST}/${SFTP_PORT}" 2>/dev/null; then
|
|
228
|
+
echo " ✓ SFTP server ${SFTP_HOST}:${SFTP_PORT} is reachable"
|
|
229
|
+
else
|
|
230
|
+
echo " ⚠️ SFTP server ${SFTP_HOST}:${SFTP_PORT} is not reachable from runner (firewall rule needed)"
|
|
231
|
+
fi
|
|
232
|
+
else
|
|
233
|
+
echo ""
|
|
234
|
+
echo " ℹ️ DEV_FTP_HOST not configured — skipping SFTP connectivity check"
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
- name: Generate Firewall Configuration
|
|
238
|
+
id: generate
|
|
239
|
+
env:
|
|
240
|
+
DEV_FTP_HOST: ${{ vars.DEV_FTP_HOST }}
|
|
241
|
+
DEV_FTP_PORT: ${{ vars.DEV_FTP_PORT }}
|
|
242
|
+
run: |
|
|
243
|
+
cat > generate_firewall_config.py << 'PYTHON_EOF'
|
|
244
|
+
#!/usr/bin/env python3
|
|
245
|
+
"""
|
|
246
|
+
Enterprise Firewall Configuration Generator
|
|
247
|
+
|
|
248
|
+
Generates firewall rules for enterprise-ready deployments allowing
|
|
249
|
+
access to trusted domains including license providers, documentation
|
|
250
|
+
sources, package registries, and platform-specific sites.
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
import json
|
|
254
|
+
import os
|
|
255
|
+
import yaml
|
|
256
|
+
import sys
|
|
257
|
+
from typing import List, Dict
|
|
258
|
+
|
|
259
|
+
# SFTP deployment server from org variables
|
|
260
|
+
_sftp_host_raw = os.environ.get("DEV_FTP_HOST", "").strip()
|
|
261
|
+
_sftp_port = os.environ.get("DEV_FTP_PORT", "").strip() or "22"
|
|
262
|
+
# Strip embedded :port suffix if present
|
|
263
|
+
_sftp_host = _sftp_host_raw.split(":")[0] if _sftp_host_raw else ""
|
|
264
|
+
if ":" in _sftp_host_raw and not _sftp_port:
|
|
265
|
+
_sftp_port = _sftp_host_raw.split(":")[1]
|
|
266
|
+
|
|
267
|
+
SFTP_HOST = _sftp_host
|
|
268
|
+
SFTP_PORT = int(_sftp_port) if _sftp_port.isdigit() else 22
|
|
269
|
+
|
|
270
|
+
# Trusted domains from .github/copilot.yml
|
|
271
|
+
TRUSTED_DOMAINS = {
|
|
272
|
+
"license_providers": [
|
|
273
|
+
"www.gnu.org",
|
|
274
|
+
"opensource.org",
|
|
275
|
+
"choosealicense.com",
|
|
276
|
+
"spdx.org",
|
|
277
|
+
"creativecommons.org",
|
|
278
|
+
"apache.org",
|
|
279
|
+
"fsf.org",
|
|
280
|
+
],
|
|
281
|
+
"documentation_standards": [
|
|
282
|
+
"semver.org",
|
|
283
|
+
"keepachangelog.com",
|
|
284
|
+
"conventionalcommits.org",
|
|
285
|
+
],
|
|
286
|
+
"github_related": [
|
|
287
|
+
"github.com",
|
|
288
|
+
"api.github.com",
|
|
289
|
+
"docs.github.com",
|
|
290
|
+
"raw.githubusercontent.com",
|
|
291
|
+
"ghcr.io",
|
|
292
|
+
],
|
|
293
|
+
"package_registries": [
|
|
294
|
+
"npmjs.com",
|
|
295
|
+
"registry.npmjs.org",
|
|
296
|
+
"pypi.org",
|
|
297
|
+
"files.pythonhosted.org",
|
|
298
|
+
"packagist.org",
|
|
299
|
+
"repo.packagist.org",
|
|
300
|
+
"rubygems.org",
|
|
301
|
+
],
|
|
302
|
+
"standards_organizations": [
|
|
303
|
+
"json-schema.org",
|
|
304
|
+
"w3.org",
|
|
305
|
+
"ietf.org",
|
|
306
|
+
],
|
|
307
|
+
"platform_specific": [
|
|
308
|
+
"joomla.org",
|
|
309
|
+
"downloads.joomla.org",
|
|
310
|
+
"docs.joomla.org",
|
|
311
|
+
"php.net",
|
|
312
|
+
"getcomposer.org",
|
|
313
|
+
"dolibarr.org",
|
|
314
|
+
"wiki.dolibarr.org",
|
|
315
|
+
"docs.dolibarr.org",
|
|
316
|
+
],
|
|
317
|
+
"moko_consulting": [
|
|
318
|
+
"mokoconsulting.tech",
|
|
319
|
+
],
|
|
320
|
+
"google_services": [
|
|
321
|
+
"drive.google.com",
|
|
322
|
+
"docs.google.com",
|
|
323
|
+
"sheets.google.com",
|
|
324
|
+
"accounts.google.com",
|
|
325
|
+
"storage.googleapis.com",
|
|
326
|
+
"fonts.googleapis.com",
|
|
327
|
+
"fonts.gstatic.com",
|
|
328
|
+
],
|
|
329
|
+
"github_extended": [
|
|
330
|
+
"upload.github.com",
|
|
331
|
+
"objects.githubusercontent.com",
|
|
332
|
+
"user-images.githubusercontent.com",
|
|
333
|
+
"codeload.github.com",
|
|
334
|
+
"pkg.github.com",
|
|
335
|
+
],
|
|
336
|
+
"developer_reference": [
|
|
337
|
+
"developer.mozilla.org",
|
|
338
|
+
"stackoverflow.com",
|
|
339
|
+
"git-scm.com",
|
|
340
|
+
],
|
|
341
|
+
"cdn_and_infrastructure": [
|
|
342
|
+
"cdn.jsdelivr.net",
|
|
343
|
+
"unpkg.com",
|
|
344
|
+
"cdnjs.cloudflare.com",
|
|
345
|
+
"img.shields.io",
|
|
346
|
+
],
|
|
347
|
+
"container_registries": [
|
|
348
|
+
"hub.docker.com",
|
|
349
|
+
"registry-1.docker.io",
|
|
350
|
+
],
|
|
351
|
+
"ci_code_quality": [
|
|
352
|
+
"codecov.io",
|
|
353
|
+
"sonarcloud.io",
|
|
354
|
+
],
|
|
355
|
+
"terraform_infrastructure": [
|
|
356
|
+
"registry.terraform.io",
|
|
357
|
+
"releases.hashicorp.com",
|
|
358
|
+
"checkpoint-api.hashicorp.com",
|
|
359
|
+
],
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
# Inject SFTP deployment server as a separate category (port 22, not 443)
|
|
363
|
+
if SFTP_HOST:
|
|
364
|
+
TRUSTED_DOMAINS["sftp_deployment_server"] = [SFTP_HOST]
|
|
365
|
+
print(f"ℹ️ SFTP deployment server: {SFTP_HOST}:{SFTP_PORT}")
|
|
366
|
+
|
|
367
|
+
def generate_sftp_iptables_rules(host: str, port: int) -> str:
|
|
368
|
+
"""Generate iptables rules specifically for SFTP egress"""
|
|
369
|
+
return (
|
|
370
|
+
f"# Allow SFTP to deployment server {host}:{port}\n"
|
|
371
|
+
f"iptables -A OUTPUT -p tcp -d $(dig +short {host} | head -1)"
|
|
372
|
+
f" --dport {port} -j ACCEPT # SFTP deploy\n"
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
def generate_sftp_ufw_rules(host: str, port: int) -> str:
|
|
376
|
+
"""Generate UFW rules for SFTP egress"""
|
|
377
|
+
return (
|
|
378
|
+
f"# Allow SFTP to deployment server\n"
|
|
379
|
+
f"ufw allow out to $(dig +short {host} | head -1)"
|
|
380
|
+
f" port {port} proto tcp comment 'SFTP deploy to {host}'\n"
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
def generate_sftp_firewalld_rules(host: str, port: int) -> str:
|
|
384
|
+
"""Generate firewalld rules for SFTP egress"""
|
|
385
|
+
return (
|
|
386
|
+
f"# Allow SFTP to deployment server\n"
|
|
387
|
+
f"firewall-cmd --permanent --add-rich-rule='"
|
|
388
|
+
f"rule family=ipv4 destination address=$(dig +short {host} | head -1)"
|
|
389
|
+
f" port port={port} protocol=tcp accept' # SFTP deploy\n"
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
def generate_iptables_rules(domains: List[str]) -> str:
|
|
393
|
+
"""Generate iptables firewall rules"""
|
|
394
|
+
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - iptables", ""]
|
|
395
|
+
rules.append("# Allow outbound HTTPS to trusted domains")
|
|
396
|
+
rules.append("")
|
|
397
|
+
|
|
398
|
+
for domain in domains:
|
|
399
|
+
rules.append(f"# Allow {domain}")
|
|
400
|
+
rules.append(f"iptables -A OUTPUT -p tcp -d $(dig +short {domain} | head -1) --dport 443 -j ACCEPT")
|
|
401
|
+
|
|
402
|
+
rules.append("")
|
|
403
|
+
rules.append("# Allow DNS lookups")
|
|
404
|
+
rules.append("iptables -A OUTPUT -p udp --dport 53 -j ACCEPT")
|
|
405
|
+
rules.append("iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT")
|
|
406
|
+
|
|
407
|
+
return "\n".join(rules)
|
|
408
|
+
|
|
409
|
+
def generate_ufw_rules(domains: List[str]) -> str:
|
|
410
|
+
"""Generate UFW firewall rules"""
|
|
411
|
+
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - UFW", ""]
|
|
412
|
+
rules.append("# Allow outbound HTTPS to trusted domains")
|
|
413
|
+
rules.append("")
|
|
414
|
+
|
|
415
|
+
for domain in domains:
|
|
416
|
+
rules.append(f"# Allow {domain}")
|
|
417
|
+
rules.append(f"ufw allow out to $(dig +short {domain} | head -1) port 443 proto tcp comment 'Allow {domain}'")
|
|
418
|
+
|
|
419
|
+
rules.append("")
|
|
420
|
+
rules.append("# Allow DNS")
|
|
421
|
+
rules.append("ufw allow out 53/udp comment 'Allow DNS UDP'")
|
|
422
|
+
rules.append("ufw allow out 53/tcp comment 'Allow DNS TCP'")
|
|
423
|
+
|
|
424
|
+
return "\n".join(rules)
|
|
425
|
+
|
|
426
|
+
def generate_firewalld_rules(domains: List[str]) -> str:
|
|
427
|
+
"""Generate firewalld rules"""
|
|
428
|
+
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - firewalld", ""]
|
|
429
|
+
rules.append("# Add trusted domains to firewall")
|
|
430
|
+
rules.append("")
|
|
431
|
+
|
|
432
|
+
for domain in domains:
|
|
433
|
+
rules.append(f"# Allow {domain}")
|
|
434
|
+
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'")
|
|
435
|
+
|
|
436
|
+
rules.append("")
|
|
437
|
+
rules.append("# Reload firewall")
|
|
438
|
+
rules.append("firewall-cmd --reload")
|
|
439
|
+
|
|
440
|
+
return "\n".join(rules)
|
|
441
|
+
|
|
442
|
+
def generate_aws_security_group(domains: List[str]) -> Dict:
|
|
443
|
+
"""Generate AWS Security Group rules (JSON format)"""
|
|
444
|
+
rules = {
|
|
445
|
+
"SecurityGroupRules": {
|
|
446
|
+
"Egress": []
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
for domain in domains:
|
|
451
|
+
rules["SecurityGroupRules"]["Egress"].append({
|
|
452
|
+
"Description": f"Allow HTTPS to {domain}",
|
|
453
|
+
"IpProtocol": "tcp",
|
|
454
|
+
"FromPort": 443,
|
|
455
|
+
"ToPort": 443,
|
|
456
|
+
"CidrIp": "0.0.0.0/0", # In practice, resolve to specific IPs
|
|
457
|
+
"Tags": [{
|
|
458
|
+
"Key": "Domain",
|
|
459
|
+
"Value": domain
|
|
460
|
+
}]
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
# Add DNS
|
|
464
|
+
rules["SecurityGroupRules"]["Egress"].append({
|
|
465
|
+
"Description": "Allow DNS",
|
|
466
|
+
"IpProtocol": "udp",
|
|
467
|
+
"FromPort": 53,
|
|
468
|
+
"ToPort": 53,
|
|
469
|
+
"CidrIp": "0.0.0.0/0"
|
|
470
|
+
})
|
|
471
|
+
|
|
472
|
+
return rules
|
|
473
|
+
|
|
474
|
+
def generate_markdown_documentation(domains_by_category: Dict[str, List[str]]) -> str:
|
|
475
|
+
"""Generate markdown documentation"""
|
|
476
|
+
md = ["# Enterprise Firewall Configuration Guide", ""]
|
|
477
|
+
md.append("## Overview")
|
|
478
|
+
md.append("")
|
|
479
|
+
md.append("This document provides firewall configuration guidance for enterprise-ready deployments.")
|
|
480
|
+
md.append("It lists trusted domains that should be whitelisted for outbound access to ensure")
|
|
481
|
+
md.append("proper functionality of license validation, package management, and documentation access.")
|
|
482
|
+
md.append("")
|
|
483
|
+
|
|
484
|
+
md.append("## Trusted Domains by Category")
|
|
485
|
+
md.append("")
|
|
486
|
+
|
|
487
|
+
all_domains = []
|
|
488
|
+
for category, domains in domains_by_category.items():
|
|
489
|
+
category_name = category.replace("_", " ").title()
|
|
490
|
+
md.append(f"### {category_name}")
|
|
491
|
+
md.append("")
|
|
492
|
+
md.append("| Domain | Purpose |")
|
|
493
|
+
md.append("|--------|---------|")
|
|
494
|
+
|
|
495
|
+
for domain in domains:
|
|
496
|
+
all_domains.append(domain)
|
|
497
|
+
purpose = get_domain_purpose(domain)
|
|
498
|
+
md.append(f"| `{domain}` | {purpose} |")
|
|
499
|
+
|
|
500
|
+
md.append("")
|
|
501
|
+
|
|
502
|
+
md.append("## Implementation Examples")
|
|
503
|
+
md.append("")
|
|
504
|
+
|
|
505
|
+
md.append("### iptables Example")
|
|
506
|
+
md.append("")
|
|
507
|
+
md.append("```bash")
|
|
508
|
+
md.append("# Allow HTTPS to trusted domain")
|
|
509
|
+
md.append(f"iptables -A OUTPUT -p tcp -d $(dig +short {all_domains[0]}) --dport 443 -j ACCEPT")
|
|
510
|
+
md.append("```")
|
|
511
|
+
md.append("")
|
|
512
|
+
|
|
513
|
+
md.append("### UFW Example")
|
|
514
|
+
md.append("")
|
|
515
|
+
md.append("```bash")
|
|
516
|
+
md.append("# Allow HTTPS to trusted domain")
|
|
517
|
+
md.append(f"ufw allow out to {all_domains[0]} port 443 proto tcp")
|
|
518
|
+
md.append("```")
|
|
519
|
+
md.append("")
|
|
520
|
+
|
|
521
|
+
md.append("### AWS Security Group Example")
|
|
522
|
+
md.append("")
|
|
523
|
+
md.append("```json")
|
|
524
|
+
md.append("{")
|
|
525
|
+
md.append(' "IpPermissions": [{')
|
|
526
|
+
md.append(' "IpProtocol": "tcp",')
|
|
527
|
+
md.append(' "FromPort": 443,')
|
|
528
|
+
md.append(' "ToPort": 443,')
|
|
529
|
+
md.append(' "IpRanges": [{"CidrIp": "0.0.0.0/0", "Description": "HTTPS to trusted domains"}]')
|
|
530
|
+
md.append(" }]")
|
|
531
|
+
md.append("}")
|
|
532
|
+
md.append("```")
|
|
533
|
+
md.append("")
|
|
534
|
+
|
|
535
|
+
md.append("## Ports Required")
|
|
536
|
+
md.append("")
|
|
537
|
+
md.append("| Port | Protocol | Purpose |")
|
|
538
|
+
md.append("|------|----------|---------|")
|
|
539
|
+
md.append("| 443 | TCP | HTTPS (secure web access) |")
|
|
540
|
+
md.append("| 80 | TCP | HTTP (redirects to HTTPS) |")
|
|
541
|
+
md.append("| 53 | UDP/TCP | DNS resolution |")
|
|
542
|
+
md.append("")
|
|
543
|
+
|
|
544
|
+
md.append("## Security Considerations")
|
|
545
|
+
md.append("")
|
|
546
|
+
md.append("1. **DNS Resolution**: Ensure DNS queries are allowed (port 53 UDP/TCP)")
|
|
547
|
+
md.append("2. **Certificate Validation**: HTTPS requires ability to reach certificate authorities")
|
|
548
|
+
md.append("3. **Dynamic IPs**: Some domains use CDNs with dynamic IPs - consider using FQDNs in rules")
|
|
549
|
+
md.append("4. **Regular Updates**: Review and update whitelist as services change")
|
|
550
|
+
md.append("5. **Logging**: Enable logging for blocked connections to identify missing rules")
|
|
551
|
+
md.append("")
|
|
552
|
+
|
|
553
|
+
md.append("## Compliance Notes")
|
|
554
|
+
md.append("")
|
|
555
|
+
md.append("- All listed domains provide read-only access to public information")
|
|
556
|
+
md.append("- License providers enable GPL compliance verification")
|
|
557
|
+
md.append("- Package registries support dependency security scanning")
|
|
558
|
+
md.append("- No authentication credentials are transmitted to these domains")
|
|
559
|
+
md.append("")
|
|
560
|
+
|
|
561
|
+
return "\n".join(md)
|
|
562
|
+
|
|
563
|
+
def get_domain_purpose(domain: str) -> str:
|
|
564
|
+
"""Get human-readable purpose for a domain"""
|
|
565
|
+
purposes = {
|
|
566
|
+
"www.gnu.org": "GNU licenses and documentation",
|
|
567
|
+
"opensource.org": "Open Source Initiative resources",
|
|
568
|
+
"choosealicense.com": "GitHub license selection tool",
|
|
569
|
+
"spdx.org": "Software Package Data Exchange identifiers",
|
|
570
|
+
"creativecommons.org": "Creative Commons licenses",
|
|
571
|
+
"apache.org": "Apache Software Foundation licenses",
|
|
572
|
+
"fsf.org": "Free Software Foundation resources",
|
|
573
|
+
"semver.org": "Semantic versioning specification",
|
|
574
|
+
"keepachangelog.com": "Changelog format standards",
|
|
575
|
+
"conventionalcommits.org": "Commit message conventions",
|
|
576
|
+
"github.com": "GitHub platform access",
|
|
577
|
+
"api.github.com": "GitHub API access",
|
|
578
|
+
"docs.github.com": "GitHub documentation",
|
|
579
|
+
"raw.githubusercontent.com": "GitHub raw content access",
|
|
580
|
+
"npmjs.com": "npm package registry",
|
|
581
|
+
"pypi.org": "Python Package Index",
|
|
582
|
+
"packagist.org": "PHP Composer package registry",
|
|
583
|
+
"rubygems.org": "Ruby gems registry",
|
|
584
|
+
"joomla.org": "Joomla CMS platform",
|
|
585
|
+
"php.net": "PHP documentation and downloads",
|
|
586
|
+
"dolibarr.org": "Dolibarr ERP/CRM platform",
|
|
587
|
+
}
|
|
588
|
+
return purposes.get(domain, "Trusted resource")
|
|
589
|
+
|
|
590
|
+
def main():
|
|
591
|
+
# Use inputs if provided (manual dispatch), otherwise use defaults (auto-run)
|
|
592
|
+
firewall_type = "${{ github.event.inputs.firewall_type }}" or "all"
|
|
593
|
+
output_format = "${{ github.event.inputs.output_format }}" or "markdown"
|
|
594
|
+
|
|
595
|
+
print(f"Running in {'manual' if '${{ github.event.inputs.firewall_type }}' else 'automatic'} mode")
|
|
596
|
+
print(f"Firewall type: {firewall_type}")
|
|
597
|
+
print(f"Output format: {output_format}")
|
|
598
|
+
print("")
|
|
599
|
+
|
|
600
|
+
# Collect all domains
|
|
601
|
+
all_domains = []
|
|
602
|
+
for domains in TRUSTED_DOMAINS.values():
|
|
603
|
+
all_domains.extend(domains)
|
|
604
|
+
|
|
605
|
+
# Remove duplicates and sort
|
|
606
|
+
all_domains = sorted(set(all_domains))
|
|
607
|
+
|
|
608
|
+
print(f"Generating firewall rules for {len(all_domains)} trusted domains...")
|
|
609
|
+
print("")
|
|
610
|
+
|
|
611
|
+
# Exclude SFTP server from HTTPS rule generation (different port)
|
|
612
|
+
https_domains = [d for d in all_domains if d != SFTP_HOST]
|
|
613
|
+
|
|
614
|
+
# Generate based on firewall type
|
|
615
|
+
if firewall_type in ["iptables", "all"]:
|
|
616
|
+
rules = generate_iptables_rules(https_domains)
|
|
617
|
+
if SFTP_HOST:
|
|
618
|
+
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
|
|
619
|
+
rules += generate_sftp_iptables_rules(SFTP_HOST, SFTP_PORT)
|
|
620
|
+
with open("firewall-rules-iptables.sh", "w") as f:
|
|
621
|
+
f.write(rules)
|
|
622
|
+
print("✓ Generated iptables rules: firewall-rules-iptables.sh")
|
|
623
|
+
|
|
624
|
+
if firewall_type in ["ufw", "all"]:
|
|
625
|
+
rules = generate_ufw_rules(https_domains)
|
|
626
|
+
if SFTP_HOST:
|
|
627
|
+
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
|
|
628
|
+
rules += generate_sftp_ufw_rules(SFTP_HOST, SFTP_PORT)
|
|
629
|
+
with open("firewall-rules-ufw.sh", "w") as f:
|
|
630
|
+
f.write(rules)
|
|
631
|
+
print("✓ Generated UFW rules: firewall-rules-ufw.sh")
|
|
632
|
+
|
|
633
|
+
if firewall_type in ["firewalld", "all"]:
|
|
634
|
+
rules = generate_firewalld_rules(https_domains)
|
|
635
|
+
if SFTP_HOST:
|
|
636
|
+
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
|
|
637
|
+
rules += generate_sftp_firewalld_rules(SFTP_HOST, SFTP_PORT)
|
|
638
|
+
with open("firewall-rules-firewalld.sh", "w") as f:
|
|
639
|
+
f.write(rules)
|
|
640
|
+
print("✓ Generated firewalld rules: firewall-rules-firewalld.sh")
|
|
641
|
+
|
|
642
|
+
if firewall_type in ["aws-security-group", "all"]:
|
|
643
|
+
rules = generate_aws_security_group(all_domains)
|
|
644
|
+
with open("firewall-rules-aws-sg.json", "w") as f:
|
|
645
|
+
json.dump(rules, f, indent=2)
|
|
646
|
+
print("✓ Generated AWS Security Group rules: firewall-rules-aws-sg.json")
|
|
647
|
+
|
|
648
|
+
if output_format in ["yaml", "all"]:
|
|
649
|
+
with open("trusted-domains.yml", "w") as f:
|
|
650
|
+
yaml.dump(TRUSTED_DOMAINS, f, default_flow_style=False)
|
|
651
|
+
print("✓ Generated YAML domain list: trusted-domains.yml")
|
|
652
|
+
|
|
653
|
+
if output_format in ["json", "all"]:
|
|
654
|
+
with open("trusted-domains.json", "w") as f:
|
|
655
|
+
json.dump(TRUSTED_DOMAINS, f, indent=2)
|
|
656
|
+
print("✓ Generated JSON domain list: trusted-domains.json")
|
|
657
|
+
|
|
658
|
+
if output_format in ["markdown", "all"]:
|
|
659
|
+
md = generate_markdown_documentation(TRUSTED_DOMAINS)
|
|
660
|
+
with open("FIREWALL_CONFIGURATION.md", "w") as f:
|
|
661
|
+
f.write(md)
|
|
662
|
+
print("✓ Generated documentation: FIREWALL_CONFIGURATION.md")
|
|
663
|
+
|
|
664
|
+
print("")
|
|
665
|
+
print("Domain Categories:")
|
|
666
|
+
for category, domains in TRUSTED_DOMAINS.items():
|
|
667
|
+
print(f" - {category}: {len(domains)} domains")
|
|
668
|
+
|
|
669
|
+
print("")
|
|
670
|
+
print("Total unique domains: ", len(all_domains))
|
|
671
|
+
|
|
672
|
+
if __name__ == "__main__":
|
|
673
|
+
main()
|
|
674
|
+
PYTHON_EOF
|
|
675
|
+
|
|
676
|
+
chmod +x generate_firewall_config.py
|
|
677
|
+
pip install PyYAML
|
|
678
|
+
python3 generate_firewall_config.py
|
|
679
|
+
|
|
680
|
+
- name: Upload Firewall Configuration Artifacts
|
|
681
|
+
uses: actions/upload-artifact@v6
|
|
682
|
+
with:
|
|
683
|
+
name: firewall-configurations
|
|
684
|
+
path: |
|
|
685
|
+
firewall-rules-*.sh
|
|
686
|
+
firewall-rules-*.json
|
|
687
|
+
trusted-domains.*
|
|
688
|
+
FIREWALL_CONFIGURATION.md
|
|
689
|
+
retention-days: 90
|
|
690
|
+
|
|
691
|
+
- name: Display Summary
|
|
692
|
+
run: |
|
|
693
|
+
echo "## Firewall Configuration" >> $GITHUB_STEP_SUMMARY
|
|
694
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
695
|
+
|
|
696
|
+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
697
|
+
echo "**Mode**: Manual Execution" >> $GITHUB_STEP_SUMMARY
|
|
698
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
699
|
+
echo "Firewall rules have been generated for enterprise-ready deployments." >> $GITHUB_STEP_SUMMARY
|
|
700
|
+
else
|
|
701
|
+
echo "**Mode**: Automatic Execution (Coding Agent Active)" >> $GITHUB_STEP_SUMMARY
|
|
702
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
703
|
+
echo "This workflow ran automatically because a coding agent (GitHub Copilot) is active." >> $GITHUB_STEP_SUMMARY
|
|
704
|
+
echo "Firewall configuration has been validated for the coding agent environment." >> $GITHUB_STEP_SUMMARY
|
|
705
|
+
fi
|
|
706
|
+
|
|
707
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
708
|
+
echo "### Files Generated" >> $GITHUB_STEP_SUMMARY
|
|
709
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
710
|
+
if ls firewall-rules-* trusted-domains.* FIREWALL_CONFIGURATION.md 2>/dev/null; then
|
|
711
|
+
ls -lh firewall-rules-* trusted-domains.* FIREWALL_CONFIGURATION.md 2>/dev/null | awk '{print "- " $9 " (" $5 ")"}' >> $GITHUB_STEP_SUMMARY
|
|
712
|
+
else
|
|
713
|
+
echo "- Documentation generated" >> $GITHUB_STEP_SUMMARY
|
|
714
|
+
fi
|
|
715
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
716
|
+
|
|
717
|
+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
718
|
+
echo "### Download Artifacts" >> $GITHUB_STEP_SUMMARY
|
|
719
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
720
|
+
echo "Download the generated firewall configurations from the workflow artifacts." >> $GITHUB_STEP_SUMMARY
|
|
721
|
+
else
|
|
722
|
+
echo "### Trusted Domains Active" >> $GITHUB_STEP_SUMMARY
|
|
723
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
724
|
+
echo "The coding agent has access to:" >> $GITHUB_STEP_SUMMARY
|
|
725
|
+
echo "- License providers (GPL, OSI, SPDX, Apache, etc.)" >> $GITHUB_STEP_SUMMARY
|
|
726
|
+
echo "- Package registries (npm, PyPI, Packagist, RubyGems)" >> $GITHUB_STEP_SUMMARY
|
|
727
|
+
echo "- Documentation sources (GitHub, Joomla, Dolibarr, PHP)" >> $GITHUB_STEP_SUMMARY
|
|
728
|
+
echo "- Standards organizations (W3C, IETF, JSON Schema)" >> $GITHUB_STEP_SUMMARY
|
|
729
|
+
fi
|
|
730
|
+
|
|
731
|
+
# Usage Instructions:
|
|
732
|
+
#
|
|
733
|
+
# This workflow runs in two modes:
|
|
734
|
+
#
|
|
735
|
+
# 1. AUTOMATIC MODE (Coding Agent):
|
|
736
|
+
# - Triggers when coding agent branches (copilot/**, agent/**) are pushed or PR'd
|
|
737
|
+
# - Validates firewall configuration for the coding agent environment
|
|
738
|
+
# - Documents accessible domains for compliance
|
|
739
|
+
# - Ensures license sources and package registries are available
|
|
740
|
+
#
|
|
741
|
+
# 2. MANUAL MODE (Enterprise Configuration):
|
|
742
|
+
# - Manually trigger from the Actions tab
|
|
743
|
+
# - Select desired firewall type and output format
|
|
744
|
+
# - Download generated artifacts
|
|
745
|
+
# - Apply firewall rules to your enterprise environment
|
|
746
|
+
#
|
|
747
|
+
# Configuration:
|
|
748
|
+
# - Trusted domains are sourced from .github/copilot.yml
|
|
749
|
+
# - Modify copilot.yml to add/remove trusted domains
|
|
750
|
+
# - Changes automatically propagate to firewall rules
|
|
751
|
+
#
|
|
752
|
+
# Important Notes:
|
|
753
|
+
# - Review generated rules before applying to production
|
|
754
|
+
# - Some domains may use CDNs with dynamic IPs
|
|
755
|
+
# - Consider using FQDN-based rules where supported
|
|
756
|
+
# - Test thoroughly in staging environment first
|
|
757
|
+
# - Monitor logs for blocked connections
|
|
758
|
+
# - Update rules as domains/services change
|