security: add tenant allowlist and WAF canary proof
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"data": {
|
||||
"default.conf": "server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n location / { try_files $uri $uri/ =404; }\n location /healthz { access_log off; return 200 \"ok\"; add_header Content-Type text/plain; }\n}\n"
|
||||
},
|
||||
"default.conf": "server {\n listen 80;\n server_name _;\n root /usr/share/nginx/html;\n index index.html;\n location / { try_files $uri $uri/ =404; }\n location = /lamp-canary/index.php { add_header Content-Type text/plain; return 200 \"lamp-index-ok\\n\"; }\n location = /lamp-canary/wp-login.php { add_header Content-Type text/plain; return 200 \"wp-login-ok\\n\"; }\n location = /lamp-canary/mediawiki/index.php { add_header Content-Type text/plain; return 200 \"mediawiki-ok\\n\"; }\n location = /admin-allowlist-proof { add_header Content-Type text/plain; return 200 \"admin-allowlist-ok\\n\"; }\n location /healthz { access_log off; return 200 \"ok\"; add_header Content-Type text/plain; }\n}\n"
|
||||
},
|
||||
"kind": "ConfigMap",
|
||||
"metadata": {
|
||||
"name": "andrew-web-nginx-conf",
|
||||
|
||||
@@ -24,12 +24,15 @@
|
||||
},
|
||||
"type": "RollingUpdate"
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"app": "andrew-web"
|
||||
}
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"flowercore.io/config-revision": "whc4-lamp-allowlist-20260618"
|
||||
},
|
||||
"labels": {
|
||||
"app": "andrew-web"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
|
||||
@@ -30,6 +30,31 @@
|
||||
"port": 8080
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "Rule",
|
||||
"match": "(Host(`bluejay.dev`) || Host(`www.bluejay.dev`)) && PathPrefix(`/admin-allowlist-proof`)",
|
||||
"middlewares": [
|
||||
{
|
||||
"name": "andrew-admin-ip-allowlist",
|
||||
"namespace": "fc-tenant-andrew"
|
||||
},
|
||||
{
|
||||
"name": "andrew-tenant-rate-limit",
|
||||
"namespace": "fc-tenant-andrew"
|
||||
},
|
||||
{
|
||||
"name": "andrew-tenant-secure-headers",
|
||||
"namespace": "fc-tenant-andrew"
|
||||
}
|
||||
],
|
||||
"priority": 300,
|
||||
"services": [
|
||||
{
|
||||
"name": "andrew-web-waf",
|
||||
"port": 8080
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tls": {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"apiVersion": "traefik.io/v1alpha1",
|
||||
"kind": "Middleware",
|
||||
"metadata": {
|
||||
"name": "andrew-admin-ip-allowlist",
|
||||
"namespace": "fc-tenant-andrew"
|
||||
},
|
||||
"spec": {
|
||||
"ipAllowList": {
|
||||
"sourceRange": [
|
||||
"10.0.56.14/32"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1128,9 +1128,48 @@ public sealed class FleetManifestLintTests
|
||||
.Should()
|
||||
.Equal("andrew-tenant-rate-limit", "andrew-tenant-secure-headers");
|
||||
|
||||
var adminRoute = ingressRoute.RootElement
|
||||
.GetProperty("spec")
|
||||
.GetProperty("routes")
|
||||
.EnumerateArray()
|
||||
.Single(route => route.GetProperty("match").GetString()!.Contains("PathPrefix(`/admin-allowlist-proof`)", StringComparison.Ordinal));
|
||||
adminRoute.GetProperty("priority").GetInt32().Should().Be(300);
|
||||
adminRoute.GetProperty("services").EnumerateArray().Should().ContainSingle().Subject
|
||||
.GetProperty("name").GetString().Should().Be("andrew-web-waf");
|
||||
adminRoute.GetProperty("middlewares")
|
||||
.EnumerateArray()
|
||||
.Select(item => item.GetProperty("name").GetString())
|
||||
.Should()
|
||||
.Equal("andrew-admin-ip-allowlist", "andrew-tenant-rate-limit", "andrew-tenant-secure-headers");
|
||||
|
||||
using var rateLimit = JsonDocument.Parse(File.ReadAllText(Path.Combine(appRoot, "middleware-andrew-tenant-rate-limit.json")));
|
||||
rateLimit.RootElement.GetProperty("spec").GetProperty("rateLimit").GetProperty("average").GetInt32().Should().Be(120);
|
||||
|
||||
using var allowlist = JsonDocument.Parse(File.ReadAllText(Path.Combine(appRoot, "middleware-andrew-admin-ip-allowlist.json")));
|
||||
allowlist.RootElement.GetProperty("kind").GetString().Should().Be("Middleware");
|
||||
allowlist.RootElement.GetProperty("spec").GetProperty("ipAllowList").GetProperty("sourceRange")
|
||||
.EnumerateArray()
|
||||
.Select(item => item.GetString())
|
||||
.Should()
|
||||
.Equal("10.0.56.14/32");
|
||||
|
||||
using var nginxConfig = JsonDocument.Parse(File.ReadAllText(Path.Combine(appRoot, "configmap-andrew-web-nginx-conf.json")));
|
||||
var nginx = nginxConfig.RootElement.GetProperty("data").GetProperty("default.conf").GetString();
|
||||
nginx.Should().Contain("location = /lamp-canary/index.php");
|
||||
nginx.Should().Contain("location = /lamp-canary/wp-login.php");
|
||||
nginx.Should().Contain("location = /lamp-canary/mediawiki/index.php");
|
||||
nginx.Should().Contain("location = /admin-allowlist-proof");
|
||||
|
||||
using var webDeployment = JsonDocument.Parse(File.ReadAllText(Path.Combine(appRoot, "deployment-andrew-web.json")));
|
||||
webDeployment.RootElement.GetProperty("spec")
|
||||
.GetProperty("template")
|
||||
.GetProperty("metadata")
|
||||
.GetProperty("annotations")
|
||||
.GetProperty("flowercore.io/config-revision")
|
||||
.GetString()
|
||||
.Should()
|
||||
.Be("whc4-lamp-allowlist-20260618");
|
||||
|
||||
using var headers = JsonDocument.Parse(File.ReadAllText(Path.Combine(appRoot, "middleware-andrew-tenant-secure-headers.json")));
|
||||
var headerSpec = headers.RootElement.GetProperty("spec").GetProperty("headers");
|
||||
headerSpec.GetProperty("contentTypeNosniff").GetBoolean().Should().BeTrue();
|
||||
|
||||
Reference in New Issue
Block a user