mirror of
https://github.com/fosrl/pangolin.git
synced 2026-06-22 15:22:12 +00:00
Compare commits
4 Commits
dependabot
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bde633c5f | ||
|
|
a7c99f336f | ||
|
|
0d960181a2 | ||
|
|
b6862093d1 |
8
.github/workflows/cicd.yml
vendored
8
.github/workflows/cicd.yml
vendored
@@ -62,7 +62,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Monitor storage space
|
- name: Monitor storage space
|
||||||
run: |
|
run: |
|
||||||
@@ -134,7 +134,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Monitor storage space
|
- name: Monitor storage space
|
||||||
run: |
|
run: |
|
||||||
@@ -201,7 +201,7 @@ jobs:
|
|||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||||
@@ -256,7 +256,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Extract tag name
|
- name: Extract tag name
|
||||||
id: get-tag
|
id: get-tag
|
||||||
|
|||||||
2
.github/workflows/linting.yml
vendored
2
.github/workflows/linting.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
|
|||||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Build Docker image sqlite
|
- name: Build Docker image sqlite
|
||||||
run: make dev-build-sqlite
|
run: make dev-build-sqlite
|
||||||
@@ -71,7 +71,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
- name: Build Docker image pg
|
- name: Build Docker image pg
|
||||||
run: make dev-build-pg
|
run: make dev-build-pg
|
||||||
|
|||||||
@@ -154,12 +154,8 @@ export async function createResourceRule(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the new resource rule
|
// Create the new resource rule
|
||||||
const isInlinePolicy =
|
if (resource.resourcePolicyId !== null) {
|
||||||
resource.resourcePolicyId === null &&
|
const policyId = resource.resourcePolicyId;
|
||||||
resource.defaultResourcePolicyId !== null;
|
|
||||||
|
|
||||||
if (isInlinePolicy) {
|
|
||||||
const policyId = resource.defaultResourcePolicyId!;
|
|
||||||
const [newRule] = await db
|
const [newRule] = await db
|
||||||
.insert(resourcePolicyRules)
|
.insert(resourcePolicyRules)
|
||||||
.values({
|
.values({
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from "express";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { db } from "@server/db";
|
import { db } from "@server/db";
|
||||||
import { resourceRules, resourcePolicyRules, resources } from "@server/db";
|
import { resourceRules, resourcePolicyRules, resources } from "@server/db";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, eq } from "drizzle-orm";
|
||||||
import response from "@server/lib/response";
|
import response from "@server/lib/response";
|
||||||
import HttpCode from "@server/types/HttpCode";
|
import HttpCode from "@server/types/HttpCode";
|
||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
@@ -73,14 +73,18 @@ export async function deleteResourceRule(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isInlinePolicy =
|
if (resource.resourcePolicyId !== null) {
|
||||||
resource.resourcePolicyId === null &&
|
|
||||||
resource.defaultResourcePolicyId !== null;
|
|
||||||
|
|
||||||
if (isInlinePolicy) {
|
|
||||||
const [deletedRule] = await db
|
const [deletedRule] = await db
|
||||||
.delete(resourcePolicyRules)
|
.delete(resourcePolicyRules)
|
||||||
.where(eq(resourcePolicyRules.ruleId, ruleId))
|
.where(
|
||||||
|
and(
|
||||||
|
eq(resourcePolicyRules.ruleId, ruleId),
|
||||||
|
eq(
|
||||||
|
resourcePolicyRules.resourcePolicyId,
|
||||||
|
resource.resourcePolicyId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
if (!deletedRule) {
|
if (!deletedRule) {
|
||||||
|
|||||||
@@ -141,16 +141,10 @@ export async function getResource(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isInlinePolicy =
|
|
||||||
resource.resourcePolicyId === null &&
|
|
||||||
resource.defaultResourcePolicyId !== null;
|
|
||||||
|
|
||||||
let returnData = resource;
|
let returnData = resource;
|
||||||
if (isInlinePolicy) {
|
if (resource.resourcePolicyId !== null) {
|
||||||
// get the policy
|
// get the policy
|
||||||
const policy = await queryInlinePolicy(
|
const policy = await queryInlinePolicy(resource.resourcePolicyId);
|
||||||
resource.defaultResourcePolicyId!
|
|
||||||
);
|
|
||||||
returnData = {
|
returnData = {
|
||||||
...returnData,
|
...returnData,
|
||||||
sso: policy?.sso || null,
|
sso: policy?.sso || null,
|
||||||
|
|||||||
@@ -140,15 +140,11 @@ export async function listResourceRules(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isInlinePolicy =
|
|
||||||
resource.resourcePolicyId === null &&
|
|
||||||
resource.defaultResourcePolicyId !== null;
|
|
||||||
|
|
||||||
let rulesList: Awaited<ReturnType<typeof queryResourceRules>>;
|
let rulesList: Awaited<ReturnType<typeof queryResourceRules>>;
|
||||||
let totalCount: number;
|
let totalCount: number;
|
||||||
|
|
||||||
if (isInlinePolicy) {
|
if (resource.resourcePolicyId !== null) {
|
||||||
const policyId = resource.defaultResourcePolicyId!;
|
const policyId = resource.resourcePolicyId;
|
||||||
const policyRules = await queryPolicyRules(policyId)
|
const policyRules = await queryPolicyRules(policyId)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(offset);
|
.offset(offset);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Request, Response, NextFunction } from "express";
|
import { Request, Response, NextFunction } from "express";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { db } from "@server/db";
|
import { db } from "@server/db";
|
||||||
import { resourceRules, resources } from "@server/db";
|
import { resourcePolicyRules, resourceRules, resources } from "@server/db";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, eq } from "drizzle-orm";
|
||||||
import response from "@server/lib/response";
|
import response from "@server/lib/response";
|
||||||
import HttpCode from "@server/types/HttpCode";
|
import HttpCode from "@server/types/HttpCode";
|
||||||
import createHttpError from "http-errors";
|
import createHttpError from "http-errors";
|
||||||
@@ -37,6 +37,29 @@ const updateResourceRuleSchema = z
|
|||||||
error: "At least one field must be provided for update"
|
error: "At least one field must be provided for update"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getRuleValueValidationError(
|
||||||
|
match: "CIDR" | "IP" | "PATH" | "COUNTRY" | "ASN" | "REGION",
|
||||||
|
value: string
|
||||||
|
): string | null {
|
||||||
|
if (match === "CIDR" && !isValidCIDR(value)) {
|
||||||
|
return "Invalid CIDR provided";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match === "IP" && !isValidIP(value)) {
|
||||||
|
return "Invalid IP provided";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match === "PATH" && !isValidUrlGlobPattern(value)) {
|
||||||
|
return "Invalid URL glob pattern provided";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match === "REGION" && !isValidRegionId(value)) {
|
||||||
|
return "Invalid region ID provided";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "post",
|
method: "post",
|
||||||
path: "/resource/{resourceId}/rule/{ruleId}",
|
path: "/resource/{resourceId}/rule/{ruleId}",
|
||||||
@@ -128,6 +151,68 @@ export async function updateResourceRule(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resource.resourcePolicyId !== null) {
|
||||||
|
const [existingRule] = await db
|
||||||
|
.select()
|
||||||
|
.from(resourcePolicyRules)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(resourcePolicyRules.ruleId, ruleId),
|
||||||
|
eq(
|
||||||
|
resourcePolicyRules.resourcePolicyId,
|
||||||
|
resource.resourcePolicyId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
|
if (!existingRule) {
|
||||||
|
return next(
|
||||||
|
createHttpError(
|
||||||
|
HttpCode.NOT_FOUND,
|
||||||
|
`Resource rule with ID ${ruleId} not found`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = updateData.match || existingRule.match;
|
||||||
|
const { value } = updateData;
|
||||||
|
|
||||||
|
if (value !== undefined) {
|
||||||
|
const validationError = getRuleValueValidationError(
|
||||||
|
match,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
if (validationError) {
|
||||||
|
return next(
|
||||||
|
createHttpError(HttpCode.BAD_REQUEST, validationError)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const [updatedRule] = await db
|
||||||
|
.update(resourcePolicyRules)
|
||||||
|
.set(updateData)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(resourcePolicyRules.ruleId, ruleId),
|
||||||
|
eq(
|
||||||
|
resourcePolicyRules.resourcePolicyId,
|
||||||
|
resource.resourcePolicyId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.returning();
|
||||||
|
|
||||||
|
return response(res, {
|
||||||
|
data: updatedRule,
|
||||||
|
success: true,
|
||||||
|
error: false,
|
||||||
|
message: "Resource rule updated successfully",
|
||||||
|
status: HttpCode.OK
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Verify that the rule exists and belongs to the specified resource
|
// Verify that the rule exists and belongs to the specified resource
|
||||||
const [existingRule] = await db
|
const [existingRule] = await db
|
||||||
.select()
|
.select()
|
||||||
@@ -157,42 +242,11 @@ export async function updateResourceRule(
|
|||||||
const { value } = updateData;
|
const { value } = updateData;
|
||||||
|
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
if (match === "CIDR") {
|
const validationError = getRuleValueValidationError(match, value);
|
||||||
if (!isValidCIDR(value)) {
|
if (validationError) {
|
||||||
return next(
|
return next(
|
||||||
createHttpError(
|
createHttpError(HttpCode.BAD_REQUEST, validationError)
|
||||||
HttpCode.BAD_REQUEST,
|
);
|
||||||
"Invalid CIDR provided"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (match === "IP") {
|
|
||||||
if (!isValidIP(value)) {
|
|
||||||
return next(
|
|
||||||
createHttpError(
|
|
||||||
HttpCode.BAD_REQUEST,
|
|
||||||
"Invalid IP provided"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (match === "PATH") {
|
|
||||||
if (!isValidUrlGlobPattern(value)) {
|
|
||||||
return next(
|
|
||||||
createHttpError(
|
|
||||||
HttpCode.BAD_REQUEST,
|
|
||||||
"Invalid URL glob pattern provided"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (match === "REGION") {
|
|
||||||
if (!isValidRegionId(value)) {
|
|
||||||
return next(
|
|
||||||
createHttpError(
|
|
||||||
HttpCode.BAD_REQUEST,
|
|
||||||
"Invalid region ID provided"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user