Seperate ip and cidr

This commit is contained in:
Owen 2025-02-10 21:06:37 -05:00
parent 5b44ffa2fb
commit 3c99fbb1ef
No known key found for this signature in database
GPG key ID: 8271FDFFD9E0CCBD
6 changed files with 51 additions and 13 deletions

View file

@ -12,12 +12,6 @@ build-arm:
build-x86:
docker buildx build --platform linux/amd64 -t fosrl/pangolin:latest .
auth-ecr:
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/g5j5p7x0
build-x86-ecr:
docker buildx build --platform linux/amd64 -t 216989133116.dkr.ecr.us-east-1.amazonaws.com/pangolin:latest --push .
build:
docker build -t fosrl/pangolin:latest .

View file

@ -378,7 +378,7 @@ export const resourceRules = sqliteTable("resourceRules", {
.notNull()
.references(() => resources.resourceId, { onDelete: "cascade" }),
action: text("action").notNull(), // ACCEPT, DROP
match: text("match").notNull(), // CIDR, PATH
match: text("match").notNull(), // CIDR, PATH, IP
value: text("value").notNull()
});

View file

@ -494,6 +494,10 @@ async function checkRules(
rule.match == "CIDR" &&
isIpInCidr(clientIp, rule.value) &&
rule.action === "DROP") ||
(clientIp &&
rule.match == "IP" &&
clientIp == rule.value &&
rule.action === "DROP") ||
(path &&
rule.match == "PATH" &&
urlGlobToRegex(rule.value).test(path) &&
@ -516,6 +520,9 @@ async function checkRules(
(clientIp &&
rule.match == "CIDR" &&
isIpInCidr(clientIp, rule.value)) ||
(clientIp &&
rule.match == "IP" &&
clientIp == rule.value) ||
(path &&
rule.match == "PATH" &&
urlGlobToRegex(rule.value).test(path))

View file

@ -12,7 +12,7 @@ import { fromError } from "zod-validation-error";
const createResourceRuleSchema = z
.object({
action: z.enum(["ACCEPT", "DROP"]),
match: z.enum(["CIDR", "PATH"]),
match: z.enum(["CIDR", "IP", "PATH"]),
value: z.string().min(1)
})
.strict();

View file

@ -27,7 +27,7 @@ const updateResourceRuleParamsSchema = z
const updateResourceRuleSchema = z
.object({
action: z.enum(["ACCEPT", "DROP"]).optional(),
match: z.enum(["CIDR", "PATH"]).optional(),
match: z.enum(["CIDR", "IP", "PATH"]).optional(),
value: z.string().min(1).optional()
})
.strict()

View file

@ -101,7 +101,7 @@ export default function ResourceRules(props: {
resolver: zodResolver(addRuleSchema),
defaultValues: {
action: "ACCEPT",
match: "CIDR",
match: "IP",
value: ""
}
});
@ -167,6 +167,15 @@ export default function ResourceRules(props: {
setLoading(false);
return;
}
if (data.match === "IP" && !isValidIP(data.value)) {
toast({
variant: "destructive",
title: "Invalid IP",
description: "Please enter a valid IP address"
});
setLoading(false);
return;
}
const newRule: LocalRule = {
...data,
@ -255,6 +264,15 @@ export default function ResourceRules(props: {
setLoading(false);
return;
}
if (rule.match === "IP" && !isValidIP(rule.value)) {
toast({
variant: "destructive",
title: "Invalid IP",
description: "Please enter a valid IP address"
});
setLoading(false);
return;
}
if (rule.new) {
const res = await api.put(`/resource/${params.resourceId}/rule`, data);
@ -336,7 +354,7 @@ export default function ResourceRules(props: {
cell: ({ row }) => (
<Select
defaultValue={row.original.match}
onValueChange={(value: "CIDR" | "PATH") =>
onValueChange={(value: "CIDR" | "IP" | "PATH") =>
updateRule(row.original.ruleId, { match: value })
}
>
@ -344,7 +362,8 @@ export default function ResourceRules(props: {
{row.original.match}
</SelectTrigger>
<SelectContent>
<SelectItem value="CIDR">CIDR</SelectItem>
<SelectItem value="IP">IP</SelectItem>
<SelectItem value="CIDR">IP Range</SelectItem>
<SelectItem value="PATH">PATH</SelectItem>
</SelectContent>
</Select>
@ -527,8 +546,11 @@ export default function ResourceRules(props: {
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="IP">
IP
</SelectItem>
<SelectItem value="CIDR">
CIDR
IP Range
</SelectItem>
{resource.http && (
<SelectItem value="PATH">
@ -657,6 +679,21 @@ function isValidCIDR(cidr: string): boolean {
});
}
function isValidIP(ip: string): boolean {
const ipPattern = /^([0-9]{1,3}\.){3}[0-9]{1,3}$/;
if (!ipPattern.test(ip)) {
return false;
}
const octets = ip.split(".");
return octets.every((octet) => {
const num = parseInt(octet, 10);
return num >= 0 && num <= 255;
});
}
function isValidUrlGlobPattern(pattern: string): boolean {
// Remove leading slash if present
pattern = pattern.startsWith("/") ? pattern.slice(1) : pattern;