Skip to content

Commit

Permalink
fix: properly validate docker image names
Browse files Browse the repository at this point in the history
  • Loading branch information
Panaetius committed Dec 11, 2024
1 parent 4bdb050 commit 96d096e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
2 changes: 1 addition & 1 deletion components/renku_data_services/notebooks/apispec.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# generated by datamodel-codegen:
# filename: api.spec.yaml
# timestamp: 2024-10-28T16:00:32+00:00
# timestamp: 2024-12-11T13:03:50+00:00

from __future__ import annotations

Expand Down
3 changes: 3 additions & 0 deletions components/renku_data_services/session/api.spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,9 @@ components:
description: A container image
type: string
maxLength: 500
# NOTE: regex for an image name, optionally with a tag or sha256 specified
# based on https://github.com/opencontainers/distribution-spec/blob/main/spec.md
pattern: "^[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*(\\/[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*)*(:[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}|@sha256:[a-fA-F0-9]{64}){0,1}$"
example: renku/renkulab-py:3.10-0.18.1
DefaultUrl:
description: The default path to open in a session
Expand Down
5 changes: 4 additions & 1 deletion components/renku_data_services/session/apispec.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# generated by datamodel-codegen:
# filename: api.spec.yaml
# timestamp: 2024-11-24T09:32:46+00:00
# timestamp: 2024-12-11T13:31:04+00:00

from __future__ import annotations

Expand Down Expand Up @@ -57,6 +57,7 @@ class Environment(BaseAPISpec):
description="A container image",
example="renku/renkulab-py:3.10-0.18.1",
max_length=500,
pattern="^[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*(\\/[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*)*(:[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}|@sha256:[a-fA-F0-9]{64}){0,1}$",
)
default_url: str = Field(
...,
Expand Down Expand Up @@ -118,6 +119,7 @@ class EnvironmentPost(BaseAPISpec):
description="A container image",
example="renku/renkulab-py:3.10-0.18.1",
max_length=500,
pattern="^[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*(\\/[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*)*(:[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}|@sha256:[a-fA-F0-9]{64}){0,1}$",
)
default_url: str = Field(
"/lab",
Expand Down Expand Up @@ -178,6 +180,7 @@ class EnvironmentPatch(BaseAPISpec):
description="A container image",
example="renku/renkulab-py:3.10-0.18.1",
max_length=500,
pattern="^[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*(\\/[a-z0-9]+((\\.|_|__|-+)[a-z0-9]+)*)*(:[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}|@sha256:[a-fA-F0-9]{64}){0,1}$",
)
default_url: Optional[str] = Field(
None,
Expand Down
41 changes: 38 additions & 3 deletions test/bases/renku_data_services/data_api/test_sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,21 @@ async def test_get_session_environment(


@pytest.mark.asyncio
async def test_post_session_environment(sanic_client: SanicASGITestClient, admin_headers) -> None:
@pytest.mark.parametrize(
"image_name",
[
"renku/renku",
"u/renku/renku:latest",
"docker.io/renku/renku:latest",
"renku/renku@sha256:eceed25752d7544db159e4144a41ed6e96e667f39ff9fa18322d79c33729a18c",
"registry.renkulab.io/john.doe/test-34:38d8b3d",
],
)
async def test_post_session_environment(sanic_client: SanicASGITestClient, admin_headers, image_name: str) -> None:
payload = {
"name": "Environment 1",
"description": "A session environment.",
"container_image": "some_image:some_tag",
"container_image": image_name,
}

_, res = await sanic_client.post("/api/data/environments", headers=admin_headers, json=payload)
Expand All @@ -93,7 +103,32 @@ async def test_post_session_environment(sanic_client: SanicASGITestClient, admin
assert res.json is not None
assert res.json.get("name") == "Environment 1"
assert res.json.get("description") == "A session environment."
assert res.json.get("container_image") == "some_image:some_tag"
assert res.json.get("container_image") == image_name


@pytest.mark.asyncio
@pytest.mark.parametrize(
"image_name",
[
"https://example.com/r/test:latest",
"renku/_bla",
"renku/test:töst",
"renku/test@sha254:abcd",
" renku/test:latest",
],
)
async def test_post_session_environment_invalid_image(
sanic_client: SanicASGITestClient, admin_headers, image_name: str
) -> None:
payload = {
"name": "Environment 1",
"description": "A session environment.",
"container_image": image_name,
}

_, res = await sanic_client.post("/api/data/environments", headers=admin_headers, json=payload)

assert res.status_code == 422, res.text


@pytest.mark.asyncio
Expand Down

0 comments on commit 96d096e

Please sign in to comment.