mirror of
https://github.com/biersoeckli/QuickStack.git
synced 2026-02-10 13:39:07 -06:00
feat: enhance network policy with INTERNET_ONLY options and update related components
This commit is contained in:
@@ -200,8 +200,8 @@ model App {
|
||||
|
||||
webhookId String?
|
||||
|
||||
ingressNetworkPolicy String @default("ALLOW_ALL") // ALLOW_ALL, NAMESPACE_ONLY, DENY_ALL
|
||||
egressNetworkPolicy String @default("ALLOW_ALL") // ALLOW_ALL, NAMESPACE_ONLY, DENY_ALL
|
||||
ingressNetworkPolicy String @default("ALLOW_ALL") // ALLOW_ALL, NAMESPACE_ONLY, DENY_ALL, INTERNET_ONLY
|
||||
egressNetworkPolicy String @default("ALLOW_ALL") // ALLOW_ALL, NAMESPACE_ONLY, DENY_ALL, INTERNET_ONLY
|
||||
|
||||
appDomains AppDomain[]
|
||||
appPorts AppPort[]
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function BasicAuth({ app, readonly }: {
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableCaption>{app.appFileMounts.length} Auth Credentials</TableCaption>
|
||||
<TableCaption>{app.appBasicAuths.length} Auth Credentials</TableCaption>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Username</TableHead>
|
||||
|
||||
@@ -44,6 +44,7 @@ export default function NetworkPolicy({ app, readonly }: {
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALLOW_ALL">Allow All (Internet + Project Apps)</SelectItem>
|
||||
<SelectItem value="INTERNET_ONLY">Internet Only</SelectItem>
|
||||
<SelectItem value="NAMESPACE_ONLY">Project Apps Only</SelectItem>
|
||||
<SelectItem value="DENY_ALL">Deny All</SelectItem>
|
||||
</SelectContent>
|
||||
@@ -64,6 +65,7 @@ export default function NetworkPolicy({ app, readonly }: {
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="ALLOW_ALL">Allow All (Internet + Project Apps)</SelectItem>
|
||||
<SelectItem value="INTERNET_ONLY">Internet Only</SelectItem>
|
||||
<SelectItem value="NAMESPACE_ONLY">Project Apps Only</SelectItem>
|
||||
<SelectItem value="DENY_ALL">Deny All</SelectItem>
|
||||
</SelectContent>
|
||||
|
||||
@@ -20,7 +20,7 @@ export default async function RootLayout({
|
||||
const session = await isAuthorizedReadForApp(appId);
|
||||
const app = await appService.getExtendedById(appId);
|
||||
|
||||
const showIngressWarning = app.appDomains.length > 0 && app.ingressNetworkPolicy !== 'ALLOW_ALL';
|
||||
const showIngressWarning = app.appDomains.length > 0 && app.ingressNetworkPolicy !== 'ALLOW_ALL' && app.ingressNetworkPolicy !== 'INTERNET_ONLY';
|
||||
|
||||
return (
|
||||
<div className="flex-1 space-y-6 pt-6">
|
||||
@@ -28,16 +28,16 @@ export default async function RootLayout({
|
||||
title={app.name}
|
||||
subtitle={`App ID: ${app.id}`}>
|
||||
</PageTitle>
|
||||
{showIngressWarning && (
|
||||
<Alert variant="destructive">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
<AlertTitle>Warning</AlertTitle>
|
||||
<AlertDescription>
|
||||
You have configured domains for this app, but the Ingress Network Policy is not set to "Allow All".
|
||||
External traffic via the domain might be blocked.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
{showIngressWarning && (
|
||||
<Alert variant="destructive">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
<AlertTitle>Warning</AlertTitle>
|
||||
<AlertDescription>
|
||||
You have configured domains for this app, but the Ingress Network Policy is not set to "Allow All" or "Internet Only".
|
||||
External traffic via the domain might be blocked.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<AppActionButtons session={session} app={app} />
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -45,11 +45,73 @@ class NetworkPolicyService {
|
||||
if (policyType === 'ALLOW_ALL') {
|
||||
// Allow from everywhere
|
||||
rules.push({
|
||||
from: [{
|
||||
ipBlock: {
|
||||
cidr: '0.0.0.0/0'
|
||||
from: [
|
||||
{
|
||||
ipBlock: {
|
||||
cidr: '0.0.0.0/0',
|
||||
except: [
|
||||
'10.0.0.0/8',
|
||||
'172.16.0.0/12',
|
||||
'192.168.0.0/16',
|
||||
'127.0.0.0/8'
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
// Allow from Traefik ingress controller
|
||||
namespaceSelector: {
|
||||
matchLabels: {
|
||||
'kubernetes.io/metadata.name': 'kube-system'
|
||||
}
|
||||
},
|
||||
podSelector: {
|
||||
matchLabels: {
|
||||
'app.kubernetes.io/name': 'traefik'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
podSelector: {} // Selects all pods in the same namespace
|
||||
}
|
||||
}]
|
||||
]
|
||||
});
|
||||
} else if (policyType === 'INTERNET_ONLY') {
|
||||
// Allow from internet (external to cluster) and from Traefik ingress controller
|
||||
// Block other internal pod traffic
|
||||
rules.push({
|
||||
from: [
|
||||
{
|
||||
ipBlock: {
|
||||
cidr: '0.0.0.0/0',
|
||||
except: [
|
||||
'10.0.0.0/8',
|
||||
'172.16.0.0/12',
|
||||
'192.168.0.0/16',
|
||||
'127.0.0.0/8'
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
// Allow from Traefik ingress controller
|
||||
namespaceSelector: {
|
||||
matchLabels: {
|
||||
'kubernetes.io/metadata.name': 'kube-system'
|
||||
}
|
||||
},
|
||||
podSelector: {
|
||||
matchLabels: {
|
||||
'app.kubernetes.io/name': 'traefik'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
podSelector: {
|
||||
matchLabels: {
|
||||
[Constants.QS_ANNOTATION_CONTAINER_TYPE]: Constants.QS_ANNOTATION_CONTAINER_TYPE_DB_BACKUP_JOB
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
} else if (policyType === 'NAMESPACE_ONLY') {
|
||||
// Allow only from same namespace
|
||||
@@ -59,7 +121,16 @@ class NetworkPolicyService {
|
||||
}]
|
||||
});
|
||||
} else if (policyType === 'DENY_ALL') {
|
||||
// No rules means deny all
|
||||
// No rules means deny all --> except the separate container for database backups
|
||||
rules.push({
|
||||
from: [{
|
||||
podSelector: {
|
||||
matchLabels: {
|
||||
[Constants.QS_ANNOTATION_CONTAINER_TYPE]: Constants.QS_ANNOTATION_CONTAINER_TYPE_DB_BACKUP_JOB
|
||||
}
|
||||
}
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
return rules;
|
||||
@@ -84,16 +155,7 @@ class NetworkPolicyService {
|
||||
"k8s-app": "kube-dns"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
ipBlock: {
|
||||
cidr: '0.0.0.0/0'
|
||||
}
|
||||
}
|
||||
],
|
||||
ports: [
|
||||
{ protocol: 'UDP', port: 53 as any },
|
||||
{ protocol: 'TCP', port: 53 as any }
|
||||
]
|
||||
});
|
||||
|
||||
@@ -116,6 +178,21 @@ class NetworkPolicyService {
|
||||
}
|
||||
]
|
||||
});
|
||||
} else if (policyType === 'INTERNET_ONLY') {
|
||||
// Allow only to internet, block internal cluster traffic
|
||||
rules.push({
|
||||
to: [{
|
||||
ipBlock: {
|
||||
cidr: '0.0.0.0/0',
|
||||
except: [
|
||||
'10.0.0.0/8',
|
||||
'172.16.0.0/12',
|
||||
'192.168.0.0/16',
|
||||
'127.0.0.0/8'
|
||||
]
|
||||
}
|
||||
}]
|
||||
});
|
||||
} else if (policyType === 'NAMESPACE_ONLY') {
|
||||
// Allow only to same namespace
|
||||
rules.push({
|
||||
|
||||
@@ -42,6 +42,7 @@ class MariaDbBackupService {
|
||||
annotations: {
|
||||
[Constants.QS_ANNOTATION_APP_ID]: app.id,
|
||||
[Constants.QS_ANNOTATION_PROJECT_ID]: app.projectId,
|
||||
[Constants.QS_ANNOTATION_CONTAINER_TYPE]: Constants.QS_ANNOTATION_CONTAINER_TYPE_DB_BACKUP_JOB
|
||||
}
|
||||
},
|
||||
spec: {
|
||||
|
||||
@@ -43,6 +43,7 @@ class MongoDbBackupService {
|
||||
annotations: {
|
||||
[Constants.QS_ANNOTATION_APP_ID]: app.id,
|
||||
[Constants.QS_ANNOTATION_PROJECT_ID]: app.projectId,
|
||||
[Constants.QS_ANNOTATION_CONTAINER_TYPE]: Constants.QS_ANNOTATION_CONTAINER_TYPE_DB_BACKUP_JOB
|
||||
}
|
||||
},
|
||||
spec: {
|
||||
|
||||
@@ -42,6 +42,7 @@ class PostgresBackupService {
|
||||
annotations: {
|
||||
[Constants.QS_ANNOTATION_APP_ID]: app.id,
|
||||
[Constants.QS_ANNOTATION_PROJECT_ID]: app.projectId,
|
||||
[Constants.QS_ANNOTATION_CONTAINER_TYPE]: Constants.QS_ANNOTATION_CONTAINER_TYPE_DB_BACKUP_JOB
|
||||
}
|
||||
},
|
||||
spec: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const appNetworkPolicy = z.enum(["ALLOW_ALL", "NAMESPACE_ONLY", "DENY_ALL"]);
|
||||
export const appNetworkPolicy = z.enum(["ALLOW_ALL", "INTERNET_ONLY", "NAMESPACE_ONLY", "DENY_ALL"]);
|
||||
export type AppNetworkPolicyType = z.infer<typeof appNetworkPolicy>;
|
||||
@@ -1,6 +1,8 @@
|
||||
export class Constants {
|
||||
static readonly QS_ANNOTATION_APP_ID = 'qs-app-id';
|
||||
static readonly QS_ANNOTATION_PROJECT_ID = 'qs-project-id';
|
||||
static readonly QS_ANNOTATION_CONTAINER_TYPE = 'qs-containter-type';
|
||||
static readonly QS_ANNOTATION_CONTAINER_TYPE_DB_BACKUP_JOB = 'qs-job-database-backup';
|
||||
static readonly QS_ANNOTATION_DEPLOYMENT_ID = 'qs-deplyoment-id';
|
||||
static readonly QS_ANNOTATION_GIT_COMMIT = 'qs-git-commit';
|
||||
static readonly K3S_JOIN_TOKEN = 'k3sJoinToken';
|
||||
|
||||
Reference in New Issue
Block a user