Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add nginx, robots.txt, HTTP headers #7683

Merged
merged 11 commits into from
Jul 15, 2024
2 changes: 2 additions & 0 deletions ietf/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.contrib import admin
from django.contrib.sitemaps import views as sitemap_views
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.http import HttpResponse
from django.urls import include, path
from django.views import static as static_view
from django.views.generic import TemplateView
Expand Down Expand Up @@ -35,6 +36,7 @@

urlpatterns = [
url(r'^$', views_search.frontpage),
url(r'^health/', lambda _: HttpResponse()),
url(r'^accounts/', include('ietf.ietfauth.urls')),
url(r'^admin/', admin.site.urls),
url(r'^admin/docs/', include('django.contrib.admindocs.urls')),
Expand Down
9 changes: 9 additions & 0 deletions ietf/utils/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,3 +679,12 @@ class TestForm(Form):
self.assertTrue(changed_form.has_changed())
unchanged_form = TestForm(initial={'test_field': [1]}, data={'test_field': [1]})
self.assertFalse(unchanged_form.has_changed())


class HealthTests(TestCase):
def test_health(self):
self.assertEqual(
self.client.get("/health/").status_code,
200,
)

48 changes: 41 additions & 7 deletions k8s/auth.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,11 @@ spec:
runAsUser: 65534 # "nobody" user by default
runAsGroup: 65534 # "nogroup" group by default
# -----------------------------------------------------
# Datatracker Container
# Auth Container
# -----------------------------------------------------
- name: datatracker
- name: auth
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
imagePullPolicy: Always
ports:
- containerPort: 8000
name: http
protocol: TCP
volumeMounts:
- name: dt-vol
mountPath: /a
Expand All @@ -74,6 +70,14 @@ spec:
envFrom:
- configMapRef:
name: django-config
startupProbe:
httpGet:
port: 8000
path: /health/
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
timeoutSeconds: 3
securityContext:
allowPrivilegeEscalation: false
capabilities:
Expand All @@ -82,6 +86,28 @@ spec:
readOnlyRootFilesystem: true
runAsUser: 1000
runAsGroup: 1000
# -----------------------------------------------------
# Nginx Container
# -----------------------------------------------------
- name: nginx
image: "ghcr.io/nginxinc/nginx-unprivileged:1.27"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
protocol: TCP
livenessProbe:
httpGet:
port: 8080
path: /health/nginx
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- name: nginx-tmp
mountPath: /tmp
- name: dt-cfg
mountPath: /etc/nginx/conf.d/auth.conf
subPath: nginx-auth.conf
volumes:
# To be overriden with the actual shared volume
- name: dt-vol
Expand All @@ -97,6 +123,9 @@ spec:
- name: dt-cfg
configMap:
name: files-cfgmap
- name: nginx-tmp
emptyDir:
sizeLimit: "500Mi"
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 60
Expand All @@ -108,9 +137,14 @@ metadata:
spec:
type: ClusterIP
ports:
- port: 8080
#
- port: 80
targetPort: http
protocol: TCP
name: http
- port: 8080
targetPort: http
protocol: TCP
name: http-old
selector:
app: auth
37 changes: 33 additions & 4 deletions k8s/datatracker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ spec:
- name: datatracker
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
imagePullPolicy: Always
ports:
- containerPort: 8000
name: http
protocol: TCP
volumeMounts:
- name: dt-vol
mountPath: /a
Expand All @@ -74,6 +70,14 @@ spec:
envFrom:
- configMapRef:
name: django-config
startupProbe:
httpGet:
port: 8000
path: /health/
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
timeoutSeconds: 3
securityContext:
allowPrivilegeEscalation: false
capabilities:
Expand All @@ -82,6 +86,28 @@ spec:
readOnlyRootFilesystem: true
runAsUser: 1000
runAsGroup: 1000
# -----------------------------------------------------
# Nginx Container
# -----------------------------------------------------
- name: nginx
image: "ghcr.io/nginxinc/nginx-unprivileged:1.27"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
protocol: TCP
livenessProbe:
httpGet:
port: 8080
path: /health/nginx
securityContext:
readOnlyRootFilesystem: true
volumeMounts:
- name: nginx-tmp
mountPath: /tmp
- name: dt-cfg
mountPath: /etc/nginx/conf.d/datatracker.conf
subPath: nginx-datatracker.conf
initContainers:
- name: migration
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
Expand Down Expand Up @@ -126,6 +152,9 @@ spec:
- name: dt-cfg
configMap:
name: files-cfgmap
- name: nginx-tmp
emptyDir:
sizeLimit: "500Mi"
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 60
Expand Down
2 changes: 2 additions & 0 deletions k8s/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ namePrefix: dt-
configMapGenerator:
- name: files-cfgmap
files:
- nginx-auth.conf
- nginx-datatracker.conf
- settings_local.py
resources:
- auth.yaml
Expand Down
34 changes: 34 additions & 0 deletions k8s/nginx-auth.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
server {
listen 8080 default_server;
server_name _;

# Note that regex location matches take priority over non-regex "prefix" matches. Use regexes so that
# our deny all rule does not squelch the other locations.
location ~ ^/health/nginx$ {
return 200;
}

location ~ ^/robots.txt$ {
add_header Content-Type text/plain;
return 200 "User-agent: *\nDisallow: /\n";
}

location ~ ^/accounts/create.* {
return 302 https://datatracker.ietf.org/accounts/create;
}

# n.b. (?!...) is a negative lookahead group
location ~ ^(/(?!(api/openid/|accounts/login/|accounts/logout/|accounts/reset/|person/.*/photo|group/groupmenu.json)).*) {
deny all;
}

location / {
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' data: https://datatracker.ietf.org/ https://www.ietf.org/ http://ietf.org/ https://analytics.ietf.org https://static.ietf.org; frame-ancestors 'self' ietf.org *.ietf.org meetecho.com *.meetecho.com gather.town *.gather.town";
proxy_set_header Host $${keepempty}host;
proxy_set_header Connection close;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $${keepempty}proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $${keepempty}remote_addr;
proxy_pass http://localhost:8000;
}
}
23 changes: 23 additions & 0 deletions k8s/nginx-datatracker.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
server {
listen 8080 default_server;
server_name _;

location /health/nginx {
return 200;
}

location /robots.txt {
add_header Content-Type text/plain;
return 200 "User-agent: *\nDisallow: /doc/pdf/\n";
}

location / {
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' data: https://datatracker.ietf.org/ https://www.ietf.org/ http://ietf.org/ https://analytics.ietf.org https://static.ietf.org; frame-ancestors 'self' ietf.org *.ietf.org meetecho.com *.meetecho.com";
proxy_set_header Host $${keepempty}host;
proxy_set_header Connection close;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $${keepempty}proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $${keepempty}remote_addr;
proxy_pass http://localhost:8000;
}
}
Loading