Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions packages/opal-server/opal_server/policy/webhook/api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Callable, List
from urllib.parse import SplitResult, urlparse

from fastapi import APIRouter, Depends, Request, status
from fastapi_websocket_pubsub.pub_sub_server import PubSubEndpoint
Expand Down Expand Up @@ -35,6 +36,19 @@ async def dummy_affected_repo_urls(request: Request) -> List[str]:
)


def is_matching_webhook_url(input_url: str, urls: List[str]) -> bool:
parsed = urlparse(input_url)
netloc = parsed.hostname

if parsed.port:
netloc = f"{parsed.hostname}:{parsed.port}"

normalized = SplitResult(
scheme=parsed.scheme, netloc=netloc, path=parsed.path, query="", fragment=""
)
return str(normalized.geturl()) in urls


def get_webhook_router(
route_dependencies: List[Depends],
git_changes: Depends,
Expand Down Expand Up @@ -83,11 +97,10 @@ async def trigger_webhook(request: Request, git_changes: GitChanges = git_change
"Webhook config is missing both event_request_key and event_header_name. Must have at least one."
)

policy_repo_url = opal_server_config.POLICY_REPO_URL

# Check if the URL we are tracking is mentioned in the webhook
if (
opal_server_config.POLICY_REPO_URL is not None
and opal_server_config.POLICY_REPO_URL in urls
):
if policy_repo_url and is_matching_webhook_url(policy_repo_url, urls):
logger.info(
"triggered webhook on repo: {repo}",
repo=opal_server_config.POLICY_REPO_URL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from fastapi_websocket_pubsub import PubSubClient
from flaky import flaky
from opal_common.schemas.webhook import GitWebhookRequestParams
from opal_server.policy.webhook.api import get_webhook_router
from opal_server.policy.webhook.api import get_webhook_router, is_matching_webhook_url
from opal_server.policy.webhook.deps import extracted_git_changes

# Add parent path to use local src as package for tests
Expand Down Expand Up @@ -340,3 +340,25 @@ async def test_webhook_mock_azure_git(azure_git_mode_server):
async with session.get(PUBLISHED_EVENTS_URL) as resp:
json_body = await resp.json()
assert "webhook" in json_body


def test_webhook_url_matcher():
url = "https://git.permit.io/opal/server"
# these should all be equivalent to the above URL
urls = [
"https://user:pass@git.permit.io/opal/server",
"https://user@git.permit.io/opal/server",
"https://user@git.permit.io/opal/server?private=1",
]

for test in urls:
assert is_matching_webhook_url(test, [url])

urls = [
"https://git.permit.io:9090/opal/server",
"http://git.permit.io/opal/server",
"https://git.permit.io/opal/client",
]

for test in urls:
assert not is_matching_webhook_url(test, [url])