chore(portal): Enforce only internet resource in internet site (#8254)

Currently, it would theoretically be possible for an admin to connect
non-internet Resources to the Internet site. This PR fixes that by
enforcing only the `internet` Resource type can belong to the `Internet`
gateway group.


Related: #6834
This commit is contained in:
Jamil
2025-02-24 19:45:40 -08:00
committed by GitHub
parent 31111257e1
commit 5650150b3f
3 changed files with 77 additions and 0 deletions

View File

@@ -22,6 +22,10 @@ defmodule Domain.Resources.Connection.Changeset do
|> assoc_constraint(:resource)
|> assoc_constraint(:gateway_group)
|> assoc_constraint(:account)
|> check_constraint(:resource,
name: :internet_resource_in_internet_site,
message: "type must be 'internet' for the Internet site"
)
|> put_change(:account_id, account_id)
end
end

View File

@@ -0,0 +1,53 @@
defmodule Domain.Repo.Migrations.RequireInternetResourceInInternetSite do
use Ecto.Migration
def change do
# Create a function to enforce only 'internet' resources in 'Internet' site
execute(
"""
CREATE OR REPLACE FUNCTION enforce_internet_resource_in_internet_gg()
RETURNS TRIGGER AS $$
DECLARE
resource_type text;
site_name text;
site_managed_by text;
BEGIN
-- Fetch the resource type and gateway group details
SELECT r.type INTO resource_type
FROM resources r
WHERE r.id = NEW.resource_id;
SELECT gg.name, gg.managed_by INTO site_name, site_managed_by
FROM gateway_groups gg
WHERE gg.id = NEW.gateway_group_id;
-- Rule 1: Prevent non-'internet' resources in the 'Internet' gateway group
IF site_name = 'Internet' AND site_managed_by = 'system' AND resource_type != 'internet' THEN
RAISE EXCEPTION 'Only internet resource type is allowed in the Internet site'
USING ERRCODE = '23514', CONSTRAINT = 'internet_resource_in_internet_site';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
""",
"""
DROP FUNCTION IF EXISTS enforce_internet_resource_in_internet_gg();
"""
)
# Create a trigger to run the check on insert or update
execute(
"""
CREATE TRIGGER internet_resource_in_internet_gg
BEFORE INSERT OR UPDATE OF resource_id, gateway_group_id
ON resource_connections
FOR EACH ROW
EXECUTE FUNCTION enforce_internet_resource_in_internet_gg();
""",
"""
DROP TRIGGER IF EXISTS internet_resource_in_internet_gg ON resource_connections;
"""
)
end
end

View File

@@ -1003,6 +1003,26 @@ defmodule Domain.ResourcesTest do
end
describe "create_resource/2" do
test "prevents adding other resources to the internet site", %{
account: account,
subject: subject
} do
{:ok, gateway_group} = Domain.Gateways.create_internet_group(account)
attrs =
Fixtures.Resources.resource_attrs(
type: :dns,
address: "example.com",
connections: [%{gateway_group_id: gateway_group.id}]
)
assert {:error, changeset} = create_resource(attrs, subject)
assert %{resource: ["type must be 'internet' for the Internet site"]} in errors_on(
changeset
).connections
end
test "returns changeset error on empty attrs", %{subject: subject} do
assert {:error, changeset} = create_resource(%{}, subject)