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

Validate environment paths #44

Merged
merged 1 commit into from
Feb 7, 2024
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
39 changes: 25 additions & 14 deletions softpack_core/schemas/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,24 @@
return InvalidInputError(message="all fields must be filled in")

if not re.fullmatch(r"^[a-zA-Z0-9_-]+$", self.name):
return InvalidInputError(

Check warning on line 161 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L161

Added line #L161 was not covered by tests
message="name must only contain alphanumerics, "
"dash, and underscore"
)

valid_dirs = [

Check warning on line 166 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L166

Added line #L166 was not covered by tests
Artifacts.users_folder_name,
Artifacts.groups_folder_name,
]
if not any(self.path.startswith(dir + "/") for dir in valid_dirs):
return InvalidInputError(message="Invalid path")

Check warning on line 171 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L171

Added line #L171 was not covered by tests

if not re.fullmatch(r"^[^/]+/[a-zA-Z0-9_-]+$", self.path):
return InvalidInputError(

Check warning on line 174 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L174

Added line #L174 was not covered by tests
message="user/group subdirectory must only contain "
"alphanumerics, dash, and underscore"
)

return None

@classmethod
Expand All @@ -182,8 +195,8 @@
return EnvironmentInput(
name=environment_name,
path="/".join(environment_dirs),
description="",
packages=list(),
description="placeholder description",
packages=[PackageInput("placeholder")],
)


Expand Down Expand Up @@ -247,15 +260,16 @@
Returns:
A message confirming the success or failure of the operation.
"""
input_err = env.validate()
if input_err is not None:
return input_err

versionless_name = env.name

Check warning on line 263 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L263

Added line #L263 was not covered by tests
version = 1

if not versionless_name:
return InvalidInputError(

Check warning on line 267 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L267

Added line #L267 was not covered by tests
message="environment name must not be blank"
)

while True:
env.name = versionless_name + "-" + str(version)

Check warning on line 272 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L272

Added line #L272 was not covered by tests
response = cls.create_new_env(
env, Artifacts.built_by_softpack_file
)
Expand All @@ -268,9 +282,9 @@
version += 1

# Send build request
try:
host = app.settings.builder.host
port = app.settings.builder.port

Check warning on line 287 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L285-L287

Added lines #L285 - L287 were not covered by tests
r = httpx.post(
f"http://{host}:{port}/environments/build",
json={
Expand All @@ -288,10 +302,10 @@
},
},
)
r.raise_for_status()
except Exception as e:
cls.delete(env.name, env.path)
return BuilderError(

Check warning on line 308 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L305-L308

Added lines #L305 - L308 were not covered by tests
message="Connection to builder failed: "
+ "".join(format_exception_only(type(e), e))
)
Expand Down Expand Up @@ -319,15 +333,12 @@
CreateResponse: a CreateEnvironmentSuccess on success, or one of
(InvalidInputError, EnvironmentAlreadyExistsError) on error.
"""
# Check if a valid path has been provided. TODO: improve this to check
# that they can only create stuff in their own users folder, or in
# TODO: improve this to check
# that users can only create stuff in their own users folder, or in
# group folders of unix groups they belong to.
valid_dirs = [
cls.artifacts.users_folder_name,
cls.artifacts.groups_folder_name,
]
if not any(env.path.startswith(dir) for dir in valid_dirs):
return InvalidInputError(message="Invalid path")
input_err = env.validate()

Check warning on line 339 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L339

Added line #L339 was not covered by tests
if input_err is not None:
return input_err

Check warning on line 341 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L341

Added line #L341 was not covered by tests

# Check if an env with same name already exists at given path
if cls.artifacts.get(Path(env.path), env.name):
Expand All @@ -347,9 +358,9 @@
for pkg in env.packages
],
)
ymlData = yaml.dump(softpack_definition)

Check warning on line 361 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L361

Added line #L361 was not covered by tests

tree_oid = cls.artifacts.create_files(

Check warning on line 363 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L363

Added line #L363 was not covered by tests
new_folder_path,
[
(env_type, ""), # e.g. .built_by_softpack
Expand All @@ -361,7 +372,7 @@
tree_oid, "create environment folder"
)
except RuntimeError as e:
return InvalidInputError(

Check warning on line 375 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L375

Added line #L375 was not covered by tests
message="".join(format_exception_only(type(e), e))
)

Expand Down Expand Up @@ -572,13 +583,13 @@
tree_oid = cls.artifacts.create_files(
Path(folder_path), new_files, overwrite=True
)
cls.artifacts.commit_and_push(tree_oid, "write artifact")

Check warning on line 586 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L586

Added line #L586 was not covered by tests
return WriteArtifactSuccess(
message="Successfully written artifact(s)",
)

except Exception as e:
return InvalidInputError(

Check warning on line 592 in softpack_core/schemas/environment.py

View check run for this annotation

Codecov / codecov/patch

softpack_core/schemas/environment.py#L592

Added line #L592 was not covered by tests
message="".join(format_exception_only(type(e), e))
)

Expand Down
15 changes: 13 additions & 2 deletions tests/integration/test_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,19 @@ def test_create_name_dashes_and_number_first_allowed(
assert isinstance(result, CreateEnvironmentSuccess)


def test_create_path_invalid_disallowed(httpx_post, testable_env_input):
testable_env_input.path = "invalid/path"
@pytest.mark.parametrize(
"path",
[
"invalid/path",
"users/",
"users/username/foo",
"users/abc123/very/nested",
"users/../nasty",
"users/user name",
],
)
def test_create_path_invalid_disallowed(httpx_post, testable_env_input, path):
testable_env_input.path = path
result = Environment.create(testable_env_input)
assert isinstance(result, InvalidInputError)

Expand Down
Loading