Skip to content
Draft
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
31 changes: 15 additions & 16 deletions platform_disk_api/api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from __future__ import annotations

from collections.abc import Sequence
import logging
from collections.abc import AsyncIterator, Awaitable, Callable
from contextlib import AsyncExitStack, asynccontextmanager
Expand Down Expand Up @@ -35,14 +38,13 @@
from apolo_kube_client.apolo import NO_ORG, normalize_name
from apolo_kube_client.config import KubeConfig
from marshmallow import Schema, fields
from neuro_auth_client import (
from neuro_admin_client import (
AuthClient,
ClientSubTreeViewRoot,
Permission,
User,
check_permissions,
)
from neuro_auth_client.security import AuthScheme, setup_security
from neuro_admin_client.security import AuthScheme, setup_security
from neuro_logging import init_logging, setup_sentry

from platform_disk_api import __version__
Expand Down Expand Up @@ -223,9 +225,6 @@ async def handle_create_disk(self, request: Request) -> Response:
resp_payload = DiskSchema().dump(disk)
return json_response(resp_payload, status=HTTPCreated.status_code)

def _check_disk_read_perm(self, disk: Disk, tree: ClientSubTreeViewRoot) -> bool:
return tree.allows(self._get_disk_read_perm(disk))

@docs(
tags=["disks"],
summary="Get Disk objects by id or name",
Expand Down Expand Up @@ -256,18 +255,18 @@ async def handle_get_disk(self, request: Request) -> Response:
@response_schema(DiskSchema(many=True), 200)
async def handle_list_disks(self, request: Request) -> Response:
username = await check_authorized(request)
tree = await self._auth_client.get_permissions_tree(
username, self._disk_cluster_uri
)
org_name = request.query.get("org_name") or normalize_name(NO_ORG)
project_name = request.query["project_name"]
disks = [
disk
for disk in await self._service.get_all_disks(
org_name=org_name, project_name=project_name
)
if self._check_disk_read_perm(disk, tree)
]
disks = await self._service.get_all_disks(
org_name=org_name, project_name=project_name
)

disks = await self._auth_client.get_authorized_entities(
user_name=username,
entities=disks,
global_perm=None,
per_entity_perms=lambda d: [self._get_disk_read_perm(d)],
)
resp_payload = DiskSchema(many=True).dump(disks)
return json_response(resp_payload, status=HTTPOk.status_code)

Expand Down
10 changes: 3 additions & 7 deletions platform_disk_api/identity.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import logging
import typing
from dataclasses import dataclass, field

from aiohttp.web import HTTPUnauthorized, Request
from aiohttp_security.api import AUTZ_KEY, IDENTITY_KEY
from neuro_auth_client.security import AuthPolicy
from aiohttp_security.api import IDENTITY_KEY
from neuro_admin_client.security import get_untrusted_user_name

logger = logging.getLogger(__name__)

Expand All @@ -21,10 +20,7 @@ async def untrusted_user(request: Request) -> Identity:
retrieve the minimal information about the user.
"""
identity = await _get_identity(request)

autz_policy = request.config_dict[AUTZ_KEY]
autz_policy = typing.cast(AuthPolicy, autz_policy) # todo: fix after python upgrade
name = autz_policy.get_user_name_from_identity(identity)
name = get_untrusted_user_name(identity)
if name is None:
raise HTTPUnauthorized()

Expand Down
1,161 changes: 594 additions & 567 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ classifiers = [
python = ">=3.12,<4.0"
aiohttp = {version = "3.12.15", extras = ["speedups"]}
yarl = "<2"
neuro-auth-client = "25.8.2"
neuro-admin-client = "25.9.2"
marshmallow = "4.0.0"
aiohttp-apispec = "3.0.0b2"
markupsafe = "3.0.2"
Expand Down Expand Up @@ -92,7 +92,7 @@ module = "jose"
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = "neuro_auth_client.*"
module = "neuro_admin_client.*"
ignore_missing_imports = true

[[tool.mypy.overrides]]
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from aiohttp import ClientError
from aiohttp.hdrs import AUTHORIZATION
from jose import jwt
from neuro_auth_client import AuthClient, Permission, User as AuthClientUser
from neuro_admin_client import AuthClient, Permission, User as AuthClientUser
from yarl import URL
from aiodocker.utils import JSONObject

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
HTTPNotFound,
HTTPUnauthorized,
)
from neuro_auth_client import AuthClient, Permission
from neuro_admin_client import AuthClient, Permission

from platform_disk_api.api import create_app
from platform_disk_api.config import Config
Expand Down
3 changes: 3 additions & 0 deletions tests/k8s/cluster.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ function k8s::apply_all_configurations {
kubectl config use-context minikube
kubectl apply -f tests/k8s/rb.default.gke.yml
kubectl apply -f tests/k8s/platformapi.yml
kubectl apply -f tests/k8s/platformconfig.yml
kubectl apply -f tests/k8s/platformadmin.yml
kubectl apply -f tests/k8s/platformnotifications.yml
kubectl apply -f tests/k8s/storageclass.yml
kubectl apply -f charts/platform-disks/templates/crd-disknaming.yaml
make dist
Expand Down
225 changes: 225 additions & 0 deletions tests/k8s/platformadmin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: platformadmin-postgres
spec:
replicas: 1
selector:
matchLabels:
service: platformadmin-postgres
template:
metadata:
labels:
service: platformadmin-postgres
spec:
containers:
- name: postgres
image: postgres:12.11
env:
- name: POSTGRES_DB
value: postgres
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
value: postgres
---
apiVersion: v1
kind: Service
metadata:
name: platformadmin-postgres
spec:
ports:
- port: 5432
targetPort: 5432
selector:
service: platformadmin-postgres
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: platformadmin
spec:
replicas: 1
selector:
matchLabels:
service: platformadmin
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
service: platformadmin
spec:
imagePullSecrets:
- name: ghcr-secret
initContainers:
- name: platformadmin-migrations
image: ghcr.io/neuro-inc/platformadmin:latest
imagePullPolicy: Always
command: ["alembic", "upgrade", "head"]
env:
- name: NP_ADMIN_POSTGRES_DSN
value: postgresql://postgres:postgres@platformadmin-postgres:5432/postgres
containers:
- name: platformadmin
image: ghcr.io/neuro-inc/platformadmin:latest
imagePullPolicy: Always
env:
- name: NP_LOG_LEVEL
value: INFO
- name: NP_ADMIN_AUTH_TOKEN
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6ImFkbWluIiwiaHR0cHM6Ly9wbGF0Zm9ybS5uZXVyb21hdGlvbi5pby91c2VyIjoiYWRtaW4ifQ._F3y_fr2W0yiJ_-r46NPszsv3H1LzWAvGNXjl0eXwVI
- name: NP_ADMIN_AUTH_URL
value: http://platformauthapi:8080
- name: NP_ADMIN_CONFIG_TOKEN
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6ImFkbWluIiwiaHR0cHM6Ly9wbGF0Zm9ybS5uZXVyb21hdGlvbi5pby91c2VyIjoiYWRtaW4ifQ._F3y_fr2W0yiJ_-r46NPszsv3H1LzWAvGNXjl0eXwVI
- name: NP_ADMIN_CONFIG_URL
value: http://platformconfig:8080
- name: NP_ADMIN_POSTGRES_DSN
value: postgresql://postgres:postgres@platformadmin-postgres:5432/postgres
- name: NP_ADMIN_NOTIFICATIONS_URL
value: http://platformnotifications:8080
- name: NP_ADMIN_NOTIFICATIONS_TOKEN
value: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZGVudGl0eSI6ImNvbXB1dGUifQ.IJDlKCfbiuNGZH9Sh6p-CdUL5KxEK5JStqzfDk4-RAA

---
apiVersion: v1
kind: Service
metadata:
name: platformadmin
spec:
type: LoadBalancer
ports:
- port: 8080
targetPort: 8080
selector:
service: platformadmin
---
apiVersion: batch/v1
kind: Job
metadata:
name: create-cluster
spec:
template:
spec:
restartPolicy: Never
initContainers:
- name: wait-for-platform-config
image: curlimages/curl:8.4.0
command: [sh]
args:
- -c
- |
code=-1

while [ $code != 0 ]
do
sleep 1
curl -f "$NP_PLATFORM_CONFIG_URL/api/v1/ping"
code=$?
done

while [ $code != 0 ]
do
sleep 1
curl -f "$NP_PLATFORM_ADMIN_URL/apis/admin/v1/ping"
code=$?
done
env:
- name: NP_PLATFORM_CONFIG_URL
value: http://platformconfig:8080
- name: NP_PLATFORM_ADMIN_URL
value: http://platformadmin:8080
containers:
- name: create-cluster
image: curlimages/curl:8.4.0
command: [sh]
args:
- -ec
- |
curl -vv -X POST \
-H "Authorization: Bearer $NP_ADMIN_TOKEN" \
-d @- \
"$NP_PLATFORM_ADMIN_URL/apis/admin/v1/users" <<EOM
{
"name": "cluster-admin",
"email": "cluster-admin@neu.ro"
}
EOM

curl -vv -X POST \
-H "Authorization: Bearer $NP_CLUSTER_ADMIN_TOKEN" \
-d @- \
"$NP_PLATFORM_ADMIN_URL/apis/admin/v1/clusters" <<EOM
{
"name": "default"
}
EOM

curl -vv -X POST \
-H "Authorization: Bearer $NP_CLUSTER_ADMIN_TOKEN" \
-d @- \
"$NP_PLATFORM_ADMIN_URL/apis/admin/v1/clusters" <<EOM
{
"name": "default2"
}
EOM

curl -vv -X PUT \
-H "Authorization: Bearer $NP_ADMIN_TOKEN" \
-d @- \
"$NP_PLATFORM_CONFIG_URL/api/v1/clusters/default" <<EOM
{
"name": "default",
"orchestrator": {
"is_http_ingress_secure": true,
"job_hostname_template": "{job_id}.jobs.neu.ro",
"job_internal_hostname_template": "{job_id}.default",
"resource_pool_types": [
{
"name": "minikube",
"min_size": 1,
"max_size": 1,
"cpu": 1.0,
"available_cpu": 1.0,
"memory": 1073741824,
"available_memory": 1073741824
}
],
"resource_presets": [
{
"name": "cpu-small",
"credits_per_hour": "0.0",
"cpu": 0.1,
"memory": 104857600
}
]
},
"storage": {"url": "http://platformapi/api/v1/storage"},
"blob_storage": {"url": "http://platformapi/api/v1/blob"},
"registry": {"url": "http://localhost:5000"},
"monitoring": {"url": "http://platformapi/api/v1/jobs"},
"secrets": {"url": "http://platformapi/api/v1/secrets"},
"metrics": {"url": "http://platformapi/api/v1/metrics"},
"disks": {"url": "http://platformapi/api/v1/disk"},
"buckets": {
"url": "http://platformapi/api/v1/buckets",
"disable_creation": false
},
"ingress": {"acme_environment": "staging"},
"energy": {"co2_grams_eq_per_kwh": 0, "schedules": []},
"timezone": "UTC"
}
EOM
env:
- name: NP_PLATFORM_CONFIG_URL
value: http://platformconfig:8080
- name: NP_PLATFORM_ADMIN_URL
value: http://platformadmin:8080
- name: NP_ADMIN_TOKEN
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6ImFkbWluIiwiaHR0cHM6Ly9wbGF0Zm9ybS5uZXVyb21hdGlvbi5pby91c2VyIjoiYWRtaW4ifQ._F3y_fr2W0yiJ_-r46NPszsv3H1LzWAvGNXjl0eXwVI
- name: NP_CLUSTER_ADMIN_TOKEN
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6ImNsdXN0ZXItYWRtaW4iLCJodHRwczovL3BsYXRmb3JtLm5ldXJvbWF0aW9uLmlvL3VzZXIiOiJjbHVzdGVyLWFkbWluIn0.ee3ufWpd0XRtRmsPhbma1_d1BZeb3c3sEsxiYk0GuFI
Loading