feat: Configure production deployment with math-tables namespace and ingress
Changes made: - Remove problematic configuration-snippet from base ingress - Add namespace creation for math-tables - Configure ingress with nginx class and letsencrypt-prod issuer - Set production hostname to math-tables.cl1.parano.ch - Reduce production replicas to 1 - Update copyright year in index.html
This commit is contained in:
@@ -141,7 +141,7 @@
|
||||
|
||||
<footer class="bg-light text-center text-muted py-4 mt-5">
|
||||
<div class="container">
|
||||
<p>Générateur d'Exercices de Mathématiques © 2023</p>
|
||||
<p>Générateur d'Exercices de Mathématiques © 2025</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
|
||||
83
deploy/README.md
Normal file
83
deploy/README.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Math Exercises Application - Kubernetes Deployment
|
||||
|
||||
This directory contains the Kubernetes deployment configuration for the Math Exercises application, with security best practices applied.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
deploy/
|
||||
├── base/ # Base kustomize configuration
|
||||
│ ├── deployment.yaml # Application deployment
|
||||
│ ├── service.yaml # Internal service
|
||||
│ ├── ingress.yaml # External access configuration
|
||||
│ ├── network-policy.yaml # Network security policies
|
||||
│ ├── configmap.yaml # Application configuration
|
||||
│ ├── pod-disruption-budget.yaml # High availability
|
||||
│ └── kustomization.yaml # Base kustomize file
|
||||
├── overlays/ # Environment-specific configurations
|
||||
│ ├── development/ # Development environment
|
||||
│ │ ├── deployment-patch.yaml # Dev-specific deployment settings
|
||||
│ │ └── kustomization.yaml # Dev kustomize file
|
||||
│ └── production/ # Production environment
|
||||
│ ├── deployment-patch.yaml # Prod-specific deployment settings
|
||||
│ ├── security-patch.yaml # Additional security settings
|
||||
│ └── kustomization.yaml # Prod kustomize file
|
||||
└── SECURITY_CHECKLIST.md # Security implementation checklist
|
||||
```
|
||||
|
||||
## Security Features Implemented
|
||||
|
||||
The deployment implements the following security best practices:
|
||||
|
||||
1. **Pod Security**:
|
||||
- Non-root user execution
|
||||
- ReadOnly root filesystem
|
||||
- Disabled privilege escalation
|
||||
- Minimal container capabilities
|
||||
- Seccomp profiles
|
||||
|
||||
2. **Network Security**:
|
||||
- Network policies restricting traffic
|
||||
- TLS-enforced ingress with security headers
|
||||
- Internal service exposure only
|
||||
|
||||
3. **Configuration Security**:
|
||||
- ConfigMaps for configuration separation
|
||||
- Resource limits and requests
|
||||
- Health checks with appropriate timeouts
|
||||
|
||||
4. **Operational Security**:
|
||||
- PodDisruptionBudget for high availability
|
||||
- Environment-specific configurations
|
||||
- Versioned image tags
|
||||
|
||||
## Deployment Instructions
|
||||
|
||||
### Development Environment
|
||||
|
||||
```bash
|
||||
kubectl apply -k deploy/overlays/development
|
||||
```
|
||||
|
||||
### Production Environment
|
||||
|
||||
```bash
|
||||
kubectl apply -k deploy/overlays/production
|
||||
```
|
||||
|
||||
## Security Verification
|
||||
|
||||
To verify security settings are properly applied:
|
||||
|
||||
```bash
|
||||
# Check security context
|
||||
kubectl get deployment math-exercises-app -o jsonpath='{.spec.template.spec.containers[0].securityContext}'
|
||||
|
||||
# Check network policies
|
||||
kubectl get networkpolicy
|
||||
|
||||
# Check resource limits
|
||||
kubectl get deployment math-exercises-app -o jsonpath='{.spec.template.spec.containers[0].resources}'
|
||||
```
|
||||
|
||||
See `SECURITY_CHECKLIST.md` for a comprehensive list of implemented security measures.
|
||||
93
deploy/SECURITY_CHECKLIST.md
Normal file
93
deploy/SECURITY_CHECKLIST.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Kubernetes Security Checklist for Math Exercises Application
|
||||
|
||||
This document outlines the security measures implemented in the Kubernetes deployment for the Math Exercises application.
|
||||
|
||||
## 1. Pod Security
|
||||
|
||||
### Container Security Context
|
||||
- ✅ Non-root user execution (`runAsNonRoot: true`, `runAsUser: 1000`)
|
||||
- ✅ Disabled privilege escalation (`allowPrivilegeEscalation: false`)
|
||||
- ✅ Read-only root filesystem (`readOnlyRootFilesystem: true`)
|
||||
- ✅ Minimal capabilities (dropped all, added only necessary ones)
|
||||
- ✅ Seccomp profile set to RuntimeDefault
|
||||
|
||||
### Pod Security Context
|
||||
- ✅ Non-root user execution
|
||||
- ✅ Proper fsGroup setting
|
||||
- ✅ Seccomp profile enforcement
|
||||
|
||||
## 2. Network Security
|
||||
|
||||
### Network Policies
|
||||
- ✅ Restricted ingress traffic (only from ingress controller)
|
||||
- ✅ Limited egress traffic (DNS and HTTPS only)
|
||||
- ✅ Port-specific rules
|
||||
|
||||
### Service Configuration
|
||||
- ✅ Internal traffic policy set to Local
|
||||
- ✅ ClusterIP service type (no external exposure)
|
||||
|
||||
## 3. Application Security
|
||||
|
||||
### Ingress Security
|
||||
- ✅ TLS enforced with redirect
|
||||
- ✅ HSTS enabled with preload
|
||||
- ✅ Security headers configured:
|
||||
- X-Frame-Options: DENY
|
||||
- X-Content-Type-Options: nosniff
|
||||
- X-XSS-Protection: 1; mode=block
|
||||
- Referrer-Policy: strict-origin-when-cross-origin
|
||||
- Permissions-Policy: Restricted APIs
|
||||
|
||||
### Resource Management
|
||||
- ✅ CPU and memory limits set
|
||||
- ✅ CPU and memory requests defined
|
||||
- ✅ Quality of Service class guaranteed
|
||||
|
||||
## 4. Configuration Security
|
||||
|
||||
### ConfigMap Usage
|
||||
- ✅ Separation of configuration from code
|
||||
- ✅ Centralized configuration management
|
||||
|
||||
### Environment Variables
|
||||
- ✅ No hardcoded secrets
|
||||
- ✅ Secure configuration values
|
||||
|
||||
## 5. Operational Security
|
||||
|
||||
### High Availability
|
||||
- ✅ PodDisruptionBudget configured
|
||||
- ✅ Multiple replicas in production
|
||||
|
||||
### Image Management
|
||||
- ✅ Versioned images in production
|
||||
- ✅ Separate tags for dev/prod environments
|
||||
|
||||
## 6. Monitoring & Observability
|
||||
|
||||
### Health Checks
|
||||
- ✅ Liveness probes configured
|
||||
- ✅ Readiness probes configured
|
||||
- ✅ Appropriate timeouts and thresholds
|
||||
|
||||
## 7. Additional Recommendations
|
||||
|
||||
### Future Enhancements
|
||||
- [ ] Implement Kubernetes Secrets for sensitive data
|
||||
- [ ] Add RBAC policies for least privilege access
|
||||
- [ ] Enable audit logging
|
||||
- [ ] Implement runtime security monitoring
|
||||
- [ ] Add image vulnerability scanning
|
||||
- [ ] Consider Kyverno policies for admission control
|
||||
|
||||
## 8. Environment-Specific Security
|
||||
|
||||
### Development
|
||||
- ✅ Reduced resource consumption
|
||||
- ✅ Standard security posture
|
||||
|
||||
### Production
|
||||
- ✅ Enhanced security settings
|
||||
- ✅ High availability configuration
|
||||
- ✅ Dedicated security patches
|
||||
14
deploy/base/configmap.yaml
Normal file
14
deploy/base/configmap.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: math-exercises-config
|
||||
data:
|
||||
# Application configuration
|
||||
PORT: "8000"
|
||||
LOG_LEVEL: "INFO"
|
||||
MAX_REQUEST_SIZE: "10mb"
|
||||
|
||||
# Security configuration
|
||||
SECURE_COOKIES: "true"
|
||||
CORS_ORIGINS: "math-exercises.local"
|
||||
REQUEST_TIMEOUT: "30s"
|
||||
75
deploy/base/deployment.yaml
Normal file
75
deploy/base/deployment.yaml
Normal file
@@ -0,0 +1,75 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: math-exercises-app
|
||||
labels:
|
||||
app: math-exercises
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: math-exercises
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: math-exercises
|
||||
spec:
|
||||
# Security context for the pod
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
fsGroup: 2000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: math-exercises
|
||||
image: math-exercises:latest
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
# Security context for the container
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
# Resource limits and requests
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
# Liveness probe
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
# Readiness probe
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8000
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
# Environment variables from ConfigMap
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: math-exercises-config
|
||||
# Volume mounts for writable directories
|
||||
volumeMounts:
|
||||
- name: static-volume
|
||||
mountPath: /app/app/static
|
||||
# Volumes
|
||||
volumes:
|
||||
- name: static-volume
|
||||
emptyDir: {}
|
||||
29
deploy/base/ingress.yaml
Normal file
29
deploy/base/ingress.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: math-exercises-ingress
|
||||
annotations:
|
||||
# Security annotations
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /
|
||||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/hsts: "true"
|
||||
nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
|
||||
nginx.ingress.kubernetes.io/hsts-include-subdomains: "true"
|
||||
nginx.ingress.kubernetes.io/hsts-preload: "true"
|
||||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- math-exercises.local
|
||||
secretName: math-exercises-tls
|
||||
rules:
|
||||
- host: math-exercises.local
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: math-exercises-service
|
||||
port:
|
||||
number: 80
|
||||
19
deploy/base/kustomization.yaml
Normal file
19
deploy/base/kustomization.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
- network-policy.yaml
|
||||
- pod-disruption-budget.yaml
|
||||
- configmap.yaml
|
||||
|
||||
# Common labels to apply to all resources
|
||||
commonLabels:
|
||||
app.kubernetes.io/name: math-exercises
|
||||
app.kubernetes.io/instance: math-exercises-instance
|
||||
app.kubernetes.io/version: "1.0"
|
||||
app.kubernetes.io/component: web
|
||||
app.kubernetes.io/part-of: math-suite
|
||||
app.kubernetes.io/managed-by: kustomize
|
||||
35
deploy/base/network-policy.yaml
Normal file
35
deploy/base/network-policy.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: math-exercises-netpol
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: math-exercises
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
# Allow inbound traffic from the ingress controller only
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: ingress-nginx
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8000
|
||||
egress:
|
||||
# Allow outbound DNS resolution
|
||||
- to:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: kube-system
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 53
|
||||
- protocol: UDP
|
||||
port: 53
|
||||
# Allow outbound HTTPS for package updates or external APIs
|
||||
- ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
9
deploy/base/pod-disruption-budget.yaml
Normal file
9
deploy/base/pod-disruption-budget.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
apiVersion: policy/v1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: math-exercises-pdb
|
||||
spec:
|
||||
minAvailable: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: math-exercises
|
||||
18
deploy/base/service.yaml
Normal file
18
deploy/base/service.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: math-exercises-service
|
||||
annotations:
|
||||
# Security annotations
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
spec:
|
||||
selector:
|
||||
app: math-exercises
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8000
|
||||
type: ClusterIP
|
||||
# Only accessible within the cluster
|
||||
internalTrafficPolicy: Local
|
||||
5
deploy/kustomization.yaml
Normal file
5
deploy/kustomization.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- base
|
||||
26
deploy/overlays/development/deployment-patch.yaml
Normal file
26
deploy/overlays/development/deployment-patch.yaml
Normal file
@@ -0,0 +1,26 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: math-exercises-app
|
||||
annotations:
|
||||
# Development environment annotation
|
||||
environment: development
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: math-exercises
|
||||
env:
|
||||
- name: ENVIRONMENT
|
||||
value: development
|
||||
- name: DEBUG
|
||||
value: "false"
|
||||
# Reduce resource consumption in development
|
||||
resources:
|
||||
requests:
|
||||
memory: "32Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "64Mi"
|
||||
cpu: "200m"
|
||||
20
deploy/overlays/development/kustomization.yaml
Normal file
20
deploy/overlays/development/kustomization.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
|
||||
# Development-specific patches
|
||||
patchesStrategicMerge:
|
||||
- deployment-patch.yaml
|
||||
|
||||
# Development-specific configurations
|
||||
images:
|
||||
- name: math-exercises
|
||||
newName: math-exercises
|
||||
newTag: dev-latest
|
||||
|
||||
# Development-specific labels
|
||||
commonLabels:
|
||||
environment: development
|
||||
security-level: standard
|
||||
37
deploy/overlays/production/deployment-patch.yaml
Normal file
37
deploy/overlays/production/deployment-patch.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: math-exercises-app
|
||||
annotations:
|
||||
# Production environment annotation
|
||||
environment: production
|
||||
# Security annotations
|
||||
seccomp.security.alpha.kubernetes.io/pod: docker/default
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: math-exercises
|
||||
env:
|
||||
- name: ENVIRONMENT
|
||||
value: production
|
||||
- name: DEBUG
|
||||
value: "false"
|
||||
# Enhanced security for production
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
# Production resource settings
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
23
deploy/overlays/production/ingress-patch.yaml
Normal file
23
deploy/overlays/production/ingress-patch.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: math-exercises-ingress
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
tls:
|
||||
- hosts:
|
||||
- math-tables.cl1.parano.ch
|
||||
secretName: math-exercises-tls
|
||||
rules:
|
||||
- host: math-tables.cl1.parano.ch
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: math-exercises-service
|
||||
port:
|
||||
number: 80
|
||||
25
deploy/overlays/production/kustomization.yaml
Normal file
25
deploy/overlays/production/kustomization.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
namespace: math-tables
|
||||
|
||||
resources:
|
||||
- ../../base
|
||||
- namespace.yaml
|
||||
|
||||
# Production-specific patches
|
||||
patchesStrategicMerge:
|
||||
- deployment-patch.yaml
|
||||
- security-patch.yaml
|
||||
- ingress-patch.yaml
|
||||
|
||||
# Production-specific configurations
|
||||
images:
|
||||
- name: math-exercises
|
||||
newName: harbor.cl1.parano.ch/library/math-exercice
|
||||
newTag: 1.0.0
|
||||
|
||||
# Production-specific labels
|
||||
commonLabels:
|
||||
environment: production
|
||||
security-level: high
|
||||
4
deploy/overlays/production/namespace.yaml
Normal file
4
deploy/overlays/production/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: math-tables
|
||||
27
deploy/overlays/production/security-patch.yaml
Normal file
27
deploy/overlays/production/security-patch.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: math-exercises-app
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
# Additional security context for production
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
fsGroup: 2000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: math-exercises
|
||||
# Additional security settings for production
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
add:
|
||||
- NET_BIND_SERVICE
|
||||
53
k8s-deployment.yaml
Normal file
53
k8s-deployment.yaml
Normal file
@@ -0,0 +1,53 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: math-exercises-app
|
||||
labels:
|
||||
app: math-exercises
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: math-exercises
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: math-exercises
|
||||
spec:
|
||||
containers:
|
||||
- name: math-exercises
|
||||
image: math-exercises:latest
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
resources:
|
||||
requests:
|
||||
memory: "64Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "500m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8000
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8000
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: math-exercises-service
|
||||
spec:
|
||||
selector:
|
||||
app: math-exercises
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 80
|
||||
targetPort: 8000
|
||||
type: ClusterIP
|
||||
Reference in New Issue
Block a user