Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove CORS configuration #2200

Merged
merged 2 commits into from
Feb 1, 2025
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
4 changes: 0 additions & 4 deletions charts/platform-api/templates/deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ spec:
value: http://localhost:8080/api/v1
- name: NP_ENFORCER_RETENTION_DELAY_DAYS
value: {{ .Values.enforcerRetentionDelayDays | quote }}
{{- if .Values.cors.origins }}
- name: NP_CORS_ORIGINS
value: {{ .Values.cors.origins | join "," | quote}}
{{- end }}
- name: NP_DB_POSTGRES_DSN
{{- if .Values.postgres.dsn }}
{{ toYaml .Values.postgres.dsn | indent 10 }}
Expand Down
3 changes: 0 additions & 3 deletions charts/platform-api/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ oauth:
successRedirectUrl: https://staging.neu.ro/oauth/login
headlessCallbackUrl: https://staging.neu.ro/oauth/show-code

cors:
origins: []

postgres:
dsn: {}

Expand Down
21 changes: 1 addition & 20 deletions platform_api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from typing import Any

import aiohttp.web
import aiohttp_cors
from aiohttp.web import HTTPUnauthorized
from aiohttp.web_urldispatcher import AbstractRoute
from aiohttp_security import check_permission
Expand Down Expand Up @@ -39,7 +38,7 @@
EnergySchedulePeriod,
VolumeConfig,
)
from .config import Config, CORSConfig
from .config import Config
from .config_client import ConfigClient
from .config_factory import EnvironConfigFactory
from .handlers import JobsHandler
Expand Down Expand Up @@ -540,8 +539,6 @@ async def _init_app(app: aiohttp.web.Application) -> AsyncIterator[None]:

app.add_subapp("/api/v1", api_v1_app)

_setup_cors(app, config.cors)

app.on_response_prepare.append(add_version_to_header)

if config.zipkin:
Expand All @@ -550,22 +547,6 @@ async def _init_app(app: aiohttp.web.Application) -> AsyncIterator[None]:
return app


def _setup_cors(app: aiohttp.web.Application, config: CORSConfig) -> None:
if not config.allowed_origins:
return

logger.info(f"Setting up CORS with allowed origins: {config.allowed_origins}")
default_options = aiohttp_cors.ResourceOptions(
allow_credentials=True, expose_headers="*", allow_headers="*"
)
cors = aiohttp_cors.setup(
app, defaults={origin: default_options for origin in config.allowed_origins}
)
for route in app.router.routes():
logger.debug(f"Setting up CORS for {route}")
cors.add(route)


def setup_tracing(config: Config) -> None:
if config.zipkin:
setup_zipkin_tracer(
Expand Down
6 changes: 0 additions & 6 deletions platform_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,6 @@ def retention_delay(self) -> timedelta:
return timedelta(days=self.retention_delay_days)


@dataclass(frozen=True)
class CORSConfig:
allowed_origins: Sequence[str] = ()


@dataclass(frozen=True)
class JobsSchedulerConfig:
# Minimal time that preepmtible job is guaranteed to run before suspended
Expand Down Expand Up @@ -271,7 +266,6 @@ class Config:
oauth: Optional[OAuthConfig] = None

jobs: JobsConfig = JobsConfig()
cors: CORSConfig = CORSConfig()

scheduler: JobsSchedulerConfig = JobsSchedulerConfig()

Expand Down
9 changes: 0 additions & 9 deletions platform_api/config_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from .config import (
AuthConfig,
Config,
CORSConfig,
DatabaseConfig,
JobPolicyEnforcerConfig,
JobsConfig,
Expand Down Expand Up @@ -65,7 +64,6 @@ def create(self) -> Config:
job_policy_enforcer=self.create_job_policy_enforcer(),
scheduler=self.create_job_scheduler(),
notifications=self.create_notifications(),
cors=self.create_cors(),
config_url=config_url,
admin_url=admin_url,
admin_public_url=admin_public_url,
Expand Down Expand Up @@ -227,13 +225,6 @@ def create_notifications(self) -> NotificationsConfig:
token = self._environ.get("NP_NOTIFICATIONS_TOKEN", "")
return NotificationsConfig(url=url, token=token)

def create_cors(self) -> CORSConfig:
origins: Sequence[str] = CORSConfig.allowed_origins
origins_str = self._environ.get("NP_CORS_ORIGINS", "").strip()
if origins_str:
origins = origins_str.split(",")
return CORSConfig(allowed_origins=origins)

def create_postgres(self) -> PostgresConfig:
try:
postgres_dsn = to_async_postgres_dsn(self._environ["NP_DB_POSTGRES_DSN"])
Expand Down
4 changes: 2 additions & 2 deletions platform_api/utils/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


async def run_and_log_exceptions(
coros: Union[Coroutine[Any, Any, Any], Iterable[Coroutine[Any, Any, Any]]]
coros: Union[Coroutine[Any, Any, Any], Iterable[Coroutine[Any, Any, Any]]],
) -> None:
try:
# Check is iterable
Expand Down Expand Up @@ -49,7 +49,7 @@ async def __aexit__(


def asyncgeneratorcontextmanager(
func: Callable[..., T_co]
func: Callable[..., T_co],
) -> Callable[..., AbstractAsyncContextManager[T_co]]:
@functools.wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> AbstractAsyncContextManager[T_co]:
Expand Down
6 changes: 1 addition & 5 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ install_requires =
cryptography==41.0.5
aiorwlock==1.3.0
neuro-notifications-client==22.6.2
neuro-logging==21.12.2
aiohttp-cors==0.7.0
neuro-logging==21.12.0
asyncpg==0.28.0
sqlalchemy==1.4.25
alembic==1.9.4
Expand Down Expand Up @@ -142,9 +141,6 @@ ignore_missing_imports = true
[mypy-_pytest.*]
ignore_missing_imports = true

[mypy-aiohttp_cors]
ignore_missing_imports = true

[mypy-asyncpg.*]
ignore_missing_imports = true

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,6 @@ def _factory(cluster_name: Optional[str] = None) -> dict[str, Any]:

@pytest.fixture
async def job_submit(
job_request_factory: Callable[[], dict[str, Any]]
job_request_factory: Callable[[], dict[str, Any]],
) -> dict[str, Any]:
return job_request_factory()
8 changes: 3 additions & 5 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
from platform_api.config import (
AuthConfig,
Config,
CORSConfig,
DatabaseConfig,
JobPolicyEnforcerConfig,
JobsConfig,
Expand Down Expand Up @@ -495,11 +494,11 @@ async def wait_pod_scheduled(
cpu = resource_requests.get("cpu")
memory = resource_requests.get("memory")
print(
f' {pod["metadata"]["name"]:40s}',
f" {pod['metadata']['name']:40s}",
f"{str(cpu):5s}",
f"{str(memory):10s}",
f'{pod["status"]["phase"]:9s}',
f'{str(pod["spec"].get("nodeName"))}',
f"{pod['status']['phase']:9s}",
f"{str(pod['spec'].get('nodeName'))}",
)
pytest.fail("Pod unscheduled")

Expand Down Expand Up @@ -906,7 +905,6 @@ def _factory(**kwargs: Any) -> Config:
jobs=jobs_config,
job_policy_enforcer=job_policy_enforcer,
notifications=notifications_config,
cors=CORSConfig(allowed_origins=["https://neu.ro"]),
config_url=config_url,
admin_url=admin_url,
admin_public_url=admin_url,
Expand Down
66 changes: 2 additions & 64 deletions tests/integration/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,67 +92,6 @@ async def test_ping_includes_version(
assert response.status == HTTPOk.status_code, await response.text()
assert "platform-api" in response.headers["X-Service-Version"]

async def test_ping_unknown_origin(
self, api: ApiConfig, client: aiohttp.ClientSession
) -> None:
async with client.get(
api.ping_url, headers={"Origin": "http://unknown"}
) as response:
assert response.status == HTTPOk.status_code, await response.text()
assert "Access-Control-Allow-Origin" not in response.headers

async def test_ping_allowed_origin(
self, api: ApiConfig, client: aiohttp.ClientSession
) -> None:
async with client.get(
api.ping_url, headers={"Origin": "https://neu.ro"}
) as resp:
assert resp.status == HTTPOk.status_code, await resp.text()
assert resp.headers["Access-Control-Allow-Origin"] == "https://neu.ro"
assert resp.headers["Access-Control-Allow-Credentials"] == "true"
assert resp.headers["Access-Control-Expose-Headers"]

async def test_ping_options_no_headers(
self, api: ApiConfig, client: aiohttp.ClientSession
) -> None:
async with client.options(api.ping_url) as resp:
assert resp.status == HTTPForbidden.status_code, await resp.text()
assert await resp.text() == (
"CORS preflight request failed: "
"origin header is not specified in the request"
)

async def test_ping_options_unknown_origin(
self, api: ApiConfig, client: aiohttp.ClientSession
) -> None:
async with client.options(
api.ping_url,
headers={
"Origin": "http://unknown",
"Access-Control-Request-Method": "GET",
},
) as resp:
assert resp.status == HTTPForbidden.status_code, await resp.text()
assert await resp.text() == (
"CORS preflight request failed: "
"origin 'http://unknown' is not allowed"
)

async def test_ping_options(
self, api: ApiConfig, client: aiohttp.ClientSession
) -> None:
async with client.options(
api.ping_url,
headers={
"Origin": "https://neu.ro",
"Access-Control-Request-Method": "GET",
},
) as resp:
assert resp.status == HTTPOk.status_code, await resp.text()
assert resp.headers["Access-Control-Allow-Origin"] == "https://neu.ro"
assert resp.headers["Access-Control-Allow-Credentials"] == "true"
assert resp.headers["Access-Control-Allow-Methods"] == "GET"

async def test_config_unauthorized(
self, api: ApiConfig, client: aiohttp.ClientSession
) -> None:
Expand Down Expand Up @@ -2955,8 +2894,7 @@ async def test_create_job_with_secret_env_wrong_scheme_fail(
assert resp.status == HTTPBadRequest.status_code, await resp.text()
msg = await resp.json()
err = (
"Invalid URI scheme: "
f"\\\\*'{wrong_scheme}\\\\*' != \\\\*'secret\\\\*'"
f"Invalid URI scheme: \\\\*'{wrong_scheme}\\\\*' != \\\\*'secret\\\\*'"
)
assert re.search(err, msg["error"]), msg

Expand Down Expand Up @@ -3149,7 +3087,7 @@ async def test_create_job_volume_wrong_cluster_name(
url = api.jobs_base_url
job_submit["container"]["volumes"] = [
{
"src_storage_uri": "storage://wrong-cluster/" f"{regular_user.name}",
"src_storage_uri": f"storage://wrong-cluster/{regular_user.name}",
"dst_path": "/var/storage",
"read_only": False,
}
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_config_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ async def handle(request: aiohttp.web.Request) -> aiohttp.web.Response:

@asynccontextmanager
async def create_config_api(
cluster_configs_payload: list[dict[str, Any]]
cluster_configs_payload: list[dict[str, Any]],
) -> AsyncIterator[URL]:
app = await create_config_app(cluster_configs_payload)
runner = ApiRunner(app, port=8082)
Expand Down
5 changes: 0 additions & 5 deletions tests/unit/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,6 @@ def test_create_defaults(self) -> None:
"https://dev.neu.ro/oauth/show-code"
)

assert not config.cors.allowed_origins

assert config.zipkin is None
assert config.sentry is None

Expand Down Expand Up @@ -424,7 +422,6 @@ def test_create_custom(self, cert_authority_path: str) -> None:
"NP_NOTIFICATIONS_URL": "http://notifications:8080",
"NP_NOTIFICATIONS_TOKEN": "token",
"NP_ENFORCER_PLATFORM_API_URL": "http://platformapi:8080/api/v1",
"NP_CORS_ORIGINS": "https://domain1.com,http://do.main",
"NP_ZIPKIN_URL": "https://zipkin:9411",
"NP_SENTRY_DSN": "https://sentry",
"NP_SENTRY_CLUSTER_NAME": "test",
Expand Down Expand Up @@ -460,8 +457,6 @@ def test_create_custom(self, cert_authority_path: str) -> None:
assert config.auth.service_token == "token"
assert config.auth.service_name == "servicename"

assert config.cors.allowed_origins == ["https://domain1.com", "http://do.main"]

assert config.zipkin
assert config.sentry

Expand Down
Loading