ma-agents 3.2.0 → 3.4.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/.opencode/skills/.ma-agents.json +99 -99
- package/.roo/rules/00-ma-agents.md +13 -0
- package/.roo/skills/.ma-agents.json +241 -0
- package/.roo/skills/MANIFEST.yaml +254 -0
- package/.roo/skills/ai-audit-trail/SKILL.md +23 -0
- package/.roo/skills/auto-bug-detection/SKILL.md +169 -0
- package/.roo/skills/cmake-best-practices/SKILL.md +64 -0
- package/.roo/skills/cmake-best-practices/examples/cmake.md +59 -0
- package/.roo/skills/code-documentation/SKILL.md +57 -0
- package/.roo/skills/code-documentation/examples/cpp.md +29 -0
- package/.roo/skills/code-documentation/examples/csharp.md +28 -0
- package/.roo/skills/code-documentation/examples/javascript_typescript.md +28 -0
- package/.roo/skills/code-documentation/examples/python.md +57 -0
- package/.roo/skills/code-review/SKILL.md +43 -0
- package/.roo/skills/commit-message/SKILL.md +79 -0
- package/.roo/skills/cpp-best-practices/SKILL.md +234 -0
- package/.roo/skills/cpp-best-practices/examples/modern-idioms.md +189 -0
- package/.roo/skills/cpp-best-practices/examples/naming-and-organization.md +102 -0
- package/.roo/skills/cpp-concurrency-safety/SKILL.md +60 -0
- package/.roo/skills/cpp-concurrency-safety/examples/concurrency.md +73 -0
- package/.roo/skills/cpp-const-correctness/SKILL.md +63 -0
- package/.roo/skills/cpp-const-correctness/examples/const_correctness.md +54 -0
- package/.roo/skills/cpp-memory-handling/SKILL.md +42 -0
- package/.roo/skills/cpp-memory-handling/examples/modern-cpp.md +49 -0
- package/.roo/skills/cpp-memory-handling/examples/smart-pointers.md +46 -0
- package/.roo/skills/cpp-modern-composition/SKILL.md +64 -0
- package/.roo/skills/cpp-modern-composition/examples/composition.md +51 -0
- package/.roo/skills/cpp-robust-interfaces/SKILL.md +55 -0
- package/.roo/skills/cpp-robust-interfaces/examples/interfaces.md +56 -0
- package/.roo/skills/create-hardened-docker-skill/SKILL.md +637 -0
- package/.roo/skills/create-hardened-docker-skill/scripts/create-all.sh +489 -0
- package/.roo/skills/csharp-best-practices/SKILL.md +278 -0
- package/.roo/skills/docker-hardening-verification/SKILL.md +28 -0
- package/.roo/skills/docker-hardening-verification/scripts/verify-hardening.sh +39 -0
- package/.roo/skills/docker-image-signing/SKILL.md +28 -0
- package/.roo/skills/docker-image-signing/scripts/sign-image.sh +33 -0
- package/.roo/skills/document-revision-history/SKILL.md +104 -0
- package/.roo/skills/git-workflow-skill/SKILL.md +194 -0
- package/.roo/skills/git-workflow-skill/hooks/commit-msg +61 -0
- package/.roo/skills/git-workflow-skill/hooks/pre-commit +38 -0
- package/.roo/skills/git-workflow-skill/hooks/prepare-commit-msg +56 -0
- package/.roo/skills/git-workflow-skill/scripts/finish-feature.sh +192 -0
- package/.roo/skills/git-workflow-skill/scripts/install-hooks.sh +55 -0
- package/.roo/skills/git-workflow-skill/scripts/start-feature.sh +110 -0
- package/.roo/skills/git-workflow-skill/scripts/validate-workflow.sh +229 -0
- package/.roo/skills/js-ts-dependency-mgmt/SKILL.md +49 -0
- package/.roo/skills/js-ts-dependency-mgmt/examples/dependency_mgmt.md +60 -0
- package/.roo/skills/js-ts-security-skill/SKILL.md +64 -0
- package/.roo/skills/js-ts-security-skill/scripts/verify-security.sh +136 -0
- package/.roo/skills/logging-best-practices/SKILL.md +50 -0
- package/.roo/skills/logging-best-practices/examples/cpp.md +36 -0
- package/.roo/skills/logging-best-practices/examples/csharp.md +49 -0
- package/.roo/skills/logging-best-practices/examples/javascript.md +77 -0
- package/.roo/skills/logging-best-practices/examples/python.md +57 -0
- package/.roo/skills/logging-best-practices/references/logging-standards.md +29 -0
- package/.roo/skills/open-presentation/SKILL.md +35 -0
- package/.roo/skills/opentelemetry-best-practices/SKILL.md +34 -0
- package/.roo/skills/opentelemetry-best-practices/examples/go.md +32 -0
- package/.roo/skills/opentelemetry-best-practices/examples/javascript.md +58 -0
- package/.roo/skills/opentelemetry-best-practices/examples/python.md +37 -0
- package/.roo/skills/opentelemetry-best-practices/references/otel-standards.md +37 -0
- package/.roo/skills/python-best-practices/SKILL.md +385 -0
- package/.roo/skills/python-dependency-mgmt/SKILL.md +42 -0
- package/.roo/skills/python-dependency-mgmt/examples/dependency_mgmt.md +67 -0
- package/.roo/skills/python-security-skill/SKILL.md +56 -0
- package/.roo/skills/python-security-skill/examples/security.md +56 -0
- package/.roo/skills/self-signed-cert/SKILL.md +42 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.ps1 +45 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.sh +43 -0
- package/.roo/skills/skill-creator/SKILL.md +196 -0
- package/.roo/skills/skill-creator/references/output-patterns.md +82 -0
- package/.roo/skills/skill-creator/references/workflows.md +28 -0
- package/.roo/skills/skill-creator/scripts/init_skill.py +208 -0
- package/.roo/skills/skill-creator/scripts/package_skill.py +99 -0
- package/.roo/skills/skill-creator/scripts/quick_validate.py +113 -0
- package/.roo/skills/story-status-lookup/SKILL.md +78 -0
- package/.roo/skills/test-accompanied-development/SKILL.md +50 -0
- package/.roo/skills/test-generator/SKILL.md +65 -0
- package/.roo/skills/vercel-react-best-practices/SKILL.md +109 -0
- package/.roo/skills/verify-hardened-docker-skill/SKILL.md +442 -0
- package/.roo/skills/verify-hardened-docker-skill/scripts/verify-docker-hardening.sh +439 -0
- package/README.md +21 -2
- package/bin/cli.js +55 -0
- package/lib/agents.js +46 -0
- package/lib/bmad-cache/cache-manifest.json +1 -1
- package/lib/bmad-customizations/bmm-demerzel.customize.yaml +36 -0
- package/lib/bmad-customizations/demerzel.md +32 -0
- package/lib/bmad-extension/module-help.csv +13 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-ml/.gitkeep +0 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-ml/SKILL.md +59 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-ml/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/generate-backlog/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-advise/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-advise/SKILL.md +76 -0
- package/lib/bmad-extension/skills/ml-advise/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-advise/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-analysis/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-analysis/SKILL.md +60 -0
- package/lib/bmad-extension/skills/ml-analysis/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-analysis/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-architecture/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-architecture/SKILL.md +55 -0
- package/lib/bmad-extension/skills/ml-architecture/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-architecture/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-detailed-design/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-detailed-design/SKILL.md +67 -0
- package/lib/bmad-extension/skills/ml-detailed-design/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-detailed-design/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-eda/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-eda/SKILL.md +56 -0
- package/lib/bmad-extension/skills/ml-eda/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-eda/scripts/baseline_classifier.py +522 -0
- package/lib/bmad-extension/skills/ml-eda/scripts/class_weights_calculator.py +295 -0
- package/lib/bmad-extension/skills/ml-eda/scripts/clustering_explorer.py +383 -0
- package/lib/bmad-extension/skills/ml-eda/scripts/eda_analyzer.py +654 -0
- package/lib/bmad-extension/skills/ml-eda/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-experiment/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-experiment/SKILL.md +74 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/advanced_trainer_configs.py +430 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/quick_trainer_setup.py +233 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/template_datamodule.py +219 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/template_gnn_module.py +341 -0
- package/lib/bmad-extension/skills/ml-experiment/assets/template_lightning_module.py +158 -0
- package/lib/bmad-extension/skills/ml-experiment/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-experiment/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-hparam/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-hparam/SKILL.md +81 -0
- package/lib/bmad-extension/skills/ml-hparam/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-hparam/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-ideation/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-ideation/SKILL.md +50 -0
- package/lib/bmad-extension/skills/ml-ideation/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-ideation/scripts/validate_ml_prd.py +287 -0
- package/lib/bmad-extension/skills/ml-ideation/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-infra/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-infra/SKILL.md +58 -0
- package/lib/bmad-extension/skills/ml-infra/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-infra/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-retrospective/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-retrospective/SKILL.md +63 -0
- package/lib/bmad-extension/skills/ml-retrospective/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-retrospective/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-revision/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-revision/SKILL.md +82 -0
- package/lib/bmad-extension/skills/ml-revision/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-revision/skill.json +7 -0
- package/lib/bmad-extension/skills/ml-techspec/.gitkeep +0 -0
- package/lib/bmad-extension/skills/ml-techspec/SKILL.md +80 -0
- package/lib/bmad-extension/skills/ml-techspec/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/ml-techspec/skill.json +7 -0
- package/lib/bmad.js +85 -8
- package/lib/skill-authoring.js +1 -1
- package/package.json +5 -4
- package/test/agent-injection-strategy.test.js +4 -4
- package/test/bmad-version-bump.test.js +34 -34
- package/test/build-bmad-args.test.js +13 -6
- package/test/convert-agents-to-skills.test.js +11 -1
- package/test/extension-module-restructure.test.js +31 -7
- package/test/migration-validation.test.js +14 -11
- package/test/roo-code-agent.test.js +166 -0
- package/test/roo-code-injection.test.js +172 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Robust Interface Examples (C++14+)
|
|
2
|
+
|
|
3
|
+
### 1. Avoiding Boolean Blindness
|
|
4
|
+
**Incorrect:**
|
|
5
|
+
```cpp
|
|
6
|
+
void setWindowVisible(bool visible, bool animate);
|
|
7
|
+
// Call site: setWindowVisible(true, false); // What is false?
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
**Correct (C++14):**
|
|
11
|
+
```cpp
|
|
12
|
+
enum class Visibility { Visible, Hidden };
|
|
13
|
+
enum class Animation { Enabled, Disabled };
|
|
14
|
+
|
|
15
|
+
void setWindowVisible(Visibility v, Animation a);
|
|
16
|
+
// Call site: setWindowVisible(Visibility::Visible, Animation::Disabled);
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### 2. Contract-Based Validation
|
|
20
|
+
Using GSL (Guidelines Support Library) style:
|
|
21
|
+
|
|
22
|
+
```cpp
|
|
23
|
+
#include <gsl/gsl>
|
|
24
|
+
|
|
25
|
+
class User {
|
|
26
|
+
public:
|
|
27
|
+
// Ensure name is never null or empty
|
|
28
|
+
void setName(gsl::not_null<const char*> name) {
|
|
29
|
+
Expects(std::strlen(name) > 0);
|
|
30
|
+
this->name = name;
|
|
31
|
+
}
|
|
32
|
+
private:
|
|
33
|
+
std::string name;
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 3. Safe Sequences with Span
|
|
38
|
+
Replaces pointer + length pairs which are prone to buffer overflows.
|
|
39
|
+
|
|
40
|
+
```cpp
|
|
41
|
+
#include <gsl/gsl> // Use gsl::span in C++14
|
|
42
|
+
|
|
43
|
+
float calculateAverage(gsl::span<const float> values) {
|
|
44
|
+
Expects(!values.empty());
|
|
45
|
+
|
|
46
|
+
float sum = 0.0f;
|
|
47
|
+
for (float v : values) {
|
|
48
|
+
sum += v;
|
|
49
|
+
}
|
|
50
|
+
return sum / values.size();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Usage:
|
|
54
|
+
// float arr[] = {1, 2, 3};
|
|
55
|
+
// calculateAverage(arr); // Automatic conversion to span
|
|
56
|
+
```
|
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Create Hardened Docker
|
|
3
|
+
description: Creates production-ready hardened Docker configurations following CIS, OWASP, and NIST standards
|
|
4
|
+
---
|
|
5
|
+
# Create Hardened Docker
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This skill creates complete, production-ready Docker configurations with comprehensive security hardening:
|
|
10
|
+
- **Multi-stage Dockerfile** with non-root execution
|
|
11
|
+
- **Security-hardened docker-compose.yml** with read-only filesystem and capability controls
|
|
12
|
+
- **Production nginx.conf** with security headers and TLS configuration
|
|
13
|
+
- **Optimized .dockerignore** for build context reduction
|
|
14
|
+
- **DEPLOYMENT.md** documentation
|
|
15
|
+
|
|
16
|
+
All configurations comply with:
|
|
17
|
+
- **CIS Docker Benchmark v1.6.0**
|
|
18
|
+
- **OWASP Docker Security Cheat Sheet**
|
|
19
|
+
- **NIST Application Container Security Guide (SP 800-190)**
|
|
20
|
+
|
|
21
|
+
## Bundled Tools
|
|
22
|
+
|
|
23
|
+
### Scripts (scripts/)
|
|
24
|
+
| Script | Purpose |
|
|
25
|
+
|--------|---------|
|
|
26
|
+
| `create-dockerfile.sh` | Generate hardened multi-stage Dockerfile |
|
|
27
|
+
| `create-docker-compose.sh` | Generate security-hardened docker-compose.yml |
|
|
28
|
+
| `create-nginx-config.sh` | Generate production nginx.conf with security headers |
|
|
29
|
+
| `create-dockerignore.sh` | Generate optimized .dockerignore |
|
|
30
|
+
| `create-deployment-docs.sh` | Generate comprehensive DEPLOYMENT.md |
|
|
31
|
+
| `create-all.sh` | Generate all Docker configuration files |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Hardening Features
|
|
36
|
+
|
|
37
|
+
### Image Security
|
|
38
|
+
✅ Specific version tags (e.g., node:18.20.4-alpine3.20)
|
|
39
|
+
✅ Minimal Alpine base images (< 50MB final image)
|
|
40
|
+
✅ Multi-stage builds (build artifacts only, no source code)
|
|
41
|
+
✅ Non-root user execution (USER nginx)
|
|
42
|
+
✅ Read-only file permissions (chmod 444 for static files)
|
|
43
|
+
✅ Proper file ownership (chown nginx:nginx)
|
|
44
|
+
✅ Build cache cleanup (npm cache clean --force)
|
|
45
|
+
✅ Unnecessary packages removed (apk del --purge)
|
|
46
|
+
✅ HEALTHCHECK instruction
|
|
47
|
+
|
|
48
|
+
### Dockerfile Security
|
|
49
|
+
✅ Non-root user creation and usage
|
|
50
|
+
✅ Correct file ownership (chown)
|
|
51
|
+
✅ Read-only permissions for static content
|
|
52
|
+
✅ No sensitive data in ENV or ARG
|
|
53
|
+
✅ BuildKit secret mount support
|
|
54
|
+
✅ Minimal layer count
|
|
55
|
+
✅ Security-focused CMD (nginx foreground mode)
|
|
56
|
+
|
|
57
|
+
### docker-compose.yml Hardening
|
|
58
|
+
✅ Read-only root filesystem (read_only: true)
|
|
59
|
+
✅ Tmpfs mounts for writable directories (/tmp, /var/cache, /var/run)
|
|
60
|
+
✅ All capabilities dropped (cap_drop: ALL)
|
|
61
|
+
✅ Minimal capability additions (CHOWN, SETGID, SETUID)
|
|
62
|
+
✅ No-new-privileges enabled (prevents privilege escalation)
|
|
63
|
+
✅ Resource limits (memory: 512M, cpus: 1.0)
|
|
64
|
+
✅ Custom network isolation
|
|
65
|
+
✅ Health check configuration
|
|
66
|
+
✅ Restart policy (unless-stopped)
|
|
67
|
+
✅ No privileged mode
|
|
68
|
+
|
|
69
|
+
### Network Security (nginx)
|
|
70
|
+
✅ Nginx version hidden (server_tokens off)
|
|
71
|
+
✅ TLS 1.2+ only (ssl_protocols TLSv1.2 TLSv1.3)
|
|
72
|
+
✅ Strong cipher suites (ECDHE-ECDSA-AES128-GCM-SHA256+)
|
|
73
|
+
✅ HSTS header (Strict-Transport-Security)
|
|
74
|
+
✅ CSP headers (Content-Security-Policy)
|
|
75
|
+
✅ Security headers (X-Frame-Options, X-Content-Type-Options)
|
|
76
|
+
✅ Gzip compression for static assets
|
|
77
|
+
✅ Non-privileged ports (8080/8443) for non-root user
|
|
78
|
+
✅ Health check endpoint (/health)
|
|
79
|
+
|
|
80
|
+
### Secrets Management
|
|
81
|
+
✅ .env in .gitignore
|
|
82
|
+
✅ .env.example template
|
|
83
|
+
✅ No hardcoded secrets in Dockerfile
|
|
84
|
+
✅ BuildKit secret mount pattern
|
|
85
|
+
✅ Runtime secret injection via environment variables
|
|
86
|
+
✅ Secret validation documentation
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
### Quick Start - Create All Files
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Generate all hardened Docker files
|
|
96
|
+
./scripts/create-all.sh [app-name] [node-version] [nginx-version]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Example:**
|
|
100
|
+
```bash
|
|
101
|
+
./scripts/create-all.sh contacts-app 18.20.4 1.27.3
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This creates:
|
|
105
|
+
- `Dockerfile` - Multi-stage hardened build
|
|
106
|
+
- `docker-compose.yml` - Security-hardened orchestration
|
|
107
|
+
- `nginx.conf` - Production configuration with security headers
|
|
108
|
+
- `.dockerignore` - Build context optimization
|
|
109
|
+
- `DEPLOYMENT.md` - Deployment documentation
|
|
110
|
+
|
|
111
|
+
### Individual File Generation
|
|
112
|
+
|
|
113
|
+
#### Create Hardened Dockerfile
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
./scripts/create-dockerfile.sh [app-name] [node-version] [nginx-version]
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Example:**
|
|
120
|
+
```bash
|
|
121
|
+
./scripts/create-dockerfile.sh contacts-app 18.20.4 1.27.3
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**What it creates:**
|
|
125
|
+
- Multi-stage Dockerfile (build + production stages)
|
|
126
|
+
- Non-root user (nginx)
|
|
127
|
+
- Read-only static file permissions
|
|
128
|
+
- HEALTHCHECK instruction
|
|
129
|
+
- Optimized for production deployment
|
|
130
|
+
|
|
131
|
+
#### Create Security-Hardened docker-compose.yml
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
./scripts/create-docker-compose.sh [app-name]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Example:**
|
|
138
|
+
```bash
|
|
139
|
+
./scripts/create-docker-compose.sh contacts-app
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**What it includes:**
|
|
143
|
+
- Read-only root filesystem
|
|
144
|
+
- Tmpfs mounts for writable directories
|
|
145
|
+
- Capability dropping (cap_drop: ALL)
|
|
146
|
+
- Resource limits (memory, CPU)
|
|
147
|
+
- Security options (no-new-privileges)
|
|
148
|
+
- Health check configuration
|
|
149
|
+
|
|
150
|
+
#### Create Production nginx.conf
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
./scripts/create-nginx-config.sh [app-name]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Example:**
|
|
157
|
+
```bash
|
|
158
|
+
./scripts/create-nginx-config.sh contacts-app
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**What it includes:**
|
|
162
|
+
- SPA fallback routing (try_files)
|
|
163
|
+
- HTTPS redirect (HTTP → HTTPS)
|
|
164
|
+
- Security headers (CSP, HSTS, X-Frame-Options)
|
|
165
|
+
- Gzip compression
|
|
166
|
+
- Non-privileged ports (8080/8443)
|
|
167
|
+
- Health check endpoint
|
|
168
|
+
|
|
169
|
+
#### Create Optimized .dockerignore
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
./scripts/create-dockerignore.sh
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**What it excludes:**
|
|
176
|
+
- node_modules (rebuilt in container)
|
|
177
|
+
- .env files (security - prevents secret leakage)
|
|
178
|
+
- .git directory (not needed in container)
|
|
179
|
+
- Build outputs (generated in Docker build)
|
|
180
|
+
- Test files (not needed in production)
|
|
181
|
+
- Documentation files (not needed in container)
|
|
182
|
+
|
|
183
|
+
#### Create DEPLOYMENT.md Documentation
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
./scripts/create-deployment-docs.sh [app-name]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**What it documents:**
|
|
190
|
+
- Build instructions
|
|
191
|
+
- Security hardening features
|
|
192
|
+
- Vulnerability scanning process
|
|
193
|
+
- Secret management (development vs production)
|
|
194
|
+
- SSL/TLS certificate setup
|
|
195
|
+
- Troubleshooting guide
|
|
196
|
+
- CIS Docker Benchmark compliance
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Configuration Templates
|
|
201
|
+
|
|
202
|
+
### Dockerfile Template (Hardened Multi-Stage)
|
|
203
|
+
|
|
204
|
+
```dockerfile
|
|
205
|
+
# syntax=docker/dockerfile:1
|
|
206
|
+
|
|
207
|
+
# ============================================================================
|
|
208
|
+
# Stage 1: Build
|
|
209
|
+
# ============================================================================
|
|
210
|
+
FROM node:18.20.4-alpine3.20 AS builder
|
|
211
|
+
|
|
212
|
+
# Security: Create non-root user for build stage
|
|
213
|
+
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
|
|
214
|
+
|
|
215
|
+
# Set working directory
|
|
216
|
+
WORKDIR /app
|
|
217
|
+
|
|
218
|
+
# Copy package files with correct ownership
|
|
219
|
+
COPY --chown=nodejs:nodejs package*.json ./
|
|
220
|
+
|
|
221
|
+
# Install dependencies (production only)
|
|
222
|
+
RUN npm ci --only=production && \
|
|
223
|
+
npm cache clean --force
|
|
224
|
+
|
|
225
|
+
# Copy source files
|
|
226
|
+
COPY --chown=nodejs:nodejs . .
|
|
227
|
+
|
|
228
|
+
# Build application
|
|
229
|
+
RUN npm run build
|
|
230
|
+
|
|
231
|
+
# ============================================================================
|
|
232
|
+
# Stage 2: Production
|
|
233
|
+
# ============================================================================
|
|
234
|
+
FROM nginx:1.27.3-alpine3.20
|
|
235
|
+
|
|
236
|
+
# Security: Run as non-root user (nginx:alpine already has nginx user)
|
|
237
|
+
RUN touch /var/run/nginx.pid && \
|
|
238
|
+
# Create necessary directories with correct ownership
|
|
239
|
+
mkdir -p /var/cache/nginx /var/log/nginx && \
|
|
240
|
+
# Set ownership for nginx user
|
|
241
|
+
chown -R nginx:nginx /var/cache/nginx /var/log/nginx /var/run/nginx.pid && \
|
|
242
|
+
# Set correct permissions
|
|
243
|
+
chmod -R 755 /var/cache/nginx /var/log/nginx && \
|
|
244
|
+
# Remove default nginx files
|
|
245
|
+
rm -rf /usr/share/nginx/html/* && \
|
|
246
|
+
# Remove unnecessary packages (if any were added)
|
|
247
|
+
apk del --purge apk-tools
|
|
248
|
+
|
|
249
|
+
# Set working directory
|
|
250
|
+
WORKDIR /usr/share/nginx/html
|
|
251
|
+
|
|
252
|
+
# Copy build artifacts from builder stage with correct ownership
|
|
253
|
+
COPY --from=builder --chown=nginx:nginx /app/build .
|
|
254
|
+
|
|
255
|
+
# Copy nginx configuration
|
|
256
|
+
COPY --chown=nginx:nginx nginx.conf /etc/nginx/nginx.conf
|
|
257
|
+
|
|
258
|
+
# Security: Set read-only permissions for static files
|
|
259
|
+
RUN find /usr/share/nginx/html -type f -exec chmod 444 {} \; && \
|
|
260
|
+
find /usr/share/nginx/html -type d -exec chmod 555 {} \;
|
|
261
|
+
|
|
262
|
+
# Expose ports (8080/8443 for non-root user)
|
|
263
|
+
EXPOSE 8080 8443
|
|
264
|
+
|
|
265
|
+
# Security: Switch to non-root user
|
|
266
|
+
USER nginx
|
|
267
|
+
|
|
268
|
+
# Health check
|
|
269
|
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
270
|
+
CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
|
|
271
|
+
|
|
272
|
+
# Run nginx in foreground
|
|
273
|
+
CMD ["nginx", "-g", "daemon off;"]
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### docker-compose.yml Template (Security-Hardened)
|
|
277
|
+
|
|
278
|
+
```yaml
|
|
279
|
+
version: '3.8'
|
|
280
|
+
|
|
281
|
+
services:
|
|
282
|
+
contacts-app:
|
|
283
|
+
build:
|
|
284
|
+
context: .
|
|
285
|
+
dockerfile: Dockerfile
|
|
286
|
+
container_name: contacts-app
|
|
287
|
+
|
|
288
|
+
# Port mapping (host:container)
|
|
289
|
+
ports:
|
|
290
|
+
- "80:8080" # HTTP
|
|
291
|
+
- "443:8443" # HTTPS
|
|
292
|
+
|
|
293
|
+
# Environment variables
|
|
294
|
+
environment:
|
|
295
|
+
- NODE_ENV=production
|
|
296
|
+
|
|
297
|
+
# Mount .env file as read-only
|
|
298
|
+
env_file:
|
|
299
|
+
- .env
|
|
300
|
+
|
|
301
|
+
# Security: Read-only root filesystem
|
|
302
|
+
read_only: true
|
|
303
|
+
|
|
304
|
+
# Security: Tmpfs mounts for writable directories
|
|
305
|
+
tmpfs:
|
|
306
|
+
- /tmp
|
|
307
|
+
- /var/cache/nginx
|
|
308
|
+
- /var/run
|
|
309
|
+
|
|
310
|
+
# Security: Drop all capabilities and add only required ones
|
|
311
|
+
cap_drop:
|
|
312
|
+
- ALL
|
|
313
|
+
cap_add:
|
|
314
|
+
- CHOWN
|
|
315
|
+
- SETGID
|
|
316
|
+
- SETUID
|
|
317
|
+
|
|
318
|
+
# Security: Prevent privilege escalation
|
|
319
|
+
security_opt:
|
|
320
|
+
- no-new-privileges:true
|
|
321
|
+
|
|
322
|
+
# Resource limits
|
|
323
|
+
deploy:
|
|
324
|
+
resources:
|
|
325
|
+
limits:
|
|
326
|
+
cpus: '1.0'
|
|
327
|
+
memory: 512M
|
|
328
|
+
reservations:
|
|
329
|
+
cpus: '0.5'
|
|
330
|
+
memory: 256M
|
|
331
|
+
|
|
332
|
+
# Restart policy
|
|
333
|
+
restart: unless-stopped
|
|
334
|
+
|
|
335
|
+
# Health check
|
|
336
|
+
healthcheck:
|
|
337
|
+
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"]
|
|
338
|
+
interval: 30s
|
|
339
|
+
timeout: 10s
|
|
340
|
+
retries: 3
|
|
341
|
+
start_period: 40s
|
|
342
|
+
|
|
343
|
+
# Network isolation
|
|
344
|
+
networks:
|
|
345
|
+
- contacts-network
|
|
346
|
+
|
|
347
|
+
networks:
|
|
348
|
+
contacts-network:
|
|
349
|
+
driver: bridge
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### nginx.conf Template (Production with Security Headers)
|
|
353
|
+
|
|
354
|
+
```nginx
|
|
355
|
+
worker_processes auto;
|
|
356
|
+
error_log /var/log/nginx/error.log warn;
|
|
357
|
+
|
|
358
|
+
events {
|
|
359
|
+
worker_connections 1024;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
http {
|
|
363
|
+
include /etc/nginx/mime.types;
|
|
364
|
+
default_type application/octet-stream;
|
|
365
|
+
|
|
366
|
+
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
367
|
+
'$status $body_bytes_sent "$http_referer" '
|
|
368
|
+
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
369
|
+
|
|
370
|
+
access_log /var/log/nginx/access.log main;
|
|
371
|
+
|
|
372
|
+
sendfile on;
|
|
373
|
+
tcp_nopush on;
|
|
374
|
+
tcp_nodelay on;
|
|
375
|
+
keepalive_timeout 65;
|
|
376
|
+
types_hash_max_size 2048;
|
|
377
|
+
|
|
378
|
+
# Security: Hide nginx version
|
|
379
|
+
server_tokens off;
|
|
380
|
+
|
|
381
|
+
# Gzip compression
|
|
382
|
+
gzip on;
|
|
383
|
+
gzip_disable "msie6";
|
|
384
|
+
gzip_vary on;
|
|
385
|
+
gzip_proxied any;
|
|
386
|
+
gzip_comp_level 6;
|
|
387
|
+
gzip_types text/plain text/css text/xml text/javascript
|
|
388
|
+
application/json application/javascript application/xml+rss
|
|
389
|
+
application/rss+xml font/truetype font/opentype
|
|
390
|
+
application/vnd.ms-fontobject image/svg+xml;
|
|
391
|
+
gzip_min_length 1000;
|
|
392
|
+
|
|
393
|
+
# HTTP server - redirect to HTTPS (port 8080 for non-root)
|
|
394
|
+
server {
|
|
395
|
+
listen 8080;
|
|
396
|
+
server_name _;
|
|
397
|
+
|
|
398
|
+
# Allow health check on HTTP
|
|
399
|
+
location /health {
|
|
400
|
+
access_log off;
|
|
401
|
+
return 200 "healthy\n";
|
|
402
|
+
add_header Content-Type text/plain;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
# Redirect all other traffic to HTTPS
|
|
406
|
+
location / {
|
|
407
|
+
return 301 https://$host$request_uri;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
# HTTPS server (port 8443 for non-root)
|
|
412
|
+
server {
|
|
413
|
+
listen 8443 ssl http2;
|
|
414
|
+
server_name _;
|
|
415
|
+
|
|
416
|
+
# SSL certificate paths (user must provide)
|
|
417
|
+
# ssl_certificate /etc/nginx/ssl/cert.pem;
|
|
418
|
+
# ssl_certificate_key /etc/nginx/ssl/key.pem;
|
|
419
|
+
|
|
420
|
+
# SSL security settings
|
|
421
|
+
ssl_protocols TLSv1.2 TLSv1.3;
|
|
422
|
+
ssl_prefer_server_ciphers on;
|
|
423
|
+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
|
|
424
|
+
|
|
425
|
+
root /usr/share/nginx/html;
|
|
426
|
+
index index.html;
|
|
427
|
+
|
|
428
|
+
# Security headers
|
|
429
|
+
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://people.googleapis.com https://oauth2.googleapis.com; font-src 'self' data:;" always;
|
|
430
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
431
|
+
add_header X-Frame-Options "DENY" always;
|
|
432
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
|
433
|
+
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
434
|
+
|
|
435
|
+
# SPA fallback routing
|
|
436
|
+
location / {
|
|
437
|
+
try_files $uri $uri/ /index.html;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
# Cache static assets
|
|
441
|
+
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
442
|
+
expires 1y;
|
|
443
|
+
add_header Cache-Control "public, immutable";
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
# No caching for index.html
|
|
447
|
+
location = /index.html {
|
|
448
|
+
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
# Health check endpoint
|
|
452
|
+
location /health {
|
|
453
|
+
access_log off;
|
|
454
|
+
return 200 "healthy\n";
|
|
455
|
+
add_header Content-Type text/plain;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Customization Options
|
|
464
|
+
|
|
465
|
+
### Application-Specific Modifications
|
|
466
|
+
|
|
467
|
+
#### Node.js Version
|
|
468
|
+
|
|
469
|
+
Update the `FROM` line in Dockerfile:
|
|
470
|
+
```dockerfile
|
|
471
|
+
FROM node:20.11.1-alpine3.19 AS builder
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
#### Build Command
|
|
475
|
+
|
|
476
|
+
Customize build command in Dockerfile:
|
|
477
|
+
```dockerfile
|
|
478
|
+
RUN npm run build:prod # or your custom build command
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### Output Directory
|
|
482
|
+
|
|
483
|
+
Change if your build outputs to a different directory:
|
|
484
|
+
```dockerfile
|
|
485
|
+
COPY --from=builder --chown=nginx:nginx /app/dist . # instead of /app/build
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
#### Port Configuration
|
|
489
|
+
|
|
490
|
+
**Option 1: Non-privileged ports (Recommended)**
|
|
491
|
+
```dockerfile
|
|
492
|
+
EXPOSE 8080 8443
|
|
493
|
+
```
|
|
494
|
+
```yaml
|
|
495
|
+
ports:
|
|
496
|
+
- "80:8080"
|
|
497
|
+
- "443:8443"
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
**Option 2: Privileged ports with capability**
|
|
501
|
+
```dockerfile
|
|
502
|
+
EXPOSE 80 443
|
|
503
|
+
```
|
|
504
|
+
```yaml
|
|
505
|
+
ports:
|
|
506
|
+
- "80:80"
|
|
507
|
+
- "443:443"
|
|
508
|
+
cap_add:
|
|
509
|
+
- NET_BIND_SERVICE
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
#### Resource Limits
|
|
513
|
+
|
|
514
|
+
Adjust based on your application needs:
|
|
515
|
+
```yaml
|
|
516
|
+
deploy:
|
|
517
|
+
resources:
|
|
518
|
+
limits:
|
|
519
|
+
cpus: '2.0' # Increase CPU
|
|
520
|
+
memory: 1024M # Increase memory
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
#### Content Security Policy (CSP)
|
|
524
|
+
|
|
525
|
+
Customize CSP for your application:
|
|
526
|
+
```nginx
|
|
527
|
+
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self' https://api.example.com;" always;
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Security Checklist
|
|
533
|
+
|
|
534
|
+
After creating Docker files, verify the configuration:
|
|
535
|
+
|
|
536
|
+
### Image Security
|
|
537
|
+
- [ ] ✅ Specific version tags (node:18.20.4-alpine3.20, nginx:1.27.3-alpine3.20)
|
|
538
|
+
- [ ] ✅ Non-root user (USER nginx)
|
|
539
|
+
- [ ] ✅ Read-only file permissions (chmod 444)
|
|
540
|
+
- [ ] ✅ HEALTHCHECK instruction
|
|
541
|
+
- [ ] ✅ No hardcoded secrets
|
|
542
|
+
|
|
543
|
+
### Runtime Security
|
|
544
|
+
- [ ] ✅ Read-only root filesystem (read_only: true)
|
|
545
|
+
- [ ] ✅ Tmpfs mounts (/tmp, /var/cache, /var/run)
|
|
546
|
+
- [ ] ✅ Capabilities dropped (cap_drop: ALL)
|
|
547
|
+
- [ ] ✅ No-new-privileges enabled
|
|
548
|
+
- [ ] ✅ Resource limits set
|
|
549
|
+
|
|
550
|
+
### Network Security
|
|
551
|
+
- [ ] ✅ Server version hidden (server_tokens off)
|
|
552
|
+
- [ ] ✅ TLS 1.2+ only
|
|
553
|
+
- [ ] ✅ Security headers (CSP, HSTS, X-Frame-Options)
|
|
554
|
+
- [ ] ✅ Gzip compression enabled
|
|
555
|
+
|
|
556
|
+
### Secrets Management
|
|
557
|
+
- [ ] ✅ .env in .gitignore
|
|
558
|
+
- [ ] ✅ .env.example exists
|
|
559
|
+
- [ ] ✅ No .env in Docker image
|
|
560
|
+
- [ ] ✅ No secrets in Dockerfile
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## Testing the Configuration
|
|
565
|
+
|
|
566
|
+
After creating the files, test the configuration:
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
# 1. Build the Docker image
|
|
570
|
+
docker build -t [app-name] .
|
|
571
|
+
|
|
572
|
+
# 2. Verify image size (should be < 100MB)
|
|
573
|
+
docker images [app-name]
|
|
574
|
+
|
|
575
|
+
# 3. Scan for vulnerabilities
|
|
576
|
+
trivy image [app-name]
|
|
577
|
+
|
|
578
|
+
# 4. Scan for secrets
|
|
579
|
+
trivy image --scanners secret [app-name]
|
|
580
|
+
|
|
581
|
+
# 5. Start the container
|
|
582
|
+
docker-compose up -d
|
|
583
|
+
|
|
584
|
+
# 6. Verify non-root user
|
|
585
|
+
docker exec [app-name] whoami
|
|
586
|
+
# Expected: nginx
|
|
587
|
+
|
|
588
|
+
# 7. Verify read-only filesystem
|
|
589
|
+
docker exec [app-name] touch /test
|
|
590
|
+
# Expected: Permission denied
|
|
591
|
+
|
|
592
|
+
# 8. Verify tmpfs is writable
|
|
593
|
+
docker exec [app-name] touch /tmp/test
|
|
594
|
+
# Expected: Success
|
|
595
|
+
|
|
596
|
+
# 9. Verify health status
|
|
597
|
+
docker ps
|
|
598
|
+
# Expected: (healthy) status
|
|
599
|
+
|
|
600
|
+
# 10. Test application
|
|
601
|
+
curl http://localhost
|
|
602
|
+
# Expected: Application loads
|
|
603
|
+
|
|
604
|
+
# 11. Verify security headers
|
|
605
|
+
curl -I https://localhost
|
|
606
|
+
# Expected: CSP, HSTS, X-Frame-Options headers
|
|
607
|
+
|
|
608
|
+
# 12. Clean up
|
|
609
|
+
docker-compose down
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## CIS Docker Benchmark Compliance
|
|
615
|
+
|
|
616
|
+
The generated configurations comply with CIS Docker Benchmark v1.6.0:
|
|
617
|
+
|
|
618
|
+
| CIS ID | Control | Implementation |
|
|
619
|
+
|--------|---------|----------------|
|
|
620
|
+
| 4.1 | Create user for container | `USER nginx` in Dockerfile |
|
|
621
|
+
| 4.3 | Verify file permissions | `chmod 444` for static files |
|
|
622
|
+
| 4.5 | Enable Content trust | Specific version tags |
|
|
623
|
+
| 5.7 | Don't map privileged ports | Ports 8080/8443 (non-root) |
|
|
624
|
+
| 5.10 | Set memory limit | `memory: 512M` in docker-compose.yml |
|
|
625
|
+
| 5.11 | Set CPU priority | `cpus: '1.0'` in docker-compose.yml |
|
|
626
|
+
| 5.12 | Read-only root filesystem | `read_only: true` in docker-compose.yml |
|
|
627
|
+
| 5.25 | No new privileges | `no-new-privileges:true` in docker-compose.yml |
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## References
|
|
632
|
+
|
|
633
|
+
- [CIS Docker Benchmark v1.6.0](https://www.cisecurity.org/benchmark/docker)
|
|
634
|
+
- [OWASP Docker Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html)
|
|
635
|
+
- [NIST SP 800-190](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-190.pdf)
|
|
636
|
+
- [Docker Security Best Practices](https://docs.docker.com/develop/security-best-practices/)
|
|
637
|
+
- [Snyk Docker Security Best Practices](https://snyk.io/blog/10-docker-image-security-best-practices/)
|